check bad move

This commit is contained in:
Evan 2020-12-13 15:02:21 -07:00
parent 28698a982d
commit ac332d5e98
15 changed files with 4408 additions and 1148 deletions

View File

@ -22,6 +22,7 @@ gBattleAI_ScriptsTable:: @ 82DBEF8
.4byte AI_DoubleBattle @ AI_SCRIPT_DOUBLE_BATTLE
.4byte AI_HPAware @ AI_SCRIPT_HP_AWARE
AI_TryToFaint:
AI_CheckBadMove:
if_target_is_ally AI_Ret
@ -3402,36 +3403,7 @@ AI_CV_DragonDance2:
AI_CV_DragonDance_End:
end
AI_TryToFaint:
if_target_is_ally AI_Ret
if_can_faint AI_TryToFaint_Can
get_how_powerful_move_is
if_equal MOVE_POWER_DISCOURAGED, Score_Minus1
AI_TryToFaint2:
if_type_effectiveness AI_EFFECTIVENESS_x4, AI_TryToFaint_DoubleSuperEffective
goto AI_TryToFaint_CheckIfDanger
AI_TryToFaint_DoubleSuperEffective:
if_random_less_than 80, AI_TryToFaint_CheckIfDanger
score +2
goto AI_TryToFaint_CheckIfDanger
AI_TryToFaint_Can:
if_effect EFFECT_EXPLOSION, AI_TryToFaint_CheckIfDanger
if_user_faster AI_TryToFaint_ScoreUp4
if_move_flag FLAG_HIGH_CRIT, AI_TryToFaint_ScoreUp4
score +2
goto AI_TryToFaint_CheckIfDanger
AI_TryToFaint_ScoreUp4:
score +4
AI_TryToFaint_CheckIfDanger:
if_user_faster AI_TryToFaint_End
if_ai_can_go_down AI_TryToFaint_Danger
AI_TryToFaint_End:
end
AI_TryToFaint_Danger:
get_how_powerful_move_is
if_not_equal MOVE_POWER_BEST, Score_Minus1
score +1
goto AI_TryToFaint_End
AI_SetupFirstTurn:
if_target_is_ally AI_Ret

View File

