Fix Substitute / Shed Tail Switch AI (#6334)
This commit is contained in:
parent
9479b67964
commit
b109c4c36b
@ -155,6 +155,7 @@ bool32 HasHighCritRatioMove(u32 battler);
|
||||
bool32 HasMagicCoatAffectedMove(u32 battler);
|
||||
bool32 HasSnatchAffectedMove(u32 battler);
|
||||
bool32 IsHazardClearingMove(u32 move);
|
||||
bool32 IsSubstituteEffect(u32 effect);
|
||||
|
||||
// status checks
|
||||
bool32 AI_CanGetFrostbite(u32 battler, u32 ability);
|
||||
@ -216,7 +217,7 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
|
||||
void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData);
|
||||
void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 IsBattlerPredictedToSwitch(u32 battler);
|
||||
bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef);
|
||||
|
||||
|
||||
@ -3650,7 +3650,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
break;
|
||||
case EFFECT_SUBSTITUTE:
|
||||
case EFFECT_SHED_TAIL:
|
||||
IncreaseSubstituteMoveScore(battlerAtk, battlerDef, move, &score);
|
||||
ADJUST_SCORE(IncreaseSubstituteMoveScore(battlerAtk, battlerDef, move));
|
||||
break;
|
||||
case EFFECT_MIMIC:
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
{
|
||||
|
||||
@ -1021,6 +1021,23 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 HasGoodSubstituteMove(u32 battler)
|
||||
{
|
||||
int i;
|
||||
u32 aiMove, aiMoveEffect, opposingBattler = GetOppositeBattler(battler);
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
aiMove = gBattleMons[battler].moves[i];
|
||||
aiMoveEffect = GetMoveEffect(aiMove);
|
||||
if (IsSubstituteEffect(aiMoveEffect))
|
||||
{
|
||||
if (IncreaseSubstituteMoveScore(battler, opposingBattler, aiMove) > 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldSwitch(u32 battler)
|
||||
{
|
||||
u32 battlerIn1, battlerIn2;
|
||||
@ -1085,19 +1102,21 @@ bool32 ShouldSwitch(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// NOTE: The sequence of the below functions matter! Do not change unless you have carefully considered the outcome.
|
||||
// Since the order is sequencial, and some of these functions prompt switch to specific party members.
|
||||
// Since the order is sequential, and some of these functions prompt switch to specific party members.
|
||||
|
||||
// FindMon functions can prompt a switch to specific party members that override GetMostSuitableMonToSwitchInto
|
||||
// The rest can prompt a switch to party member returned by GetMostSuitableMonToSwitchInto
|
||||
|
||||
// These Functions can prompt switch to specific party members that override GetMostSuitableMonToSwitchInto
|
||||
if (FindMonThatHitsWonderGuard(battler))
|
||||
return TRUE;
|
||||
if (FindMonThatAbsorbsOpponentsMove(battler))
|
||||
return TRUE;
|
||||
|
||||
// These Functions can prompt switch to party member returned by GetMostSuitableMonToSwitchInto
|
||||
if ((AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE))
|
||||
return FALSE;
|
||||
if (HasGoodSubstituteMove(battler))
|
||||
return FALSE;
|
||||
if (ShouldSwitchIfTrapperInParty(battler))
|
||||
return TRUE;
|
||||
if (FindMonThatAbsorbsOpponentsMove(battler))
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfOpponentChargingOrInvulnerable(battler))
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfTruant(battler))
|
||||
|
||||
@ -2427,6 +2427,19 @@ bool32 IsSwitchOutEffect(u32 effect)
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsSubstituteEffect(u32 effect)
|
||||
{
|
||||
// Substitute effects like Substitute, Shed Tail, etc.
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_SUBSTITUTE:
|
||||
case EFFECT_SHED_TAIL:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsChaseEffect(u32 effect)
|
||||
{
|
||||
// Effects that hit switching out mons like Pursuit
|
||||
@ -4232,31 +4245,32 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st
|
||||
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL));
|
||||
}
|
||||
|
||||
void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
{
|
||||
u32 effect = GetMoveEffect(move);
|
||||
u32 scoreIncrease = 0;
|
||||
if (effect == EFFECT_SUBSTITUTE) // Substitute specific
|
||||
{
|
||||
if (HasAnyKnownMove(battlerDef) && GetBestDmgFromBattler(battlerDef, battlerAtk) < gBattleMons[battlerAtk].maxHP / 4)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
scoreIncrease += GOOD_EFFECT;
|
||||
}
|
||||
else if (effect == EFFECT_SHED_TAIL) // Shed Tail specific
|
||||
{
|
||||
if ((ShouldPivot(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_THINKING_STRUCT->movesetIndex))
|
||||
&& (HasAnyKnownMove(battlerDef) && (GetBestDmgFromBattler(battlerDef, battlerAtk) < gBattleMons[battlerAtk].maxHP / 2)))
|
||||
ADJUST_SCORE_PTR(BEST_EFFECT);
|
||||
scoreIncrease += BEST_EFFECT;
|
||||
}
|
||||
|
||||
if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
scoreIncrease += GOOD_EFFECT;
|
||||
|
||||
if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
scoreIncrease += GOOD_EFFECT;
|
||||
else if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE))
|
||||
ADJUST_SCORE_PTR(DECENT_EFFECT);
|
||||
scoreIncrease += DECENT_EFFECT;
|
||||
|
||||
if (IsBattlerPredictedToSwitch(battlerDef))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
scoreIncrease += DECENT_EFFECT;
|
||||
|
||||
if (HasMoveEffect(battlerDef, EFFECT_SLEEP)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_TOXIC)
|
||||
@ -4265,10 +4279,11 @@ void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *
|
||||
|| HasMoveEffect(battlerDef, EFFECT_WILL_O_WISP)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_CONFUSE)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_LEECH_SEED))
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
scoreIncrease += GOOD_EFFECT;
|
||||
|
||||
if (AI_DATA->hpPercents[battlerAtk] > 70)
|
||||
ADJUST_SCORE_PTR(WEAK_EFFECT);
|
||||
scoreIncrease += WEAK_EFFECT;
|
||||
return scoreIncrease;
|
||||
}
|
||||
|
||||
bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef)
|
||||
|
||||
@ -86,22 +86,22 @@ SINGLE_BATTLE_TEST("Shed Tail's HP cost doesn't trigger effects that trigger on
|
||||
}
|
||||
}
|
||||
|
||||
// Passes for some reason even though it seems there is some code missing
|
||||
/*
|
||||
AI_SINGLE_BATTLE_TEST("AI will use Shed Tail to pivot to another mon while in damage stalemate with player")
|
||||
AI_SINGLE_BATTLE_TEST("AI will use Shed Tail to pivot to another mon while in damage stalemate with player rather than hard switching")
|
||||
{
|
||||
KNOWN_FAILING; // missing AI code
|
||||
u32 aiFlags;
|
||||
PARAMETRIZE { aiFlags = 0; }
|
||||
PARAMETRIZE { aiFlags = AI_FLAG_SMART_SWITCHING | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES; }
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiFlags);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(100); Ability(ABILITY_RUN_AWAY); Moves(MOVE_TACKLE, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Ability(ABILITY_RUN_AWAY); Moves(MOVE_CONFUSION, MOVE_SHED_TAIL); }
|
||||
OPPONENT(SPECIES_SCIZOR) { Speed(101); Moves(MOVE_CELEBRATE, MOVE_X_SCISSOR); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_CONFUSION); }
|
||||
if (aiFlags == 0)
|
||||
TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_CONFUSION); }
|
||||
TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_SHED_TAIL); }
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SINGLE_BATTLE_TEST("Shed Tail creates a Substitute with 1/4 of user maximum health")
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user