Fixes AI not seeing primal weather and partner absorbing abilities (#6936)
This commit is contained in:
parent
f9400332fc
commit
87cbb457f1
@ -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)
|
||||
{
|
||||
|
||||
@ -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); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user