Skip to content

Commit

Permalink
Fix Explosion + Galvanize + Volt Absorb and Mind Blown (#2688)
Browse files Browse the repository at this point in the history
* Fix Explosion and Mind Blown
* Use battler ability in jumpifabilitypresent
  • Loading branch information
DizzyEggg authored Feb 21, 2023
1 parent f3c6b64 commit d73ab02
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 43 deletions.
6 changes: 6 additions & 0 deletions asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,12 @@
.2byte \holdEffect
.4byte \jumpInstr
.endm
.macro jumpifmorethanhalfHP battler:req, jumpInstr:req
callnative BS_JumpIfMoreThanHalfHP
.byte \battler
.4byte \jumpInstr
.endm

@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
Expand Down
69 changes: 42 additions & 27 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -3417,27 +3417,20 @@ BattleScript_EffectFreezeHit::
BattleScript_EffectParalyzeHit::
setmoveeffect MOVE_EFFECT_PARALYSIS
goto BattleScript_EffectHit

BattleScript_EffectExplosion::
attackcanceler
attackstring
ppreduce
@ Below jumps to BattleScript_DampStopsExplosion if it fails (only way it can)
tryexplosion
setatkhptozero
waitstate
jumpifbyte CMP_NO_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_MISSED, BattleScript_ExplosionDoAnimStartLoop

BattleScript_EffectExplosion_AnimDmgRet:
jumpifbyte CMP_NO_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_MISSED, BattleScript_ExplosionAnimRet
call BattleScript_PreserveMissedBitDoMoveAnim
goto BattleScript_ExplosionLoop
BattleScript_ExplosionDoAnimStartLoop:
goto BattleScript_ExplosionDmgRet
BattleScript_ExplosionAnimRet:
attackanimation
waitanimation
BattleScript_ExplosionLoop:
BattleScript_ExplosionDmgRet:
movevaluescleanup
critcalc
damagecalc
adjustdamage
accuracycheck BattleScript_ExplosionMissed, ACC_CURR_MOVE
accuracycheck BattleScript_ExplosionMissedRet, ACC_CURR_MOVE
effectivenesssound
hitanimation BS_TARGET
waitstate
Expand All @@ -3448,32 +3441,54 @@ BattleScript_ExplosionLoop:
resultmessage
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_ExplosionLoop
tryfaintmon BS_ATTACKER
moveendcase MOVEEND_CLEAR_BITS
end
BattleScript_ExplosionMissed:
BattleScript_ExplosionAnimEndRet_Return:
return
BattleScript_ExplosionMissedRet:
effectivenesssound
resultmessage
waitmessage B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_ExplosionLoop
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
tryexplosion
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
dmg_1_2_attackerhp
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
waitstate
jumpifbyte CMP_NO_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_MISSED, BattleScript_ExplosionDoAnimStartLoop
call BattleScript_PreserveMissedBitDoMoveAnim
goto BattleScript_ExplosionLoop
BattleScript_EffectMindBlown_AnimDmgNoFaint:
call BattleScript_EffectExplosion_AnimDmgRet
goto BattleScript_MoveEnd

BattleScript_PreserveMissedBitDoMoveAnim:
bichalfword gMoveResultFlags, MOVE_RESULT_MISSED
Expand Down Expand Up @@ -8360,9 +8375,9 @@ BattleScript_AbilityRaisesDefenderStat::
BattleScript_AbilityPopUp:
.if B_ABILITY_POP_UP == TRUE
showabilitypopup BS_ABILITY_BATTLER
recordability BS_ABILITY_BATTLER
pause 40
.endif
recordability BS_ABILITY_BATTLER
sethword sABILITY_OVERWRITE, 0
return

Expand Down
33 changes: 22 additions & 11 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -5017,10 +5017,17 @@ static void Cmd_jumpifabilitypresent(void)
{
CMD_ARGS(u16 ability, const u8 *jumpInstr);

if (IsAbilityOnField(cmd->ability))
u16 ability = cmd->ability;
u32 abilityBattler = IsAbilityOnField(ability);
if (abilityBattler)
{
gBattlerAbility = abilityBattler - 1;
gBattlescriptCurrInstr = cmd->jumpInstr;
}
else
{
gBattlescriptCurrInstr = cmd->nextInstr;
}
}

static void Cmd_endselectionscript(void)
Expand Down Expand Up @@ -11183,14 +11190,15 @@ static void Cmd_tryexplosion(void)
{
CMD_ARGS();

u32 dampBattler;
if (gBattleControllerExecFlags)
return;

if ((gBattlerTarget = IsAbilityOnField(ABILITY_DAMP)))
if ((dampBattler = IsAbilityOnField(ABILITY_DAMP)))
{
// Failed, a battler has Damp
gLastUsedAbility = ABILITY_DAMP;
RecordAbilityBattle(--gBattlerTarget, ABILITY_DAMP);
gBattlerTarget = --dampBattler;
gBattlescriptCurrInstr = BattleScript_DampStopsExplosion;
return;
}
Expand All @@ -11200,14 +11208,6 @@ static void Cmd_tryexplosion(void)
BtlController_EmitHealthBarUpdate(BUFFER_A, INSTANT_HP_BAR_DROP);
MarkBattlerForControllerExec(gActiveBattler);
gBattlescriptCurrInstr = cmd->nextInstr;

for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
{
if (gBattlerTarget == gBattlerAttacker)
continue;
if (IsBattlerAlive(gBattlerTarget))
break;
}
}

static void Cmd_setatkhptozero(void)
Expand Down Expand Up @@ -16033,6 +16033,17 @@ void BS_CalcMetalBurstDmg(void)
}
}