@ -5,6 +5,8 @@
#define AI_CHECK_FASTER 0 // if_user_faster
#define AI_CHECK_SLOWER 1 // if_target_faster
#define FOE(battler) ((battler ^ BIT_SIDE) & BIT_SIDE)
void RecordLastUsedMoveByTarget(void);
bool32 IsBattlerAIControlled(u32 battlerId);
void ClearBattlerMoveHistory(u8 battlerId);
@ -20,11 +22,73 @@ void RestoreBattlerData(u8 battlerId);
u32 GetHealthPercentage(u8 battler);
bool32 IsBattlerTrapped(u8 battler, bool8 switching);
bool32 IsBattlerFaster(u8 battler);
bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk);
s32 AI_GetAbility(u32 battlerId);
u16 AI_GetHoldEffect(u32 battlerId);
u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u8 atkHoldEffect, u8 defHoldEffect, u16 move);
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move);
bool32 AI_WeatherHasEffect(void);
bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index);
s32 CountUsablePartyMons(u8 battlerId);
bool32 IsPartyFullyHealedExceptBattler(u8 battler);
bool32 AI_IsBattlerGrounded(u8 battlerId);
bool32 BattlerHasDamagingMove(u8 battlerId);
bool32 BattlerHasSecondaryDamage(u8 battlerId);
bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability);
bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u32 accuracy, u16 move);
bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveIndex);
u16 GetBattlerSideSpeedAverage(u8 battler);
// stat stage checks
bool32 AnyStatIsRaised(u8 battlerId);
bool32 BattlerStatCanFall(u8 battler, u16 battlerAbility, u8 stat);
bool32 BattlerStatCanRise(u8 battler, u16 battlerAbility, u8 stat);
bool32 AreBattlersStatsMaxed(u8 battler);
bool32 BattlerHasAnyStatRaised(u8 battlerId);
u32 CountPositiveStatStages(u8 battlerId);
u32 CountNegativeStatStages(u8 battlerId);
bool32 BattlerShouldRaiseAttacks(u8 battlerId, u16 ability);
// move checks
u8 GetMovePowerResult(u16 move);
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef);
u8 GetMoveEffectiveness(u16 move);
bool32 IsBattlerFaster(u8 battler);
bool32 CanTargetFaintAi(void);
s32 AI_GetAbility(u32 battlerId, bool32 guess);
u8 AI_GetMoveEffectiveness(u16 move);
u16 *GetMovesArray(u32 battler);
bool32 IsConfusionMoveEffect(u16 moveEffect);
bool32 HasMoveWithSplit(u32 battler, u32 split);
bool32 HasMoveWithType(u32 battler, u8 type);
bool32 TestMoveFlagsInMoveset(u8 battler, u32 flags);
bool32 IsAromaVeilProtectedMove(u16 move);
bool32 IsNonVolatileStatusMoveEffect(u16 moveEffect);
bool32 IsStatLoweringMoveEffect(u16 moveEffect);
bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility);
bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move);
bool32 IsHazardMoveEffect(u16 moveEffect);
bool32 MoveCallsOtherMove(u16 move);
bool32 MoveRequiresRecharging(u16 move);
bool32 IsInstructBannedMove(u16 move);
// status checks
bool32 AI_ShouldPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AI_ShouldPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof);
bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGender, u8 defGender);
// partner logic
u16 GetAllyChosenMove(void);
bool32 IsValidDoubleBattle(u8 battlerAtk);
bool32 IsTargetingPartner(u8 battlerAtk, u8 battlerDef);
bool32 DoesPartnerHaveSameMoveEffect(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove);
bool32 PartnerHasSameMoveEffectWithoutTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 PartnerMoveEffectIsStatusSameTarget(u8 battlerAtkPartner, u8 battlerDef, u16 partnerMove);
bool32 PartnerMoveEffectIsWeather(u8 battlerAtkPartner, u16 partnerMove);
bool32 PartnerMoveEffectIsTerrain(u8 battlerAtkPartner, u16 partnerMove);
bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck);
bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove);
bool32 PartnerMoveIsSameNoTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove);
#endif //GUARD_BATTLE_AI_UTIL_H

View File

@ -6,6 +6,12 @@
#define WINDOW_CLEAR 0x1
#define WINDOW_x80 0x80
struct StatFractions
{
u8 dividend;
u8 divisor;
};
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility);
u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move);
u8 GetBattlerTurnOrderNum(u8 battlerId);
@ -26,8 +32,11 @@ u32 IsFlowerVeilProtected(u32 battler);
u32 IsLeafGuardProtected(u32 battler);
bool32 IsShieldsDownProtected(u32 battler);
u32 IsAbilityStatusProtected(u32 battler);
bool32 CanCamouflage(u8 battlerId);
u16 GetNaturePowerMove(void);
extern void (* const gBattleScriptingCommandsTable[])(void);
extern const u8 gBattlePalaceNatureToMoveGroupLikelihood[NUM_NATURES][4];
extern const struct StatFractions gAccuracyStageRatios[];
#endif // GUARD_BATTLE_SCRIPT_COMMANDS_H

View File

@ -130,5 +130,19 @@ void ClearIllusionMon(u32 battlerId);
bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId);
bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId);
u8 GetBattleMoveSplit(u32 moveId);
bool32 TestMoveFlags(u16 move, u32 flag);
struct Pokemon *GetBattlerPartyData(u8 battlerId);
bool32 CanFling(u8 battlerId);
bool32 IsTelekinesisBannedSpecies(u16 species);
bool32 IsHealBlockPreventingMove(u32 battler, u32 move);
// ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
bool32 IsRolePlayBannedAbility(u16 ability);
bool32 IsSkillSwapBannedAbility(u16 ability);
bool32 IsWorrySeedBannedAbility(u16 ability);
bool32 IsGastroAcidBannedAbility(u16 ability);
bool32 IsEntrainmentBannedAbilityAttacker(u16 ability);
bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -220,6 +220,8 @@
#define SIDE_STATUS_CRAFTY_SHIELD (1 << 20)
#define SIDE_STATUS_MAT_BLOCK (1 << 21)
#define SIDE_HAZARDS_ANY (SIDE_STATUS_SPIKES | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES | SIDE_STATUS_STEALTH_ROCK)
// Field affecting statuses.
#define STATUS_FIELD_MAGIC_ROOM 0x1
#define STATUS_FIELD_TRICK_ROOM 0x2

