Add even more type checking (#8972)

This commit is contained in:
Bassoonian 2026-01-21 12:56:13 +01:00 committed by GitHub
parent da62ebcffd
commit 61f8a50751
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 205 additions and 185 deletions

View File

@ -265,7 +265,7 @@ bool32 DoesAbilityRaiseStatsWhenLowered(enum Ability ability);
bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability);
bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, enum Move move, struct AiLogicData *aiData);
void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, enum Move move, s32 *score, struct AiLogicData *aiData);
s32 BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData);
enum AIScore BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData);
// partner logic
bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef);

View File

@ -1,8 +1,6 @@
#ifndef GUARD_BATTLE_Z_MOVE_H
#define GUARD_BATTLE_Z_MOVE_H
#include "constants/battle_z_move_effects.h"
#define MOVE_Z_STATUS 0xFFFF
struct SignatureZMove

View File

@ -1,38 +1,40 @@
#ifndef GUARD_Z_MOVE_EFFECTS_H
#define GUARD_Z_MOVE_EFFECTS_H
#define Z_EFFECT_NONE 0
#define Z_EFFECT_RESET_STATS 1
#define Z_EFFECT_ALL_STATS_UP_1 2
#define Z_EFFECT_BOOST_CRITS 3
#define Z_EFFECT_FOLLOW_ME 4
#define Z_EFFECT_CURSE 5
#define Z_EFFECT_RECOVER_HP 6
#define Z_EFFECT_RESTORE_REPLACEMENT_HP 7
enum ZEffect
{
Z_EFFECT_NONE,
Z_EFFECT_RESET_STATS,
Z_EFFECT_ALL_STATS_UP_1,
Z_EFFECT_BOOST_CRITS,
Z_EFFECT_FOLLOW_ME,
Z_EFFECT_CURSE,
Z_EFFECT_RECOVER_HP,
Z_EFFECT_RESTORE_REPLACEMENT_HP,
#define Z_EFFECT_ATK_UP_1 8
#define Z_EFFECT_DEF_UP_1 9
#define Z_EFFECT_SPD_UP_1 10
#define Z_EFFECT_SPATK_UP_1 11
#define Z_EFFECT_SPDEF_UP_1 12
#define Z_EFFECT_ACC_UP_1 13
#define Z_EFFECT_EVSN_UP_1 14
Z_EFFECT_ATK_UP_1,
Z_EFFECT_DEF_UP_1,
Z_EFFECT_SPD_UP_1,
Z_EFFECT_SPATK_UP_1,
Z_EFFECT_SPDEF_UP_1,
Z_EFFECT_ACC_UP_1,
Z_EFFECT_EVSN_UP_1,
#define Z_EFFECT_ATK_UP_2 15
#define Z_EFFECT_DEF_UP_2 16
#define Z_EFFECT_SPD_UP_2 17
#define Z_EFFECT_SPATK_UP_2 18
#define Z_EFFECT_SPDEF_UP_2 19
#define Z_EFFECT_ACC_UP_2 20
#define Z_EFFECT_EVSN_UP_2 21
#define Z_EFFECT_ATK_UP_3 22
#define Z_EFFECT_DEF_UP_3 23
#define Z_EFFECT_SPD_UP_3 24
#define Z_EFFECT_SPATK_UP_3 25
#define Z_EFFECT_SPDEF_UP_3 26
#define Z_EFFECT_ACC_UP_3 27
#define Z_EFFECT_EVSN_UP_3 28
Z_EFFECT_ATK_UP_2,
Z_EFFECT_DEF_UP_2,
Z_EFFECT_SPD_UP_2,
Z_EFFECT_SPATK_UP_2,
Z_EFFECT_SPDEF_UP_2,
Z_EFFECT_ACC_UP_2,
Z_EFFECT_EVSN_UP_2,
Z_EFFECT_ATK_UP_3,
Z_EFFECT_DEF_UP_3,
Z_EFFECT_SPD_UP_3,
Z_EFFECT_SPATK_UP_3,
Z_EFFECT_SPDEF_UP_3,
Z_EFFECT_ACC_UP_3,
Z_EFFECT_EVSN_UP_3,
};
#endif // GUARD_Z_MOVE_EFFECTS_H

View File

@ -69,29 +69,32 @@
#define ITEM6_RESET_EV 0
// Used for GetItemEffectType.
#define ITEM_EFFECT_X_ITEM 0
#define ITEM_EFFECT_RAISE_LEVEL 1
#define ITEM_EFFECT_HEAL_HP 2
#define ITEM_EFFECT_CURE_POISON 3
#define ITEM_EFFECT_CURE_SLEEP 4
#define ITEM_EFFECT_CURE_BURN 5
#define ITEM_EFFECT_CURE_FREEZE_FROSTBITE 6
#define ITEM_EFFECT_CURE_PARALYSIS 7
#define ITEM_EFFECT_CURE_CONFUSION 8
#define ITEM_EFFECT_CURE_INFATUATION 9
#define ITEM_EFFECT_SACRED_ASH 10
#define ITEM_EFFECT_CURE_ALL_STATUS 11
#define ITEM_EFFECT_ATK_EV 12
#define ITEM_EFFECT_HP_EV 13
#define ITEM_EFFECT_SPATK_EV 14
#define ITEM_EFFECT_SPDEF_EV 15
#define ITEM_EFFECT_SPEED_EV 16
#define ITEM_EFFECT_DEF_EV 17
#define ITEM_EFFECT_EVO_STONE 18
#define ITEM_EFFECT_PP_UP 19
#define ITEM_EFFECT_PP_MAX 20
#define ITEM_EFFECT_HEAL_PP 21
#define ITEM_EFFECT_NONE 22
enum ItemEffectType
{
ITEM_EFFECT_X_ITEM,
ITEM_EFFECT_RAISE_LEVEL,
ITEM_EFFECT_HEAL_HP,
ITEM_EFFECT_CURE_POISON,
ITEM_EFFECT_CURE_SLEEP,
ITEM_EFFECT_CURE_BURN,
ITEM_EFFECT_CURE_FREEZE_FROSTBITE,
ITEM_EFFECT_CURE_PARALYSIS,
ITEM_EFFECT_CURE_CONFUSION,
ITEM_EFFECT_CURE_INFATUATION,
ITEM_EFFECT_SACRED_ASH,
ITEM_EFFECT_CURE_ALL_STATUS,
ITEM_EFFECT_ATK_EV,
ITEM_EFFECT_HP_EV,
ITEM_EFFECT_SPATK_EV,
ITEM_EFFECT_SPDEF_EV,
ITEM_EFFECT_SPEED_EV,
ITEM_EFFECT_DEF_EV,
ITEM_EFFECT_EVO_STONE,
ITEM_EFFECT_PP_UP,
ITEM_EFFECT_PP_MAX,
ITEM_EFFECT_HEAL_PP,
ITEM_EFFECT_NONE
};
#define ITEM_FRIENDSHIP_MAPSEC_BONUS 1 // The amount of bonus friendship gained when an item is used on a Pokémon whose met location matches the current map section.
#define ITEM_FRIENDSHIP_LUXURY_BONUS 1 // The amount of bonus friendship gained when a Pokémon is in the Luxury Ball.

