Merge pull request #1810 from BuffelSaft/ai_improvements

AI: Multi-strike moves, variable power moves, sleep check
This commit is contained in:
ghoulslash 2021-11-04 12:28:00 -04:00 committed by GitHub
commit 0ac6860855
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 24 deletions

View File

@ -161,7 +161,7 @@ void TryToApplyMimicry(u8 battlerId, bool8 various);
void TryToRevertMimicry(void); void TryToRevertMimicry(void);
void RestoreBattlerOriginalTypes(u8 battlerId); void RestoreBattlerOriginalTypes(u8 battlerId);
// ability checks // Ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbilityAtk(u16 ability);
bool32 IsRolePlayBannedAbility(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability);
bool32 IsSkillSwapBannedAbility(u16 ability); bool32 IsSkillSwapBannedAbility(u16 ability);

View File

@ -308,6 +308,7 @@
#define FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING (1 << 24) // Makes a Ground type move do 1x damage to flying and levitating targets #define FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING (1 << 24) // Makes a Ground type move do 1x damage to flying and levitating targets
#define FLAG_THAW_USER (1 << 25) #define FLAG_THAW_USER (1 << 25)
#define FLAG_HIT_IN_SUBSTITUTE (1 << 26) // Hyperspace Fury #define FLAG_HIT_IN_SUBSTITUTE (1 << 26) // Hyperspace Fury
#define FLAG_TWO_STRIKES (1 << 27) // A move with this flag will strike twice, and may apply its effect on each hit
// Split defines. // Split defines.
#define SPLIT_PHYSICAL 0x0 #define SPLIT_PHYSICAL 0x0

View File

@ -733,28 +733,45 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
else else
dmg = (critDmg + normalDmg * (critChance - 1)) / critChance; dmg = (critDmg + normalDmg * (critChance - 1)) / critChance;
// handle dynamic move damage // Handle dynamic move damage
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
{ {
case EFFECT_LEVEL_DAMAGE: case EFFECT_LEVEL_DAMAGE:
case EFFECT_PSYWAVE: case EFFECT_PSYWAVE:
//psywave's expected damage is equal to the user's level dmg = gBattleMons[battlerAtk].level * (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND ? 2 : 1);
dmg = gBattleMons[battlerAtk].level;
break; break;
case EFFECT_DRAGON_RAGE: case EFFECT_DRAGON_RAGE:
dmg = 40; dmg = 40 * (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND ? 2 : 1);
break; break;
case EFFECT_SONICBOOM: case EFFECT_SONICBOOM:
dmg = 20; dmg = 20 * (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND ? 2 : 1);
break; break;
//case EFFECT_METAL_BURST: case EFFECT_MULTI_HIT:
//case EFFECT_COUNTER: dmg *= (AI_DATA->atkAbility == ABILITY_SKILL_LINK ? 5 : 3);
default: break;
//do not add the random factor, it's an average case analysis case EFFECT_TRIPLE_KICK:
//dmg *= (100 - (Random() % 10)) / 100; // add random factor dmg *= (AI_DATA->atkAbility == ABILITY_SKILL_LINK ? 6 : 5);
break;
case EFFECT_ENDEAVOR:
// If target has less HP than user, Endeavor does no damage
dmg = max(0, gBattleMons[battlerDef].hp - gBattleMons[battlerAtk].hp);
break;
case EFFECT_SUPER_FANG:
dmg = (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND
? max(2, gBattleMons[battlerDef].hp * 3 / 4)
: max(1, gBattleMons[battlerDef].hp / 2));
break;
case EFFECT_FINAL_GAMBIT:
dmg = gBattleMons[battlerAtk].hp;
break; break;
} }
// Handle other multi-strike moves
if (gBattleMoves[move].flags & FLAG_TWO_STRIKES)
dmg *= 2;
else if (move == MOVE_SURGING_STRIKES || (move == MOVE_WATER_SHURIKEN && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_ASH))
dmg *= 3;
RestoreBattlerData(battlerAtk); RestoreBattlerData(battlerAtk);
RestoreBattlerData(battlerDef); RestoreBattlerData(battlerDef);
@ -2606,7 +2623,6 @@ bool32 AI_CanSleep(u8 battler, u16 ability)
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove) bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{ {
if (!AI_CanSleep(battlerDef, defAbility) if (!AI_CanSleep(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep || PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep
return FALSE; return FALSE;
@ -2654,7 +2670,7 @@ bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16
return TRUE; return TRUE;
} }
static bool32 CanBeParayzed(u8 battler, u16 ability) static bool32 AI_CanBeParalyzed(u8 battler, u16 ability)
{ {
if (ability == ABILITY_LIMBER if (ability == ABILITY_LIMBER
|| IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC) || IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC)
@ -2666,7 +2682,7 @@ static bool32 CanBeParayzed(u8 battler, u16 ability)
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove) bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{ {
if (!CanBeParayzed(battlerDef, defAbility) if (!AI_CanBeParalyzed(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD || gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)

View File

@ -378,7 +378,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -649,7 +649,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 20, .secondaryEffectChance = 20,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_SHEER_FORCE_BOOST, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -2460,7 +2460,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -7267,7 +7267,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -8367,7 +8367,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -8575,7 +8575,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -10726,9 +10726,9 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_DOUBLE_IRON_BASH] = [MOVE_DOUBLE_IRON_BASH] =
{ {
#if B_UPDATED_MOVE_DATA >= GEN_8 #if B_UPDATED_MOVE_DATA >= GEN_8
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST | FLAG_TWO_STRIKES,
#else #else
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_DMG_MINIMIZE | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_DMG_MINIMIZE | FLAG_IRON_FIST_BOOST | FLAG_SHEER_FORCE_BOOST | FLAG_TWO_STRIKES,
#endif #endif
.effect = EFFECT_DOUBLE_IRON_BASH, .effect = EFFECT_DOUBLE_IRON_BASH,
.power = 60, .power = 60,
@ -10850,7 +10850,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },
@ -11480,7 +11480,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0, .secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, .target = MOVE_TARGET_SELECTED,
.priority = 0, .priority = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TWO_STRIKES,
.split = SPLIT_PHYSICAL, .split = SPLIT_PHYSICAL,
}, },