mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-04-25 08:03:39 -05:00
Refactor protect failure to match vanilla (#8832)
This commit is contained in:
parent
ad31eb7149
commit
c76c3b37bb
|
|
@ -468,5 +468,7 @@ bool32 IsUsableWhileAsleepEffect(enum BattleMoveEffects effect);
|
|||
void SetWrapTurns(u32 battler, enum HoldEffect holdEffect);
|
||||
bool32 ChangeOrderTargetAfterAttacker(void);
|
||||
void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, enum Move usedMove);
|
||||
bool32 CanUseMoveConsecutively(u32 battler);
|
||||
void TryResetConsecutiveUseCounter(u32 battler);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
#define B_EXTRAPOLATED_MOVE_FLAGS TRUE // Adds move flags to moves that they don't officially have but would likely have if they were in the latest core series game.
|
||||
#define B_HIDDEN_POWER_COUNTER GEN_LATEST // Prior to Gen4, Counter and Mirror Coat treat Hidden Power as Physical regardless of type.
|
||||
#define B_MODERN_TRICK_CHOICE_LOCK GEN_LATEST // In Gen5+, if a Choice Item is swapped for a Choice Item, the Trick/Switcheroo user can pick another move, and then they'll be locked into it.
|
||||
#define B_PROTECT_FAILURE_RATE GEN_LATEST // In Gen5+, protect moves fails 1/3 of the time instead of 1/2
|
||||
|
||||
// Ability data settings
|
||||
#define B_UPDATED_ABILITY_DATA GEN_LATEST // Affects flags
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ enum VolatileFlags
|
|||
F(VOLATILE_TRANSFORMED_MON_PID, transformedMonPID, (u32, UINT32_MAX)) \
|
||||
F(VOLATILE_DISABLED_MOVE, disabledMove, (u32, MOVES_COUNT_ALL)) \
|
||||
F(VOLATILE_ENCORED_MOVE, encoredMove, (u32, MOVES_COUNT_ALL)) \
|
||||
F(VOLATILE_PROTECT_USES, protectUses, (u32, UINT8_MAX)) \
|
||||
F(VOLATILE_PROTECT_USES, consecutiveMoveUses, (u32, UINT8_MAX)) \
|
||||
F(VOLATILE_STOCKPILE_COUNTER, stockpileCounter, (u32, MAX_STAT_STAGE)) \
|
||||
F(VOLATILE_STOCKPILE_DEF, stockpileDef, (u32, MAX_STAT_STAGE)) \
|
||||
F(VOLATILE_STOCKPILE_SP_DEF, stockpileSpDef, (u32, MAX_STAT_STAGE)) \
|
||||
|
|
|
|||
|
|
@ -835,7 +835,6 @@ enum ProtectLikeUsedStringID
|
|||
{
|
||||
B_MSG_PROTECTED_ITSELF,
|
||||
B_MSG_BRACED_ITSELF,
|
||||
B_MSG_PROTECT_FAILED,
|
||||
B_MSG_PROTECTED_TEAM,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2399,14 +2399,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
|
|||
{
|
||||
ADJUST_SCORE(-10); //Don't protect if you're going to faint after protecting
|
||||
}
|
||||
else if (gBattleMons[battlerAtk].volatiles.protectUses == 1 && Random() % 100 < 50)
|
||||
else if (gBattleMons[battlerAtk].volatiles.consecutiveMoveUses == 1 && Random() % 100 < 50)
|
||||
{
|
||||
if (isBattle1v1)
|
||||
ADJUST_SCORE(-6);
|
||||
else
|
||||
ADJUST_SCORE(-10); //Don't try double protecting in doubles
|
||||
}
|
||||
else if (gBattleMons[battlerAtk].volatiles.protectUses >= 2)
|
||||
else if (gBattleMons[battlerAtk].volatiles.consecutiveMoveUses >= 2)
|
||||
{
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2250,7 +2250,7 @@ s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, enum Move move, enum Move pred
|
|||
s32 score = 0;
|
||||
|
||||
// TODO more sophisticated logic
|
||||
u32 uses = gBattleMons[battlerAtk].volatiles.protectUses;
|
||||
u32 uses = gBattleMons[battlerAtk].volatiles.consecutiveMoveUses;
|
||||
|
||||
/*if (GetMoveResultFlags(predictedMove) & (MOVE_RESULT_NO_EFFECT | MOVE_RESULT_MISSED))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1065,7 +1065,6 @@ const u16 gProtectLikeUsedStringIds[] =
|
|||
{
|
||||
[B_MSG_PROTECTED_ITSELF] = STRINGID_PKMNPROTECTEDITSELF2,
|
||||
[B_MSG_BRACED_ITSELF] = STRINGID_PKMNBRACEDITSELF,
|
||||
[B_MSG_PROTECT_FAILED] = STRINGID_BUTITFAILED,
|
||||
[B_MSG_PROTECTED_TEAM] = STRINGID_PROTECTEDTEAM,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -907,8 +907,6 @@ static const struct SpriteTemplate sSpriteTemplate_MonIconOnLvlUpBanner =
|
|||
.callback = SpriteCB_MonIconOnLvlUpBanner
|
||||
};
|
||||
|
||||
static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX / 4, USHRT_MAX / 8};
|
||||
|
||||
#define _ 0
|
||||
|
||||
static const struct PickupItem sPickupTable[] =
|
||||
|
|
@ -7425,65 +7423,28 @@ static void Cmd_unused_0x78(void)
|
|||
{
|
||||
}
|
||||
|
||||
static void TryResetProtectUseCounter(u32 battler)
|
||||
{
|
||||
u32 lastMove = gLastResultingMoves[battler];
|
||||
if (lastMove == MOVE_UNAVAILABLE)
|
||||
{
|
||||
gBattleMons[battler].volatiles.protectUses = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove);
|
||||
if (!gBattleMoveEffects[lastEffect].usesProtectCounter)
|
||||
{
|
||||
if (GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) < GEN_9 || lastEffect != EFFECT_ALLY_SWITCH)
|
||||
gBattleMons[battler].volatiles.protectUses = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_setprotectlike(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
|
||||
bool32 notLastTurn = TRUE;
|
||||
u32 protectMethod = GetMoveProtectMethod(gCurrentMove);
|
||||
|
||||
TryResetProtectUseCounter(gBattlerAttacker);
|
||||
|
||||
if (IsLastMonToMove(gBattlerAttacker))
|
||||
notLastTurn = FALSE;
|
||||
|
||||
if ((sProtectSuccessRates[gBattleMons[gBattlerAttacker].volatiles.protectUses] >= RandomUniform(RNG_PROTECT_FAIL, 0, USHRT_MAX) && notLastTurn)
|
||||
|| (protectMethod == PROTECT_WIDE_GUARD && GetConfig(CONFIG_WIDE_GUARD) >= GEN_6)
|
||||
|| (protectMethod == PROTECT_QUICK_GUARD && GetConfig(CONFIG_QUICK_GUARD) >= GEN_6))
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE)
|
||||
{
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.endured = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF;
|
||||
}
|
||||
else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].protected = protectMethod;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].protected = protectMethod;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF;
|
||||
}
|
||||
|
||||
gBattleMons[gBattlerAttacker].volatiles.protectUses++;
|
||||
gBattleMons[gBattlerAttacker].volatiles.endured = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF;
|
||||
}
|
||||
else // Protect failed
|
||||
else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.protectUses = 0;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECT_FAILED;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2;
|
||||
gProtectStructs[gBattlerAttacker].protected = protectMethod;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].protected = protectMethod;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF;
|
||||
}
|
||||
|
||||
gBattleMons[gBattlerAttacker].volatiles.consecutiveMoveUses++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
|
|
@ -13058,16 +13019,17 @@ void BS_TryAllySwitch(void)
|
|||
}
|
||||
else if (GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9)
|
||||
{
|
||||
TryResetProtectUseCounter(gBattlerAttacker);
|
||||
if (sProtectSuccessRates[gBattleMons[gBattlerAttacker].volatiles.protectUses] < Random())
|
||||
TryResetConsecutiveUseCounter(gBattlerAttacker);
|
||||
|
||||
if (CanUseMoveConsecutively(gBattlerAttacker))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.protectUses = 0;
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
gBattleMons[gBattlerAttacker].volatiles.consecutiveMoveUses++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.protectUses++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
gBattleMons[gBattlerAttacker].volatiles.consecutiveMoveUses = 0;
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -2814,7 +2814,27 @@ static enum MoveCanceler CancelerMoveFailure(struct BattleContext *ctx)
|
|||
battleScript = BattleScript_ButItFailed;
|
||||
break;
|
||||
case EFFECT_PROTECT:
|
||||
// TODO
|
||||
case EFFECT_ENDURE:
|
||||
TryResetConsecutiveUseCounter(gBattlerAttacker);
|
||||
if (IsLastMonToMove(ctx->battlerAtk))
|
||||
{
|
||||
battleScript = BattleScript_ButItFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 protectMethod = GetMoveProtectMethod(ctx->move);
|
||||
bool32 canUseProtectSecondTime = CanUseMoveConsecutively(ctx->battlerAtk);
|
||||
bool32 canUseWideGuard = (GetConfig(CONFIG_WIDE_GUARD) >= GEN_6 && protectMethod == PROTECT_WIDE_GUARD);
|
||||
bool32 canUseQuickGuard = (GetConfig(CONFIG_QUICK_GUARD) >= GEN_6 && protectMethod == PROTECT_QUICK_GUARD);
|
||||
|
||||
if (!canUseProtectSecondTime && !canUseWideGuard && !canUseQuickGuard)
|
||||
battleScript = BattleScript_ButItFailed;
|
||||
}
|
||||
if (battleScript != NULL)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.consecutiveMoveUses = 0;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2;
|
||||
}
|
||||
break;
|
||||
case EFFECT_REST:
|
||||
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP
|
||||
|
|
@ -12246,3 +12266,51 @@ void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, enum Move u
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const u16 sProtectSuccessRates[] =
|
||||
{
|
||||
USHRT_MAX,
|
||||
USHRT_MAX / 2,
|
||||
USHRT_MAX / 4,
|
||||
USHRT_MAX / 8
|
||||
};
|
||||
|
||||
static const u16 sGen5ProtectSuccessRates[] =
|
||||
{
|
||||
USHRT_MAX,
|
||||
USHRT_MAX / 3,
|
||||
USHRT_MAX / 9,
|
||||
USHRT_MAX / 27
|
||||
};
|
||||
|
||||
bool32 CanUseMoveConsecutively(u32 battler)
|
||||
{
|
||||
u32 moveUses = gBattleMons[battler].volatiles.consecutiveMoveUses;
|
||||
if (moveUses >= ARRAY_COUNT(sProtectSuccessRates))
|
||||
moveUses = ARRAY_COUNT(sProtectSuccessRates) - 1;
|
||||
|
||||
u32 successRate = sGen5ProtectSuccessRates[moveUses];
|
||||
if (B_PROTECT_FAILURE_RATE < GEN_5)
|
||||
successRate = sProtectSuccessRates[moveUses];
|
||||
|
||||
return successRate >= RandomUniform(RNG_PROTECT_FAIL, 0, USHRT_MAX);
|
||||
}
|
||||
|
||||
// Used for Protect, Endure and Ally switch
|
||||
void TryResetConsecutiveUseCounter(u32 battler)
|
||||
{
|
||||
u32 lastMove = gLastResultingMoves[battler];
|
||||
if (lastMove == MOVE_UNAVAILABLE)
|
||||
{
|
||||
gBattleMons[battler].volatiles.consecutiveMoveUses = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove);
|
||||
if (!gBattleMoveEffects[lastEffect].usesProtectCounter)
|
||||
{
|
||||
if (GetConfig(CONFIG_ALLY_SWITCH_FAIL_CHANCE) < GEN_9 || lastEffect != EFFECT_ALLY_SWITCH)
|
||||
gBattleMons[battler].volatiles.consecutiveMoveUses = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ DOUBLE_BATTLE_TEST("Ally Switch doesn't increase the Protect-like moves counter
|
|||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); }
|
||||
} THEN {
|
||||
EXPECT(gBattleMons[B_POSITION_PLAYER_RIGHT].volatiles.protectUses == 0);
|
||||
EXPECT(gBattleMons[B_POSITION_PLAYER_RIGHT].volatiles.consecutiveMoveUses == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter (Gen9+)
|
|||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); }
|
||||
} THEN {
|
||||
EXPECT(gBattleMons[B_POSITION_PLAYER_RIGHT].volatiles.protectUses == 1);
|
||||
EXPECT(gBattleMons[B_POSITION_PLAYER_RIGHT].volatiles.consecutiveMoveUses == 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user