Improved hazards logic and Mycelium Might ignores ability checks (#7509)

This commit is contained in:
surskitty 2025-08-08 03:54:30 -04:00 committed by GitHub
parent 6cb18f2048
commit 070a4f1dfa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 24 deletions

View File

@ -289,7 +289,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl
u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority);
s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, 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);
u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move);

View File

@ -4416,11 +4416,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
ADJUST_SCORE(GOOD_EFFECT);
}
break;
case EFFECT_CEASELESS_EDGE:
case EFFECT_SPIKES:
case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_STONE_AXE:
case EFFECT_TOXIC_SPIKES:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData))
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData))
{
if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT);
@ -5319,16 +5321,6 @@ case EFFECT_GUARD_SPLIT:
break;
}
break;
case EFFECT_STONE_AXE:
case EFFECT_CEASELESS_EDGE:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData));
{
if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT);
else
ADJUST_SCORE(DECENT_EFFECT);
}
break;
default:
break;
} // move effect checks
@ -5473,7 +5465,7 @@ case EFFECT_GUARD_SPLIT:
ADJUST_SCORE(DECENT_EFFECT);
break;
case MOVE_EFFECT_STEALTH_ROCK:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData));
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData));
{
if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT);
@ -6062,7 +6054,7 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_TOXIC_SPIKES:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, gAiLogicData))
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, gAiLogicData))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_GRASSY_TERRAIN:

View File

@ -1639,6 +1639,9 @@ bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move)
if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE)
return FALSE; // AI handicap flag: doesn't understand ability suppression concept
if (atkAbility == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(move))
return TRUE;
if (IsMoldBreakerTypeAbility(battlerAtk, atkAbility) || MoveIgnoresTargetAbility(move))
return TRUE;
@ -1750,10 +1753,12 @@ bool32 IsHazardMove(u32 move)
u32 i, moveEffect = GetMoveEffect(move);
switch (moveEffect)
{
case EFFECT_CEASELESS_EDGE:
case EFFECT_SPIKES:
case EFFECT_TOXIC_SPIKES:
case EFFECT_STICKY_WEB:
case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_STONE_AXE:
case EFFECT_TOXIC_SPIKES:
return TRUE;
}
@ -1763,6 +1768,7 @@ bool32 IsHazardMove(u32 move)
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i);
switch (additionalEffect->moveEffect)
{
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_STEELSURGE:
return TRUE;
default:
@ -4967,17 +4973,32 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef)
}
//TODO - track entire opponent party data to determine hazard effectiveness
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData)
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData)
{
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE
|| CountUsablePartyMons(battlerDef) == 0
|| HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN)
|| HasMoveWithEffect(battlerDef, EFFECT_TIDY_UP)
|| HasMoveWithEffect(battlerDef, EFFECT_DEFOG)
|| HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_DEFOG)
|| HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT))
if (CountUsablePartyMons(battlerDef) == 0
|| HasBattlerSideMoveWithEffect(battlerDef, EFFECT_COURT_CHANGE)
|| HasBattlerSideMoveWithEffect(battlerDef, EFFECT_DEFOG)
|| HasBattlerSideMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN)
|| HasBattlerSideMoveWithEffect(battlerDef, EFFECT_TIDY_UP)
|| HasBattlerSideMoveWithEffect(battlerDef, MOVE_EFFECT_DEFOG))
return FALSE;
if (IsBattleMoveStatus(move))
{
if (HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT))
return FALSE;
if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
return TRUE;
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE)
return FALSE;
}
else
{
if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
return TRUE;
if (aiData->abilities[battlerDef] == ABILITY_SHIELD_DUST)
return FALSE;
}
return TRUE;
}