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); 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); s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef); 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); void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData); bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData);
u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move); 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); ADJUST_SCORE(GOOD_EFFECT);
} }
break; break;
case EFFECT_CEASELESS_EDGE:
case EFFECT_SPIKES: case EFFECT_SPIKES:
case EFFECT_STEALTH_ROCK: case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB: case EFFECT_STICKY_WEB:
case EFFECT_STONE_AXE:
case EFFECT_TOXIC_SPIKES: case EFFECT_TOXIC_SPIKES:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)) if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData))
{ {
if (gDisableStructs[battlerAtk].isFirstTurn) if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT); ADJUST_SCORE(BEST_EFFECT);
@ -5319,16 +5321,6 @@ case EFFECT_GUARD_SPLIT:
break; break;
} }
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: default:
break; break;
} // move effect checks } // move effect checks
@ -5473,7 +5465,7 @@ case EFFECT_GUARD_SPLIT:
ADJUST_SCORE(DECENT_EFFECT); ADJUST_SCORE(DECENT_EFFECT);
break; break;
case MOVE_EFFECT_STEALTH_ROCK: case MOVE_EFFECT_STEALTH_ROCK:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData));
{ {
if (gDisableStructs[battlerAtk].isFirstTurn) if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT); 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_STEALTH_ROCK:
case EFFECT_STICKY_WEB: case EFFECT_STICKY_WEB:
case EFFECT_TOXIC_SPIKES: case EFFECT_TOXIC_SPIKES:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, gAiLogicData)) if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, gAiLogicData))
ADJUST_SCORE(POWERFUL_STATUS_MOVE); ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break; break;
case EFFECT_GRASSY_TERRAIN: 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) if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE)
return FALSE; // AI handicap flag: doesn't understand ability suppression concept 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)) if (IsMoldBreakerTypeAbility(battlerAtk, atkAbility) || MoveIgnoresTargetAbility(move))
return TRUE; return TRUE;
@ -1750,10 +1753,12 @@ bool32 IsHazardMove(u32 move)
u32 i, moveEffect = GetMoveEffect(move); u32 i, moveEffect = GetMoveEffect(move);
switch (moveEffect) switch (moveEffect)
{ {
case EFFECT_CEASELESS_EDGE:
case EFFECT_SPIKES: case EFFECT_SPIKES:
case EFFECT_TOXIC_SPIKES:
case EFFECT_STICKY_WEB:
case EFFECT_STEALTH_ROCK: case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_STONE_AXE:
case EFFECT_TOXIC_SPIKES:
return TRUE; return TRUE;
} }
@ -1763,6 +1768,7 @@ bool32 IsHazardMove(u32 move)
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i);
switch (additionalEffect->moveEffect) switch (additionalEffect->moveEffect)
{ {
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_STEELSURGE: case MOVE_EFFECT_STEELSURGE:
return TRUE; return TRUE;
default: default:
@ -4967,17 +4973,32 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef)
} }
//TODO - track entire opponent party data to determine hazard effectiveness //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 if (CountUsablePartyMons(battlerDef) == 0
|| CountUsablePartyMons(battlerDef) == 0 || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_COURT_CHANGE)
|| HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_DEFOG)
|| HasMoveWithEffect(battlerDef, EFFECT_TIDY_UP) || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN)
|| HasMoveWithEffect(battlerDef, EFFECT_DEFOG) || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_TIDY_UP)
|| HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_DEFOG) || HasBattlerSideMoveWithEffect(battlerDef, MOVE_EFFECT_DEFOG))
|| HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT))
return FALSE; 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; return TRUE;
} }