AI handles multi-strike and fixed dmg moves

Does not account for Parental Bond or Beat Up yet as those require some functions from #1676.
This commit is contained in:
BuffelSaft 2021-10-24 18:49:17 +13:00
parent bbe2eccf62
commit 4310868bee
3 changed files with 113 additions and 8 deletions

View File

@ -156,7 +156,7 @@ void BufferStatChange(u8 battlerId, u8 statId, u8 stringId);
void DoBurmyFormChange(u32 monId);
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget);
// ability checks
// Ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
bool32 IsRolePlayBannedAbility(u16 ability);
bool32 IsSkillSwapBannedAbility(u16 ability);
@ -173,4 +173,7 @@ bool32 CanBeFrozen(u8 battlerId);
bool32 CanBeConfused(u8 battlerId);
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag);
// Move checks
bool8 IsTwoStrikesMove(u16 move);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -733,20 +733,85 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
else
dmg = (critDmg + normalDmg * (critChance - 1)) / critChance;
// handle dynamic move damage
// Handle dynamic move damage
switch (gBattleMoves[move].effect)
{
case EFFECT_LEVEL_DAMAGE:
case EFFECT_PSYWAVE:
//psywave's expected damage is equal to the user's level
dmg = gBattleMons[battlerAtk].level;
{
// Psywave's expected damage is equal to the user's level
if (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0)
dmg = 0;
else if (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND)
dmg = 2 * gBattleMons[battlerAtk].level;
else
dmg = gBattleMons[battlerAtk].level;
break;
}
case EFFECT_DRAGON_RAGE:
dmg = 40;
{
if (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0)
dmg = 0;
else if (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND)
dmg = 80;
else
dmg = 40;
break;
}
case EFFECT_SONICBOOM:
dmg = 20;
{
if (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0)
dmg = 0;
else if (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND)
dmg = 40;
else
dmg = 20;
break;
}
case EFFECT_MULTI_HIT:
{
if (AI_DATA->atkAbility == ABILITY_SKILL_LINK)
dmg *= 5;
else
dmg *= 3; // Average number of hits is three
break;
}
case EFFECT_TRIPLE_KICK:
{
if (AI_DATA->atkAbility == ABILITY_SKILL_LINK)
dmg *= 6; // Skill Link ensures the 2nd and 3rd hits will connect if the first does
else
dmg *= 5; // Triple Kick/Triple Axel's average power is almost 5x its base power
break;
}
case EFFECT_ENDEAVOR:
{
if (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0)
dmg = 0;
else
// 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:
{
if (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0)
dmg = 0;
// Two hits of Super Fang halves HP twice, leaving target with 25% HP
else if (AI_DATA->atkAbility == ABILITY_PARENTAL_BOND)
dmg = gBattleMons[battlerDef].hp * 3 / 4;
else
dmg = gBattleMons[battlerDef].hp / 2;
break;
}
case EFFECT_FINAL_GAMBIT:
{
if (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0)
dmg = 0;
else
dmg = gBattleMons[battlerAtk].hp;
break;
}
//case EFFECT_METAL_BURST:
//case EFFECT_COUNTER:
default:
@ -755,6 +820,17 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
break;
}
// Handle other multi-strike moves
if (IsTwoStrikesMove(move))
{
dmg *= 2;
}
else if (move == MOVE_SURGING_STRIKES
|| (move == MOVE_WATER_SHURIKEN && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_ASH))
{
dmg *= 3;
}
RestoreBattlerData(battlerAtk);
RestoreBattlerData(battlerDef);
@ -2653,7 +2729,7 @@ bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16
return TRUE;
}
static bool32 CanBeParalyzed(u8 battler, u16 ability)
static bool32 AI_CanBeParalyzed(u8 battler, u16 ability)
{
if (ability == ABILITY_LIMBER
|| IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC)
@ -2665,7 +2741,7 @@ static bool32 CanBeParalyzed(u8 battler, u16 ability)
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{
if (!CanBeParalyzed(battlerDef, defAbility)
if (!AI_CanBeParalyzed(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)

View File

@ -217,6 +217,20 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
ABILITY_GULP_MISSILE,
};
static const u16 sTwoStrikeMoves[] =
{
MOVE_BONEMERANG,
MOVE_DOUBLE_HIT,
MOVE_DOUBLE_IRON_BASH,
MOVE_DOUBLE_KICK,
MOVE_DRAGON_DARTS,
MOVE_DUAL_CHOP,
MOVE_DUAL_WINGBEAT,
MOVE_GEAR_GRIND,
MOVE_TWINEEDLE,
0xFFFF
};
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
{
u32 ability = GetBattlerAbility(battlerAtk);
@ -9509,3 +9523,15 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 chec
#endif
return FALSE;
}
bool8 IsTwoStrikesMove(u16 move)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sTwoStrikeMoves); i++)
{
if (move == sTwoStrikeMoves[i])
return TRUE;
}
return FALSE;
}