View File

@ -35,20 +35,24 @@
#define MOVE_POWER_GOOD 2 // Similar dmg range with best.
#define MOVE_POWER_WEAK 3 // Significantly lower than best and good.
// script's table id to bit
#define AI_SCRIPT_CHECK_BAD_MOVE (1 << 0)
#define AI_SCRIPT_TRY_TO_FAINT (1 << 1)
#define AI_SCRIPT_CHECK_VIABILITY (1 << 2)
#define AI_SCRIPT_SETUP_FIRST_TURN (1 << 3)
#define AI_SCRIPT_RISKY (1 << 4)
#define AI_SCRIPT_PREFER_STRONGEST_MOVE (1 << 5)
#define AI_SCRIPT_PREFER_BATON_PASS (1 << 6)
#define AI_SCRIPT_DOUBLE_BATTLE (1 << 7)
#define AI_SCRIPT_HP_AWARE (1 << 8)
#define AI_SCRIPT_UNKNOWN (1 << 9)
// 10 - 28 are not used
#define AI_SCRIPT_ROAMING (1 << 29)
#define AI_SCRIPT_SAFARI (1 << 30)
#define AI_SCRIPT_FIRST_BATTLE (1 << 31)
// AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts
#define AI_FLAG_CHECK_BAD_MOVE (1 << 0)
#define AI_FLAG_TRY_TO_FAINT (1 << 1)
#define AI_FLAG_CHECK_VIABILITY (1 << 2)
#define AI_FLAG_SETUP_FIRST_TURN (1 << 3)
#define AI_FLAG_RISKY (1 << 4)
#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5)
#define AI_FLAG_PREFER_BATON_PASS (1 << 6)
#define AI_FLAG_DOUBLE_BATTLE (1 << 7)
#define AI_FLAG_HP_AWARE (1 << 8)
// Flags that don't run specific checks themselves, but are used in other score functions
#define AI_FLAG_NEGATE_AWARE (1 << 9) // AI is aware of negating effects like wonder room, mold breaker, etc (eg. smart trainers). TODO unfinished
#define AI_FLAG_HELP_PARTNER (1 << 10) // AI can try to help partner. If not set, will tend not to target partner
#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc
// 'other' ai logic flags
#define AI_FLAG_ROAMING (1 << 29)
#define AI_FLAG_SAFARI (1 << 30)
#define AI_FLAG_FIRST_BATTLE (1 << 31)
#endif // GUARD_CONSTANTS_BATTLE_AI_H

View File

@ -123,6 +123,7 @@
// Item settings
#define B_HP_BERRIES GEN_6 // In Gen4+, berries which restore hp activate immediately after hp drops to half. In gen3, the effect occurs at the end of the turn.
#define B_BERRIES_INSTANT GEN_6 // In Gen4+, most berries activate on battle start/switch-in if applicable. In gen3, they only activate either at the move end or turn end.
#define B_MENTAL_HERB GEN_5 // In Gen5+, mental herb cures Taunt, Encore, Heal Block, and Disable
// Flag settings.
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag for toggling the feature.

View File

@ -136,6 +136,14 @@
#define HOLD_EFFECT_MEMORY 153
#define HOLD_EFFECT_PLATE 154
// Gen8 hold effects
#define HOLD_EFFECT_UTILITY_UMBRELLA 155
#define HOLD_EFFECT_EJECT_PACK 156
#define HOLD_EFFECT_ROOM_SERVICE 157
#define HOLD_EFFECT_BLUNDER_POLICY 158
#define HOLD_EFFECT_HEAVY_DUTY_BOOTS 159
#define HOLD_EFFECT_THROAT_SPRAY 160
#define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS))
#endif // GUARD_HOLD_EFFECTS_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -850,13 +850,13 @@ u32 GetAiScriptsInBattleFactory(void)
int challengeNum = gSaveBlock2Ptr->frontier.factoryWinStreaks[battleMode][lvlMode] / 7;
if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN)
return AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_TRY_TO_FAINT | AI_SCRIPT_CHECK_VIABILITY;
return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY;
else if (challengeNum < 2)
return 0;
else if (challengeNum < 4)
return AI_SCRIPT_CHECK_BAD_MOVE;
return AI_FLAG_CHECK_BAD_MOVE;
else
return AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_TRY_TO_FAINT | AI_SCRIPT_CHECK_VIABILITY;
return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY;
}
}

