Review fixes
Added more move effect considerations to AI; redid way it calculates secondaryEffectChance; misc fixes
This commit is contained in:
parent
417a02c95e
commit
7c38056da7
@ -64,9 +64,6 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
|
||||
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u32 move);
|
||||
u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move);
|
||||
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove);
|
||||
u32 AI_CalcSecondaryEffectChance(u32 battler, u32 secondaryEffectChance);
|
||||
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
|
||||
u32 AI_ShouldSetUpHazards(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef);
|
||||
|
||||
// stat stage checks
|
||||
bool32 AnyStatIsRaised(u32 battlerId);
|
||||
@ -104,6 +101,7 @@ bool32 HasOnlyMovesWithCategory(u32 battlerId, u32 category, bool32 onlyOffensiv
|
||||
bool32 HasMoveWithCategory(u32 battler, u32 category);
|
||||
bool32 HasMoveWithType(u32 battler, u32 type);
|
||||
bool32 HasMoveEffect(u32 battlerId, u32 moveEffect);
|
||||
bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument);
|
||||
bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect, u32 effectHitOnly);
|
||||
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
|
||||
bool32 IsAromaVeilProtectedMove(u32 move);
|
||||
|
||||
@ -48,7 +48,6 @@ u32 IsAbilityStatusProtected(u32 battler);
|
||||
bool32 TryResetBattlerStatChanges(u8 battler);
|
||||
bool32 CanCamouflage(u8 battlerId);
|
||||
u16 GetNaturePowerMove(void);
|
||||
u16 GetSecretPowerMoveEffect(void);
|
||||
void StealTargetItem(u8 battlerStealer, u8 battlerItem);
|
||||
u8 GetCatchingBattler(void);
|
||||
u32 GetHighestStatId(u32 battlerId);
|
||||
|
||||
@ -221,7 +221,6 @@ void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon);
|
||||
void RecalcBattlerStats(u32 battler, struct Pokemon *mon);
|
||||
bool32 IsAlly(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 IsGen6ExpShareEnabled(void);
|
||||
bool32 MoveEffectIsGuaranteed(u32 secondaryEffectChance);
|
||||
bool32 MoveHasMoveEffect(u32 move, u32 moveEffect, bool32 effectHitOnly);
|
||||
bool32 MoveHasMoveEffectWithChance(u32 move, u32 moveEffect, u32 chance);
|
||||
bool32 MoveHasMoveEffectSelf(u32 move, u32 moveEffect);
|
||||
@ -252,7 +251,8 @@ void RemoveConfusionStatus(u32 battler);
|
||||
u8 GetBattlerGender(u32 battler);
|
||||
bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2);
|
||||
bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2);
|
||||
u32 CalcSecondaryEffectChance(u32 battler, const struct AdditionalEffect *additionalEffect);
|
||||
u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect);
|
||||
bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect);
|
||||
u8 GetBattlerType(u32 battler, u8 typeIndex);
|
||||
bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon);
|
||||
bool8 IsMonBannedFromSkyBattles(u16 species);
|
||||
|
||||
@ -192,7 +192,7 @@
|
||||
#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8.
|
||||
#define B_FOG_TERRAIN TRUE // If TRUE, overworld Fog generates Misty Terrain as in Gen 8.
|
||||
#define B_TERRAIN_TYPE_BOOST GEN_LATEST // In Gen8, damage is boosted by 30% instead of 50%.
|
||||
#define B_SECRET_POWER_EFFECT GEN_LATEST // Secret Power's effects change depending on terrain and generation. See GetSecretPowerMoveEffect.
|
||||
#define B_SECRET_POWER_EFFECT GEN_LATEST // Secret Power's effects change depending on terrain and generation. See MOVE_EFFECT_SECRET_POWER.
|
||||
#define B_SECRET_POWER_ANIMATION GEN_LATEST // Secret Power's animations change depending on terrain and generation.
|
||||
#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves.
|
||||
#define B_CAMOUFLAGE_TYPES GEN_LATEST // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType.
|
||||
|
||||
@ -50,6 +50,10 @@ static s32 AI_Roaming(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_Safari(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
|
||||
static bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
|
||||
static s32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
|
||||
|
||||
|
||||
static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
|
||||
{
|
||||
@ -2665,6 +2669,51 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
return score;
|
||||
}
|
||||
|
||||
static s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle)
|
||||
{
|
||||
if (isDoubleBattle)
|
||||
return min(CountPositiveStatStages(battlerDef) + CountPositiveStatStages(BATTLE_PARTNER(battlerDef)), 7);
|
||||
else
|
||||
return min(CountPositiveStatStages(battlerDef), 4);
|
||||
}
|
||||
|
||||
static bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
u8 i;
|
||||
// Want to copy positive stat changes
|
||||
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
|
||||
{
|
||||
if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i])
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case STAT_ATK:
|
||||
return (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_PHYSICAL));
|
||||
case STAT_SPATK:
|
||||
return (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_SPECIAL));
|
||||
case STAT_ACC:
|
||||
case STAT_EVASION:
|
||||
case STAT_SPEED:
|
||||
return TRUE;
|
||||
case STAT_DEF:
|
||||
case STAT_SPDEF:
|
||||
return (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//TODO - track entire opponent party data to determine hazard effectiveness
|
||||
static s32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData)
|
||||
{
|
||||
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
|
||||
return 0;
|
||||
|
||||
return 2 * gDisableStructs[battlerAtk].isFirstTurn;
|
||||
}
|
||||
|
||||
// double battle logic
|
||||
static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
{
|
||||
@ -3487,13 +3536,15 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
ADJUST_SCORE(-3);
|
||||
break;
|
||||
}
|
||||
score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle);
|
||||
break;
|
||||
case EFFECT_ROAR:
|
||||
if (aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF || aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS)
|
||||
if ((gBattleMoves[move].soundMove && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) || aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS)
|
||||
{
|
||||
ADJUST_SCORE(-3);
|
||||
break;
|
||||
}
|
||||
score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE);
|
||||
break;
|
||||
case EFFECT_MULTI_HIT:
|
||||
case EFFECT_TRIPLE_KICK:
|
||||
@ -3840,7 +3891,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
case EFFECT_STEALTH_ROCK:
|
||||
case EFFECT_STICKY_WEB:
|
||||
case EFFECT_TOXIC_SPIKES:
|
||||
score += AI_ShouldSetUpHazards(aiData, battlerAtk, battlerDef);
|
||||
score += AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData);
|
||||
break;
|
||||
case EFFECT_FORESIGHT:
|
||||
if (aiData->abilities[battlerAtk] == ABILITY_SCRAPPY || aiData->abilities[battlerAtk] == ABILITY_MINDS_EYE)
|
||||
@ -4672,7 +4723,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
|
||||
{
|
||||
// Only consider effects with a guaranteed chance to happen
|
||||
if (!MoveEffectIsGuaranteed(AI_CalcSecondaryEffectChance(battlerAtk, gBattleMoves[move].additionalEffects[i].chance)))
|
||||
if (!MoveEffectIsGuaranteed(battlerAtk, aiData->abilities[battlerAtk], &gBattleMoves[move].additionalEffects[i]))
|
||||
continue;
|
||||
|
||||
// Consider move effects that target self
|
||||
@ -4689,6 +4740,8 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
case MOVE_EFFECT_DEF_PLUS_1:
|
||||
case MOVE_EFFECT_SP_ATK_PLUS_1:
|
||||
case MOVE_EFFECT_SP_DEF_PLUS_1:
|
||||
case MOVE_EFFECT_ACC_PLUS_1:
|
||||
case MOVE_EFFECT_EVS_PLUS_1:
|
||||
IncreaseStatUpScore(
|
||||
battlerAtk,
|
||||
battlerDef,
|
||||
@ -4696,7 +4749,25 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
&score
|
||||
);
|
||||
break;
|
||||
case MOVE_EFFECT_ATK_PLUS_2:
|
||||
case MOVE_EFFECT_DEF_PLUS_2:
|
||||
case MOVE_EFFECT_SP_ATK_PLUS_2:
|
||||
case MOVE_EFFECT_SP_DEF_PLUS_2:
|
||||
case MOVE_EFFECT_ACC_PLUS_2:
|
||||
case MOVE_EFFECT_EVS_PLUS_2:
|
||||
IncreaseStatUpScore(
|
||||
battlerAtk,
|
||||
battlerDef,
|
||||
STAT_ATK + gBattleMoves[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_2,
|
||||
&score
|
||||
);
|
||||
break;
|
||||
// Effects that lower stat(s) - only need to consider Contrary
|
||||
case MOVE_EFFECT_ATK_MINUS_1:
|
||||
case MOVE_EFFECT_DEF_MINUS_1:
|
||||
case MOVE_EFFECT_SPD_MINUS_1:
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_1:
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_1:
|
||||
case MOVE_EFFECT_V_CREATE:
|
||||
case MOVE_EFFECT_DEF_SPDEF_DOWN:
|
||||
case MOVE_EFFECT_ATK_DEF_DOWN:
|
||||
@ -4714,6 +4785,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move);
|
||||
break;
|
||||
case MOVE_EFFECT_SPD_MINUS_1:
|
||||
case MOVE_EFFECT_SPD_MINUS_2:
|
||||
if (!ShouldLowerSpeed(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
|
||||
break;
|
||||
case MOVE_EFFECT_ATK_MINUS_1:
|
||||
@ -4725,11 +4797,20 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
if (aiData->abilities[battlerDef] != ABILITY_CONTRARY)
|
||||
ADJUST_SCORE(2);
|
||||
break;
|
||||
case MOVE_EFFECT_ATK_MINUS_2:
|
||||
case MOVE_EFFECT_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_2:
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_ACC_MINUS_2:
|
||||
case MOVE_EFFECT_EVS_MINUS_2:
|
||||
if (aiData->abilities[battlerDef] != ABILITY_CONTRARY)
|
||||
ADJUST_SCORE(3);
|
||||
break;
|
||||
case MOVE_EFFECT_POISON:
|
||||
IncreasePoisonScore(battlerAtk, battlerDef, move, &score);
|
||||
break;
|
||||
case MOVE_EFFECT_CLEAR_SMOG:
|
||||
score += min(CountPositiveStatStages(battlerDef), 4);
|
||||
score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE);
|
||||
break;
|
||||
case MOVE_EFFECT_SPECTRAL_THIEF:
|
||||
score += AI_ShouldCopyStatChanges(battlerAtk, battlerDef);
|
||||
@ -4822,7 +4903,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
break;
|
||||
case MOVE_EFFECT_STEALTH_ROCK:
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
score += AI_ShouldSetUpHazards(aiData, battlerAtk, battlerDef);
|
||||
score += AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData);
|
||||
break;
|
||||
case MOVE_EFFECT_FEINT:
|
||||
if (gBattleMoves[predictedMove].effect == EFFECT_PROTECT)
|
||||
|
||||
@ -845,7 +845,6 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3
|
||||
u32 abilityDef = AI_DATA->abilities[battlerDef];
|
||||
u32 abilityAtk = AI_DATA->abilities[battlerAtk];
|
||||
|
||||
|
||||
switch (gBattleMoves[move].effect)
|
||||
{
|
||||
case EFFECT_HIT_ESCAPE:
|
||||
@ -1968,6 +1967,22 @@ bool32 HasMoveEffect(u32 battlerId, u32 effect)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument)
|
||||
{
|
||||
s32 i;
|
||||
u16 *moves = GetMovesArray(battlerId);
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE
|
||||
&& gBattleMoves[moves[i]].effect == effect
|
||||
&& (gBattleMoves[moves[i]].argument & argument))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect, u32 effectHitOnly)
|
||||
{
|
||||
s32 i;
|
||||
@ -3667,8 +3682,7 @@ void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT))
|
||||
ADJUST_SCORE_PTR(1); // stall tactic
|
||||
|
||||
if ((HasMoveEffect(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_PSN_ANY)
|
||||
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PSN_ANY)
|
||||
|| HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH)
|
||||
|| AI_DATA->abilities[battlerAtk] == ABILITY_MERCILESS)
|
||||
ADJUST_SCORE_PTR(2);
|
||||
@ -3692,10 +3706,8 @@ void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
ADJUST_SCORE_PTR(2); // burning the target to stay alive is cool
|
||||
}
|
||||
|
||||
if ((HasMoveEffect(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_BURN)
|
||||
|| (HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_BURN))
|
||||
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN)
|
||||
|| HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN))
|
||||
ADJUST_SCORE_PTR(1);
|
||||
}
|
||||
}
|
||||
@ -3712,8 +3724,7 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
u32 defSpeed = AI_DATA->speedStats[battlerDef];
|
||||
|
||||
if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe
|
||||
|| (HasMoveEffect(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_PARALYSIS)
|
||||
|| HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PARALYSIS)
|
||||
|| HasMoveWithMoveEffect(battlerAtk, MOVE_EFFECT_FLINCH, TRUE) // filter out Fake Out
|
||||
|| gBattleMons[battlerDef].status2 & STATUS2_INFATUATION
|
||||
|| gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
|
||||
@ -3738,10 +3749,8 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
&& !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK)))
|
||||
ADJUST_SCORE_PTR(1);
|
||||
|
||||
if ((HasMoveEffect(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_SLEEP)
|
||||
|| (HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_SLEEP))
|
||||
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP)
|
||||
|| HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP))
|
||||
ADJUST_SCORE_PTR(1);
|
||||
}
|
||||
|
||||
@ -3778,10 +3787,8 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score
|
||||
ADJUST_SCORE_PTR(2); // frostbiting the target to stay alive is cool
|
||||
}
|
||||
|
||||
if ((HasMoveEffect(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_FROSTBITE)
|
||||
|| (HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS)
|
||||
&& gBattleMoves[move].argument & STATUS1_FROSTBITE))
|
||||
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE)
|
||||
|| HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE))
|
||||
ADJUST_SCORE_PTR(1);
|
||||
}
|
||||
}
|
||||
@ -3830,49 +3837,4 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
bool32 AI_IsBattlerAsleepOrComatose(u32 battlerId)
|
||||
{
|
||||
return (gBattleMons[battlerId].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerId] == ABILITY_COMATOSE;
|
||||
}
|
||||
|
||||
u32 AI_CalcSecondaryEffectChance(u32 battler, u32 secondaryEffectChance)
|
||||
{
|
||||
if (AI_DATA->abilities[battler] == ABILITY_SERENE_GRACE)
|
||||
secondaryEffectChance *= 2;
|
||||
|
||||
return secondaryEffectChance;
|
||||
}
|
||||
|
||||
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
u8 i;
|
||||
// Want to copy positive stat changes
|
||||
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
|
||||
{
|
||||
if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i])
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case STAT_ATK:
|
||||
return (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_PHYSICAL));
|
||||
case STAT_SPATK:
|
||||
return (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_SPECIAL));
|
||||
case STAT_ACC:
|
||||
case STAT_EVASION:
|
||||
case STAT_SPEED:
|
||||
return TRUE;
|
||||
case STAT_DEF:
|
||||
case STAT_SPDEF:
|
||||
return (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//TODO - track entire opponent party data to determine hazard effectiveness
|
||||
u32 AI_ShouldSetUpHazards(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
|
||||
return 0;
|
||||
|
||||
return 2 * gDisableStructs[battlerAtk].isFirstTurn;
|
||||
}
|
||||
}
|
||||
@ -976,7 +976,6 @@ static const u16 sFinalStrikeOnlyEffects[] =
|
||||
MOVE_EFFECT_STEAL_ITEM,
|
||||
MOVE_EFFECT_BURN_UP,
|
||||
MOVE_EFFECT_DOUBLE_SHOCK,
|
||||
MOVE_EFFECT_SECRET_POWER,
|
||||
MOVE_EFFECT_SMACK_DOWN,
|
||||
MOVE_EFFECT_REMOVE_STATUS,
|
||||
MOVE_EFFECT_RECOIL_HP_25,
|
||||
@ -3696,7 +3695,86 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SECRET_POWER:
|
||||
gBattleScripting.moveEffect = GetSecretPowerMoveEffect();
|
||||
if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
|
||||
{
|
||||
switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
|
||||
{
|
||||
case STATUS_FIELD_MISTY_TERRAIN:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1;
|
||||
break;
|
||||
case STATUS_FIELD_GRASSY_TERRAIN:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP;
|
||||
break;
|
||||
case STATUS_FIELD_ELECTRIC_TERRAIN:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
|
||||
break;
|
||||
case STATUS_FIELD_PSYCHIC_TERRAIN:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1;
|
||||
break;
|
||||
default:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gBattleTerrain)
|
||||
{
|
||||
case BATTLE_TERRAIN_GRASS:
|
||||
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON);
|
||||
break;
|
||||
case BATTLE_TERRAIN_UNDERWATER:
|
||||
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1);
|
||||
break;
|
||||
case BATTLE_TERRAIN_POND:
|
||||
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1);
|
||||
break;
|
||||
case BATTLE_TERRAIN_MOUNTAIN:
|
||||
if (B_SECRET_POWER_EFFECT >= GEN_5)
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1;
|
||||
else if (B_SECRET_POWER_EFFECT >= GEN_4)
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
|
||||
else
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION;
|
||||
break;
|
||||
case BATTLE_TERRAIN_PUDDLE:
|
||||
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1);
|
||||
break;
|
||||
case BATTLE_TERRAIN_LONG_GRASS:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP;
|
||||
break;
|
||||
case BATTLE_TERRAIN_SAND:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1;
|
||||
break;
|
||||
case BATTLE_TERRAIN_WATER:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1;
|
||||
break;
|
||||
case BATTLE_TERRAIN_CAVE:
|
||||
case BATTLE_TERRAIN_BURIAL_GROUND:
|
||||
case BATTLE_TERRAIN_SPACE:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
|
||||
break;
|
||||
case BATTLE_TERRAIN_SOARING:
|
||||
case BATTLE_TERRAIN_SKY_PILLAR:
|
||||
case BATTLE_TERRAIN_MARSH:
|
||||
case BATTLE_TERRAIN_SWAMP:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1;
|
||||
break;
|
||||
case BATTLE_TERRAIN_SNOW:
|
||||
case BATTLE_TERRAIN_ICE:
|
||||
gBattleScripting.moveEffect = (B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE);
|
||||
break;
|
||||
case BATTLE_TERRAIN_VOLCANO:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_BURN;
|
||||
break;
|
||||
case BATTLE_TERRAIN_ULTRA_SPACE:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_1;
|
||||
break;
|
||||
default:
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetMoveEffect(FALSE, 0);
|
||||
break;
|
||||
}
|
||||
@ -3735,6 +3813,7 @@ static void Cmd_seteffectwithchance(void)
|
||||
{
|
||||
u32 percentChance = CalcSecondaryEffectChance(
|
||||
gBattlerAttacker,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
&gBattleMoves[gCurrentMove].additionalEffects[gBattleStruct->additionalEffectsCounter]
|
||||
);
|
||||
|
||||
@ -14352,93 +14431,6 @@ static void Cmd_unused0xe4(void)
|
||||
{
|
||||
}
|
||||
|
||||
u16 GetSecretPowerMoveEffect(void)
|
||||
{
|
||||
u16 moveEffect;
|
||||
u32 fieldTerrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY;
|
||||
if (fieldTerrain)
|
||||
{
|
||||
switch (fieldTerrain)
|
||||
{
|
||||
case STATUS_FIELD_MISTY_TERRAIN:
|
||||
moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1;
|
||||
break;
|
||||
case STATUS_FIELD_GRASSY_TERRAIN:
|
||||
moveEffect = MOVE_EFFECT_SLEEP;
|
||||
break;
|
||||
case STATUS_FIELD_ELECTRIC_TERRAIN:
|
||||
moveEffect = MOVE_EFFECT_PARALYSIS;
|
||||
break;
|
||||
case STATUS_FIELD_PSYCHIC_TERRAIN:
|
||||
moveEffect = MOVE_EFFECT_SPD_MINUS_1;
|
||||
break;
|
||||
default:
|
||||
moveEffect = MOVE_EFFECT_PARALYSIS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gBattleTerrain)
|
||||
{
|
||||
case BATTLE_TERRAIN_GRASS:
|
||||
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON);
|
||||
break;
|
||||
case BATTLE_TERRAIN_UNDERWATER:
|
||||
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1);
|
||||
break;
|
||||
case BATTLE_TERRAIN_POND:
|
||||
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1);
|
||||
break;
|
||||
case BATTLE_TERRAIN_MOUNTAIN:
|
||||
if (B_SECRET_POWER_EFFECT >= GEN_5)
|
||||
moveEffect = MOVE_EFFECT_ACC_MINUS_1;
|
||||
else if (B_SECRET_POWER_EFFECT >= GEN_4)
|
||||
moveEffect = MOVE_EFFECT_FLINCH;
|
||||
else
|
||||
moveEffect = MOVE_EFFECT_CONFUSION;
|
||||
break;
|
||||
case BATTLE_TERRAIN_PUDDLE:
|
||||
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1);
|
||||
break;
|
||||
case BATTLE_TERRAIN_LONG_GRASS:
|
||||
moveEffect = MOVE_EFFECT_SLEEP;
|
||||
break;
|
||||
case BATTLE_TERRAIN_SAND:
|
||||
moveEffect = MOVE_EFFECT_ACC_MINUS_1;
|
||||
break;
|
||||
case BATTLE_TERRAIN_WATER:
|
||||
moveEffect = MOVE_EFFECT_ATK_MINUS_1;
|
||||
break;
|
||||
case BATTLE_TERRAIN_CAVE:
|
||||
case BATTLE_TERRAIN_BURIAL_GROUND:
|
||||
case BATTLE_TERRAIN_SPACE:
|
||||
moveEffect = MOVE_EFFECT_FLINCH;
|
||||
break;
|
||||
case BATTLE_TERRAIN_SOARING:
|
||||
case BATTLE_TERRAIN_SKY_PILLAR:
|
||||
case BATTLE_TERRAIN_MARSH:
|
||||
case BATTLE_TERRAIN_SWAMP:
|
||||
moveEffect = MOVE_EFFECT_SPD_MINUS_1;
|
||||
break;
|
||||
case BATTLE_TERRAIN_SNOW:
|
||||
case BATTLE_TERRAIN_ICE:
|
||||
moveEffect = (B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE);
|
||||
break;
|
||||
case BATTLE_TERRAIN_VOLCANO:
|
||||
moveEffect = MOVE_EFFECT_BURN;
|
||||
break;
|
||||
case BATTLE_TERRAIN_ULTRA_SPACE:
|
||||
moveEffect = MOVE_EFFECT_DEF_MINUS_1;
|
||||
break;
|
||||
default:
|
||||
moveEffect = MOVE_EFFECT_PARALYSIS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return moveEffect;
|
||||
}
|
||||
|
||||
static void Cmd_pickup(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
|
||||
@ -11381,9 +11381,9 @@ bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2)
|
||||
return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 == gender2);
|
||||
}
|
||||
|
||||
u32 CalcSecondaryEffectChance(u32 battler, const struct AdditionalEffect *additionalEffect)
|
||||
u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect)
|
||||
{
|
||||
bool8 hasSereneGrace = (GetBattlerAbility(battler) == ABILITY_SERENE_GRACE);
|
||||
bool8 hasSereneGrace = (battlerAbility == ABILITY_SERENE_GRACE);
|
||||
bool8 hasRainbow = (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_RAINBOW) != 0;
|
||||
u16 secondaryEffectChance = additionalEffect->chance;
|
||||
|
||||
@ -11398,6 +11398,11 @@ u32 CalcSecondaryEffectChance(u32 battler, const struct AdditionalEffect *additi
|
||||
return secondaryEffectChance;
|
||||
}
|
||||
|
||||
bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect)
|
||||
{
|
||||
return additionalEffect->chance == 0 || CalcSecondaryEffectChance(battler, battlerAbility, additionalEffect) >= 100;
|
||||
}
|
||||
|
||||
bool32 IsAlly(u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
return (GetBattlerSide(battlerAtk) == GetBattlerSide(battlerDef));
|
||||
@ -11412,11 +11417,6 @@ bool32 IsGen6ExpShareEnabled(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool32 MoveEffectIsGuaranteed(u32 secondaryEffectChance)
|
||||
{
|
||||
return secondaryEffectChance == 0 || secondaryEffectChance >= 100;
|
||||
}
|
||||
|
||||
bool32 MoveHasMoveEffect(u32 move, u32 moveEffect, bool32 effectHitOnly)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user