Explosion and Mind Blown / Steel Beam refactor (CFRU port) (#4516)

* Explosion and Mind Blown / Steel Beam refactor (CFRU port)

* forgot ndebug

* Restored EFFECT_MIND_BLOWN

* requested changes

---------

Co-authored-by: Eduardo Quezada <eduardo602002@gmail.com>
This commit is contained in:
Alex 2024-05-12 17:41:18 +02:00 committed by GitHub
parent f502ba2a69
commit 56cee80fbf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 321 additions and 190 deletions

View File

@ -2379,10 +2379,6 @@
manipulatedamage DMG_CURR_ATTACKER_HP
.endm
.macro dmg_1_2_attackerhp
manipulatedamage DMG_1_2_ATTACKER_HP
.endm
.macro jumpifflowerveil jumpInstr:req
jumpifnottype BS_TARGET, TYPE_GRASS, 1f
jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr

View File

@ -547,36 +547,6 @@ BattleScript_EffectShellTrap::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectMaxHp50Recoil::
attackcanceler
attackstring
ppreduce
accuracycheck BattleScript_SteelBeamMiss, ACC_CURR_MOVE
call BattleScript_EffectHit_RetFromCritCalc
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_SteelBeamAfterSelfDamage
call BattleScript_SteelBeamSelfDamage
BattleScript_SteelBeamAfterSelfDamage::
waitstate
tryfaintmon BS_ATTACKER
tryfaintmon BS_TARGET
goto BattleScript_MoveEnd
BattleScript_SteelBeamMiss::
pause B_WAIT_TIME_SHORT
effectivenesssound
resultmessage
waitmessage B_WAIT_TIME_LONG
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_MoveEnd
bichalfword gMoveResultFlags, MOVE_RESULT_MISSED
call BattleScript_SteelBeamSelfDamage
orhalfword gMoveResultFlags, MOVE_RESULT_MISSED
goto BattleScript_SteelBeamAfterSelfDamage
BattleScript_SteelBeamSelfDamage::
dmg_1_2_attackerhp
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
return
BattleScript_EffectCourtChange::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
@ -2968,84 +2938,26 @@ BattleScript_AbsorbHealBlock::
tryfaintmon BS_TARGET
goto BattleScript_MoveEnd
BattleScript_EffectExplosion_AnimDmgRet:
jumpifbyte CMP_NO_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_MISSED, BattleScript_ExplosionAnimRet
call BattleScript_PreserveMissedBitDoMoveAnim
goto BattleScript_ExplosionDmgRet
BattleScript_ExplosionAnimRet:
attackanimation
waitanimation
BattleScript_ExplosionDmgRet:
movevaluescleanup
critcalc
damagecalc
adjustdamage
accuracycheck BattleScript_ExplosionMissedRet, ACC_CURR_MOVE
effectivenesssound
hitanimation BS_TARGET
waitstate
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
critmessage
waitmessage B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
BattleScript_ExplosionAnimEndRet_Return:
return
BattleScript_ExplosionMissedRet:
effectivenesssound
resultmessage
waitmessage B_WAIT_TIME_LONG
goto BattleScript_ExplosionAnimEndRet_Return
BattleScript_EffectExplosion::
attackcanceler
attackstring
ppreduce
@ Below jumps to BattleScript_DampStopsExplosion if it fails (only way it can)
tryexplosion
waitstate
BattleScript_EffectExplosion_AnimDmgFaintAttacker:
call BattleScript_EffectExplosion_AnimDmgRet
moveendall
setatkhptozero
tryfaintmon BS_ATTACKER
end
BattleScript_EffectMindBlown::
attackcanceler
attackstring
ppreduce
jumpifbyte CMP_GREATER_THAN, sB_ANIM_TARGETS_HIT, 0, BattleScript_EffectMindBlown_NoHpLoss
jumpifabilitypresent ABILITY_DAMP, BattleScript_MindBlownDamp
jumpifmorethanhalfHP BS_ATTACKER, BattleScript_EffectMindBlown_HpDown
setbyte sMULTIHIT_EFFECT, 0 @ Note to faint the attacker
instanthpdrop BS_ATTACKER
waitstate
goto BattleScript_EffectExplosion_AnimDmgFaintAttacker
BattleScript_EffectMindBlown_NoHpLoss:
jumpifbyte CMP_EQUAL, sMULTIHIT_EFFECT, 0, BattleScript_EffectExplosion_AnimDmgFaintAttacker
goto BattleScript_EffectMindBlown_AnimDmgNoFaint
BattleScript_MindBlownDamp:
copybyte gBattlerTarget, gBattlerAbility
goto BattleScript_DampStopsExplosion
BattleScript_EffectMindBlown_HpDown:
setbyte sMULTIHIT_EFFECT, 1 @ Note to not faint the attacker
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_EffectMindBlown_AnimDmgNoFaint
dmg_1_2_attackerhp
jumpiffainted BS_TARGET, TRUE, BattleScript_MoveEnd
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
goto BattleScript_HitFromCritCalc
BattleScript_FaintAttackerForExplosion::
tryfaintmon BS_ATTACKER
return
BattleScript_MaxHp50Recoil::
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
waitstate
BattleScript_EffectMindBlown_AnimDmgNoFaint:
call BattleScript_EffectExplosion_AnimDmgRet
goto BattleScript_MoveEnd
BattleScript_PreserveMissedBitDoMoveAnim:
bichalfword gMoveResultFlags, MOVE_RESULT_MISSED
attackanimation
waitanimation
orhalfword gMoveResultFlags, MOVE_RESULT_MISSED
tryfaintmon BS_ATTACKER
return
BattleScript_EffectDreamEater::
@ -7597,6 +7509,15 @@ BattleScript_AbilityPopUp:
sethword sABILITY_OVERWRITE, 0
return
BattleScript_AbilityPopUpScripting:
.if B_ABILITY_POP_UP == TRUE
showabilitypopup BS_SCRIPTING
pause 40
.endif
recordability BS_SCRIPTING
sethword sABILITY_OVERWRITE, 0
return
BattleScript_SpeedBoostActivates::
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_SpeedBoostActivatesEnd
call BattleScript_AbilityPopUp
@ -8130,7 +8051,7 @@ BattleScript_SturdyPreventsOHKO::
BattleScript_DampStopsExplosion::
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUpTarget
call BattleScript_AbilityPopUpScripting
printstring STRINGID_PKMNPREVENTSUSAGE
pause B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET

View File

@ -152,6 +152,8 @@ extern const u8 BattleScript_MoveEffectPayDay[];
extern const u8 BattleScript_MoveEffectWrap[];
extern const u8 BattleScript_MoveEffectConfusion[];
extern const u8 BattleScript_MoveEffectRecoil[];
extern const u8 BattleScript_FaintAttackerForExplosion[];
extern const u8 BattleScript_MaxHp50Recoil[];
extern const u8 BattleScript_DoRecoil33[];
extern const u8 BattleScript_Recoil33End[];
extern const u8 BattleScript_ItemSteal[];
@ -772,7 +774,6 @@ extern const u8 BattleScript_EffectLaserFocus[];
extern const u8 BattleScript_EffectMagneticFlux[];
extern const u8 BattleScript_EffectGearUp[];
extern const u8 BattleScript_EffectStrengthSap[];
extern const u8 BattleScript_EffectMindBlown[];
extern const u8 BattleScript_EffectPurify[];
extern const u8 BattleScript_FailIfNotArgType[];
extern const u8 BattleScript_EffectShoreUp[];
@ -804,7 +805,6 @@ extern const u8 BattleScript_EffectClangorousSoul[];
extern const u8 BattleScript_EffectSkyDrop[];
extern const u8 BattleScript_EffectMeteorBeam[];
extern const u8 BattleScript_EffectCourtChange[];
extern const u8 BattleScript_EffectMaxHp50Recoil[];
extern const u8 BattleScript_EffectExtremeEvoboost[];
extern const u8 BattleScript_EffectHitSetRemoveTerrain[];
extern const u8 BattleScript_EffectDarkVoid[];

View File

@ -91,6 +91,7 @@ enum
CANCELLER_POWDER_MOVE,
CANCELLER_POWDER_STATUS,
CANCELLER_THROAT_CHOP,
CANCELLER_EXPLODING_DAMP,
CANCELLER_MULTIHIT_MOVES,
CANCELLER_Z_MOVES,
CANCELLER_END,

View File

@ -275,7 +275,6 @@ enum {
EFFECT_MAGNETIC_FLUX,
EFFECT_GEAR_UP,
EFFECT_STRENGTH_SAP,
EFFECT_MIND_BLOWN,
EFFECT_PURIFY,
EFFECT_FAIL_IF_NOT_ARG_TYPE,
EFFECT_SHORE_UP,
@ -318,6 +317,7 @@ enum {
EFFECT_BEAK_BLAST,
EFFECT_COURT_CHANGE,
EFFECT_MAX_HP_50_RECOIL,
EFFECT_MIND_BLOWN, // Same as EFFECT_MAX_HP_50_RECOIL but is cancelled by Damp
EFFECT_EXTREME_EVOBOOST,
EFFECT_HIT_SET_REMOVE_TERRAIN,
EFFECT_DARK_VOID,

View File

@ -246,8 +246,7 @@
#define DMG_FULL_ATTACKER_HP 4
#define DMG_CURR_ATTACKER_HP 5
#define DMG_BIG_ROOT 6
#define DMG_1_2_ATTACKER_HP 7
#define DMG_RECOIL_FROM_IMMUNE 8 // Used to calculate recoil for the Gen 4 version of Jump Kick
#define DMG_RECOIL_FROM_IMMUNE 7 // Used to calculate recoil for the Gen 4 version of Jump Kick
// Cmd_jumpifcantswitch
#define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7)

View File

@ -733,8 +733,8 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s
switch (gMovesInfo[move].effect)
{
case EFFECT_MIND_BLOWN:
case EFFECT_MAX_HP_50_RECOIL:
case EFFECT_MIND_BLOWN:
return TRUE;
case EFFECT_RECOIL_IF_MISS:
if (AI_IsDamagedByRecoil(battlerAtk))

View File

@ -1289,7 +1289,7 @@ static void Cmd_attackcanceler(void)
gCurrentActionFuncId = B_ACTION_FINISHED;
return;
}
if (gBattleMons[gBattlerAttacker].hp == 0 && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
if (gBattleMons[gBattlerAttacker].hp == 0 && gMovesInfo[gCurrentMove].effect != EFFECT_EXPLOSION && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
{
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
gBattlescriptCurrInstr = BattleScript_MoveEnd;
@ -5549,18 +5549,38 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++;
break;
case MOVEEND_RECOIL:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
&& IsBattlerAlive(gBattlerAttacker)
&& gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
{
if (gMovesInfo[gCurrentMove].recoil > 0)
{
gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gMovesInfo[gCurrentMove].recoil) / 100);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
effect = TRUE;
}
gBattleScripting.moveendState++;
break;
}
else if (gMovesInfo[gCurrentMove].recoil > 0
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& IsBattlerAlive(gBattlerAttacker)
&& gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one
{
gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gMovesInfo[gCurrentMove].recoil) / 100);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
effect = TRUE;
}
else if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION && !IsAbilityOnField(ABILITY_DAMP))
{
gBattleMoveDamage = 0;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion;
effect = TRUE;
}
else if ((gMovesInfo[gCurrentMove].effect == EFFECT_MAX_HP_50_RECOIL
|| gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN)
&& IsBattlerAlive(gBattlerAttacker)
&& !(gMoveResultFlags & MOVE_RESULT_FAILED)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil;
effect = TRUE;
}
gBattleScripting.moveendState++;
break;
@ -5905,7 +5925,11 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState = 0;
MoveValuesCleanUp();
gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect;
BattleScriptPush(GET_MOVE_BATTLESCRIPT(gCurrentMove));
if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION)
BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); // Edge case for Explosion not changing targets
else
BattleScriptPush(GET_MOVE_BATTLESCRIPT(gCurrentMove));
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
return;
}
@ -7200,22 +7224,10 @@ static void Cmd_switchineffects(void)
gDisableStructs[battler].truantSwitchInHack = 0;
// Don't activate switch-in abilities if the opposing field is empty.
// This could happen when a mon uses explosion and causes everyone to faint.
if ((battlerAbility == ABILITY_INTIMIDATE || battlerAbility == ABILITY_SUPERSWEET_SYRUP || battlerAbility == ABILITY_DOWNLOAD)
&& !IsBattlerAlive(BATTLE_OPPOSITE(battler))
&& !IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battler))))
{
if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE))
return;
}
else
{
if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE))
return;
else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0))
return;
}
if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE))
return;
else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0))
return;
gDisableStructs[battler].stickyWebDone = FALSE;
gDisableStructs[battler].spikesDone = FALSE;
@ -10946,19 +10958,9 @@ static void Cmd_tryexplosion(void)
{
CMD_ARGS();
u32 dampBattler;
if (gBattleControllerExecFlags)
return;
if ((dampBattler = IsAbilityOnField(ABILITY_DAMP)))
{
// Failed, a battler has Damp
gLastUsedAbility = ABILITY_DAMP;
gBattlerTarget = --dampBattler;
gBattlescriptCurrInstr = BattleScript_DampStopsExplosion;
return;
}
gBattleMoveDamage = gBattleMons[gBattlerAttacker].hp;
BtlController_EmitHealthBarUpdate(gBattlerAttacker, BUFFER_A, INSTANT_HP_BAR_DROP);
MarkBattlerForControllerExec(gBattlerAttacker);
@ -11183,9 +11185,6 @@ static void Cmd_manipulatedamage(void)
case DMG_BIG_ROOT:
gBattleMoveDamage = GetDrainedBigRootHp(gBattlerAttacker, gBattleMoveDamage);
break;
case DMG_1_2_ATTACKER_HP:
gBattleMoveDamage = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
break;
case DMG_RECOIL_FROM_IMMUNE:
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
break;

View File

@ -3554,6 +3554,20 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_EXPLODING_DAMP:
{
u32 dampBattler = IsAbilityOnField(ABILITY_DAMP);
if (dampBattler && (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION
|| gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN))
{
gBattleScripting.battler = dampBattler - 1;
gBattlescriptCurrInstr = BattleScript_DampStopsExplosion;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
effect = 1;
}
gBattleStruct->atkCancellerTracker++;
break;
}
case CANCELLER_MULTIHIT_MOVES:
if (gMovesInfo[gCurrentMove].effect == EFFECT_MULTI_HIT)
{

View File

@ -1766,12 +1766,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_MIND_BLOWN] =
{
.battleScript = BattleScript_EffectMindBlown,
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_PURIFY] =
{
.battleScript = BattleScript_EffectPurify,
@ -2029,7 +2023,13 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_MAX_HP_50_RECOIL] =
{
.battleScript = BattleScript_EffectMaxHp50Recoil,
.battleScript = BattleScript_EffectHit,
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_MIND_BLOWN] =
{
.battleScript = BattleScript_EffectHit,
.battleTvScore = 0, // TODO: Assign points
},

View File

@ -94,17 +94,14 @@ SINGLE_BATTLE_TEST("Supreme Overlord does not boost attack if party members are
SINGLE_BATTLE_TEST("Supreme Overlord's message displays correctly after all battlers fainted - Player")
{
// For some reason the Ability Pop Up fails to appear after Explosion.
KNOWN_FAILING;
GIVEN {
ASSUME(gMovesInfo[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION);
PLAYER(SPECIES_WOBBUFFET) { HP(1);}
PLAYER(SPECIES_KINGAMBIT);
PLAYER(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_EXPLOSION); SEND_OUT(player, 1); SEND_OUT(opponent, 1); }
TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_KOWTOW_CLEAVE); }
} SCENE {
HP_BAR(opponent, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, opponent);
@ -118,18 +115,14 @@ SINGLE_BATTLE_TEST("Supreme Overlord's message displays correctly after all batt
SINGLE_BATTLE_TEST("Supreme Overlord's message displays correctly after all battlers fainted - Opponent")
{
// For some reason the Ability Pop Up fails to appear after Explosion.
KNOWN_FAILING;
GIVEN {
ASSUME(gMovesInfo[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1);}
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KINGAMBIT);
OPPONENT(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); }
} WHEN {
TURN { MOVE(player, MOVE_EXPLOSION); SEND_OUT(player, 1); SEND_OUT(opponent, 1); }
TURN { SWITCH(opponent, 2); MOVE(player, MOVE_TACKLE); }
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);

View File

@ -62,7 +62,6 @@ SINGLE_BATTLE_TEST("Explosion causes the user to faint even if it has no effect"
TURN { MOVE(player, MOVE_EXPLOSION); }
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);
MESSAGE("It doesn't affect Foe Gastly…");
NOT HP_BAR(opponent);
MESSAGE("Wobbuffet fainted!");
@ -91,3 +90,36 @@ DOUBLE_BATTLE_TEST("Explosion causes everyone to faint in a double battle")
MESSAGE("Wobbuffet fainted!");
}
}
SINGLE_BATTLE_TEST("Explosion is blocked by Ability Damp")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_DAMP); }
} WHEN {
TURN { MOVE(player, MOVE_EXPLOSION); }
} SCENE {
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);
HP_BAR(player, hp: 0);
}
ABILITY_POPUP(opponent, ABILITY_DAMP);
MESSAGE("Foe Golduck's Damp prevents Wobbuffet from using Explosion!");
}
}
SINGLE_BATTLE_TEST("Explosion does not trigger Destiny Bond")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_DESTINY_BOND); MOVE(opponent, MOVE_EXPLOSION);}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, opponent);
HP_BAR(player);
NOT HP_BAR(opponent);
}
}

