Refactor / Simlify Cmd_adjustdamage and remove redundancy (#6499)

This commit is contained in:
Alex 2025-04-02 23:52:54 +02:00 committed by GitHub
parent c1f18d0765
commit 5b9077e207
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 88 additions and 60 deletions

View File

@ -193,17 +193,17 @@ struct SpecialStatus
u8 lightningRodRedirected:1;
u8 restoredBattlerSprite: 1;
u8 faintedHasReplacement:1;
u8 focusBanded:1;
u8 focusSashed:1;
u8 emergencyExited:1;
u8 afterYou:1;
// End of byte
u8 sturdied:1;
u8 enduredDamage:1;
u8 stormDrainRedirected:1;
// End of byte
u8 switchInAbilityDone:1;
u8 switchInItemDone:1;
u8 instructedChosenTarget:3;
u8 berryReduced:1;
u8 announceNeutralizingGas:1; // See Cmd_switchineffects
u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS
// End of byte
u8 gemParam;
// End of byte
@ -211,19 +211,15 @@ struct SpecialStatus
u8 rototillerAffected:1; // to be affected by rototiller
u8 parentalBondState:2;
u8 multiHitOn:1;
u8 announceNeutralizingGas:1; // See Cmd_switchineffects
u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS
u8 affectionEndured:1;
// End of byte
u8 dancerUsedMove:1;
u8 dancerOriginalTarget:3;
u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects.
u8 distortedTypeMatchups:1;
u8 teraShellAbilityDone:1;
u8 criticalHit:1;
// End of byte
u8 enduredDamage:1;
u8 padding:7;
u8 dancerUsedMove:1;
u8 dancerOriginalTarget:3;
u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects.
u8 unused:3;
// End of byte
};
struct SideTimer

View File

