Fixes Echoed Voice base power increase depending on attacker's use of the move (#7997)
This commit is contained in:
parent
2d73286777
commit
2416bfb53b
@ -722,7 +722,7 @@ struct BattleStruct
|
||||
struct Illusion illusion[MAX_BATTLERS_COUNT];
|
||||
u8 soulheartBattlerId;
|
||||
u8 friskedBattler; // Frisk needs to identify 2 battlers in double battles.
|
||||
u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used.
|
||||
u8 metronomeItemCounter[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used.
|
||||
u8 quickClawBattlerId;
|
||||
struct LostItem itemLost[NUM_BATTLE_SIDES][PARTY_SIZE]; // Pokemon that had items consumed or stolen (two bytes per party member per side)
|
||||
u8 blunderPolicy:1; // should blunder policy activate
|
||||
@ -782,7 +782,8 @@ struct BattleStruct
|
||||
u8 hazardsQueue[NUM_BATTLE_SIDES][HAZARDS_MAX_COUNT];
|
||||
u8 numHazards[NUM_BATTLE_SIDES];
|
||||
u8 hazardsCounter:4; // Counter for applying hazard on switch in
|
||||
u8 padding2:4;
|
||||
u8 incrementEchoedVoice:1;
|
||||
u8 echoedVoiceCounter:3;
|
||||
};
|
||||
|
||||
struct AiBattleData
|
||||
|
||||
@ -168,6 +168,17 @@ static bool32 HandleEndTurnVarious(u32 battler)
|
||||
gBattleStruct->hpBefore[i] = gBattleMons[i].hp;
|
||||
}
|
||||
|
||||
if (gBattleStruct->incrementEchoedVoice)
|
||||
{
|
||||
if (gBattleStruct->echoedVoiceCounter < 4)
|
||||
gBattleStruct->echoedVoiceCounter++;
|
||||
gBattleStruct->incrementEchoedVoice = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleStruct->echoedVoiceCounter = 0;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
@ -3227,7 +3227,7 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
gLastHitBy[battler] = 0xFF;
|
||||
|
||||
gBattleStruct->lastTakenMove[battler] = 0;
|
||||
gBattleStruct->sameMoveTurns[battler] = 0;
|
||||
gBattleStruct->metronomeItemCounter[battler] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][0] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][1] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][2] = 0;
|
||||
@ -3348,7 +3348,7 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gLastHitBy[battler] = 0xFF;
|
||||
|
||||
gBattleStruct->choicedMove[battler] = MOVE_NONE;
|
||||
gBattleStruct->sameMoveTurns[battler] = 0;
|
||||
gBattleStruct->metronomeItemCounter[battler] = 0;
|
||||
gBattleStruct->lastTakenMove[battler] = MOVE_NONE;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][0] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][1] = 0;
|
||||
|
||||
@ -1541,7 +1541,7 @@ static void Cmd_ppreduce(void)
|
||||
|
||||
// For item Metronome, echoed voice
|
||||
if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] || WasUnableToUseMove(gBattlerAttacker))
|
||||
gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0;
|
||||
gBattleStruct->metronomeItemCounter[gBattlerAttacker] = 0;
|
||||
|
||||
if (gBattleMons[gBattlerAttacker].pp[gCurrMovePos] > ppToDeduct)
|
||||
gBattleMons[gBattlerAttacker].pp[gCurrMovePos] -= ppToDeduct;
|
||||
@ -6893,9 +6893,9 @@ static void Cmd_moveend(void)
|
||||
if (gCurrentMove != gLastResultingMoves[gBattlerAttacker]
|
||||
|| gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT
|
||||
|| gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0;
|
||||
gBattleStruct->metronomeItemCounter[gBattlerAttacker] = 0;
|
||||
else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT)
|
||||
gBattleStruct->sameMoveTurns[gBattlerAttacker]++;
|
||||
gBattleStruct->metronomeItemCounter[gBattlerAttacker]++;
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits.
|
||||
@ -6949,6 +6949,8 @@ static void Cmd_moveend(void)
|
||||
SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE);
|
||||
if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
|
||||
gBattleMons[gBattlerAttacker].volatiles.charge = FALSE;
|
||||
if (moveEffect == EFFECT_ECHOED_VOICE && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE))
|
||||
gBattleStruct->incrementEchoedVoice = TRUE;
|
||||
// check if Stellar type boost should be used up
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA
|
||||
&& GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR
|
||||
|
||||
@ -8074,10 +8074,10 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx)
|
||||
break;
|
||||
}
|
||||
case EFFECT_ECHOED_VOICE:
|
||||
// gBattleStruct->sameMoveTurns incremented in ppreduce
|
||||
if (gBattleStruct->sameMoveTurns[battlerAtk] != 0 && GetMoveEffect(gLastResultingMoves[battlerAtk]) == EFFECT_ECHOED_VOICE)
|
||||
// gBattleStruct->echoedVoiceCounter incremented in EndTurnVarious called by DoEndTurnEffects
|
||||
if (gBattleStruct->echoedVoiceCounter != 0)
|
||||
{
|
||||
basePower += (basePower * gBattleStruct->sameMoveTurns[battlerAtk]);
|
||||
basePower += (basePower * gBattleStruct->echoedVoiceCounter);
|
||||
if (basePower > 200)
|
||||
basePower = 200;
|
||||
}
|
||||
@ -9207,7 +9207,7 @@ static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEff
|
||||
{
|
||||
case HOLD_EFFECT_METRONOME:
|
||||
metronomeBoostBase = PercentToUQ4_12(GetBattlerHoldEffectParam(battlerAtk));
|
||||
metronomeTurns = min(gBattleStruct->sameMoveTurns[battlerAtk], 5);
|
||||
metronomeTurns = min(gBattleStruct->metronomeItemCounter[battlerAtk], 5);
|
||||
// according to bulbapedia this is the "correct" way to calculate the metronome boost
|
||||
// due to the limited domain of damage numbers it will never really matter whether this is off by one
|
||||
return uq4_12_add(UQ_4_12(1.0), metronomeBoostBase * metronomeTurns);
|
||||
|
||||
@ -1,7 +1,169 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Echoed Voice's power is multiplied for every consecutive turn used, capped at 5");
|
||||
TO_DO_BATTLE_TEST("Echoed Voice's power is reset when using a different move");
|
||||
TO_DO_BATTLE_TEST("Echoed Voice's power is increased even if it misses");
|
||||
TO_DO_BATTLE_TEST("Echoed Voice's power is increased even if it's blocked by Protect");
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_ECHOED_VOICE) == EFFECT_ECHOED_VOICE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Echoed Voice's power is multiplied for every consecutive turn used, capped at 5")
|
||||
{
|
||||
s16 damage[6];
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SOFT_BOILED) == EFFECT_SOFTBOILED);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BLISSEY);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); MOVE(opponent, MOVE_SOFT_BOILED); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); MOVE(opponent, MOVE_SOFT_BOILED); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[2]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[3]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[4]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[5]);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(2.0), damage[1]);
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(3.0), damage[2]);
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(4.0), damage[3]);
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(5.0), damage[4]);
|
||||
EXPECT_EQ(damage[4], damage[5]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Echoed Voice's power increases even if used by another battler")
|
||||
{
|
||||
s16 damage[2];
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, opponent);
|
||||
HP_BAR(player, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(2.0), damage[1]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Echoed Voice's power does not change until the end of the turn")
|
||||
{
|
||||
s16 damage[3];
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); MOVE(opponent, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, opponent);
|
||||
HP_BAR(player, captureDamage: &damage[1]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[2]);
|
||||
} THEN {
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(2.0), damage[2]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Echoed Voice's power increase is reset when no battler uses it successfully during a turn")
|
||||
{
|
||||
s16 damage[3];
|
||||
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_BITE, MOVE_EFFECT_FLINCH));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(opponent, MOVE_BITE); MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, opponent);
|
||||
HP_BAR(player, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponent);
|
||||
MESSAGE("Wobbuffet flinched and couldn't move!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[2]);
|
||||
} THEN {
|
||||
EXPECT_EQ(damage[0], damage[2]);
|
||||
EXPECT_NE(damage[1], damage[2]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Echoed Voice's power is increased even if it misses")
|
||||
{
|
||||
s16 damage[3];
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SAND_ATTACK) == EFFECT_ACCURACY_DOWN);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); MOVE(opponent, MOVE_SAND_ATTACK); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE, hit: FALSE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
MESSAGE("Wobbuffet's attack missed!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[2]);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(2.0), damage[1]);
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(4.0), damage[2]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Echoed Voice's power is increased even if it's blocked by Protect")
|
||||
{
|
||||
s16 damage[3];
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_PROTECT) == EFFECT_PROTECT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); MOVE(opponent, MOVE_PROTECT); }
|
||||
TURN { MOVE(player, MOVE_ECHOED_VOICE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[2]);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(2.0), damage[1]);
|
||||
EXPECT_MUL_EQ(damage[0], UQ_4_12(4.0), damage[2]);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user