Skip to content

Commit

Permalink
Fixes spread damage in double battles
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexOn1ine committed Jul 29, 2024
1 parent b54226d commit 3e06d9c
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 29 deletions.
1 change: 1 addition & 0 deletions include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ struct BattleStruct
u8 trainerSlideDynamaxMsgDone:1;
u8 pledgeMove:1;
u8 isSkyBattle:1;
u8 isSpreadMoveDamage:1;
u32 aiDelayTimer; // Counts number of frames AI takes to choose an action.
u32 aiDelayFrames; // Number of frames it took to choose an action.
u8 timesGotHit[NUM_BATTLE_SIDES][PARTY_SIZE];
Expand Down
25 changes: 23 additions & 2 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -2005,10 +2005,30 @@ static void Cmd_critcalc(void)
static void Cmd_damagecalc(void)
{
CMD_ARGS();
u32 moveType;
u32 moveTarget;
GET_MOVE_TYPE(gCurrentMove, moveType);

u8 moveType;
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
if (!gBattleStruct->isSpreadMoveDamage
&& IsDoubleBattle()
&& (moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
{
u32 numTargets = 0;
u32 battlerDef = 0;
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
{
if (!IsBattlerAlive(battlerDef)
|| battlerDef == gBattlerAttacker
|| (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && (moveTarget == MOVE_TARGET_BOTH)))
continue;

numTargets++;
}
if (numTargets >= 2)
gBattleStruct->isSpreadMoveDamage = TRUE;
}

GET_MOVE_TYPE(gCurrentMove, moveType);
if (gBattleStruct->shellSideArmCategory[gBattlerAttacker][gBattlerTarget] == DAMAGE_CATEGORY_PHYSICAL && gCurrentMove == MOVE_SHELL_SIDE_ARM)
gBattleStruct->swapDamageCategory = TRUE;
gBattleMoveDamage = CalculateMoveDamage(gCurrentMove, gBattlerAttacker, gBattlerTarget, moveType, 0, gIsCriticalHit, TRUE, TRUE);
Expand Down Expand Up @@ -6412,6 +6432,7 @@ static void Cmd_moveend(void)
gBattleStruct->bouncedMoveIsUsed = FALSE;
gBattleStruct->enduredDamage = 0;
gBattleStruct->additionalEffectsCounter = 0;
gBattleStruct->isSpreadMoveDamage = FALSE;
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
gBattleScripting.moveendState++;
break;
Expand Down
27 changes: 1 addition & 26 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -8526,31 +8526,6 @@ u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc)
return count;
}

u32 GetMoveTargetCount(u32 move, u32 battlerAtk, u32 battlerDef)
{
switch (GetBattlerMoveTargetType(gBattlerAttacker, move))
{
case MOVE_TARGET_BOTH:
return IsBattlerAlive(battlerDef)
+ IsBattlerAlive(BATTLE_PARTNER(battlerDef));
case MOVE_TARGET_FOES_AND_ALLY:
return IsBattlerAlive(battlerDef)
+ IsBattlerAlive(BATTLE_PARTNER(battlerDef))
+ IsBattlerAlive(BATTLE_PARTNER(battlerAtk));
case MOVE_TARGET_OPPONENTS_FIELD:
return 1;
case MOVE_TARGET_DEPENDS:
case MOVE_TARGET_SELECTED:
case MOVE_TARGET_RANDOM:
case MOVE_TARGET_USER_OR_SELECTED:
return IsBattlerAlive(battlerDef);
case MOVE_TARGET_USER:
return IsBattlerAlive(battlerAtk);
default:
return 0;
}
}

static const u8 sFlailHpScaleToPowerTable[] =
{
1, 200,
Expand Down Expand Up @@ -9653,7 +9628,7 @@ static inline s32 CalculateBaseDamage(u32 power, u32 userFinalAttack, u32 level,

static inline uq4_12_t GetTargetDamageModifier(u32 move, u32 battlerAtk, u32 battlerDef)
{
if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2)
if (gBattleStruct->isSpreadMoveDamage)
return B_MULTIPLE_TARGETS_DMG >= GEN_4 ? UQ_4_12(0.75) : UQ_4_12(0.5);
return UQ_4_12(1.0);
}
Expand Down
2 changes: 1 addition & 1 deletion test/battle/ability/moxie.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ SINGLE_BATTLE_TEST("Moxie does not trigger when already at maximum Attack stage"
MESSAGE("Salamence cut its own HP and maximized ATTACK!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player);
MESSAGE("Foe Snorunt fainted!");
NONE_OF {
NONE_OF {
ABILITY_POPUP(player, ABILITY_MOXIE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Salamence's Moxie raised its Attack!");
Expand Down
30 changes: 30 additions & 0 deletions test/battle/damage_formula.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,33 @@ SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Marshadow vs Mawile)")
EXPECT_EQ(expectedDamage, dmg);
}
}

DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move")
{
s16 damage[5];
GIVEN {
PLAYER(SPECIES_REGIROCK);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(200); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); }
TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); }
TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
HP_BAR(opponentLeft, captureDamage: &damage[0]);
HP_BAR(opponentRight, captureDamage: &damage[1]);

ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
HP_BAR(opponentLeft, captureDamage: &damage[2]);
HP_BAR(opponentRight, captureDamage: &damage[3]);

ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
HP_BAR(opponentRight, captureDamage: &damage[4]);
} THEN {
EXPECT_EQ(damage[0], damage[1]);
EXPECT_EQ(damage[1], damage[3]);
EXPECT_MUL_EQ(damage[4], UQ_4_12(0.75), damage[3]);
}
}

0 comments on commit 3e06d9c

Please sign in to comment.