mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Merge 6f894ded4d into c47809abcd
This commit is contained in:
commit
4cfa1fe734
|
|
@ -210,7 +210,6 @@ struct AiLogicData
|
|||
enum Ability abilities[MAX_BATTLERS_COUNT];
|
||||
enum Item items[MAX_BATTLERS_COUNT];
|
||||
enum HoldEffect holdEffects[MAX_BATTLERS_COUNT];
|
||||
u8 holdEffectParams[MAX_BATTLERS_COUNT];
|
||||
enum Move lastUsedMove[MAX_BATTLERS_COUNT];
|
||||
u8 hpPercents[MAX_BATTLERS_COUNT];
|
||||
enum Move partnerMove;
|
||||
|
|
@ -223,6 +222,7 @@ struct AiLogicData
|
|||
u8 mostSuitableMonId[MAX_BATTLERS_COUNT]; // Stores result of GetMostSuitableMonToSwitchInto, which decides which generic mon the AI would switch into if they decide to switch. This can be overruled by specific mons found in ShouldSwitch; the final resulting mon is stored in AI_monToSwitchIntoId.
|
||||
enum Move predictedMove[MAX_BATTLERS_COUNT];
|
||||
u8 resistBerryAffected[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // Tracks whether currently calc'd move is affected by a resist berry into given target
|
||||
u8 turnOrder[MAX_BATTLERS_COUNT];
|
||||
|
||||
// Flags
|
||||
u32 weatherHasEffect:1; // The same as HasWeatherEffect(). Stored here, so it's called only once.
|
||||
|
|
|
|||
|
|
@ -121,8 +121,6 @@ struct BattleContext
|
|||
enum HoldEffect holdEffectAtk;
|
||||
enum HoldEffect holdEffectDef;
|
||||
|
||||
u8 aiTurnOrder[MAX_BATTLERS_COUNT];
|
||||
|
||||
// Flags
|
||||
u32 isCrit:1;
|
||||
u32 randomFactor:1;
|
||||
|
|
|
|||
|
|
@ -643,7 +643,6 @@ void SetBattlerAiData(enum BattlerId battler, struct AiLogicData *aiData)
|
|||
ability = aiData->abilities[battler] = AI_DecideKnownAbilityForTurn(battler);
|
||||
aiData->items[battler] = gBattleMons[battler].item;
|
||||
holdEffect = aiData->holdEffects[battler] = AI_DecideHoldEffectForTurn(battler);
|
||||
aiData->holdEffectParams[battler] = GetBattlerHoldEffectParam(battler);
|
||||
aiData->lastUsedMove[battler] = (gLastMoves[battler] == MOVE_UNAVAILABLE) ? MOVE_NONE : gLastMoves[battler];
|
||||
aiData->hpPercents[battler] = GetHealthPercentage(battler);
|
||||
aiData->moveLimitations[battler] = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL);
|
||||
|
|
@ -678,6 +677,22 @@ static u32 Ai_SetMoveAccuracy(struct AiLogicData *aiData, enum BattlerId battler
|
|||
}
|
||||
#undef BYPASSES_ACCURACY_CALC
|
||||
|
||||
static void SetBattlerTurnOrder(u8 *aiTurnOrder)
|
||||
{
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
for (u32 j = 0; j < gBattlersCount; j++)
|
||||
{
|
||||
if (AI_WhoStrikesFirst(aiTurnOrder[i], aiTurnOrder[j], MOVE_NONE, MOVE_NONE, DONT_CONSIDER_PRIORITY) == AI_IS_FASTER)
|
||||
{
|
||||
u32 temp = aiTurnOrder[i];
|
||||
aiTurnOrder[i] = aiTurnOrder[j];
|
||||
aiTurnOrder[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalcBattlerAiMovesData(struct AiLogicData *aiData, enum BattlerId battlerAtk, enum BattlerId battlerDef, u32 weather, u32 fieldStatus)
|
||||
{
|
||||
enum Move move;
|
||||
|
|
@ -723,32 +738,34 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, enum BattlerId bat
|
|||
|
||||
void SetAiLogicDataForTurn(struct AiLogicData *aiData)
|
||||
{
|
||||
u32 battlersCount, weather;
|
||||
|
||||
memset(aiData, 0, sizeof(struct AiLogicData));
|
||||
gAiBattleData->aiUsingGimmick = 0;
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_HAS_AI) && !IsWildMonSmart())
|
||||
return;
|
||||
|
||||
gAiLogicData->aiCalcInProgress = TRUE;
|
||||
|
||||
|
||||
if (DEBUG_AI_DELAY_TIMER)
|
||||
AIDebugTimerStart();
|
||||
|
||||
aiData->weatherHasEffect = HasWeatherEffect();
|
||||
weather = AI_GetWeather();
|
||||
u32 weather = AI_GetWeather();
|
||||
|
||||
// get/assume all battler data and simulate AI damage
|
||||
battlersCount = gBattlersCount;
|
||||
u32 battlersCount = gBattlersCount;
|
||||
|
||||
for (enum BattlerId battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++)
|
||||
for (enum BattlerId battler = 0; battler < battlersCount; battler++)
|
||||
{
|
||||
if (!IsBattlerAlive(battlerAtk))
|
||||
if (!IsBattlerAlive(battler))
|
||||
continue;
|
||||
|
||||
SetBattlerAiData(battlerAtk, aiData);
|
||||
SetBattlerAiData(battler, aiData);
|
||||
}
|
||||
|
||||
for (enum BattlerId battler = 0; battler < battlersCount; battler++)
|
||||
aiData->turnOrder[battler] = battler;
|
||||
SetBattlerTurnOrder(aiData->turnOrder);
|
||||
|
||||
for (enum BattlerId battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++)
|
||||
{
|
||||
if (!IsBattlerAlive(battlerAtk))
|
||||
|
|
@ -757,22 +774,22 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
|
|||
SetBattlerAiMovesData(aiData, battlerAtk, battlersCount, weather);
|
||||
}
|
||||
|
||||
for (enum BattlerId battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++)
|
||||
for (enum BattlerId battler = 0; battler < battlersCount; battler++)
|
||||
{
|
||||
// Prediction limited to player side but can be expanded to read partners move in the future
|
||||
if (!IsOnPlayerSide(battlerAtk) || !CanAiPredictMove(battlerAtk))
|
||||
if (!IsOnPlayerSide(battler) || !CanAiPredictMove(battler))
|
||||
continue;
|
||||
|
||||
// This can potentially be cleaned up more
|
||||
BattleAI_SetupAIData(0xF, battlerAtk);
|
||||
u32 chosenMoveIndex = ChooseMoveOrAction(battlerAtk);
|
||||
gAiLogicData->predictedMove[battlerAtk] = gBattleMons[battlerAtk].moves[chosenMoveIndex];
|
||||
BattleAI_SetupAIData(0xF, battler);
|
||||
u32 chosenMoveIndex = ChooseMoveOrAction(battler);
|
||||
gAiLogicData->predictedMove[battler] = gBattleMons[battler].moves[chosenMoveIndex];
|
||||
aiData->predictingMove = RandomPercentage(RNG_AI_PREDICT_MOVE, PREDICT_MOVE_CHANCE);
|
||||
}
|
||||
|
||||
if (DEBUG_AI_DELAY_TIMER)
|
||||
AIDebugTimerEnd();
|
||||
|
||||
|
||||
gAiLogicData->aiCalcInProgress = FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1272,7 +1289,7 @@ static s32 AI_CheckBadMove(enum BattlerId battlerAtk, enum BattlerId battlerDef,
|
|||
{
|
||||
ADJUST_SCORE(-5);
|
||||
}
|
||||
|
||||
|
||||
// check non-user target
|
||||
if (moveTarget != TARGET_USER)
|
||||
{
|
||||
|
|
@ -5068,7 +5085,7 @@ static s32 AI_CalcMoveEffectScore(enum BattlerId battlerAtk, enum BattlerId batt
|
|||
&& AI_WhoStrikesFirst(battlerAtk, battlerDef, MOVE_FAKE_OUT, MOVE_FAKE_OUT, CONSIDER_PRIORITY) == AI_IS_FASTER)
|
||||
|| (HasMove(battlerDefPartner, MOVE_FAKE_OUT) && gBattleStruct->battlerState[battlerDefPartner].isFirstTurn
|
||||
&& AI_WhoStrikesFirst(battlerAtk, battlerDefPartner, MOVE_FAKE_OUT, MOVE_FAKE_OUT, CONSIDER_PRIORITY) == AI_IS_FASTER))
|
||||
{
|
||||
{
|
||||
ADJUST_SCORE(FAST_KILL + 2);
|
||||
}
|
||||
// If ally has KO on target's partner, but target can fast KO ally (checking move and priority combinations for everything likely gets a bit complicated)
|
||||
|
|
@ -5091,7 +5108,7 @@ static s32 AI_CalcMoveEffectScore(enum BattlerId battlerAtk, enum BattlerId batt
|
|||
}
|
||||
}
|
||||
// If ally has slow KO with their chosen move, user sees no KOs while outspeeding (checking move and priority combinations for everything likely gets a bit complicated)
|
||||
else if (hasPartner
|
||||
else if (hasPartner
|
||||
&& (atkPartnerKoDef && AI_WhoStrikesFirst(battlerAtkPartner, battlerDef, gBattleMons[battlerAtkPartner].moves[gAiBattleData->chosenMoveIndex[battlerAtkPartner]], predictedMoveSpeedCheck, CONSIDER_PRIORITY) == AI_IS_SLOWER)
|
||||
&& !(atkKoDef && AI_WhoStrikesFirst(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY) == AI_IS_FASTER)
|
||||
&& !(atkKoDefPartner && AI_WhoStrikesFirst(battlerAtk, battlerDefPartner, move, MOVE_SCRATCH, DONT_CONSIDER_PRIORITY) == AI_IS_FASTER))
|
||||
|
|
@ -5099,7 +5116,7 @@ static s32 AI_CalcMoveEffectScore(enum BattlerId battlerAtk, enum BattlerId batt
|
|||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include "constants/moves.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
static void AI_SetBattlerTurnOrder(u8 *aiTurnOrder);
|
||||
static u32 GetAIEffectGroup(enum BattleMoveEffects effect);
|
||||
static u32 GetAIEffectGroupFromMove(enum BattlerId battler, enum Move move);
|
||||
|
||||
|
|
@ -959,7 +958,6 @@ struct SimulatedDamage AI_CalcDamage(enum Move move, enum BattlerId battlerAtk,
|
|||
ctx.abilityDef = AI_GetMoldBreakerSanitizedAbility(battlerAtk, ctx.abilityAtk, aiData->abilities[battlerDef], ctx.holdEffectDef, move);
|
||||
ctx.isCrit = ShouldCalcCritDamage(&ctx);
|
||||
ctx.typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(&ctx);
|
||||
AI_SetBattlerTurnOrder(ctx.aiTurnOrder);
|
||||
|
||||
u32 movePower = GetMovePower(move);
|
||||
|
||||
|
|
@ -2188,7 +2186,7 @@ bool32 ShouldTryOHKO(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum
|
|||
u32 accuracy = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex];
|
||||
|
||||
gPotentialItemEffectBattler = battlerDef;
|
||||
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < gAiLogicData->holdEffectParams[battlerDef])
|
||||
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < GetBattlerHoldEffectParam(battlerDef))
|
||||
return FALSE; //probabilistically speaking, focus band should activate so dont OHKO
|
||||
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AI_BattlerAtMaxHp(battlerDef))
|
||||
return FALSE;
|
||||
|
|
@ -6501,23 +6499,3 @@ bool32 IsPartyMonPlannedToBeSwitchedInByPartner(u32 partyIndex, enum BattlerId b
|
|||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void AI_SetBattlerTurnOrder(u8 *aiTurnOrder)
|
||||
{
|
||||
for (u32 battler = 0; battler < gBattlersCount; battler++)
|
||||
aiTurnOrder[battler] = battler;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
for (u32 j = 0; j < gBattlersCount; j++)
|
||||
{
|
||||
if (AI_WhoStrikesFirst(aiTurnOrder[i], aiTurnOrder[j], MOVE_NONE, MOVE_NONE, DONT_CONSIDER_PRIORITY) == AI_IS_FASTER)
|
||||
{
|
||||
u32 temp = aiTurnOrder[i];
|
||||
aiTurnOrder[i] = aiTurnOrder[j];
|
||||
aiTurnOrder[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1113,25 +1113,25 @@ bool32 IsLastMonToMove(enum BattlerId battler)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static u32 GetAiTurnOrder(u8 *aiTurnOrder, enum BattlerId battler)
|
||||
static u32 GetAiTurnOrder(enum BattlerId battler)
|
||||
{
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (aiTurnOrder[i] == battler)
|
||||
if (gAiLogicData->turnOrder[i] == battler)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool32 Ai_AttackerMovesAfterTarget(struct BattleContext *ctx)
|
||||
static bool32 Ai_AttackerMovesAfterTarget(enum BattlerId battlerAtk, enum BattlerId battlerDef)
|
||||
{
|
||||
return GetAiTurnOrder(ctx->aiTurnOrder, ctx->battlerAtk) > GetAiTurnOrder(ctx->aiTurnOrder, ctx->battlerDef);
|
||||
return GetAiTurnOrder(battlerAtk) > GetAiTurnOrder(battlerDef);
|
||||
}
|
||||
|
||||
static bool32 Ai_AttackerMovesLast(struct BattleContext *ctx)
|
||||
static bool32 Ai_AttackerMovesLast(enum BattlerId battlerAtk)
|
||||
{
|
||||
u32 numAliveBattlers = 0;
|
||||
u32 battlerTurnOrder = GetAiTurnOrder(ctx->aiTurnOrder, ctx->battlerAtk);
|
||||
u32 battlerTurnOrder = GetAiTurnOrder(battlerAtk);
|
||||
|
||||
for (enum BattlerId battler = B_BATTLER_0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
|
|
@ -6344,7 +6344,7 @@ static inline u32 CalcMoveBasePower(struct BattleContext *ctx)
|
|||
case EFFECT_PAYBACK:
|
||||
if (ctx->aiCalc)
|
||||
{
|
||||
if (Ai_AttackerMovesAfterTarget(ctx))
|
||||
if (Ai_AttackerMovesAfterTarget(battlerAtk, battlerDef))
|
||||
basePower *= 2;
|
||||
}
|
||||
else if (HasBattlerActedThisTurn(battlerDef)
|
||||
|
|
@ -6356,7 +6356,7 @@ static inline u32 CalcMoveBasePower(struct BattleContext *ctx)
|
|||
case EFFECT_BOLT_BEAK:
|
||||
if (ctx->aiCalc)
|
||||
{
|
||||
if (!Ai_AttackerMovesAfterTarget(ctx))
|
||||
if (!Ai_AttackerMovesAfterTarget(battlerAtk, battlerDef))
|
||||
basePower *= 2;
|
||||
}
|
||||
else if (!HasBattlerActedThisTurn(battlerDef)
|
||||
|
|
@ -6567,7 +6567,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct BattleContext *ctx)
|
|||
|
||||
if (ctx->aiCalc)
|
||||
{
|
||||
if (Ai_AttackerMovesLast(ctx))
|
||||
if (Ai_AttackerMovesLast(battlerAtk))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
}
|
||||
else if (IsLastMonToMove(battlerAtk))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user