Fixes Charged up status (#5274)

Charge changed to last until the damage boost is consumed instead of next turn, previous behavior accessible with `B_CHARGE`
This commit is contained in:
Alex 2024-08-27 20:01:51 +02:00 committed by GitHub
parent 930cac6aca
commit 98dbf3a575
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 179 additions and 15 deletions

View file

@ -115,17 +115,15 @@ struct DisableStruct
u8 disableTimer:4;
u8 encoreTimer:4;
u8 perishSongTimer:4;
u8 furyCutterCounter;
u8 rolloutTimer:4;
u8 rolloutTimerStartValue:4;
u8 chargeTimer:4;
u8 tauntTimer:4;
u8 furyCutterCounter;
u8 battlerPreventingEscape;
u8 battlerWithSureHit;
u8 isFirstTurn;
u8 truantCounter:1;
u8 truantSwitchInHack:1;
u8 mimickedMoves:4;
u8 chargeTimer:4;
u8 rechargeTimer;
u8 autotomizeCount;
u8 slowStartTimer;
@ -138,6 +136,8 @@ struct DisableStruct
u8 wrapTurns;
u8 tormentTimer:4; // used for G-Max Meltdown
u8 usedMoves:4;
u8 truantCounter:1;
u8 truantSwitchInHack:1;
u8 noRetreat:1;
u8 tarShot:1;
u8 octolock:1;

View file

@ -121,6 +121,7 @@
#define B_SKETCH_BANS GEN_LATEST // In Gen9+, Sketch is unable to copy more moves than in previous generations.
#define B_KNOCK_OFF_REMOVAL GEN_LATEST // In Gen5+, Knock Off removes the foe's item instead of rendering it unusable.
#define B_HEAL_BELL_SOUNDPROOF GEN_LATEST // In Gen5, Heal Bell affects all mons with Soundproof. In Gen6-8 it affects inactive mons, but not battlers. In Gen9 it always affects the user.
#define B_CHARGE GEN_LATEST // In Gen8-, Charge status is lost regardless of the typing of the next move.
// Ability settings
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.

View file

@ -6427,9 +6427,11 @@ static void Cmd_moveend(void)
gBattleStruct->additionalEffectsCounter = 0;
gBattleStruct->poisonPuppeteerConfusion = FALSE;
gBattleStruct->fickleBeamBoosted = FALSE;
gBattleStruct->distortedTypeMatchups = 0;
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE);
gBattleStruct->distortedTypeMatchups = 0;
if (B_CHARGE <= GEN_8 || moveType == TYPE_ELECTRIC)
gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP);
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
gBattleScripting.moveendState++;
break;
@ -14012,7 +14014,10 @@ static void Cmd_setcharge(void)
u8 battler = GetBattlerForBattleScript(cmd->battler);
gStatuses3[battler] |= STATUS3_CHARGED_UP;
gDisableStructs[battler].chargeTimer = 2;
if (B_CHARGE < GEN_9)
gDisableStructs[battler].chargeTimer = 2;
else
gDisableStructs[battler].chargeTimer = 0;
gBattlescriptCurrInstr++;
gBattlescriptCurrInstr = cmd->nextInstr;
}

View file