View File

@ -137,6 +137,7 @@ SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in
SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: opposing side")
{
KNOWN_FAILING;
GIVEN {
PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); };
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }

View File

@ -6,21 +6,80 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_STEEL_BEAM].effect == EFFECT_MAX_HP_50_RECOIL);
}
SINGLE_BATTLE_TEST("Steel Beam causes the user to take damage equal to half of its maximum HP")
SINGLE_BATTLE_TEST("Steel Beam makes the user lose 1/2 of its Max HP")
{
s16 recoilDamage;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_STEEL_BEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(opponent);
HP_BAR(player, captureDamage: &recoilDamage);
} THEN {
EXPECT_EQ(player->maxHP / 2, recoilDamage);
HP_BAR(player, damage: 200);
NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint.
}
}
DOUBLE_BATTLE_TEST("Steel Beam makes the user lose 1/2 of its Max HP in a double battle")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_STEEL_BEAM, target:opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, playerLeft);
HP_BAR(playerLeft, damage: 200);
NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint.
}
}
SINGLE_BATTLE_TEST("Steel Beam causes the user to faint when below 1/2 of its Max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_STEEL_BEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(player, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
DOUBLE_BATTLE_TEST("Steel Beam causes the user to faint when below 1/2 of its Max HP in a double battle")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_STEEL_BEAM, target:opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, playerLeft);
HP_BAR(playerLeft, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
SINGLE_BATTLE_TEST("Steel Beam causes the user & the target to faint when below 1/2 of its Max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(200) ; MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_STEEL_BEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(opponent, hp: 0);
MESSAGE("Foe Wobbuffet fainted!");
HP_BAR(player, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
@ -32,8 +91,58 @@ SINGLE_BATTLE_TEST("Steel Beam hp loss is prevented by Magic Guard")
} WHEN {
TURN { MOVE(player, MOVE_STEEL_BEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(opponent);
NOT HP_BAR(player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
}
}
SINGLE_BATTLE_TEST("Steel Beam makes the user lose HP even if the opposing mon protected")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_STEEL_BEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(player);
}
}
SINGLE_BATTLE_TEST("Steel Beam does not cause the user to lose HP if there is no target")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_MEMENTO); MOVE(player, MOVE_STEEL_BEAM); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(player);
}
MESSAGE("Wobbuffet used Steel Beam!");
MESSAGE("But it failed!");
MESSAGE("2 sent out Wobbuffet!");
}
}
SINGLE_BATTLE_TEST("Steel Beam is not blocked by Damp")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_DAMP); }
} WHEN {
TURN { MOVE(player, MOVE_STEEL_BEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player);
HP_BAR(player, damage: 200);
NONE_OF {
ABILITY_POPUP(opponent, ABILITY_DAMP);
MESSAGE("Foe Golduck's Damp prevents Wobbuffet from using Steel Beam!");
}
}
}