View File

@ -1116,29 +1116,33 @@ enum __attribute__((packed)) Item
#define EXP_30000 5
// Item type IDs (used to determine the exit callback)
#define ITEM_USE_MAIL 0
#define ITEM_USE_PARTY_MENU 1
#define ITEM_USE_FIELD 2
#define ITEM_USE_PBLOCK_CASE 3
#define ITEM_USE_BAG_MENU 4 // No exit callback, stays in bag menu
#define ITEM_USE_PARTY_MENU_MOVES 5
#define ITEM_USE_BATTLER 6 // Auto-select in Singles but lets you choose from party menu in Doubles
enum ItemType
{
ITEM_USE_MAIL,
ITEM_USE_PARTY_MENU,
ITEM_USE_FIELD,
ITEM_USE_PBLOCK_CASE,
ITEM_USE_BAG_MENU, // No exit callback, stays in bag menu
ITEM_USE_PARTY_MENU_MOVES,
ITEM_USE_BATTLER, // Auto-select in Singles but lets you choose from party menu in Doubles
};
// Item battle script IDs (need to be non-zero)
#define EFFECT_ITEM_RESTORE_HP 1
#define EFFECT_ITEM_CURE_STATUS 2
#define EFFECT_ITEM_HEAL_AND_CURE_STATUS 3
#define EFFECT_ITEM_INCREASE_STAT 4
#define EFFECT_ITEM_SET_MIST 5
#define EFFECT_ITEM_SET_FOCUS_ENERGY 6
#define EFFECT_ITEM_ESCAPE 7
#define EFFECT_ITEM_THROW_BALL 8
#define EFFECT_ITEM_REVIVE 9
#define EFFECT_ITEM_RESTORE_PP 10
#define EFFECT_ITEM_INCREASE_ALL_STATS 11
#define EFFECT_ITEM_USE_POKE_FLUTE 12
// Enigma Berry dummy constant
#define EFFECT_ITEM_ENIGMA_BERRY_EREADER 1
enum EffectItem
{
EFFECT_ITEM_ENIGMA_BERRY_EREADER = 1, // dummy constant
EFFECT_ITEM_RESTORE_HP = 1, // needs to be non-zero
EFFECT_ITEM_CURE_STATUS,
EFFECT_ITEM_HEAL_AND_CURE_STATUS,
EFFECT_ITEM_INCREASE_STAT,
EFFECT_ITEM_SET_MIST,
EFFECT_ITEM_SET_FOCUS_ENERGY,
EFFECT_ITEM_ESCAPE,
EFFECT_ITEM_THROW_BALL,
EFFECT_ITEM_REVIVE,
EFFECT_ITEM_RESTORE_PP,
EFFECT_ITEM_INCREASE_ALL_STATS,
EFFECT_ITEM_USE_POKE_FLUTE,
};
#endif // GUARD_CONSTANTS_ITEMS_H

View File

@ -237,9 +237,9 @@ const u8 *GetItemDescription(enum Item itemId);
u8 GetItemImportance(enum Item itemId);
u8 GetItemConsumability(enum Item itemId);
enum Pocket GetItemPocket(enum Item itemId);
u8 GetItemType(enum Item itemId);
enum ItemType GetItemType(enum Item itemId);
ItemUseFunc GetItemFieldFunc(enum Item itemId);
u8 GetItemBattleUsage(enum Item itemId);
enum EffectItem GetItemBattleUsage(enum Item itemId);
u32 GetItemSecondaryId(enum Item itemId);
u32 GetItemFlingPower(enum Item itemId);
u32 GetItemStatus1Mask(enum Item itemId);

View File

@ -7,6 +7,7 @@
#include "constants/battle_factory.h"
#include "constants/battle_move_effects.h"
#include "constants/battle_string_ids.h"
#include "constants/battle_z_move_effects.h"
#include "constants/moves.h"
// For defining EFFECT_HIT etc. with battle TV scores and flags etc.
@ -267,7 +268,7 @@ static inline u32 GetMovePP(enum Move moveId)
return gMovesInfo[SanitizeMoveId(moveId)].pp;
}
static inline u32 GetMoveZEffect(enum Move moveId)
static inline enum ZEffect GetMoveZEffect(enum Move moveId)
{
moveId = SanitizeMoveId(moveId);
assertf(GetMoveCategory(moveId) == DAMAGE_CATEGORY_STATUS, "not a status move: %S", gMovesInfo[moveId].name);
@ -644,7 +645,7 @@ static inline u32 GetMoveTerrainBoost_GroundCheck(enum Move moveId)
return gMovesInfo[moveId].argument.terrainBoost.groundCheck;
}
static inline u32 GetMoveTerrainBoost_HitsBothFoes(enum Move moveId)
static inline bool32 GetMoveTerrainBoost_HitsBothFoes(enum Move moveId)
{
moveId = SanitizeMoveId(moveId);
assertf(gMovesInfo[moveId].effect == EFFECT_TERRAIN_BOOST, "not a terrain boosted move: %S", GetMoveName(moveId));
@ -719,7 +720,7 @@ static inline u32 GetMoveRecoil(enum Move moveId)
return gMovesInfo[moveId].argument.recoilPercentage;
}
static inline u32 GetMoveNonVolatileStatus(enum Move move)
static inline enum MoveEffect GetMoveNonVolatileStatus(enum Move move)
{
move = SanitizeMoveId(move);
switch (GetMoveEffect(move))

View File

@ -77,7 +77,7 @@ void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task);
void ItemUseCB_RotomCatalog(u8 taskId, TaskFunc task);
void ItemUseCB_ZygardeCube(u8 taskId, TaskFunc task);
void ItemUseCB_Fusion(u8 taskId, TaskFunc task);
u8 GetItemEffectType(enum Item item);
enum ItemEffectType GetItemEffectType(enum Item item);
void CB2_PartyMenuFromStartMenu(void);
void CB2_ChooseMonToGiveItem(void);
void ChooseMonToGiveMailFromMailbox(void);

View File

