mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 11:37:40 +01:00
New AI command for using priority moves in death situatiions
This commit is contained in:
parent
c1f9032989
commit
a001faeced
@ -615,6 +615,11 @@
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro if_ai_can_go_down ptr:req
|
||||
.byte 0x6C
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
@ useful script macros
|
||||
.macro if_has_physical_move battler:req, ptr:req
|
||||
if_has_move_with_split \battler, SPLIT_PHYSICAL, \ptr
|
||||
|
@ -887,10 +887,24 @@ Score_Plus10:
|
||||
score +10
|
||||
end
|
||||
|
||||
@ omae wa mou shindeiru
|
||||
@ Basically a scenario where the players mon is faster, able to hit and able to OHKO
|
||||
@ In which, it would be best to use a priority move to deal any damage
|
||||
AI_CheckIfAlreadyDead:
|
||||
if_status2 AI_TARGET, STATUS2_RECHARGE | STATUS2_BIDE, AI_Ret
|
||||
if_ai_can_go_down AI_CheckIfAlreadyDeadPriorities
|
||||
end
|
||||
AI_CheckIfAlreadyDeadPriorities:
|
||||
if_target_faster Score_Minus1
|
||||
if_random_less_than 126, AI_Ret
|
||||
score +1
|
||||
end
|
||||
|
||||
AI_CheckViability:
|
||||
if_target_is_ally AI_Ret
|
||||
call_if_always_hit AI_CV_AlwaysHit
|
||||
call_if_move_flag FLAG_HIGH_CRIT, AI_CV_HighCrit
|
||||
call AI_CheckIfAlreadyDead
|
||||
if_effect EFFECT_HIT, AI_CV_Hit
|
||||
if_effect EFFECT_SLEEP, AI_CV_Sleep
|
||||
if_effect EFFECT_ABSORB, AI_CV_Absorb
|
||||
|
@ -69,7 +69,8 @@ u8 IsRunningFromBattleImpossible(void);
|
||||
void sub_803BDA0(u8 battlerId);
|
||||
void SwapTurnOrder(u8 id1, u8 id2);
|
||||
u32 GetBattlerTotalSpeedStat(u8 battlerId);
|
||||
s8 GetMovePriority(u8 battlerId);
|
||||
s8 GetChosenMovePriority(u32 battlerId);
|
||||
s8 GetMovePriority(u32 battlerId, u16 move);
|
||||
u8 GetWhoStrikesFirst(u8 battlerId1, u8 battlerId2, bool8 ignoreChosenMoves);
|
||||
void RunBattleScriptCommands_PopCallbacksStack(void);
|
||||
void RunBattleScriptCommands(void);
|
||||
|
@ -93,7 +93,7 @@ static void BattleAICmd_get_how_powerful_move_is(void);
|
||||
static void BattleAICmd_get_last_used_battler_move(void);
|
||||
static void BattleAICmd_if_equal_(void);
|
||||
static void BattleAICmd_if_not_equal_(void);
|
||||
static void BattleAICmd_if_user_goes(void);
|
||||
void BattleAICmd_if_user_goes(void);
|
||||
static void BattleAICmd_if_user_doesnt_go(void);
|
||||
static void BattleAICmd_nullsub_2A(void);
|
||||
static void BattleAICmd_nullsub_2B(void);
|
||||
@ -161,6 +161,7 @@ static void BattleAICmd_if_cant_use_last_resort(void);
|
||||
static void BattleAICmd_if_has_move_with_split(void);
|
||||
static void BattleAICmd_if_has_no_move_with_split(void);
|
||||
static void BattleAICmd_if_physical_moves_unusable(void);
|
||||
static void BattleAICmd_if_ai_can_go_down(void);
|
||||
|
||||
// ewram
|
||||
EWRAM_DATA const u8 *gAIScriptPtr = NULL;
|
||||
@ -279,6 +280,7 @@ static const BattleAICmdFunc sBattleAICmdTable[] =
|
||||
BattleAICmd_if_has_move_with_split, // 0x69
|
||||
BattleAICmd_if_has_no_move_with_split, // 0x6A
|
||||
BattleAICmd_if_physical_moves_unusable, // 0x6B
|
||||
BattleAICmd_if_ai_can_go_down, // 0x6C
|
||||
};
|
||||
|
||||
static const u16 sDiscouragedPowerfulMoveEffects[] =
|
||||
@ -1434,19 +1436,55 @@ static void BattleAICmd_if_not_equal_(void) // Same as if_not_equal.
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
|
||||
static void BattleAICmd_if_user_goes(void)
|
||||
void BattleAICmd_if_user_goes(void)
|
||||
{
|
||||
u32 fasterAI = 0, fasterPlayer = 0, i;
|
||||
s8 prioAI, prioPlayer;
|
||||
|
||||
// Check move priorities first.
|
||||
prioAI = GetMovePriority(sBattler_AI, AI_THINKING_STRUCT->moveConsidered);
|
||||
SaveBattlerData(gBattlerTarget);
|
||||
SetBattlerData(gBattlerTarget);
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (gBattleMons[gBattlerTarget].moves[i] == 0 || gBattleMons[gBattlerTarget].moves[i] == 0xFFFF)
|
||||
continue;
|
||||
|
||||
prioPlayer = GetMovePriority(gBattlerTarget, gBattleMons[gBattlerTarget].moves[i]);
|
||||
if (prioAI > prioPlayer)
|
||||
fasterAI++;
|
||||
else if (prioPlayer > prioAI)
|
||||
fasterPlayer++;
|
||||
}
|
||||
RestoreBattlerData(gBattlerTarget);
|
||||
|
||||
if (fasterAI > fasterPlayer)
|
||||
{
|
||||
if (gAIScriptPtr[1] == 0)
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
|
||||
else
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
else if (fasterAI < fasterPlayer)
|
||||
{
|
||||
if (gAIScriptPtr[1] == 1)
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
|
||||
else
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Priorities are the same(at least comparing to moves the AI is aware of), decide by speed.
|
||||
if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) == gAIScriptPtr[1])
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
|
||||
else
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleAICmd_if_user_doesnt_go(void)
|
||||
{
|
||||
if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) != gAIScriptPtr[1])
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
|
||||
else
|
||||
// To be changed. Not needed since the above does the same.
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
|
||||
@ -2622,3 +2660,23 @@ static void BattleAICmd_if_physical_moves_unusable(void)
|
||||
else
|
||||
gAIScriptPtr += 7;
|
||||
}
|
||||
|
||||
// Check if target has means to faint ai mon.
|
||||
static void BattleAICmd_if_ai_can_go_down(void)
|
||||
{
|
||||
s32 i, dmg;
|
||||
u32 unusable = CheckMoveLimitations(gBattlerTarget, 0, 0xFF & ~MOVE_LIMITATION_PP);
|
||||
u16 *moves = gBattleResources->battleHistory->usedMoves[gBattlerTarget].moves;
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i])
|
||||
&& AI_CalcDamage(moves[i], gBattlerTarget, sBattler_AI) >= gBattleMons[sBattler_AI].hp)
|
||||
{
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gAIScriptPtr += 5;
|
||||
}
|
||||
|
@ -4328,9 +4328,8 @@ u32 GetBattlerTotalSpeedStat(u8 battlerId)
|
||||
return speed;
|
||||
}
|
||||
|
||||
s8 GetMovePriority(u8 battlerId)
|
||||
s8 GetChosenMovePriority(u32 battlerId)
|
||||
{
|
||||
s8 priority;
|
||||
u16 move;
|
||||
|
||||
if (gProtectStructs[battlerId].noValidMoves)
|
||||
@ -4338,6 +4337,13 @@ s8 GetMovePriority(u8 battlerId)
|
||||
else
|
||||
move = gBattleMons[battlerId].moves[*(gBattleStruct->chosenMovePositions + battlerId)];
|
||||
|
||||
return GetMovePriority(battlerId, move);
|
||||
}
|
||||
|
||||
s8 GetMovePriority(u32 battlerId, u16 move)
|
||||
{
|
||||
s8 priority;
|
||||
|
||||
priority = gBattleMoves[move].priority;
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_GALE_WINGS
|
||||
&& gBattleMoves[move].type == TYPE_FLYING
|
||||
@ -4397,9 +4403,9 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves)
|
||||
if (!ignoreChosenMoves)
|
||||
{
|
||||
if (gChosenActionByBattler[battler1] == B_ACTION_USE_MOVE)
|
||||
priority1 = GetMovePriority(battler1);
|
||||
priority1 = GetChosenMovePriority(battler1);
|
||||
if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE)
|
||||
priority2 = GetMovePriority(battler2);
|
||||
priority2 = GetChosenMovePriority(battler2);
|
||||
}
|
||||
|
||||
if (priority1 == priority2)
|
||||
|
@ -902,7 +902,7 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move)
|
||||
else if (gProtectStructs[battlerId].kingsShielded && gBattleMoves[move].power != 0)
|
||||
return TRUE;
|
||||
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD
|
||||
&& GetMovePriority(gBattlerAttacker) > 0)
|
||||
&& GetChosenMovePriority(gBattlerAttacker) > 0)
|
||||
return TRUE;
|
||||
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD
|
||||
&& gBattleMoves[move].power == 0)
|
||||
|
@ -2345,7 +2345,7 @@ u8 AtkCanceller_UnableToUseMove2(void)
|
||||
case CANCELLER_PSYCHIC_TERRAIN:
|
||||
if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN
|
||||
&& IsBattlerGrounded(gBattlerAttacker)
|
||||
&& GetMovePriority(gBattlerAttacker) > 0
|
||||
&& GetChosenMovePriority(gBattlerAttacker) > 0
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
|
||||
{
|
||||
CancelMultiTurnMoves(gBattlerAttacker);
|
||||
@ -2989,7 +2989,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
else if ((gLastUsedAbility == ABILITY_DAZZLING
|
||||
|| (IsBattlerAlive(battler ^= BIT_FLANK) && GetBattlerAbility(battler) == ABILITY_DAZZLING)
|
||||
)
|
||||
&& GetMovePriority(battler) > 0
|
||||
&& GetChosenMovePriority(battler) > 0
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler))
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
|
Loading…
Reference in New Issue
Block a user