View File

@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_MIND_BLOWN].effect == EFFECT_MIND_BLOWN);
}
SINGLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP")
SINGLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its Max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
@ -14,13 +14,13 @@ SINGLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP")
} WHEN {
TURN { MOVE(player, MOVE_MIND_BLOWN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(player, damage: 200);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint.
}
}
DOUBLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP in a double battle")
DOUBLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its Max HP in a double battle")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
@ -30,13 +30,13 @@ DOUBLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP in a double bat
} WHEN {
TURN { MOVE(playerLeft, MOVE_MIND_BLOWN); }
} SCENE {
HP_BAR(playerLeft, damage: 200);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, playerLeft);
HP_BAR(playerLeft, damage: 200);
NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint.
}
}
SINGLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP")
SINGLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its Max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); }
@ -44,13 +44,13 @@ SINGLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP
} WHEN {
TURN { MOVE(player, MOVE_MIND_BLOWN); }
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(player, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
DOUBLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP in a double battle")
DOUBLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its Max HP in a double battle")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); }
@ -60,13 +60,13 @@ DOUBLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP
} WHEN {
TURN { MOVE(playerLeft, MOVE_MIND_BLOWN); }
} SCENE {
HP_BAR(playerLeft, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, playerLeft);
HP_BAR(playerLeft, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
SINGLE_BATTLE_TEST("Mind Blown causes the user & the target to faint when below 1/2 of its HP")
SINGLE_BATTLE_TEST("Mind Blown causes the user & the target to faint when below 1/2 of its Max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(200) ; MaxHP(400); }
@ -75,10 +75,10 @@ SINGLE_BATTLE_TEST("Mind Blown causes the user & the target to faint when below
} WHEN {
TURN { MOVE(player, MOVE_MIND_BLOWN); }
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(opponent, hp: 0);
MESSAGE("Foe Wobbuffet fainted!");
HP_BAR(player, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
@ -94,7 +94,6 @@ DOUBLE_BATTLE_TEST("Mind Blown causes everyone to faint in a double battle")
} WHEN {
TURN { MOVE(playerLeft, MOVE_MIND_BLOWN); }
} SCENE {
HP_BAR(playerLeft, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, playerLeft);
HP_BAR(opponentLeft, hp: 0);
MESSAGE("Foe Abra fainted!");
@ -102,6 +101,7 @@ DOUBLE_BATTLE_TEST("Mind Blown causes everyone to faint in a double battle")
MESSAGE("Wynaut fainted!");
HP_BAR(opponentRight, hp: 0);
MESSAGE("Foe Kadabra fainted!");
HP_BAR(playerLeft, hp: 0);
MESSAGE("Wobbuffet fainted!");
}
}
@ -118,3 +118,69 @@ SINGLE_BATTLE_TEST("Mind Blown hp loss is prevented by Magic Guard")
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
}
}
SINGLE_BATTLE_TEST("Mind Blown is blocked by Damp")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_DAMP); }
} WHEN {
TURN { MOVE(player, MOVE_MIND_BLOWN); }
} SCENE {
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(player, damage: 200);
}
ABILITY_POPUP(opponent, ABILITY_DAMP);
MESSAGE("Foe Golduck's Damp prevents Wobbuffet from using Mind Blown!");
}
}
SINGLE_BATTLE_TEST("Mind Blown makes the user lose HP even if the opposing mon protected")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_MIND_BLOWN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(player);
}
}
SINGLE_BATTLE_TEST("Mind Blown makes the user lose HP even if it is absorbed by Flash Fire")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_MIND_BLOWN].type == TYPE_FIRE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_CYNDAQUIL) { Ability(ABILITY_FLASH_FIRE); }
} WHEN {
TURN { MOVE(player, MOVE_MIND_BLOWN); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_FLASH_FIRE);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(player);
}
}
SINGLE_BATTLE_TEST("Mind Blown does not cause the user to lose HP if there is no target")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_MEMENTO); MOVE(player, MOVE_MIND_BLOWN); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player);
HP_BAR(player);
}
MESSAGE("Wobbuffet used Mind Blown!");
MESSAGE("But it failed!");
MESSAGE("2 sent out Wobbuffet!");
}
}