@ -341,7 +341,6 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler)
|| HasBattlerTerrainBoostMove(RIGHT_FOE(battler), STATUS_FIELD_ELECTRIC_TERRAIN))
return FIELD_EFFECT_NEGATIVE;
return FIELD_EFFECT_NEUTRAL;
}
@ -475,7 +474,6 @@ static enum FieldEffectOutcome BenefitsFromGravity(u32 battler)
return FIELD_EFFECT_NEUTRAL;
}
static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler)
{
// If we're in singles, we literally only care about speed.
@ -603,4 +601,3 @@ s32 CalcWeatherScore(u32 battlerAtk, u32 battlerDef, enum Move move, struct AiLo
return score;
}

View File

@ -28,7 +28,7 @@ static u32 GetHPHealAmount(u8 itemEffectParam, struct Pokemon *mon);
bool32 ShouldUseItem(u32 battler)
{
struct Pokemon *party;
u8 validMons = 0;
u32 validMons = 0;
bool32 shouldUse = FALSE;
u32 healAmount = 0;
@ -51,16 +51,14 @@ bool32 ShouldUseItem(u32 battler)
for (u32 monIndex = 0; monIndex < PARTY_SIZE; monIndex++)
{
if (IsValidForBattle(&party[monIndex]))
{
validMons++;
}
}
for (u32 itemIndex = 0; itemIndex < MAX_TRAINER_ITEMS; itemIndex++)
{
enum Item item;
const u8 *itemEffects;
u8 battlerSide;
u32 battlerSide;
item = gBattleHistory->trainerItems[itemIndex];
if (item == ITEM_NONE)
@ -226,13 +224,17 @@ static bool32 AI_ShouldHeal(u32 battler, u32 healAmount)
if (AI_OpponentCanFaintAiWithMod(battler, 0)
&& !AI_OpponentCanFaintAiWithMod(battler, healAmount)
&& healAmount > 2*maxDamage)
{
return TRUE;
}
// also heal, if the expected damage is outhealed and it's the last remaining mon
if (AI_OpponentCanFaintAiWithMod(battler, 0)
&& !AI_OpponentCanFaintAiWithMod(battler, healAmount)
&& CountUsablePartyMons(battler) == 0)
{
return TRUE;
}
return shouldHeal;
}

View File

@ -143,7 +143,7 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, enum Move, s32) =
void BattleAI_SetupItems(void)
{
u8 *data = (u8 *)gBattleHistory;
const u16 *items = GetTrainerItemsFromId(TRAINER_BATTLE_PARAM.opponentA);
const enum Item *items = GetTrainerItemsFromId(TRAINER_BATTLE_PARAM.opponentA);
for (u32 i = 0; i < sizeof(struct BattleHistory); i++)
data[i] = 0;
@ -614,7 +614,7 @@ void RecordStatusMoves(u32 battler)
void SetBattlerAiData(u32 battler, struct AiLogicData *aiData)
{
enum Ability ability;
u32 holdEffect;
enum HoldEffect holdEffect;
ability = aiData->abilities[battler] = AI_DecideKnownAbilityForTurn(battler);
aiData->items[battler] = gBattleMons[battler].item;
@ -753,9 +753,9 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
gAiLogicData->aiCalcInProgress = FALSE;
}
u32 GetPartyMonAbility(struct Pokemon *mon)
enum Ability GetPartyMonAbility(struct Pokemon *mon)
{
// Doesn't have any special handling yet
// Doesn't have any special handling yet
u32 species = GetMonData(mon, MON_DATA_SPECIES);
enum Ability ability = GetSpeciesAbility(species, GetMonData(mon, MON_DATA_ABILITY_NUM));
return ability;
@ -1150,7 +1150,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
// move data
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
u32 nonVolatileStatus = GetMoveNonVolatileStatus(move);
enum MoveEffect nonVolatileStatus = GetMoveNonVolatileStatus(move);
enum Type moveType;
enum MoveTarget moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
struct AiLogicData *aiData = gAiLogicData;
@ -1204,7 +1204,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
// Don't use anything but super effective thawing moves if target is frozen if any other attack available
if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY))
{
u32 aiMove;
enum Move aiMove;
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
aiMove = gBattleMons[battlerAtk].moves[moveIndex];
@ -3086,6 +3086,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
if (!ShouldBurn(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
ADJUST_SCORE(-5);
break;
default:
break;
}
// Choice items
@ -3167,7 +3169,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
u32 battlerAtkPartner = BATTLE_PARTNER(battlerAtk);
struct AiLogicData *aiData = gAiLogicData;
enum Ability atkPartnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)];
u32 atkPartnerHoldEffect = aiData->holdEffects[BATTLE_PARTNER(battlerAtk)];
enum HoldEffect atkPartnerHoldEffect = aiData->holdEffects[BATTLE_PARTNER(battlerAtk)];
enum BattleMoveEffects partnerEffect = GetMoveEffect(aiData->partnerMove);
bool32 partnerProtecting = IsAllyProtectingFromMove(battlerAtk, move, aiData->partnerMove) && !MoveIgnoresProtect(move);
bool32 partnerHasBadAbility = (gAbilitiesInfo[atkPartnerAbility].aiRating < 0);
@ -3181,12 +3183,11 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, enum Move move, s32 s
bool32 hasPartner = HasPartner(battlerAtk);
u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk);
u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING, CONSIDER_ENDURE);
bool32 wouldPartnerFaint = hasPartner && CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING)
&& !partnerProtecting;
bool32 wouldPartnerFaint = hasPartner && CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING) && !partnerProtecting;
bool32 isFriendlyFireOK = !wouldPartnerFaint && (noOfHitsToKOPartner == 0 || noOfHitsToKOPartner > friendlyFireThreshold);
// check what effect partner is using
if (aiData->partnerMove != 0 && hasPartner)
if (aiData->partnerMove != MOVE_NONE && hasPartner)
{
// This catches weather, terrain, screens, etc
if (AreMovesEquivalent(battlerAtk, battlerAtkPartner, move, aiData->partnerMove))
@ -4330,6 +4331,8 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, enum Move move
case MOVE_EFFECT_BURN:
IncreaseBurnScore(battlerAtk, battlerDef, move, &score);
break;
default:
break;
}
// move effect checks
switch (moveEffect)
@ -4740,10 +4743,12 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, enum Move move
case MOVE_EFFECT_PARALYSIS:
encourage = TRUE;
break;
default:
break;
}
if (gBattleMons[battlerDef].volatiles.encoreTimer == 0
&& (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)
&& (encourage))
&& (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)
&& (encourage))
ADJUST_SCORE(BEST_EFFECT);
break;
}
@ -5942,7 +5947,7 @@ static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, enum Mov
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_EVS_MINUS_1:
{
u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1;
enum Stat statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1;
if (CanLowerStat(battlerAtk, battlerDef, aiData, statId))
ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId));
break;
@ -5953,7 +5958,7 @@ static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, enum Mov
case MOVE_EFFECT_SP_DEF_MINUS_2:
case MOVE_EFFECT_EVS_MINUS_2:
{
u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2;
enum Stat statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2;
if (CanLowerStat(battlerAtk, battlerDef, aiData, statId))
ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId));
break;
@ -5976,7 +5981,7 @@ static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, enum Mov
case MOVE_EFFECT_LOWER_SP_ATK_SIDE:
case MOVE_EFFECT_LOWER_SP_DEF_SIDE:
{
u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_LOWER_ATTACK_SIDE;
enum Stat statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_LOWER_ATTACK_SIDE;
if (CanLowerStat(battlerAtk, battlerDef, aiData, statId))
ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId));
break;
@ -6642,6 +6647,8 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, enum Move move, s32 score)
case MOVE_EFFECT_POISON:
ADJUST_SCORE(-2);
break;
default:
break;
}
}
else
@ -6776,7 +6783,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, enum Move move, s32
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
struct AiLogicData *aiData = gAiLogicData;
uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex];
u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData);
enum Move predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData);
enum Move predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData);
// Switch benefit
@ -6979,7 +6986,6 @@ static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, enum Move move, s32 sc
return score;
}
// Dynamic AI Functions
// For specific battle scenarios