@ -775,7 +775,7 @@ void BattleTv_SetDataBasedOnMove(u16 move, u16 weatherFlags, struct DisableStruc
tvPtr->side[atkSide].usedMoveSlot = moveSlot;
AddMovePoints(PTS_MOVE_EFFECT, moveSlot, move, 0);
AddPointsBasedOnWeather(weatherFlags, move, moveSlot);
if (disableStructPtr->chargeTimer != 0)
if (gStatuses3[gBattlerAttacker] & STATUS3_CHARGED_UP)
AddMovePoints(PTS_ELECTRIC, move, moveSlot, 0);
if (move == MOVE_WISH)

View file

@ -2303,8 +2303,8 @@ enum
ENDTURN_HEALBLOCK,
ENDTURN_EMBARGO,
ENDTURN_LOCK_ON,
ENDTURN_CHARGE,
ENDTURN_LASER_FOCUS,
ENDTURN_CHARGE,
ENDTURN_TAUNT,
ENDTURN_YAWN,
ENDTURN_ITEMS2,
@ -2767,7 +2767,7 @@ u8 DoBattlerEndTurnEffects(void)
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_CHARGE: // charge
if (gDisableStructs[battler].chargeTimer && --gDisableStructs[battler].chargeTimer == 0)
if (gDisableStructs[battler].chargeTimer > 0 && --gDisableStructs[battler].chargeTimer == 0)
gStatuses3[battler] &= ~STATUS3_CHARGED_UP;
gBattleStruct->turnEffectsTracker++;
break;

View file

@ -1,9 +1,167 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Charge doubles the damage of the next Electric move of the user");
TO_DO_BATTLE_TEST("Charge's effect is removed regardless if the next move is Electric or not (Gen 3-8)");
TO_DO_BATTLE_TEST("Charge's effect is kept until the user uses an Electric move (Gen 9+)");
TO_DO_BATTLE_TEST("Charge's effect is removed if the user fails using an Electric move (Gen 9+)");
TO_DO_BATTLE_TEST("Charge's effect does not stack with Electromorphosis");
TO_DO_BATTLE_TEST("Charge's effect does not stack with Wind Power");
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_THUNDERBOLT].power != 0);
ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC);
}
SINGLE_BATTLE_TEST("Charge doubles the damage of the next Electric move of the user")
{
s16 normalDamage = 0;
s16 chargedUpDamage = 0;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(player, MOVE_CHARGE); }
TURN { MOVE(player, MOVE_THUNDERBOLT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &normalDamage);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &chargedUpDamage);
} THEN {
EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage);
}
}
SINGLE_BATTLE_TEST("Charge's effect is kept until the user uses an Electric move (Gen 9+)")
{
s16 normalDamage = 0;
s16 chargedUpDamage = 0;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(player, MOVE_CHARGE); }
TURN { MOVE(player, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_THUNDERBOLT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &normalDamage);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &chargedUpDamage);
} THEN {
EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage);
}
}
SINGLE_BATTLE_TEST("Charge's effect is removed if the user fails using an Electric move (Gen 9+)")
{
s16 damage[2];
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_THUNDER); }
TURN { MOVE(player, MOVE_CHARGE); }
TURN { MOVE(player, MOVE_THUNDER, hit: FALSE); }
TURN { MOVE(player, MOVE_THUNDER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Charge's effect does not stack with Electromorphosis or Wind Power")
{
u32 species, ability;
s16 normalDamage = 0;
s16 chargedUpDamage = 0;
PARAMETRIZE { species = SPECIES_WATTREL; ability = ABILITY_WIND_POWER; }
PARAMETRIZE { species = SPECIES_TADBULB; ability = ABILITY_ELECTROMORPHOSIS; }
GIVEN {
ASSUME(gMovesInfo[MOVE_AIR_CUTTER].windMove == TRUE);
PLAYER(species) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(player, MOVE_CHARGE); MOVE(opponent, MOVE_AIR_CUTTER); }
TURN { MOVE(player, MOVE_THUNDERBOLT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &normalDamage);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_AIR_CUTTER, opponent);
ABILITY_POPUP(player, ability);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &chargedUpDamage);
} THEN {
EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage);
}
}
SINGLE_BATTLE_TEST("Charge's effect is removed regardless if the next move is Electric or not (Gen 3-8)")
{
s16 normalDamage = 0;
s16 chargedUpDamage = 0;
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].type != TYPE_ELECTRIC);
ASSUME(gMovesInfo[MOVE_TACKLE].power != 0);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(player, MOVE_CHARGE); }
TURN { MOVE(player, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_THUNDERBOLT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &normalDamage);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &chargedUpDamage);
} THEN {
if (B_CHARGE < GEN_9)
EXPECT_EQ(normalDamage, chargedUpDamage);
else
EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage);
}
}
SINGLE_BATTLE_TEST("Charge will not expire if it flinches twice in a row")
{
s16 normalDamage = 0;
s16 chargedUpDamage = 0;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); }
} WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(player, MOVE_CHARGE); }
TURN { MOVE(opponent, MOVE_IRON_HEAD); MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(opponent, MOVE_IRON_HEAD); MOVE(player, MOVE_THUNDERBOLT); }
TURN { MOVE(player, MOVE_THUNDERBOLT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &normalDamage);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &chargedUpDamage);
} THEN {
if (B_CHARGE < GEN_9)
EXPECT_EQ(normalDamage, chargedUpDamage);
else
EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage);
}
}