Z Status move handling: Conversion, Detect, Nature Power, Transform (#7721)
This commit is contained in:
parent
63d04947e4
commit
82ab4fe98d
@ -112,6 +112,7 @@
|
||||
|
||||
// HP thresholds to use a status z-move.
|
||||
#define Z_EFFECT_FOLLOW_ME_THRESHOLD 30
|
||||
#define Z_EFFECT_RESTORE_HP_THRESHOLD 60
|
||||
#define Z_EFFECT_RESTORE_HP_LOWER_THRESHOLD ENABLE_RECOVERY_THRESHOLD // threshold used for moves you could conceivably use more than once
|
||||
#define Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD 90 // these moves are one-time use or drop your HP
|
||||
|
||||
#endif // GUARD_CONFIG_AI_H
|
||||
|
||||
@ -1986,7 +1986,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY)
|
||||
ADJUST_SCORE(-10);
|
||||
else if (aiData->hpPercents[battlerAtk] <= 60 && (GetActiveGimmick(battlerAtk) != GIMMICK_Z_MOVE || GetMoveZEffect(move) == Z_EFFECT_NONE))
|
||||
else if (aiData->hpPercents[battlerAtk] <= 60 && !IsConsideringZMove(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_FUTURE_SIGHT:
|
||||
@ -4322,7 +4322,13 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
||||
break;
|
||||
case EFFECT_CONVERSION:
|
||||
if (!IS_BATTLER_OF_TYPE(battlerAtk, GetMoveType(gBattleMons[battlerAtk].moves[0])))
|
||||
{
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
if (aiData->abilities[battlerAtk] == ABILITY_ADAPTABILITY)
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
if (IsConsideringZMove(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
}
|
||||
break;
|
||||
case EFFECT_SWALLOW:
|
||||
if (gDisableStructs[battlerAtk].stockpileCounter == 0)
|
||||
|
||||
@ -4920,12 +4920,16 @@ bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move
|
||||
|
||||
bool32 IsConsideringZMove(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
{
|
||||
if (GetMovePower(move) == 0 && GetMoveZEffect(move) == Z_EFFECT_NONE)
|
||||
return FALSE;
|
||||
|
||||
return gBattleStruct->gimmick.usableGimmick[battlerAtk] == GIMMICK_Z_MOVE && ShouldUseZMove(battlerAtk, battlerDef, move);
|
||||
}
|
||||
|
||||
//TODO - this could use some more sophisticated logic
|
||||
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
{
|
||||
|
||||
// simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent
|
||||
if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk) && !(GetBattlerMoveTargetType(battlerAtk, chosenMove) & MOVE_TARGET_ALLY))
|
||||
return FALSE; // don't use z move on partner
|
||||
@ -4934,6 +4938,39 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
|
||||
if (IsViableZMove(battlerAtk, chosenMove))
|
||||
{
|
||||
enum BattleMoveEffects baseEffect = GetMoveEffect(chosenMove);
|
||||
bool32 isEager = FALSE; // more likely to use a z move than typical
|
||||
|
||||
u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData);
|
||||
bool32 isSlower = AI_IsSlower(battlerAtk, battlerDef, chosenMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY);
|
||||
|
||||
switch (baseEffect)
|
||||
{
|
||||
case EFFECT_BELLY_DRUM:
|
||||
case EFFECT_FILLET_AWAY:
|
||||
if (isSlower)
|
||||
return TRUE;
|
||||
isEager = TRUE;
|
||||
break;
|
||||
case EFFECT_PROTECT:
|
||||
if (HasDamagingMoveOfType(battlerAtk, GetMoveType(gMovesInfo[chosenMove].type)))
|
||||
return FALSE;
|
||||
else
|
||||
isEager = TRUE;
|
||||
break;
|
||||
case EFFECT_TELEPORT:
|
||||
isEager = TRUE;
|
||||
break;
|
||||
case EFFECT_TRANSFORM:
|
||||
if (IsBattlerTrapped(battlerDef, battlerAtk) && !HasDamagingMoveOfType(battlerDef, GetMoveType(gMovesInfo[chosenMove].type)))
|
||||
return TRUE;
|
||||
if (isSlower)
|
||||
isEager = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
u32 zMove = GetUsableZMove(battlerAtk, chosenMove);
|
||||
|
||||
if (IsBattleMoveStatus(chosenMove))
|
||||
@ -4952,7 +4989,9 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
switch (zEffect)
|
||||
{
|
||||
case Z_EFFECT_NONE:
|
||||
return FALSE;
|
||||
if (GetMovePower(chosenMove) == 0)
|
||||
return FALSE;
|
||||
break;
|
||||
case Z_EFFECT_RESET_STATS:
|
||||
if (CountNegativeStatStages(battlerAtk) > 1)
|
||||
return TRUE;
|
||||
@ -4965,7 +5004,11 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
return HasPartnerIgnoreFlags(battlerAtk) && (GetHealthPercentage(battlerAtk) <= Z_EFFECT_FOLLOW_ME_THRESHOLD || GetBestNoOfHitsToKO(battlerDef, battlerAtk, AI_DEFENDING) == 1);
|
||||
break;
|
||||
case Z_EFFECT_RECOVER_HP:
|
||||
return gAiLogicData->hpPercents[battlerAtk] <= Z_EFFECT_RESTORE_HP_THRESHOLD;
|
||||
if (GetBestNoOfHitsToKO(battlerDef, battlerAtk, AI_DEFENDING) == 1 && GetHealthPercentage(battlerAtk) > Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD)
|
||||
return TRUE;
|
||||
if (isEager)
|
||||
return GetHealthPercentage(battlerAtk) <= Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD;
|
||||
return GetHealthPercentage(battlerAtk) <= Z_EFFECT_RESTORE_HP_LOWER_THRESHOLD;
|
||||
case Z_EFFECT_RESTORE_REPLACEMENT_HP:
|
||||
break;
|
||||
case Z_EFFECT_ACC_UP_1:
|
||||
@ -5003,8 +5046,9 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (statChange != 0 && IncreaseStatUpScore(battlerAtk, battlerDef, statChange) > 0)
|
||||
if (statChange != 0 && (isEager || IncreaseStatUpScore(battlerAtk, battlerDef, statChange) > 0))
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
else if (GetMoveEffect(zMove) == EFFECT_EXTREME_EVOBOOST)
|
||||
{
|
||||
|
||||
@ -32,37 +32,6 @@ AI_SINGLE_BATTLE_TEST("AI does not use damaging Z-moves if the player would fain
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_QUICK_ATTACK, gimmick: GIMMICK_NONE); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Splash")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT );
|
||||
ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_POUND, MOVE_SPLASH); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_SPLASH, gimmick: GIMMICK_Z_MOVE);
|
||||
SCORE_GT_VAL(opponent, MOVE_SPLASH, AI_SCORE_DEFAULT); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE);
|
||||
SCORE_EQ_VAL(opponent, MOVE_SPLASH, 90); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Happy Hour")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT );
|
||||
ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_POUND, MOVE_HAPPY_HOUR); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_HAPPY_HOUR, gimmick: GIMMICK_Z_MOVE);
|
||||
SCORE_GT_VAL(opponent, MOVE_HAPPY_HOUR, AI_SCORE_DEFAULT); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE);
|
||||
SCORE_EQ_VAL(opponent, MOVE_HAPPY_HOUR, 90); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Extreme Evoboost")
|
||||
{
|
||||
GIVEN {
|
||||
@ -88,6 +57,25 @@ AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- 10,000,000 Volt Thunderbolt")
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_THUNDERBOLT, gimmick: GIMMICK_Z_MOVE); }
|
||||
}
|
||||
}
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Conversion")
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_NONE; }
|
||||
PARAMETRIZE { ability = ABILITY_OPPORTUNIST; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT );
|
||||
ASSUME(GetMoveType(MOVE_CONVERSION) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Ability(ABILITY_ADAPTABILITY); Moves(MOVE_THUNDERBOLT, MOVE_CONVERSION); }
|
||||
} WHEN {
|
||||
if (ability == ABILITY_OPPORTUNIST)
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_CONVERSION, gimmick: GIMMICK_NONE); }
|
||||
else
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_CONVERSION, gimmick: GIMMICK_Z_MOVE); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Destiny Bond is not used in singles")
|
||||
{
|
||||
@ -120,3 +108,94 @@ AI_DOUBLE_BATTLE_TEST("AI uses Z-Moves -- Z-Destiny Bond is used when about to d
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Detect")
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_THUNDERBOLT; }
|
||||
PARAMETRIZE { move = MOVE_CLOSE_COMBAT; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE );
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_FAKE_OUT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FIGHTINIUM_Z); Moves(MOVE_DETECT, move); }
|
||||
} WHEN {
|
||||
if (move == MOVE_CLOSE_COMBAT)
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_DETECT, gimmick: GIMMICK_NONE); }
|
||||
else
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_DETECT, gimmick: GIMMICK_Z_MOVE); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Happy Hour")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT );
|
||||
ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_POUND, MOVE_HAPPY_HOUR); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_HAPPY_HOUR, gimmick: GIMMICK_Z_MOVE);
|
||||
SCORE_GT_VAL(opponent, MOVE_HAPPY_HOUR, AI_SCORE_DEFAULT); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE);
|
||||
SCORE_EQ_VAL(opponent, MOVE_HAPPY_HOUR, 90); }
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Haze")
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Mirror Move")
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Nature Power")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_NATURE_POWER, MOVE_HEADBUTT); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_NATURE_POWER, gimmick: GIMMICK_Z_MOVE); }
|
||||
}
|
||||
}
|
||||
|
||||
// Requires handling for Wish passing/Healing Wish/other ways to determine what pokemon to heal via switching into.
|
||||
TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Parting Shot")
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Splash")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT );
|
||||
ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Moves(MOVE_POUND, MOVE_SPLASH); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_SPLASH, gimmick: GIMMICK_Z_MOVE);
|
||||
SCORE_GT_VAL(opponent, MOVE_SPLASH, AI_SCORE_DEFAULT); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_POUND, gimmick: GIMMICK_NONE);
|
||||
SCORE_EQ_VAL(opponent, MOVE_SPLASH, 90); }
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Tailwind")
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves -- Z-Transform")
|
||||
{
|
||||
u32 currentHP, move;
|
||||
PARAMETRIZE { currentHP = 1; move = MOVE_HEADBUTT; }
|
||||
PARAMETRIZE { currentHP = 1; move = MOVE_THUNDERBOLT; }
|
||||
PARAMETRIZE { currentHP = 500; move = MOVE_HEADBUTT; }
|
||||
PARAMETRIZE { currentHP = 500; move = MOVE_THUNDERBOLT; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT );
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(move, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(currentHP); Item(ITEM_NORMALIUM_Z); Moves(MOVE_TRANSFORM); }
|
||||
} WHEN {
|
||||
if (currentHP == 1 || move == MOVE_THUNDERBOLT)
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_TRANSFORM, gimmick: GIMMICK_Z_MOVE); }
|
||||
else
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_TRANSFORM, gimmick: GIMMICK_NONE); }
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: AI uses Z-Moves -- Z-Trick Room")
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user