Fixes AI not seeing primal weather and partner absorbing abilities (#6936)

This commit is contained in:
Alex 2025-05-22 23:25:29 +02:00 committed by GitHub
parent f9400332fc
commit 87cbb457f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 5 deletions

View File

@ -421,19 +421,50 @@ static inline s32 DmgRoll(s32 dmg)
return dmg;
}
bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveType)
bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveType, uq4_12_t effectiveness, u32 weather)
{
u32 battlerDefAbility;
u32 partnerDefAbility;
struct AiLogicData *aiData = AI_DATA;
if (effectiveness == UQ_4_12(0.0))
return TRUE;
if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
return TRUE;
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef], ABILITY_CHECK_TRIGGER))
// aiData->abilities does not check for Mold Breaker since it happens during combat so it needs to be done manually
if (IsMoldBreakerTypeAbility(battlerAtk, aiData->abilities[battlerAtk]) || MoveIgnoresTargetAbility(move))
{
battlerDefAbility = ABILITY_NONE;
partnerDefAbility = ABILITY_NONE;
}
else
{
battlerDefAbility = aiData->abilities[battlerDef];
partnerDefAbility = aiData->abilities[BATTLE_PARTNER(battlerDef)];
}
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, battlerDefAbility, ABILITY_CHECK_TRIGGER))
return TRUE;
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType, ABILITY_CHECK_TRIGGER))
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, battlerDefAbility, move, moveType, ABILITY_CHECK_TRIGGER))
return TRUE;
// Limited to Lighning Rod and Storm Drain because otherwise the AI would consider Water Absorb, etc...
if (partnerDefAbility == ABILITY_LIGHTNING_ROD || partnerDefAbility == ABILITY_STORM_DRAIN)
{
if (CanAbilityAbsorbMove(battlerAtk, BATTLE_PARTNER(battlerDef), partnerDefAbility, move, moveType, ABILITY_CHECK_TRIGGER))
return TRUE;
}
if (HasWeatherEffect())
{
if (weather & B_WEATHER_SUN_PRIMAL && moveType == TYPE_WATER)
return TRUE;
if (weather & B_WEATHER_RAIN_PRIMAL && moveType == TYPE_FIRE)
return TRUE;
}
switch (GetMoveEffect(move))
{
case EFFECT_DREAM_EATER:
@ -469,6 +500,11 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy
if (!gDisableStructs[battlerAtk].isFirstTurn)
return TRUE;
break;
case EFFECT_EXPLOSION:
case EFFECT_MIND_BLOWN:
if (battlerDefAbility == ABILITY_DAMP || partnerDefAbility == ABILITY_DAMP)
return TRUE;
break;
}
return FALSE;
@ -658,7 +694,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
u32 movePower = GetMovePower(move);
if (movePower)
isDamageMoveUnusable = IsDamageMoveUnusable(battlerAtk, battlerDef, move, moveType);
isDamageMoveUnusable = IsDamageMoveUnusable(battlerAtk, battlerDef, move, moveType, effectivenessMultiplier, weather);
if (movePower && !isDamageMoveUnusable)
{

View File

@ -915,6 +915,36 @@ SINGLE_BATTLE_TEST("AI correctly records used moves")
}
}
AI_SINGLE_BATTLE_TEST("AI sees that Primal weather can block a move by type")
{
GIVEN {
ASSUME(GetMoveType(MOVE_HYDRO_PUMP) == TYPE_WATER);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT);
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_BLASTOISE) { Moves(MOVE_HYDRO_PUMP, MOVE_POUND); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_POUND); }
}
}
AI_DOUBLE_BATTLE_TEST("AI sees opposing drain ability")
{
GIVEN {
ASSUME(GetMoveType(MOVE_THUNDERBOLT) == TYPE_ELECTRIC);
ASSUME(GetMoveType(MOVE_RAZOR_LEAF) != TYPE_ELECTRIC);
ASSUME(GetMoveType(MOVE_METAL_CLAW) != TYPE_ELECTRIC);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
PLAYER(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); Moves(MOVE_CELEBRATE); }
PLAYER(SPECIES_KRABBY) { Ability(ABILITY_VOLT_ABSORB); Moves(MOVE_CELEBRATE); }
OPPONENT(SPECIES_MAGNETON) { Moves(MOVE_THUNDERBOLT, MOVE_RAZOR_LEAF); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_THUNDERBOLT, MOVE_METAL_CLAW); }
} WHEN {
TURN {
NOT_EXPECT_MOVE(opponentLeft, MOVE_THUNDERBOLT);
NOT_EXPECT_MOVE(opponentRight, MOVE_THUNDERBOLT); }
}
}
AI_SINGLE_BATTLE_TEST("AI will not set up Weather if it wont have any affect")
{
u32 ability;
@ -934,4 +964,3 @@ AI_SINGLE_BATTLE_TEST("AI will not set up Weather if it wont have any affect")
TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_RAIN_DANCE); }
}
}