void BS_JumpIfMoreThanHalfHP(void)
{
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);

u8 battler = GetBattlerForBattleScript(cmd->battler);
if (gBattleMons[battler].hp > (gBattleMons[battler].maxHP + 1) / 2)
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}

void BS_JumpIfHoldEffect(void)
{
u8 battler = gBattlescriptCurrInstr[5];
Expand Down
20 changes: 20 additions & 0 deletions test/ability_damp.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies")
}
}

DOUBLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies in a double battle")
{
u32 move;
PARAMETRIZE { move = MOVE_EXPLOSION; }
PARAMETRIZE { move = MOVE_SELF_DESTRUCT; }
PARAMETRIZE { move = MOVE_MIND_BLOWN; }
PARAMETRIZE { move = MOVE_MISTY_EXPLOSION; }
GIVEN {
PLAYER(SPECIES_PARAS) { Ability(ABILITY_DAMP); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, move); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_DAMP);
NONE_OF { HP_BAR(playerLeft); HP_BAR(opponentLeft); HP_BAR(playerRight); HP_BAR(opponentRight); }
}
}

SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from self")
{
u32 move;
Expand Down
28 changes: 26 additions & 2 deletions test/ability_volt_absorb.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,30 @@ SINGLE_BATTLE_TEST("Volt Absorb is only triggered once on multi strike moves")
}
}

DOUBLE_BATTLE_TEST("Volt Absorb does not stop Electric Typed Explosion from damaging other pokemon", s16 damage1, s16 damage2) // Fixed issue #1961
{
GIVEN {
ASSUME(gBattleMoves[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION);
ASSUME(gBattleMoves[MOVE_EXPLOSION].type == TYPE_NORMAL);
PLAYER(SPECIES_JOLTEON) { Ability(ABILITY_VOLT_ABSORB); HP(1); MaxHP(TEST_MAX_HP); }
PLAYER(SPECIES_ABRA);
OPPONENT(SPECIES_GRAVELER_ALOLAN) { Ability(ABILITY_GALVANIZE); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_EXPLOSION); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_VOLT_ABSORB);
HP_BAR(playerLeft, hp: TEST_MAX_HP / 4 + 1);
MESSAGE("Jolteon restored HP using its Volt Absorb!");
HP_BAR(playerRight, captureDamage: &results->damage1);
HP_BAR(opponentRight, captureDamage: &results->damage2);
}
FINALLY {
EXPECT_NE(results[0].damage1, 0);
EXPECT_NE(results[0].damage2, 0);
}
}

SINGLE_BATTLE_TEST("Volt Absorb prevents Cell Battery from activating")
{
GIVEN {
Expand All @@ -75,11 +99,11 @@ SINGLE_BATTLE_TEST("Volt Absorb prevents Cell Battery from activating")
ABILITY_POPUP(player, ABILITY_VOLT_ABSORB);
HP_BAR(player, hp: TEST_MAX_HP / 4 + 1);
MESSAGE("Jolteon restored HP using its Volt Absorb!");
NONE_OF {
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Cell Battery, the attack of Jolteon rose!");
}

}
}
46 changes: 43 additions & 3 deletions test/move_effect_explosion.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ ASSUMPTIONS

SINGLE_BATTLE_TEST("Explosion causes the user to faint")
{
u16 remainingHP;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
Expand All @@ -17,12 +16,29 @@ SINGLE_BATTLE_TEST("Explosion causes the user to faint")
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);
MESSAGE("Wobbuffet fainted!");
}
}

SINGLE_BATTLE_TEST("Explosion causes the user & the target to faint")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_EXPLOSION); }
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);
HP_BAR(opponent, hp: 0);
MESSAGE("Foe Wobbuffet fainted!");
MESSAGE("Wobbuffet fainted!");
}
}

SINGLE_BATTLE_TEST("Explosion causes the user to faint even if it misses")
{
u16 remainingHP;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
Expand All @@ -31,12 +47,12 @@ SINGLE_BATTLE_TEST("Explosion causes the user to faint even if it misses")
} SCENE {
HP_BAR(player, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);
MESSAGE("Wobbuffet fainted!");
}
}

SINGLE_BATTLE_TEST("Explosion causes the user to faint even if it has no effect")
{
u16 remainingHP;
GIVEN {
ASSUME(gBattleMoves[MOVE_EXPLOSION].type == TYPE_NORMAL);
ASSUME(gSpeciesInfo[SPECIES_GASTLY].types[0] == TYPE_GHOST);
Expand All @@ -49,5 +65,29 @@ SINGLE_BATTLE_TEST("Explosion causes the user to faint even if it has no effect"
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player);
MESSAGE("It doesn't affect Foe Gastly…");
NOT HP_BAR(opponent);
MESSAGE("Wobbuffet fainted!");
}
}

DOUBLE_BATTLE_TEST("Explosion causes everyone to faint in a double battle")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT) { HP(1); }
OPPONENT(SPECIES_ABRA) { HP(1); }
OPPONENT(SPECIES_KADABRA) { HP(1); }
OPPONENT(SPECIES_KADABRA);
} WHEN {
TURN { MOVE(playerLeft, MOVE_EXPLOSION); }
} SCENE {
HP_BAR(playerLeft, hp: 0);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft);
HP_BAR(opponentLeft, hp: 0);
MESSAGE("Foe Abra fainted!");
HP_BAR(playerRight, hp: 0);
MESSAGE("Wynaut fainted!");
HP_BAR(opponentRight, hp: 0);
MESSAGE("Foe Kadabra fainted!");
MESSAGE("Wobbuffet fainted!");
}
}
Loading

0 comments on commit d73ab02

Please sign in to comment.