View File

@ -813,13 +813,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_metalburstdamagecalculator, // 0xFF
};
struct StatFractions
{
u8 dividend;
u8 divisor;
};
static const struct StatFractions sAccuracyStageRatios[] =
const struct StatFractions gAccuracyStageRatios[] =
{
{ 33, 100}, // -6
{ 36, 100}, // -5
@ -1536,8 +1530,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move)
if (defAbility == ABILITY_WONDER_SKIN && gBattleMoves[move].power == 0)
moveAcc = 50;
calc = sAccuracyStageRatios[buff].dividend * moveAcc;
calc /= sAccuracyStageRatios[buff].divisor;
calc = gAccuracyStageRatios[buff].dividend * moveAcc;
calc /= gAccuracyStageRatios[buff].divisor;
if (atkAbility == ABILITY_COMPOUND_EYES)
calc = (calc * 130) / 100; // 1.3 compound eyes boost
@ -7646,51 +7640,25 @@ static void Cmd_various(void)
gBattlescriptCurrInstr += 7;
return;
case VARIOUS_SET_SIMPLE_BEAM:
switch (gBattleMons[gActiveBattler].ability)
if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gActiveBattler].ability))
{
case ABILITY_SIMPLE:
case ABILITY_TRUANT:
case ABILITY_STANCE_CHANGE:
case ABILITY_DISGUISE:
case ABILITY_MULTITYPE:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
break;
default:
}
else
{
gBattleMons[gActiveBattler].ability = ABILITY_SIMPLE;
gBattlescriptCurrInstr += 7;
break;
}
return;
case VARIOUS_TRY_ENTRAINMENT:
switch (gBattleMons[gBattlerTarget].ability)
if (IsEntrainmentBannedAbilityAttacker(gBattleMons[gBattlerAttacker].ability)
|| IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gBattlerTarget].ability))
{
case ABILITY_TRUANT:
case ABILITY_MULTITYPE:
case ABILITY_STANCE_CHANGE:
case ABILITY_SCHOOLING:
case ABILITY_COMATOSE:
case ABILITY_SHIELDS_DOWN:
case ABILITY_DISGUISE:
case ABILITY_RKS_SYSTEM:
case ABILITY_BATTLE_BOND:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
return;
}
switch (gBattleMons[gBattlerAttacker].ability)
{
case ABILITY_TRACE:
case ABILITY_FORECAST:
case ABILITY_FLOWER_GIFT:
case ABILITY_ZEN_MODE:
case ABILITY_ILLUSION:
case ABILITY_IMPOSTER:
case ABILITY_POWER_OF_ALCHEMY:
case ABILITY_RECEIVER:
case ABILITY_DISGUISE:
case ABILITY_POWER_CONSTRUCT:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
return;
}
if (gBattleMons[gBattlerTarget].ability == gBattleMons[gBattlerAttacker].ability)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
@ -10945,6 +10913,12 @@ static void Cmd_callterrainattack(void) // nature power
gBattlescriptCurrInstr++;
}
u16 GetNaturePowerMove(void)
{
//TODO terrain
return sNaturePowerMoves[gBattleTerrain];
}
static void Cmd_cureifburnedparalysedorpoisoned(void) // refresh
{
if (gBattleMons[gBattlerAttacker].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON))
@ -11111,18 +11085,20 @@ static void Cmd_tryswapitems(void) // trick
static void Cmd_trycopyability(void) // role play
{
switch (gBattleMons[gBattlerTarget].ability)
u16 defAbility = gBattleMons[gBattlerTarget].ability;
if (gBattleMons[gBattlerAttacker].ability == defAbility
|| defAbility == ABILITY_NONE
|| IsRolePlayBannedAbilityAtk(gBattleMons[gBattlerAttacker].ability)
|| IsRolePlayBannedAbility(defAbility))
{
case ABILITY_NONE:
case ABILITY_WONDER_GUARD:
case ABILITY_DISGUISE:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
break;
default:
gBattleMons[gBattlerAttacker].ability = gBattleMons[gBattlerTarget].ability;
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
gBattlescriptCurrInstr += 5;
break;
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
else
{
gBattleMons[gBattlerAttacker].ability = defAbility;
gLastUsedAbility = defAbility;
gBattlescriptCurrInstr += 5;
}
}
@ -11176,23 +11152,14 @@ static void Cmd_settoxicspikes(void)
static void Cmd_setgastroacid(void)
{
switch (gBattleMons[gBattlerTarget].ability)
if (IsGastroAcidBannedAbility(gBattleMons[gBattlerTarget].ability))
{
case ABILITY_MULTITYPE:
case ABILITY_STANCE_CHANGE:
case ABILITY_SCHOOLING:
case ABILITY_COMATOSE:
case ABILITY_SHIELDS_DOWN:
case ABILITY_DISGUISE:
case ABILITY_RKS_SYSTEM:
case ABILITY_BATTLE_BOND:
case ABILITY_POWER_CONSTRUCT:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
break;
default:
}
else
{
gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID;
gBattlescriptCurrInstr += 5;
break;
}
}
@ -11261,24 +11228,13 @@ static void Cmd_setroom(void)
static void Cmd_tryswapabilities(void) // skill swap
{
switch (gBattleMons[gBattlerAttacker].ability)
if (IsSkillSwapBannedAbility(gBattleMons[gBattlerAttacker].ability)
|| IsSkillSwapBannedAbility(gBattleMons[gBattlerTarget].ability))
{
case ABILITY_NONE:
case ABILITY_WONDER_GUARD:
case ABILITY_DISGUISE:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
return;
}
switch (gBattleMons[gBattlerTarget].ability)
{
case ABILITY_NONE:
case ABILITY_WONDER_GUARD:
case ABILITY_DISGUISE:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
return;
}
if (gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
@ -11751,6 +11707,13 @@ static void Cmd_tryrecycleitem(void)
}
}
bool32 CanCamouflage(u8 battlerId)
{
if (IS_BATTLER_OF_TYPE(battlerId, sTerrainToType[gBattleTerrain]))
return FALSE;
return TRUE;
}
static void Cmd_settypetoterrain(void)
{
if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, sTerrainToType[gBattleTerrain]))
@ -12271,11 +12234,36 @@ static void Cmd_trainerslideout(void)
gBattlescriptCurrInstr += 2;
}
static const u16 sTelekinesisBanList[] =
{
SPECIES_DIGLETT,
SPECIES_DUGTRIO,
#ifdef POKEMON_EXPANSION
SPECIES_DIGLETT_ALOLAN,
SPECIES_DUGTRIO_ALOLAN,
SPECIES_SANDYGAST,
SPECIES_PALOSSAND,
SPECIES_GENGAR_MEGA,
#endif
};
bool32 IsTelekinesisBannedSpecies(u16 species)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sTelekinesisBanList); i++)
{
if (species == sTelekinesisBanList[i])
return TRUE;
}
return FALSE;
}
static void Cmd_settelekinesis(void)
{
if (gStatuses3[gBattlerTarget] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN)
|| gFieldStatuses & STATUS_FIELD_GRAVITY
|| (gBattleMons[gBattlerTarget].species == SPECIES_DIGLETT || gBattleMons[gBattlerTarget].species == SPECIES_DUGTRIO))
|| IsTelekinesisBannedSpecies(gBattleMons[gBattlerTarget].species))
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
@ -12343,19 +12331,14 @@ static void Cmd_trygetbaddreamstarget(void)
static void Cmd_tryworryseed(void)
{
switch (gBattleMons[gBattlerTarget].ability)
if (IsWorrySeedBannedAbility(gBattleMons[gBattlerTarget].ability))
{
case ABILITY_INSOMNIA:
case ABILITY_MULTITYPE:
case ABILITY_TRUANT:
case ABILITY_STANCE_CHANGE:
case ABILITY_DISGUISE:
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
break;
default:
}
else
{
gBattleMons[gBattlerTarget].ability = ABILITY_INSOMNIA;
gBattlescriptCurrInstr += 5;
break;
}
}

