Move RestoreBattlerData out of Ai_CalcDmg and add SaveBattlerData Protections (#4156)

* move restorebattlerdata out of Ai_CalcDmg

* fix SetBattlerdata calls

* add saved field to struct AI_SavedBattleMon to prevent overwriting saved mon info

* AI_CalcPartyMonDamage set opposing battler known data

---------

Co-authored-by: ghoulslash <pokevoyager0@gmail.com>
This commit is contained in:
ghoulslash 2024-05-15 14:39:03 -04:00 committed by GitHub
parent ab682ce900
commit 9c6dfb7c0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 12 deletions

View file

@ -312,7 +312,8 @@ struct AI_SavedBattleMon
u16 ability;
u16 moves[MAX_MON_MOVES];
u16 heldItem;
u16 species;
u16 species:15;
u16 saved:1;
u8 types[3];
};

View file

@ -438,6 +438,8 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
moves = GetMovesArray(battlerAtk);
weather = AI_GetWeather(aiData);
SetBattlerData(battlerAtk);
// Simulate dmg for both ai controlled mons and for player controlled mons.
for (battlerDef = 0; battlerDef < battlersCount; battlerDef++)
{
@ -445,6 +447,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
continue;
SaveBattlerData(battlerDef);
SetBattlerData(battlerDef);
for (i = 0; i < MAX_MON_MOVES; i++)
{
s32 dmg = 0;
@ -462,7 +465,9 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
aiData->simulatedDmg[battlerAtk][battlerDef][i] = dmg;
aiData->effectiveness[battlerAtk][battlerDef][i] = effectiveness;
}
RestoreBattlerData(battlerDef);
}
RestoreBattlerData(battlerAtk);
}
void SetAiLogicDataForTurn(struct AiLogicData *aiData)

View file

@ -143,10 +143,11 @@ void ClearBattlerItemEffectHistory(u32 battlerId)
void SaveBattlerData(u32 battlerId)
{
if (!BattlerHasAi(battlerId))
if (!BattlerHasAi(battlerId) && !AI_THINKING_STRUCT->saved[battlerId].saved)
{
u32 i;
AI_THINKING_STRUCT->saved[battlerId].saved = TRUE;
AI_THINKING_STRUCT->saved[battlerId].ability = gBattleMons[battlerId].ability;
AI_THINKING_STRUCT->saved[battlerId].heldItem = gBattleMons[battlerId].item;
AI_THINKING_STRUCT->saved[battlerId].species = gBattleMons[battlerId].species;
@ -196,7 +197,7 @@ static bool32 ShouldFailForIllusion(u32 illusionSpecies, u32 battlerId)
void SetBattlerData(u32 battlerId)
{
if (!BattlerHasAi(battlerId))
if (!BattlerHasAi(battlerId) && AI_THINKING_STRUCT->saved[battlerId].saved)
{
u32 i, species, illusionSpecies, side;
side = GetBattlerSide(battlerId);
@ -240,10 +241,11 @@ void SetBattlerData(u32 battlerId)
void RestoreBattlerData(u32 battlerId)
{
if (!BattlerHasAi(battlerId))
if (!BattlerHasAi(battlerId) && AI_THINKING_STRUCT->saved[battlerId].saved)
{
u32 i;
AI_THINKING_STRUCT->saved[battlerId].saved = FALSE;
gBattleMons[battlerId].ability = AI_THINKING_STRUCT->saved[battlerId].ability;
gBattleMons[battlerId].item = AI_THINKING_STRUCT->saved[battlerId].heldItem;
gBattleMons[battlerId].species = AI_THINKING_STRUCT->saved[battlerId].species;
@ -354,9 +356,15 @@ bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category)
// To save computation time this function has 2 variants. One saves, sets and restores battlers, while the other doesn't.
s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower)
{
s32 dmg = 0;
SaveBattlerData(battlerAtk);
SaveBattlerData(battlerDef);
return AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA));
SetBattlerData(battlerAtk);
SetBattlerData(battlerDef);
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA));
RestoreBattlerData(battlerAtk);
RestoreBattlerData(battlerDef);
return dmg;
}
static inline s32 LowestRollDmg(s32 dmg)
@ -457,9 +465,6 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
bool32 toggledTera = FALSE;
struct AiLogicData *aiData = AI_DATA;
SetBattlerData(battlerAtk);
SetBattlerData(battlerDef);
// Temporarily enable Z-Moves for damage calcs
if (considerZPower && IsViableZMove(battlerAtk, move))
{
@ -592,9 +597,6 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
dmg = 0;
}
RestoreBattlerData(battlerAtk);
RestoreBattlerData(battlerDef);
// convert multiper to AI_EFFECTIVENESS_xX
*typeEffectiveness = AI_GetEffectiveness(effectivenessMultiplier);
@ -3282,11 +3284,20 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl
s32 dmg;
u8 effectiveness;
struct BattlePokemon *savedBattleMons = AllocSaveBattleMons();
if(isPartyMonAttacker)
if (isPartyMonAttacker)
{
gBattleMons[battlerAtk] = switchinCandidate;
SetBattlerData(battlerDef); // set known opposing battler data
}
else
{
gBattleMons[battlerDef] = switchinCandidate;
SetBattlerData(battlerAtk); // set known opposing battler data
}
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, FALSE, AI_GetWeather(AI_DATA));
// restores original gBattleMon struct
FreeRestoreBattleMons(savedBattleMons);
return dmg;
}