Version 1.4.2 (#2847)

Co-authored-by: DizzyEggg <jajkodizzy@wp.pl>
Co-authored-by: ghoulslash <41651341+ghoulslash@users.noreply.github.com>
Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
Fix wrong Contrary message when affected by Intimidate (#2723)
Fixes certain moves preventing Z status moves. (#2791)
Fixes the check for speed on electrify (#2819)
Fixed score for Work up and Growth (#2813)
Fixed Wring Out's power (#2824)
Fixes #2823
This commit is contained in:
Eduardo Quezada D'Ottone 2023-03-27 16:47:15 -03:00 committed by GitHub
parent 8bfd4d0f51
commit bdb5cfe8b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 207 additions and 53 deletions

View File

@ -484,15 +484,13 @@ BattleScript_Teatimevul:
moveendcase MOVEEND_CLEAR_BITS
goto BattleScript_MoveEnd
BattleScript_Teatimesorb:
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_TeatimeLoop
moveendcase MOVEEND_CLEAR_BITS
goto BattleScript_MoveEnd
BattleScript_Teatimerod:
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
playstatchangeanimation BS_TARGET, BIT_SPATK, STAT_CHANGE_BY_TWO
setstatchanger STAT_SPATK, 1, FALSE
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer
@ -504,8 +502,7 @@ BattleScript_Teatimerod:
moveendcase MOVEEND_CLEAR_BITS
goto BattleScript_MoveEnd
BattleScript_Teatimemotor:
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
playstatchangeanimation BS_TARGET, BIT_SPEED, STAT_CHANGE_BY_TWO
setstatchanger STAT_SPEED, 1, FALSE
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer
@ -3374,8 +3371,7 @@ BattleScript_EffectAbsorb::
setbyte cMULTISTRING_CHOOSER, B_MSG_ABSORB
goto BattleScript_AbsorbUpdateHp
BattleScript_AbsorbLiquidOoze::
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
manipulatedamage DMG_CHANGE_SIGN
setbyte cMULTISTRING_CHOOSER, B_MSG_ABSORB_OOZE
BattleScript_AbsorbUpdateHp::
@ -5479,9 +5475,8 @@ BattleScript_NotAffected::
goto BattleScript_MoveEnd
BattleScript_NotAffectedAbilityPopUp::
copybyte gBattlerAbility, gBattlerTarget
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
orhalfword gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE
resultmessage
waitmessage B_WAIT_TIME_LONG
@ -5970,8 +5965,7 @@ BattleScript_EffectSkillSwap:
attackanimation
waitanimation
.if B_ABILITY_POP_UP == TRUE
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
pause 20
copybyte gBattlerAbility, gBattlerAttacker
call BattleScript_AbilityPopUp
@ -7726,9 +7720,8 @@ BattleScript_EnduredMsg::
return
BattleScript_SturdiedMsg::
copybyte gBattlerAbility, gBattlerTarget
pause B_WAIT_TIME_SHORTEST
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
printstring STRINGID_ENDUREDSTURDY
waitmessage B_WAIT_TIME_LONG
return
@ -7869,8 +7862,7 @@ BattleScript_CudChewActivates::
BattleScript_TargetFormChange::
pause 5
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
printstring STRINGID_EMPTYSTRING3
waitmessage 1
handleformchange BS_TARGET, 0
@ -7882,8 +7874,7 @@ BattleScript_TargetFormChange::
BattleScript_TargetFormChangeWithString::
pause 5
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
printstring STRINGID_EMPTYSTRING3
waitmessage 1
handleformchange BS_TARGET, 0
@ -8346,6 +8337,8 @@ BattleScript_AbilityRaisesDefenderStat::
waitmessage B_WAIT_TIME_LONG
return
BattleScript_AbilityPopUpTarget:
copybyte gBattlerAbility, gBattlerTarget
BattleScript_AbilityPopUp:
.if B_ABILITY_POP_UP == TRUE
showabilitypopup BS_ABILITY_BATTLER
@ -8586,8 +8579,10 @@ BattleScript_IntimidateEffect:
copybyte sBATTLER, gBattlerAttacker
statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_IntimidateLoopIncrement
setgraphicalstatchangevalues
jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_IntimidateContrary
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printstring STRINGID_PKMNCUTSATTACKWITH
BattleScript_IntimidateEffect_WaitString:
waitmessage B_WAIT_TIME_LONG
copybyte sBATTLER, gBattlerTarget
call BattleScript_TryAdrenalineOrb
@ -8599,6 +8594,16 @@ BattleScript_IntimidateEnd:
pause B_WAIT_TIME_MED
end3
BattleScript_IntimidateContrary:
call BattleScript_AbilityPopUpTarget
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_IntimidateContrary_WontIncrease
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printfromtable gStatUpStringIds
goto BattleScript_IntimidateEffect_WaitString
BattleScript_IntimidateContrary_WontIncrease:
printstring STRINGID_TARGETSTATWONTGOHIGHER
goto BattleScript_IntimidateEffect_WaitString
BattleScript_IntimidatePrevented:
call BattleScript_AbilityPopUp
pause B_WAIT_TIME_LONG
@ -8612,8 +8617,7 @@ BattleScript_IntimidatePrevented_Item:
BattleScript_IntimidateInReverse:
copybyte sBATTLER, gBattlerTarget
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
pause B_WAIT_TIME_SHORT
modifybattlerstatstage BS_TARGET, STAT_ATK, INCREASE, 1, BattleScript_IntimidateLoopIncrement, ANIM_ON
call BattleScript_TryAdrenalineOrb
@ -8856,8 +8860,7 @@ BattleScript_SturdyPreventsOHKO::
BattleScript_DampStopsExplosion::
pause B_WAIT_TIME_SHORT
copybyte gBattlerAbility, gBattlerTarget
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
printstring STRINGID_PKMNPREVENTSUSAGE
pause B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET

View File

@ -52,7 +52,7 @@ Debug_FlagsNotSetMessage::
Debug_FlagsNotSetMessage_Text:
.string "Feature unavailable!\n"
.string "Please define a usable flag in:\l"
.string "'include/constants/overworld{UNDERSCORE}config.h'!$"
.string "'include/config/overworld.h'!$"
Debug_Script_1::
end

View File

@ -1117,10 +1117,9 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break;
case EFFECT_GROWTH:
case EFFECT_ATTACK_SPATK_UP: // work up
if (!BattlerStatCanRise(battlerAtk, AI_DATA->abilities[battlerAtk], STAT_ATK) || !HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL))
if ((!BattlerStatCanRise(battlerAtk, AI_DATA->abilities[battlerAtk], STAT_ATK) && !BattlerStatCanRise(battlerAtk, AI_DATA->abilities[battlerAtk], STAT_SPATK))
|| (!HasDamagingMove(battlerAtk)))
score -= 10;
else if (!BattlerStatCanRise(battlerAtk, AI_DATA->abilities[battlerAtk], STAT_SPATK) || !HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL))
score -= 8;
break;
case EFFECT_ROTOTILLER:
if (isDoubleBattle)
@ -2447,7 +2446,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
case EFFECT_ELECTRIFY:
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
//|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, AI_DATA->partnerMove))
score -= 10;
@ -2632,7 +2631,7 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION)
{
// this move can faint the target
if (!WillAIStrikeFirst() || GetMovePriority(battlerAtk, move) > 0)
if (WillAIStrikeFirst() || GetMovePriority(battlerAtk, move) > 0)
score += 4; // we go first or we're using priority move
else
score += 2;
@ -4641,7 +4640,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 2; // Give target more weaknesses
break;
case EFFECT_ELECTRIFY:
if (predictedMove != MOVE_NONE && gBattleMoves[predictedMove].type == TYPE_NORMAL
if (predictedMove != MOVE_NONE
&& (AI_DATA->abilities[battlerAtk] == ABILITY_VOLT_ABSORB
|| AI_DATA->abilities[battlerAtk] == ABILITY_MOTOR_DRIVE
|| AI_DATA->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD))

View File

@ -744,6 +744,10 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness,
SetBattlerData(battlerDef);
gBattleStruct->dynamicMoveType = 0;
if (move == MOVE_NATURE_POWER)
move = GetNaturePowerMove();
SetTypeBeforeUsingMove(move, battlerAtk);
GET_MOVE_TYPE(move, moveType);
@ -802,6 +806,7 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness,
}
else
{
effectivenessMultiplier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE);
dmg = 0;
}
@ -1166,7 +1171,7 @@ s32 AI_GetAbility(u32 battlerId)
// We've had ability overwritten by e.g. Worry Seed. It is not part of AI_PARTY in case of switching
if (gBattleStruct->overwrittenAbilities[battlerId])
return gBattleStruct->overwrittenAbilities[battlerId];
// The AI knows its own ability.
if (IsBattlerAIControlled(battlerId))
return knownAbility;

View File

@ -185,7 +185,7 @@ static const struct WindowTemplate sStandardBattleWindowTemplates[] =
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 55,
.width = 12, //for z move names
.width = 16, //for z move names
.height = 2,
.paletteNum = 5,
.baseBlock = 0x0300,

View File

@ -1742,7 +1742,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
u32 holdEffect = GetBattlerHoldEffect(gActiveBattler, TRUE);
u16 *choicedMove = &gBattleStruct->choicedMove[gActiveBattler];
if (gDisableStructs[gActiveBattler].disabledMove == move && move != MOVE_NONE)
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gDisableStructs[gActiveBattler].disabledMove == move && move != MOVE_NONE)
{
gBattleScripting.battler = gActiveBattler;
gCurrentMove = move;
@ -1758,7 +1758,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (move == gLastMoves[gActiveBattler] && move != MOVE_STRUGGLE && (gBattleMons[gActiveBattler].status2 & STATUS2_TORMENT))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && move == gLastMoves[gActiveBattler] && move != MOVE_STRUGGLE && (gBattleMons[gActiveBattler].status2 & STATUS2_TORMENT))
{
CancelMultiTurnMoves(gActiveBattler);
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1773,7 +1773,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (!gBattleStruct->zmove.active && gDisableStructs[gActiveBattler].tauntTimer != 0 && IS_MOVE_STATUS(move))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gDisableStructs[gActiveBattler].tauntTimer != 0 && IS_MOVE_STATUS(move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1788,7 +1788,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (!gBattleStruct->zmove.active && gDisableStructs[gActiveBattler].throatChopTimer != 0 && gBattleMoves[move].flags & FLAG_SOUND)
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gDisableStructs[gActiveBattler].throatChopTimer != 0 && gBattleMoves[move].flags & FLAG_SOUND)
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1803,7 +1803,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (!gBattleStruct->zmove.active && GetImprisonedMovesCount(gActiveBattler, move))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && GetImprisonedMovesCount(gActiveBattler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1818,7 +1818,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (!gBattleStruct->zmove.active && IsGravityPreventingMove(move))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && IsGravityPreventingMove(move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1833,7 +1833,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (!gBattleStruct->zmove.active && IsHealBlockPreventingMove(gActiveBattler, move))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && IsHealBlockPreventingMove(gActiveBattler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1848,7 +1848,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (!gBattleStruct->zmove.active && IsBelchPreventingMove(gActiveBattler, move))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && IsBelchPreventingMove(gActiveBattler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -3534,7 +3534,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_DISABLED: // disabled move
if (gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE)
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE)
{
gProtectStructs[gBattlerAttacker].usedDisabledMove = TRUE;
gBattleScripting.battler = gBattlerAttacker;
@ -3546,7 +3546,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_HEAL_BLOCKED:
if (gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove))
{
gProtectStructs[gBattlerAttacker].usedHealBlockedMove = TRUE;
gBattleScripting.battler = gBattlerAttacker;
@ -3570,7 +3570,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_TAUNTED: // taunt
if (gDisableStructs[gBattlerAttacker].tauntTimer && IS_MOVE_STATUS(gCurrentMove))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gDisableStructs[gBattlerAttacker].tauntTimer && IS_MOVE_STATUS(gCurrentMove))
{
gProtectStructs[gBattlerAttacker].usedTauntedMove = TRUE;
CancelMultiTurnMoves(gBattlerAttacker);
@ -3581,7 +3581,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_IMPRISONED: // imprisoned
if (GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove))
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove))
{
gProtectStructs[gBattlerAttacker].usedImprisonedMove = TRUE;
CancelMultiTurnMoves(gBattlerAttacker);
@ -3745,7 +3745,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_THROAT_CHOP:
if (gDisableStructs[gBattlerAttacker].throatChopTimer && gBattleMoves[gCurrentMove].flags & FLAG_SOUND)
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] == MOVE_NONE && gDisableStructs[gBattlerAttacker].throatChopTimer && gBattleMoves[gCurrentMove].flags & FLAG_SOUND)
{
gProtectStructs[gBattlerAttacker].usedThroatChopPreventedMove = TRUE;
CancelMultiTurnMoves(gBattlerAttacker);
@ -9837,7 +9837,17 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat
&& gBattleMons[battlerDef].type3 != gBattleMons[battlerDef].type1)
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type3, battlerAtk, recordAbilities);
if (moveType == TYPE_GROUND && !IsBattlerGrounded2(battlerDef, TRUE) && !(gBattleMoves[move].flags & FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING))
if (gBattleMoves[move].split == SPLIT_STATUS && move != MOVE_THUNDER_WAVE)
{
modifier = UQ_4_12(1.0);
#if B_GLARE_GHOST <= GEN_3
if (move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST))
{
modifier = UQ_4_12(0.0);
}
#endif
}
else if (moveType == TYPE_GROUND && !IsBattlerGrounded2(battlerDef, TRUE) && !(gBattleMoves[move].flags & FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING))
{
modifier = UQ_4_12(0.0);
if (recordAbilities && defAbility == ABILITY_LEVITATE)
@ -9855,12 +9865,6 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat
modifier = UQ_4_12(0.0);
}
#endif
#if B_GLARE_GHOST >= GEN_4
else if (move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST))
{
modifier = UQ_4_12(1.0);
}
#endif
// Thousand Arrows ignores type modifiers for flying mons
if (!IsBattlerGrounded(battlerDef) && (gBattleMoves[move].flags & FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING)

View File

@ -4847,7 +4847,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] =
[MOVE_NATURE_POWER] =
{
.effect = EFFECT_NATURE_POWER,
.power = 0,
.power = 1,
.type = TYPE_NORMAL,
.accuracy = 0,
.pp = 20,
@ -6843,7 +6843,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] =
[MOVE_WRING_OUT] =
{
.effect = EFFECT_WRING_OUT,
.power = 0,
.power = 1,
.type = TYPE_NORMAL,
.accuracy = 100,
.pp = 5,

143
test/ability_contrary.c Normal file
View File

@ -0,0 +1,143 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
}
SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CONTRARY; }
PARAMETRIZE { ability = ABILITY_TANGLED_FEET; }
GIVEN {
PLAYER(SPECIES_MIGHTYENA) { Ability(ABILITY_INTIMIDATE); }
OPPONENT(SPECIES_SPINDA) { Ability(ability); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
if (ability == ABILITY_CONTRARY) {
ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack rose!");
}
HP_BAR(player, captureDamage: &results[i].damage);
}
FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.125), results[0].damage);
}
}
SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normally lower them: Overheat", s16 damageBefore, s16 damageAfter)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CONTRARY; }
PARAMETRIZE { ability = ABILITY_TANGLED_FEET; }
GIVEN {
ASSUME(gBattleMoves[MOVE_OVERHEAT].effect == EFFECT_OVERHEAT);
ASSUME(gBattleMoves[MOVE_OVERHEAT].split == SPLIT_SPECIAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SPINDA) { Ability(ability); }
} WHEN {
TURN { MOVE(opponent, MOVE_OVERHEAT); }
TURN { MOVE(opponent, MOVE_OVERHEAT); }
} SCENE {
MESSAGE("Foe Spinda used Overheat!");
HP_BAR(player, captureDamage: &results[i].damageBefore);
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack sharply rose!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack harshly fell!");
}
// MESSAGE("Foe Spinda used Overheat!");
HP_BAR(player, captureDamage: &results[i].damageAfter);
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack sharply rose!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack harshly fell!");
}
}
FINALLY {
EXPECT_MUL_EQ(results[0].damageBefore, Q_4_12(2.0), results[0].damageAfter);
EXPECT_MUL_EQ(results[1].damageBefore, Q_4_12(0.5), results[1].damageAfter);
}
}
SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normally raise it: Swords Dance", s16 damageBefore, s16 damageAfter)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CONTRARY; }
PARAMETRIZE { ability = ABILITY_TANGLED_FEET; }
GIVEN {
ASSUME(gBattleMoves[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2);
PLAYER(SPECIES_WOBBUFFET) {Defense(102); }
OPPONENT(SPECIES_SPINDA) { Ability(ability); Attack(100); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Foe Spinda used Tackle!");
HP_BAR(player, captureDamage: &results[i].damageBefore);
//MESSAGE("Foe Spinda used Swords Dance!");
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack harshly fell!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack sharply rose!");
}
// MESSAGE("Foe Spinda used Tackle!");
HP_BAR(player, captureDamage: &results[i].damageAfter);
}
FINALLY {
EXPECT_MUL_EQ(results[0].damageBefore, Q_4_12(0.5), results[0].damageAfter);
EXPECT_MUL_EQ(results[1].damageBefore, Q_4_12(2.0), results[1].damageAfter);
}
}
SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normally lower it: Growl", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CONTRARY; }
PARAMETRIZE { ability = ABILITY_TANGLED_FEET; }
GIVEN {
ASSUME(gBattleMoves[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN);
PLAYER(SPECIES_WOBBUFFET) {Speed(3); }
OPPONENT(SPECIES_SPINDA) { Ability(ability); Speed(2); }
} WHEN {
TURN { MOVE(player, MOVE_GROWL); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Wobbuffet used Growl!");
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack rose!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack fell!");
}
MESSAGE("Foe Spinda used Tackle!");
HP_BAR(player, captureDamage: &results[i].damage);
}
FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.125), results[0].damage);
}
}