View File

@ -312,7 +312,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
aiMoveEffect = GetMoveEffect(aiMove);
if (aiMove != MOVE_NONE && gBattleMons[battler].pp[moveIndex] > 0)
{
u32 nonVolatileStatus = GetMoveNonVolatileStatus(aiMove);
enum MoveEffect nonVolatileStatus = GetMoveNonVolatileStatus(aiMove);
// Check if mon has an "important" status move
if (aiMoveEffect == EFFECT_REFLECT || aiMoveEffect == EFFECT_LIGHT_SCREEN
|| aiMoveEffect == EFFECT_SPIKES || aiMoveEffect == EFFECT_TOXIC_SPIKES || aiMoveEffect == EFFECT_STEALTH_ROCK || aiMoveEffect == EFFECT_STICKY_WEB || aiMoveEffect == EFFECT_LEECH_SEED
@ -652,7 +652,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler)
{
u32 opposingBattler = GetOppositeBattler(battler);
u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData);
enum Move incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData);
bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove);
@ -1326,7 +1326,8 @@ bool32 ShouldSwitchIfAllScoresBad(u32 battler)
bool32 ShouldStayInToUseMove(u32 battler)
{
u32 aiMove, opposingBattler = GetOppositeBattler(battler);
enum Move aiMove;
u32 opposingBattler = GetOppositeBattler(battler);
enum BattleMoveEffects aiMoveEffect;
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
@ -1424,9 +1425,10 @@ bool32 IsSwitchinValid(u32 battler)
static u32 GetSwitchinHazardsDamage(u32 battler)
{
u8 tSpikesLayers;
u16 heldItemEffect = gAiLogicData->holdEffects[battler];
enum HoldEffect heldItemEffect = gAiLogicData->holdEffects[battler];
u32 maxHP = gBattleMons[battler].maxHP;
enum Ability ability = gAiLogicData->abilities[battler], status = gBattleMons[battler].status1;
enum Ability ability = gAiLogicData->abilities[battler];
u32 status = gBattleMons[battler].status1;
u32 spikesDamage = 0, tSpikesDamage = 0, hazardDamage = 0;
enum BattleSide side = GetBattlerSide(battler);
@ -1818,7 +1820,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler, const struct Incomi
static u32 GetBattlerTypeMatchup(u32 opposingBattler, u32 battler)
{
// Check type matchup
u32 typeEffectiveness1 = UQ_4_12(1.0), typeEffectiveness2 = UQ_4_12(1.0);
uq4_12_t typeEffectiveness1 = UQ_4_12(1.0), typeEffectiveness2 = UQ_4_12(1.0);
enum Type atkType1 = gBattleMons[opposingBattler].types[0], atkType2 = gBattleMons[opposingBattler].types[1];
enum Type defType1 = gBattleMons[battler].types[0], defType2 = gBattleMons[battler].types[1];
@ -2315,7 +2317,7 @@ static u32 GetBestMonVanilla(struct Pokemon *party, int firstId, int lastId, u32
if (gBattleMons[battler].pp[moveIndex] < 1)
continue;
u32 aiMove = gBattleMons[battler].moves[moveIndex];
enum Move aiMove = gBattleMons[battler].moves[moveIndex];
// Baton Pass
if (GetMoveEffect(aiMove) == EFFECT_BATON_PASS)

View File

@ -69,7 +69,7 @@ bool32 AI_IsBattlerGrounded(u32 battler)
return IsBattlerGrounded(battler, gAiLogicData->abilities[battler], gAiLogicData->holdEffects[battler]);
}
static u32 AI_CanBattlerHitBothFoesInTerrain(u32 battler, enum Move move, enum BattleMoveEffects effect)
static bool32 AI_CanBattlerHitBothFoesInTerrain(u32 battler, enum Move move, enum BattleMoveEffects effect)
{
return effect == EFFECT_TERRAIN_BOOST
&& GetMoveTerrainBoost_HitsBothFoes(move)
@ -93,7 +93,6 @@ u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcC
{
if (calcContext == AI_ATTACKING && BattlerHasAi(battlerAtk))
{
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)) // Risky assumes it deals max damage
return aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum;
if ((gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) && !(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_RISKY)) // Conservative assumes it deals min damage
@ -279,7 +278,7 @@ void RecordItemEffectBattle(u32 battlerId, enum HoldEffect itemEffect)
void ClearBattlerItemEffectHistory(u32 battlerId)
{
gBattleHistory->itemEffects[battlerId] = 0;
gBattleHistory->itemEffects[battlerId] = HOLD_EFFECT_NONE;
}
void SaveBattlerData(u32 battlerId)
@ -398,8 +397,8 @@ void SetBattlerData(u32 battlerId)
{
if (!BattlerHasAi(battlerId) && gAiThinkingStruct->saved[battlerId].saved)
{
u32 species, illusionSpecies, side;
side = GetBattlerSide(battlerId);
u32 species, illusionSpecies;
enum BattleSide side = GetBattlerSide(battlerId);
// Simulate Illusion
species = gBattleMons[battlerId].species;
@ -1806,7 +1805,7 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, enum Ability ability)
// does NOT include ability suppression checks
enum Ability AI_DecideKnownAbilityForTurn(u32 battlerId)
{
u32 validAbilities[NUM_ABILITY_SLOTS];
enum Ability validAbilities[NUM_ABILITY_SLOTS];
u8 numValidAbilities = 0;
enum Ability knownAbility = GetBattlerAbilityIgnoreMoldBreaker(battlerId);
enum Ability indexAbility;
@ -2060,7 +2059,7 @@ bool32 IsHazardMove(enum Move move)
bool32 IsHazardClearingMove(enum Move move)
{
// Hazard clearing effects like Rapid Spin, Tidy Up, etc.
u32 moveEffect = GetMoveEffect(move);
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
switch (moveEffect)
{
case EFFECT_RAPID_SPIN:
@ -2070,6 +2069,8 @@ bool32 IsHazardClearingMove(enum Move move)
if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_6)
return TRUE;
break;
default:
break;
}
u32 additionalEffectCount = GetMoveAdditionalEffectCount(move);
@ -2102,7 +2103,7 @@ bool32 IsAllyProtectingFromMove(u32 battlerAtk, enum Move attackerMove, enum Mov
if (protectMethod == PROTECT_QUICK_GUARD)
{
u32 priority = GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], attackerMove);
s32 priority = GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], attackerMove);
return (priority > 0);
}
@ -2503,7 +2504,7 @@ u32 CountNegativeStatStages(u32 battlerId)
bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext)
{
s32 dmg;
u16 *moves = gBattleMons[battlerAtk].moves;
enum Move *moves = gBattleMons[battlerAtk].moves;
if (IsDoubleBattle() && battlerDef == BATTLE_PARTNER(battlerAtk))
dmg = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveIndex].maximum; // Attacking partner, be careful
@ -2547,7 +2548,7 @@ bool32 HasPhysicalBestMove(u32 battlerAtk, u32 battlerDef, enum DamageCalcContex
}
else
{
if (GetBattleMoveCategory(atkBestMoves[moveIndex]) == DAMAGE_CATEGORY_SPECIAL)
if (GetBattleMoveCategory(atkBestMoves[moveIndex]) == DAMAGE_CATEGORY_SPECIAL)
{
bestMoveIsPhysical = FALSE;
break;
@ -2786,6 +2787,7 @@ bool32 HasMoveThatLowersOwnStats(u32 battlerId)
{
enum Move aiMove;
enum Move *moves = GetMovesArray(battlerId);
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
aiMove = moves[moveIndex];
@ -2807,6 +2809,7 @@ bool32 HasMoveThatRaisesOwnStats(u32 battlerId)
{
enum Move aiMove;
enum Move *moves = GetMovesArray(battlerId);
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
aiMove = moves[moveIndex];
@ -3169,6 +3172,8 @@ static inline bool32 IsMoveSleepClauseTrigger(enum Move move)
{
case MOVE_EFFECT_SLEEP:
return TRUE;
default:
break;
}
// Sleeping effects like G-Max Befuddle, G-Max Snooze, etc.
@ -3455,7 +3460,7 @@ bool32 AnyUsefulStatIsRaised(u32 battler)
bool32 BattlerHasMaxHPProtection(u32 battler)
{
u32 ability = gAiLogicData->abilities[battler];
enum Ability ability = gAiLogicData->abilities[battler];
if (!AI_BattlerAtMaxHp(battler))
return FALSE;
if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_FOCUS_SASH)
@ -3905,7 +3910,7 @@ bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 mo
return TRUE;
}
static inline bool32 RecoveryEnablesWinning1v1(u32 battlerAtk, u32 battlerDef, enum Move move, u32 aiIsFaster, u32 healAmount)
static inline bool32 RecoveryEnablesWinning1v1(u32 battlerAtk, u32 battlerDef, enum Move move, bool32 aiIsFaster, u32 healAmount)
{
if (aiIsFaster)
{
@ -3988,7 +3993,7 @@ bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, enum Move move, u32 healPer
bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect)
{
u32 atkSide = GetBattlerSide(battlerAtk);
enum BattleSide atkSide = GetBattlerSide(battlerAtk);
// Don't waste a turn if screens will be broken
if (HasMoveWithAIEffect(battlerDef, AI_EFFECT_BREAK_SCREENS))
@ -4348,7 +4353,7 @@ bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef
return FALSE;
enum BattleMoveEffects partnerEffect = GetMoveEffect(partnerMove);
u32 nonVolatileStatus = GetMoveNonVolatileStatus(partnerMove);
enum MoveEffect nonVolatileStatus = GetMoveNonVolatileStatus(partnerMove);
if (partnerMove != MOVE_NONE
&& gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef
&& (nonVolatileStatus == MOVE_EFFECT_POISON
@ -4415,7 +4420,7 @@ bool32 PartnerMoveActivatesSleepClause(enum Move partnerMove)
bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, enum Move move)
{
s32 firstId, lastId;
struct Pokemon* party;
struct Pokemon *party;
bool32 hasStatus = AnyPartyMemberStatused(battlerAtk, IsSoundMove(move));
bool32 needHealing = FALSE;
@ -4564,8 +4569,7 @@ s32 CountUsablePartyMons(u32 battlerId)
bool32 IsPartyFullyHealedExceptBattler(u32 battlerId)
{
struct Pokemon *party;
party = GetBattlerParty(battlerId);
struct Pokemon *party = GetBattlerParty(battlerId);
for (u32 monIndex = 0; monIndex < PARTY_SIZE; monIndex++)
{
@ -4703,7 +4707,7 @@ bool32 IsRecycleEncouragedItem(enum Item item)
return FALSE;
}
static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, u32 aiIsFaster)
static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, bool32 aiIsFaster)
{
enum Move *moves = GetMovesArray(battlerId);
@ -4806,8 +4810,8 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef,
enum AIScore tempScore = NO_INCREASE;
u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk, DONT_CONSIDER_ENDURE);
enum Move predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData);
u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise
u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS);
bool32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise
bool32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS);
enum Stat statId = GetStatBeingChanged(statChange);
u32 stages = GetStagesOfStatChange(statChange);
@ -4992,7 +4996,7 @@ void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, enum Move move, s32 *scor
&& GetSpeciesBaseAttack(gBattleMons[battlerDef].species) >= GetSpeciesBaseSpAttack(gBattleMons[battlerDef].species) + 10))
{
enum Move defBestMoves[MAX_MON_MOVES] = {MOVE_NONE};
bool8 hasPhysical = FALSE;
bool32 hasPhysical = FALSE;
GetBestDmgMovesFromBattler(battlerAtk, battlerDef, AI_DEFENDING, defBestMoves);
@ -5105,7 +5109,7 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, enum Move move, s32
&& GetSpeciesBaseSpAttack(gBattleMons[battlerDef].species) >= GetSpeciesBaseAttack(gBattleMons[battlerDef].species) + 10))
{
enum Move defBestMoves[MAX_MON_MOVES] = {MOVE_NONE};
bool8 hasSpecial = FALSE;
bool32 hasSpecial = FALSE;
GetBestDmgMovesFromBattler(battlerAtk, battlerDef, AI_DEFENDING, defBestMoves);
@ -5144,6 +5148,7 @@ bool32 AI_MoveMakesContact(u32 battlerAtk, u32 battlerDef, enum Ability ability,
{
return FALSE;
}
if (ability == ABILITY_LONG_REACH)
return FALSE;
if (holdEffect == HOLD_EFFECT_PROTECTIVE_PADS)
@ -5168,8 +5173,10 @@ bool32 IsUnseenFistContactMove(u32 battlerAtk, u32 battlerDef, enum Move move)
{
return FALSE;
}
if (gAiLogicData->holdEffects[battlerAtk] == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move))
return FALSE;
return TRUE;
}
@ -5227,11 +5234,11 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, enum Move chosenMove)
break;
}
u32 zMove = GetUsableZMove(battlerAtk, chosenMove);
enum Move zMove = GetUsableZMove(battlerAtk, chosenMove);
if (IsBattleMoveStatus(chosenMove))
{
u8 zEffect = GetMoveZEffect(chosenMove);
enum ZEffect zEffect = GetMoveZEffect(chosenMove);
enum StatChange statChange = 0;
if (zEffect == Z_EFFECT_CURSE)
@ -5366,7 +5373,8 @@ bool32 IsAIUsingGimmick(u32 battler)
return (gAiBattleData->aiUsingGimmick & (1<<battler)) != 0;
}
struct AltTeraCalcs {
struct AltTeraCalcs
{
struct SimulatedDamage takenWithTera[MAX_MON_MOVES];
struct SimulatedDamage dealtWithoutTera[MAX_MON_MOVES];
};
@ -5468,8 +5476,8 @@ enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, str
numPossibleTera++;
}
u16 aiHp = gBattleMons[battler].hp;
u16 oppHp = gBattleMons[opposingBattler].hp;
u32 aiHp = gBattleMons[battler].hp;
u32 oppHp = gBattleMons[opposingBattler].hp;
enum Move *aiMoves = GetMovesArray(battler);
enum Move *oppMoves = GetMovesArray(opposingBattler);
@ -5573,7 +5581,7 @@ enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, str
}
// Decide to conserve tera based on number of possible later oppotunities
u16 conserveTeraChance = AI_CONSERVE_TERA_CHANCE_PER_MON * (numPossibleTera-1);
u32 conserveTeraChance = AI_CONSERVE_TERA_CHANCE_PER_MON * (numPossibleTera-1);
if (RandomPercentage(RNG_AI_CONSERVE_TERA, conserveTeraChance))
return NO_GIMMICK;
@ -5615,7 +5623,6 @@ enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, str
#undef takenWithTera
#undef takenWithoutTera
bool32 AI_IsBattlerAsleepOrComatose(u32 battlerId)
{
return (gBattleMons[battlerId].status1 & STATUS1_SLEEP) || gAiLogicData->abilities[battlerId] == ABILITY_COMATOSE;
@ -5705,7 +5712,7 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, enum Move move, s32 *sc
bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, enum Move move, struct AiLogicData *aiData)
{
u32 preventsStatLoss;
bool32 preventsStatLoss;
enum Ability partnerAbility = aiData->abilities[battlerAtkPartner];
enum BattlerPosition opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battlerAtk));
u32 opposingBattler = GetBattlerAtPosition(opposingPosition);
@ -5903,7 +5910,7 @@ bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability
// At the moment, the parts about Mummy and Wandering Spirit are not actually used.
bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, enum Move move, struct AiLogicData *aiData)
{
u32 effect = GetMoveEffect(move);
enum BattleMoveEffects effect = GetMoveEffect(move);
// Dynamaxed Pokemon are immune to some ability-changing effects.
if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
@ -5952,7 +5959,7 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, enum Move move, st
if (HasPartnerIgnoreFlags(battlerAtk))
{
u32 partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)];
enum Ability partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)];
if (gAbilitiesInfo[partnerAbility].cantBeSuppressed)
return FALSE;
if (partnerAbility == defAbility)
@ -6036,14 +6043,14 @@ bool32 DoesEffectReplaceTargetAbility(u32 effect)
void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, enum Move move, s32 *score, struct AiLogicData *aiData)
{
u32 effect = GetMoveEffect(move);
enum BattleMoveEffects effect = GetMoveEffect(move);
bool32 isTargetingPartner = IsTargetingPartner(battlerAtk, battlerDef);
enum Ability abilityAtk = aiData->abilities[battlerAtk];
enum Ability abilityDef = aiData->abilities[battlerDef];
bool32 partnerHasBadAbility = FALSE;
u32 partnerAbility = ABILITY_NONE;
enum Ability partnerAbility = ABILITY_NONE;
bool32 attackerHasBadAbility = (gAbilitiesInfo[abilityAtk].aiRating < 0);
s32 currentAbilityScore, transferredAbilityScore = 0;
enum AIScore currentAbilityScore, transferredAbilityScore = NO_INCREASE;
if (HasPartner(battlerAtk))
{
@ -6107,7 +6114,7 @@ void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, enum Move move, s32 *sco
}
}
s32 BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData)
enum AIScore BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData)
{
if (gAbilitiesInfo[ability].aiRating < 0)
return WORST_EFFECT;
@ -6268,9 +6275,7 @@ bool32 ShouldFinalGambit(u32 battlerAtk, u32 battlerDef, bool32 aiIsFaster)
if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_OMNISCIENT)
{
if (gBattleMons[battlerAtk].hp >= gBattleMons[battlerDef].hp && aiIsFaster)
{
return TRUE;
}
}
else if (gAiLogicData->hpPercents[battlerAtk] >= gAiLogicData->hpPercents[battlerDef] // Consider using GetScaledHPFraction and moving B_HEALTHBAR_PIXELS define
&& GetSpeciesBaseHP(gBattleMons[battlerAtk].species) >= GetSpeciesBaseHP(gBattleMons[battlerDef].species)

View File

@ -14,7 +14,7 @@
static void ValidateBattlers(void);
static enum Move GetOriginallyUsedMove(enum Move chosenMove);
static void SetSameMoveTurnValues(u32 moveEffect);
static void SetSameMoveTurnValues(enum BattleMoveEffects moveEffect);
static void TryClearChargeVolatile(enum Type moveType);
static inline bool32 IsBattlerUsingBeakBlast(u32 battler);
static void RequestNonVolatileChangee(u32 battlerAtk);
@ -483,7 +483,7 @@ static enum CancelerResult CancelerZMoves(struct BattleContext *ctx)
static enum CancelerResult CancelerChoiceLock(struct BattleContext *ctx)
{
u16 *choicedMoveAtk = &gBattleStruct->choicedMove[ctx->battlerAtk];
enum Move *choicedMoveAtk = &gBattleStruct->choicedMove[ctx->battlerAtk];
enum HoldEffect holdEffect = GetBattlerHoldEffect(ctx->battlerAtk);
if (gChosenMove != MOVE_STRUGGLE
@ -625,7 +625,7 @@ static enum CancelerResult CancelerPPDeduction(struct BattleContext *ctx)
return CANCELER_RESULT_SUCCESS;
s32 ppToDeduct = 1;
u32 moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->move);
enum MoveTarget moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->move);
u32 movePosition = gCurrMovePos;
if (gBattleStruct->submoveAnnouncement == SUBMOVE_SUCCESS)
@ -832,7 +832,7 @@ static enum CancelerResult CancelerMoveFailure(struct BattleContext *ctx)
}
else
{
u32 protectMethod = GetMoveProtectMethod(ctx->move);
enum ProtectMethod protectMethod = GetMoveProtectMethod(ctx->move);
bool32 canUseProtectSecondTime = CanUseMoveConsecutively(ctx->battlerAtk);
bool32 canUseWideGuard = (GetConfig(CONFIG_WIDE_GUARD) >= GEN_6 && protectMethod == PROTECT_WIDE_GUARD);
bool32 canUseQuickGuard = (GetConfig(CONFIG_QUICK_GUARD) >= GEN_6 && protectMethod == PROTECT_QUICK_GUARD);
@ -864,7 +864,7 @@ static enum CancelerResult CancelerMoveFailure(struct BattleContext *ctx)
break;
case EFFECT_UPPER_HAND:
{
u32 prio = GetChosenMovePriority(ctx->battlerDef, GetBattlerAbility(ctx->battlerDef));
s32 prio = GetChosenMovePriority(ctx->battlerDef, GetBattlerAbility(ctx->battlerDef));
if (prio < 1 || prio > 3 // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status
|| HasBattlerActedThisTurn(ctx->battlerDef)
|| gChosenMoveByBattler[ctx->battlerDef] == MOVE_NONE
@ -952,7 +952,7 @@ static enum CancelerResult CancelerPriorityBlock(struct BattleContext *ctx)
return CANCELER_RESULT_SUCCESS;
u32 battler;
u32 ability = ABILITY_NONE; // ability of battler who is blocking
enum Ability ability = ABILITY_NONE; // ability of battler who is blocking
bool32 isSpreadMove = IsSpreadMove(GetBattlerMoveTargetType(ctx->battlerAtk, ctx->move));
for (battler = 0; battler < gBattlersCount; battler++)
{
@ -1088,7 +1088,7 @@ static enum CancelerResult CancelerCharging(struct BattleContext *ctx)
return result;
}
static bool32 NoTargetPresent(u32 battler, u32 move, u32 moveTarget)
static bool32 NoTargetPresent(u32 battler, enum Move move, enum MoveTarget moveTarget)
{
switch (moveTarget)
{
@ -1113,6 +1113,8 @@ static bool32 NoTargetPresent(u32 battler, u32 move, u32 moveTarget)
if (!IsBattlerAlive(gBattlerTarget) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))
return TRUE;
break;
default:
break;
}
return FALSE;
@ -1264,7 +1266,7 @@ static bool32 (*const sShouldCheckTargetMoveFailure[])(u32 battlerAtk, u32 battl
[TARGET_ALL_BATTLERS] = IsTargetingAllBattlers,
};
static bool32 ShouldCheckTargetMoveFailure(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTarget)
static bool32 ShouldCheckTargetMoveFailure(u32 battlerAtk, u32 battlerDef, enum Move move, enum MoveTarget moveTarget)
{
// For Bounced moves
if (IsBattlerUnaffectedByMove(battlerDef))
@ -2503,7 +2505,7 @@ static enum MoveEndResult MoveEndMoveBlock(void)
&& IsBattlerAlive(gBattlerAttacker)
&& gBattleMons[BATTLE_PARTNER(gBattlerTarget)].volatiles.semiInvulnerable != STATE_COMMANDER)
{
u32 targetAbility = GetBattlerAbility(gBattlerTarget);
enum Ability targetAbility = GetBattlerAbility(gBattlerTarget);
if (targetAbility == ABILITY_GUARD_DOG)
break;
@ -2754,7 +2756,7 @@ static enum MoveEndResult MoveEndKeeMarangaHpThresholdItemTarget(void)
return MOVEEND_RESULT_CONTINUE;
}
static bool32 TryRedCard(u32 battlerAtk, u32 redCardBattler, u32 move)
static bool32 TryRedCard(u32 battlerAtk, u32 redCardBattler, enum Move move)
{
if (!IsBattlerAlive(redCardBattler)
|| !IsBattlerTurnDamaged(redCardBattler)
@ -3409,7 +3411,7 @@ static enum Move GetOriginallyUsedMove(enum Move chosenMove)
return (gChosenMove == MOVE_UNAVAILABLE) ? MOVE_NONE : gChosenMove;
}
static void SetSameMoveTurnValues(u32 moveEffect)
static void SetSameMoveTurnValues(enum BattleMoveEffects moveEffect)
{
bool32 increment = IsAnyTargetAffected()
&& !gBattleStruct->unableToUseMove
@ -3499,7 +3501,7 @@ static enum Move GetMirrorMoveMove(void)
{
s32 i, validMovesCount;
enum Move move = MOVE_NONE;
u16 validMoves[MAX_BATTLERS_COUNT] = {0};
enum Move validMoves[MAX_BATTLERS_COUNT] = {MOVE_NONE};
for (validMovesCount = 0, i = 0; i < gBattlersCount; i++)
{
@ -3563,7 +3565,7 @@ static enum Move GetAssistMove(void)
enum Move move = MOVE_NONE;
u32 chooseableMovesNo = 0;
struct Pokemon *party;
u16 validMoves[PARTY_SIZE * MAX_MON_MOVES] = {MOVE_NONE};
enum Move validMoves[PARTY_SIZE * MAX_MON_MOVES] = {MOVE_NONE};
party = GetBattlerParty(gBattlerAttacker);
@ -3708,7 +3710,7 @@ static bool32 TryMagicCoat(struct BattleContext *ctx)
static bool32 TryActivatePowderStatus(enum Move move)
{
u32 partnerMove = GetChosenMoveFromPosition(BATTLE_PARTNER(gBattlerAttacker));
enum Move partnerMove = GetChosenMoveFromPosition(BATTLE_PARTNER(gBattlerAttacker));
if (!gBattleMons[gBattlerAttacker].volatiles.powder)
return FALSE;
if (GetBattleMoveType(move) == TYPE_FIRE && !gBattleStruct->pledgeMove)

View File

@ -1309,7 +1309,7 @@ static void TryCloseBagToGiveItem(u8 taskId)
static void BagAction_UseInBattle(u8 taskId)
{
// Safety check
u16 type = GetItemType(gSpecialVar_ItemId);
enum ItemType type = GetItemType(gSpecialVar_ItemId);
if (!GetItemBattleUsage(gSpecialVar_ItemId))
return;

View File

@ -843,6 +843,8 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3)
case MOVE_EFFECT_TOXIC:
baseFromEffect += 5;
break;
default:
break;
}
// Guaranteed hit but without negative priority

View File

@ -277,7 +277,7 @@ bool32 MoveSelectionDisplayZMove(enum Move zmove, u32 battler)
if (IsBattleMoveStatus(move))
{
u8 zEffect = GetMoveZEffect(move);
enum ZEffect zEffect = GetMoveZEffect(move);
gDisplayedStringBattle[0] = EOS;
@ -436,7 +436,7 @@ static void ZMoveSelectionDisplayMoveType(enum Move zMove, u32 battler)
void SetZEffect(void)
{
u32 i;
u32 effect = GetMoveZEffect(gChosenMove);
enum ZEffect effect = GetMoveZEffect(gChosenMove);
if (effect == Z_EFFECT_CURSE)
{

View File

@ -4,7 +4,6 @@
#include "constants/battle_move_effects.h"
#include "constants/battle_script_commands.h"
#include "constants/battle_string_ids.h"
#include "constants/battle_z_move_effects.h"
#include "constants/hold_effects.h"
#include "constants/moves.h"
#include "constants/contest.h"

View File

@ -851,7 +851,7 @@ enum Pocket GetItemPocket(enum Item itemId)
return gItemsInfo[SanitizeItemId(itemId)].pocket;
}
u8 GetItemType(enum Item itemId)
enum ItemType GetItemType(enum Item itemId)
{
return gItemsInfo[SanitizeItemId(itemId)].type;
}
@ -862,7 +862,7 @@ ItemUseFunc GetItemFieldFunc(enum Item itemId)
}
// Returns an item's battle effect script ID.
u8 GetItemBattleUsage(enum Item itemId)
enum EffectItem GetItemBattleUsage(enum Item itemId)
{
enum Item item = SanitizeItemId(itemId);
// Handle E-Reader berries.

View File

@ -2091,7 +2091,7 @@ static void ItemMenu_Cancel(u8 taskId)
static void ItemMenu_UseInBattle(u8 taskId)
{
// Safety check
u16 type = GetItemType(gSpecialVar_ItemId);
enum ItemType type = GetItemType(gSpecialVar_ItemId);
if (!GetItemBattleUsage(gSpecialVar_ItemId))
return;

View File

@ -123,7 +123,7 @@ static const struct YesNoFuncTable sUseTMHMYesNoFuncTable =
#define tEnigmaBerryType data[4]
static void SetUpItemUseCallback(u8 taskId)
{
u8 type;
enum ItemType type;
if (gSpecialVar_ItemId == ITEM_ENIGMA_BERRY_E_READER)
type = gTasks[taskId].tEnigmaBerryType - 1;
else

View File

@ -5222,7 +5222,7 @@ void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task)
{
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
enum Item item = gSpecialVar_ItemId;
u8 effectType = GetItemEffectType(item);
enum ItemEffectType effectType = GetItemEffectType(item);
u16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP);
u16 ev = ItemEffectToMonEv(mon, effectType);
bool8 cannotUseEffect = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0);
@ -6923,7 +6923,7 @@ void TryItemHoldFormChange(struct Pokemon *mon, s8 slotId)
#undef tAnimWait
#undef tNextFunc
u8 GetItemEffectType(enum Item item)
enum ItemEffectType GetItemEffectType(enum Item item)
{
u32 statusCure;
const u8 *itemEffect = GetItemEffect(item);

View File

@ -1,6 +1,5 @@
#include "global.h"
#include "test/battle.h"
#include "constants/battle_z_move_effects.h"
SINGLE_BATTLE_TEST("Dancer can copy a dance move immediately after it was used and allow the user of Dancer to still use its move")
{

View File

@ -1,6 +1,5 @@
#include "global.h"
#include "test/battle.h"
#include "constants/battle_z_move_effects.h"
ASSUMPTIONS
{

View File

@ -1,7 +1,6 @@
#include "global.h"
#include "test/battle.h"
#include "battle_ai_util.h"
#include "constants/battle_z_move_effects.h"
AI_SINGLE_BATTLE_TEST("AI uses Z-Moves.")
{

View File

@ -1,6 +1,5 @@
#include "global.h"
#include "test/battle.h"
#include "constants/battle_z_move_effects.h"
// Basic Functionality
SINGLE_BATTLE_TEST("(Z-MOVE) Z-Moves do not retain priority")

View File

@ -3100,9 +3100,10 @@ void UseItem(u32 sourceLine, struct BattlePokemon *battler, struct ItemContext c
{
s32 i;
s32 battlerId = battler - gBattleMons;
bool32 requirePartyIndex = GetItemType(ctx.itemId) == ITEM_USE_PARTY_MENU
|| GetItemType(ctx.itemId) == ITEM_USE_PARTY_MENU_MOVES
|| (GetItemType(ctx.itemId) == ITEM_USE_BATTLER && GetBattleTest()->type != BATTLE_TEST_AI_DOUBLES && STATE->battlersCount > 2);
enum ItemType ctxItemType = GetItemType(ctx.itemId);
bool32 requirePartyIndex = ctxItemType == ITEM_USE_PARTY_MENU
|| ctxItemType == ITEM_USE_PARTY_MENU_MOVES
|| (ctxItemType == ITEM_USE_BATTLER && GetBattleTest()->type != BATTLE_TEST_AI_DOUBLES && STATE->battlersCount > 2);
// Check general bad use.
INVALID_IF(DATA.turnState == TURN_CLOSED, "USE_ITEM outside TURN");
INVALID_IF(DATA.actionBattlers & (1 << battlerId), "Multiple battler actions");
@ -3112,7 +3113,7 @@ void UseItem(u32 sourceLine, struct BattlePokemon *battler, struct ItemContext c
INVALID_IF(requirePartyIndex && ctx.partyIndex >= ((battlerId & BIT_SIDE) == B_SIDE_PLAYER ? DATA.playerPartySize : DATA.opponentPartySize), \
"USE_ITEM to invalid party index");
// Check move slot items.
if (GetItemType(ctx.itemId) == ITEM_USE_PARTY_MENU_MOVES)
if (ctxItemType == ITEM_USE_PARTY_MENU_MOVES)
{
INVALID_IF(!ctx.explicitMove, "%S requires an explicit move", GetItemName(ctx.itemId));
for (i = 0; i < MAX_MON_MOVES; i++)