@ -2161,6 +2161,7 @@ static void Cmd_adjustdamage(void)
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
u32 moveEffect = GetMoveEffect(gCurrentMove);
bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove);
bool32 enduredHit = FALSE;
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
{
@ -2202,65 +2203,58 @@ static void Cmd_adjustdamage(void)
gPotentialItemEffectBattler = battlerDef;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param)
if (moveEffect == EFFECT_FALSE_SWIPE)
{
enduredHit = TRUE;
}
else if (gProtectStructs[battlerDef].endured)
{
enduredHit = TRUE;
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED;
}
else if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param)
{
enduredHit = TRUE;
RecordItemEffectBattle(battlerDef, holdEffect);
gSpecialStatuses[battlerDef].focusBanded = TRUE;
gLastUsedItem = gBattleMons[battlerDef].item;
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
}
else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef))
{
enduredHit = TRUE;
RecordAbilityBattle(battlerDef, ABILITY_STURDY);
gSpecialStatuses[battlerDef].sturdied = TRUE;
gLastUsedAbility = ABILITY_STURDY;
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED;
}
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef))
{
enduredHit = TRUE;
RecordItemEffectBattle(battlerDef, holdEffect);
gSpecialStatuses[battlerDef].focusSashed = TRUE;
gLastUsedItem = gBattleMons[battlerDef].item;
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
}
else if (B_AFFECTION_MECHANICS == TRUE && GetBattlerSide(battlerDef) == B_SIDE_PLAYER && affectionScore >= AFFECTION_THREE_HEARTS)
{
if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20)
|| (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15)
|| (affectionScore == AFFECTION_THREE_HEARTS && rand < 10))
gSpecialStatuses[battlerDef].affectionEndured = TRUE;
{
enduredHit = TRUE;
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
}
}
if (moveEffect != EFFECT_FALSE_SWIPE
&& !gProtectStructs[battlerDef].endured
&& !gSpecialStatuses[battlerDef].focusBanded
&& !gSpecialStatuses[battlerDef].focusSashed
&& (B_AFFECTION_MECHANICS == FALSE || !gSpecialStatuses[battlerDef].affectionEndured)
&& !gSpecialStatuses[battlerDef].sturdied)
continue;
// Handle reducing the dmg to 1 hp.
gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1;
gSpecialStatuses[battlerDef].enduredDamage = TRUE;
if (gProtectStructs[battlerDef].endured)
if (enduredHit)
{
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED;
}
else if (gSpecialStatuses[battlerDef].focusBanded || gSpecialStatuses[battlerDef].focusSashed)
{
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
gLastUsedItem = gBattleMons[battlerDef].item;
gSpecialStatuses[battlerDef].focusBanded = FALSE;
gSpecialStatuses[battlerDef].focusSashed = FALSE;
}
else if (gSpecialStatuses[battlerDef].sturdied)
{
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED;
gLastUsedAbility = ABILITY_STURDY;
}
else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[battlerDef].affectionEndured)
{
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1;
gSpecialStatuses[battlerDef].enduredDamage = TRUE;
}
}
if (calcSpreadMoveDamage)
gBattleStruct->calculatedDamageDone = TRUE;
gBattlescriptCurrInstr = cmd->nextInstr;
if (gSpecialStatuses[gBattlerAttacker].gemBoost
@ -2289,7 +2283,6 @@ static void Cmd_multihitresultmessage(void)
if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_STURDIED)
{
gBattleStruct->moveResultFlags[gBattlerTarget] &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_HUNG_ON);
gSpecialStatuses[gBattlerTarget].sturdied = FALSE; // Delete this line to make Sturdy last for the duration of the whole move turn.
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SturdiedMsg;
return;
@ -2299,8 +2292,6 @@ static void Cmd_multihitresultmessage(void)
gLastUsedItem = gBattleMons[gBattlerTarget].item;
gPotentialItemEffectBattler = gBattlerTarget;
gBattleStruct->moveResultFlags[gBattlerTarget] &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_HUNG_ON);
gSpecialStatuses[gBattlerTarget].focusBanded = FALSE; // Delete this line to make Focus Band last for the duration of the whole move turn.
gSpecialStatuses[gBattlerTarget].focusSashed = FALSE; // Delete this line to make Focus Sash last for the duration of the whole move turn.
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
return;
@ -2967,7 +2958,6 @@ static void Cmd_resultmessage(void)
else if (*moveResultFlags & MOVE_RESULT_STURDIED)
{
*moveResultFlags &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON);
gSpecialStatuses[gBattlerTarget].sturdied = FALSE;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SturdiedMsg;
return;
@ -2994,7 +2984,6 @@ static void Cmd_resultmessage(void)
}
else if (B_AFFECTION_MECHANICS == TRUE && (*moveResultFlags & MOVE_RESULT_FOE_ENDURED_AFFECTION))
{
gSpecialStatuses[gBattlerTarget].affectionEndured = FALSE;
*moveResultFlags &= ~MOVE_RESULT_FOE_ENDURED_AFFECTION;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_AffectionBasedEndurance;
@ -7209,9 +7198,6 @@ static void Cmd_moveend(void)
gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING);
gBattleScripting.animTargetsHit = 0;
gBattleScripting.moveendState = 0;
gSpecialStatuses[gBattlerTarget].sturdied = 0;
gSpecialStatuses[gBattlerTarget].focusBanded = 0; // Delete this line to make Focus Band last for the duration of the whole move turn.
gSpecialStatuses[gBattlerTarget].focusSashed = 0; // Delete this line to make Focus Sash last for the duration of the whole move turn.
gSpecialStatuses[gBattlerAttacker].multiHitOn = TRUE;
MoveValuesCleanUp();
BattleScriptPush(GetMoveBattleScript(gCurrentMove));
@ -13089,6 +13075,10 @@ static void Cmd_setlightscreen(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
#define NOT_ENDURED 0
#define FOCUS_SASHED 1
#define FOCUS_BANDED 2
#define AFFECTION_ENDURED 3
static void Cmd_tryKO(void)
{
CMD_ARGS(const u8 *failInstr);
@ -13096,6 +13086,9 @@ static void Cmd_tryKO(void)
bool32 lands = FALSE;
u32 holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE);
u16 targetAbility = GetBattlerAbility(gBattlerTarget);
u32 rand = Random() % 100;
u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget);
u32 endured = NOT_ENDURED;
// Dynamaxed Pokemon cannot be hit by OHKO moves.
if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX))
@ -13110,14 +13103,21 @@ static void Cmd_tryKO(void)
if (holdEffect == HOLD_EFFECT_FOCUS_BAND
&& (Random() % 100) < GetBattlerHoldEffectParam(gBattlerTarget))
{
gSpecialStatuses[gBattlerTarget].focusBanded = TRUE;
endured = FOCUS_BANDED;
RecordItemEffectBattle(gBattlerTarget, holdEffect);
}
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget))
{
gSpecialStatuses[gBattlerTarget].focusSashed = TRUE;
endured = FOCUS_SASHED;
RecordItemEffectBattle(gBattlerTarget, holdEffect);
}
else if (B_AFFECTION_MECHANICS == TRUE && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && affectionScore >= AFFECTION_THREE_HEARTS)
{
if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20)
|| (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15)
|| (affectionScore == AFFECTION_THREE_HEARTS && rand < 10))
endured = AFFECTION_ENDURED;
}
if (targetAbility == ABILITY_STURDY)
{
@ -13152,13 +13152,13 @@ static void Cmd_tryKO(void)
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED;
}
else if (gSpecialStatuses[gBattlerTarget].focusBanded || gSpecialStatuses[gBattlerTarget].focusSashed)
else if (endured == FOCUS_BANDED || endured == FOCUS_SASHED)
{
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_HUNG_ON;
gLastUsedItem = gBattleMons[gBattlerTarget].item;
}
else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[gBattlerTarget].affectionEndured)
else if (endured == AFFECTION_ENDURED)
{
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
@ -13181,6 +13181,10 @@ static void Cmd_tryKO(void)
}
}
}
#undef NOT_ENDURED
#undef FOCUS_SASHED
#undef FOCUS_BANDED
#undef AFFECTION_ENDURED
// Super Fang
static void Cmd_damagetohalftargethp(void)

View File

@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon")
SINGLE_BATTLE_TEST("OHKO moves can hit semi-invulnerable mons when the user has No-Guard")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SHEER_COLD) == EFFECT_OHKO);
ASSUME(ItemId_GetHoldEffect(ITEM_FOCUS_SASH) == HOLD_EFFECT_FOCUS_SASH);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NO_GUARD); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -36,6 +36,34 @@ SINGLE_BATTLE_TEST("OHKO moves can hit semi-invulnerable mons when the user has
}
}
SINGLE_BATTLE_TEST("OHKO moves can can be endured by Focus Sash")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); }
} WHEN {
TURN { MOVE(player, MOVE_SHEER_COLD); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
HP_BAR(opponent, hp: 1);
MESSAGE("The opposing Wobbuffet hung on using its Focus Sash!");
}
}
SINGLE_BATTLE_TEST("OHKO moves can can be endured by Sturdy")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GEODUDE) { Ability(ABILITY_STURDY); }
} WHEN {
TURN { MOVE(player, MOVE_SHEER_COLD); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
ABILITY_POPUP(opponent, ABILITY_STURDY);
MESSAGE("The opposing Geodude was protected by Sturdy!");
}
}
TO_DO_BATTLE_TEST("Fissure faints the target, skipping regular damage calculations")
TO_DO_BATTLE_TEST("Fissure always fails if the target has a higher level than the user")
TO_DO_BATTLE_TEST("Fissure's accuracy increases by 1% for every level the user has over the target")