View File

@ -63,6 +63,131 @@ static const u8 sPkblToEscapeFactor[][3] = {{0, 0, 0}, {3, 5, 0}, {2, 3, 0}, {1,
static const u8 sGoNearCounterToCatchFactor[] = {4, 3, 2, 1};
static const u8 sGoNearCounterToEscapeFactor[] = {4, 4, 4, 4};
static const u16 sSkillSwapBannedAbilities[] =
{
ABILITY_WONDER_GUARD,
ABILITY_MULTITYPE,
ABILITY_ILLUSION,
ABILITY_STANCE_CHANGE,
ABILITY_SCHOOLING,
ABILITY_COMATOSE,
ABILITY_SHIELDS_DOWN,
ABILITY_DISGUISE,
ABILITY_RKS_SYSTEM,
ABILITY_BATTLE_BOND,
ABILITY_POWER_CONSTRUCT,
ABILITY_NEUTRALIZING_GAS,
ABILITY_ICE_FACE,
ABILITY_HUNGER_SWITCH,
ABILITY_GULP_MISSILE,
};
static const u16 sRolePlayBannedAbilities[] =
{
ABILITY_TRACE,
ABILITY_WONDER_GUARD,
ABILITY_FORECAST,
ABILITY_FLOWER_GIFT,
ABILITY_MULTITYPE,
ABILITY_ILLUSION,
ABILITY_ZEN_MODE,
ABILITY_IMPOSTER,
ABILITY_STANCE_CHANGE,
ABILITY_POWER_OF_ALCHEMY,
ABILITY_RECEIVER,
ABILITY_SCHOOLING,
ABILITY_COMATOSE,
ABILITY_SHIELDS_DOWN,
ABILITY_DISGUISE,
ABILITY_RKS_SYSTEM,
ABILITY_BATTLE_BOND,
ABILITY_POWER_CONSTRUCT,
ABILITY_ICE_FACE,
ABILITY_HUNGER_SWITCH,
ABILITY_GULP_MISSILE,
};
static const u16 sRolePlayBannedAttackerAbilities[] =
{
ABILITY_MULTITYPE,
ABILITY_ZEN_MODE,
ABILITY_STANCE_CHANGE,
ABILITY_SCHOOLING,
ABILITY_COMATOSE,
ABILITY_SHIELDS_DOWN,
ABILITY_DISGUISE,
ABILITY_RKS_SYSTEM,
ABILITY_BATTLE_BOND,
ABILITY_POWER_CONSTRUCT,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
};
static const u16 sWorrySeedBannedAbilities[] =
{
ABILITY_MULTITYPE,
ABILITY_STANCE_CHANGE,
ABILITY_SCHOOLING,
ABILITY_COMATOSE,
ABILITY_SHIELDS_DOWN,
ABILITY_DISGUISE,
ABILITY_RKS_SYSTEM,
ABILITY_BATTLE_BOND,
ABILITY_POWER_CONSTRUCT,
ABILITY_TRUANT,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
};
static const u16 sGastroAcidBannedAbilities[] =
{
ABILITY_MULTITYPE,
ABILITY_STANCE_CHANGE,
ABILITY_SCHOOLING,
ABILITY_COMATOSE,
ABILITY_SHIELDS_DOWN,
ABILITY_DISGUISE,
ABILITY_RKS_SYSTEM,
ABILITY_BATTLE_BOND,
ABILITY_POWER_CONSTRUCT,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
};
static const u16 sEntrainmentBannedAttackerAbilities[] =
{
ABILITY_TRACE,
ABILITY_FORECAST,
ABILITY_FLOWER_GIFT,
ABILITY_ZEN_MODE,
ABILITY_ILLUSION,
ABILITY_IMPOSTER,
ABILITY_POWER_OF_ALCHEMY,
ABILITY_RECEIVER,
ABILITY_DISGUISE,
ABILITY_POWER_CONSTRUCT,
ABILITY_NEUTRALIZING_GAS,
ABILITY_ICE_FACE,
ABILITY_HUNGER_SWITCH,
ABILITY_GULP_MISSILE,
};
static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
{
ABILITY_TRUANT,
ABILITY_MULTITYPE,
ABILITY_STANCE_CHANGE,
ABILITY_SCHOOLING,
ABILITY_COMATOSE,
ABILITY_SHIELDS_DOWN,
ABILITY_DISGUISE,
ABILITY_RKS_SYSTEM,
ABILITY_BATTLE_BOND,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
};
// Functions
void HandleAction_UseMove(void)
{
u32 i, side, moveType, var = 4;
@ -1325,11 +1450,11 @@ static bool32 IsGravityPreventingMove(u32 move)
}
}
static bool32 IsHealBlockPreventingMove(u32 battler, u32 move)
bool32 IsHealBlockPreventingMove(u32 battler, u32 move)
{
if (!(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
return FALSE;
switch (gBattleMoves[move].effect)
{
case EFFECT_ABSORB:
@ -5339,10 +5464,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
u8 ppBonuses;
u16 move;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
else
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
mon = GetBattlerPartyData(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
move = GetMonData(mon, MON_DATA_MOVE1 + i);
@ -7830,3 +7952,123 @@ u8 GetBattleMoveSplit(u32 moveId)
else
return SPLIT_SPECIAL;
}
bool32 TestMoveFlags(u16 move, u32 flag)
{
if (gBattleMoves[move].flags & flag)
return TRUE;
return FALSE;
}
struct Pokemon *GetBattlerPartyData(u8 battlerId)
{
struct Pokemon *mon;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
else
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
return mon;
}
//Make sure the input bank is any bank on the specific mon's side
bool32 CanFling(u8 battlerId)
{
u16 item = gBattleMons[battlerId].item;
u16 itemEffect = ItemId_GetHoldEffect(item);
if (item == ITEM_NONE
|| GetBattlerAbility(battlerId) == ABILITY_KLUTZ
|| gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
|| gDisableStructs[battlerId].embargoTimer != 0
|| !CanBattlerGetOrLoseItem(battlerId, item)
//|| itemEffect == HOLD_EFFECT_PRIMAL_ORB
|| itemEffect == HOLD_EFFECT_GEMS
#ifdef ITEM_ABILITY_CAPSULE
|| item == ITEM_ABILITY_CAPSULE
#endif
|| (ItemId_GetPocket(item) == POCKET_BERRIES && IsAbilityOnSide(battlerId, ABILITY_UNNERVE))
|| GetPocketByItemId(item) == POCKET_POKE_BALLS)
return FALSE;
return TRUE;
}
// ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sRolePlayBannedAttackerAbilities); i++)
{
if (ability == sRolePlayBannedAttackerAbilities[i])
return TRUE;
}
return FALSE;
}
bool32 IsRolePlayBannedAbility(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sRolePlayBannedAbilities); i++)
{
if (ability == sRolePlayBannedAbilities[i])
return TRUE;
}
return FALSE;
}
bool32 IsSkillSwapBannedAbility(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sSkillSwapBannedAbilities); i++)
{
if (ability == sSkillSwapBannedAbilities[i])
return TRUE;
}
return FALSE;
}
bool32 IsWorrySeedBannedAbility(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sWorrySeedBannedAbilities); i++)
{
if (ability == sWorrySeedBannedAbilities[i])
return TRUE;
}
return FALSE;
}
bool32 IsGastroAcidBannedAbility(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sGastroAcidBannedAbilities); i++)
{
if (ability == sGastroAcidBannedAbilities[i])
return TRUE;
}
return FALSE;
}
bool32 IsEntrainmentBannedAbilityAttacker(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sEntrainmentBannedAttackerAbilities); i++)
{
if (ability == sEntrainmentBannedAttackerAbilities[i])
return TRUE;
}
return FALSE;
}
bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sEntrainmentTargetSimpleBeamBannedAbilities); i++)
{
if (ability == sEntrainmentTargetSimpleBeamBannedAbilities[i])
return TRUE;
}
return FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@ -897,7 +897,7 @@ void FillHillTrainersParties(void)
// hill trainers.
u32 GetTrainerHillAIFlags(void)
{
return (AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_TRY_TO_FAINT | AI_SCRIPT_CHECK_VIABILITY);
return (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY);
}
u8 GetTrainerEncounterMusicIdInTrainerHill(u16 trainerId)