Skip to content

Commit

Permalink
Implemented a CannotUseItemsInBattle function (#3524)
Browse files Browse the repository at this point in the history
* Implemented a CannotUseItemsInBattle function
This fucntion is the result of merging CannotUseBagBattleItem and CannotUsePartyBattleItem. No reason to split the work between 2 functions when you can do it all with just 1.

Misc. Changes:
-Turned most of the if statements inside the function into "else if" statements for performance reasons.
-Refactored how the local variable "cannotUse" was used turning it into a bool.

* Made CannotUseItemsInBattle use a switch statement

Misc. Changes:
-Removed pointless parentheses from case EFFECT_ITEM_SET_FOCUS_ENERGY
-Removed pointless i loop variable from case EFFECT_ITEM_INCREASE_ALL_STATS and replaced a hardcoded 1 in its for loop.
-Turned the i loop variable declared at the top of the function into a u32 variable
-Removed pointless comments. The EFFECT_ITEM constants are readable enough to convey what sort of items they affect.

---------

Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
  • Loading branch information
LOuroboros and AlexOn1ine authored Dec 24, 2023
1 parent f700466 commit 58b03cb
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 115 deletions.
1 change: 1 addition & 0 deletions include/item_use.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ enum {
};

bool32 CanThrowBall(void);
bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon);

#endif // GUARD_ITEM_USE_H
135 changes: 82 additions & 53 deletions src/item_use.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ static void SetDistanceOfClosestHiddenItem(u8, s16, s16);
static void CB2_OpenPokeblockFromBag(void);
static void ItemUseOnFieldCB_Honey(u8 taskId);
static bool32 IsValidLocationForVsSeeker(void);
static bool32 CannotUseBagBattleItem(u16 itemId);

// EWRAM variables
EWRAM_DATA static void(*sItemUseOnFieldCB)(u8 taskId) = NULL;
Expand Down Expand Up @@ -1142,89 +1141,119 @@ void ItemUseInBattle_PartyMenuChooseMove(u8 taskId)
}

// Returns whether an item can be used in battle and sets the fail text.
static bool32 CannotUseBagBattleItem(u16 itemId)
bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon)
{
u8 cannotUse = FALSE;
u16 battleUsage = ItemId_GetBattleUsage(itemId);
bool8 cannotUse = FALSE;
const u8* failStr = NULL;
u32 i;
u16 hp = GetMonData(mon, MON_DATA_HP);

// Embargo Check
if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO)
|| (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO))
{
return TRUE;
}
// X-Items
if (battleUsage == EFFECT_ITEM_INCREASE_STAT
&& gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE)
{
cannotUse++;
}
// Dire Hit
if (battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY
&& (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY))
{
cannotUse++;
}
// Guard Spec
if (battleUsage == EFFECT_ITEM_SET_MIST
&& gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST)
{
cannotUse++;
}
// Escape Items
if (battleUsage == EFFECT_ITEM_ESCAPE
&& gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
cannotUse++;
}
// Poke Balls
if (battleUsage == EFFECT_ITEM_THROW_BALL)

// battleUsage checks
switch (battleUsage)
{
case EFFECT_ITEM_INCREASE_STAT:
if (gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE)
cannotUse = TRUE;
break;
case EFFECT_ITEM_SET_FOCUS_ENERGY:
if (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY)
cannotUse = TRUE;
break;
case EFFECT_ITEM_SET_MIST:
if (gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST)
cannotUse = TRUE;
break;
case EFFECT_ITEM_ESCAPE:
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
cannotUse = TRUE;
break;
case EFFECT_ITEM_THROW_BALL:
switch (GetBallThrowableState())
{
case BALL_THROW_UNABLE_TWO_MONS:
failStr = sText_CantThrowPokeBall_TwoMons;
cannotUse++;
break;
case BALL_THROW_UNABLE_NO_ROOM:
failStr = gText_BoxFull;
cannotUse++;
break;
case BALL_THROW_UNABLE_SEMI_INVULNERABLE:
failStr = sText_CantThrowPokeBall_SemiInvulnerable;
cannotUse++;
break;
case BALL_THROW_UNABLE_DISABLED_FLAG:
failStr = sText_CantThrowPokeBall_Disabled;
cannotUse++;
break;
case BALL_THROW_UNABLE_TWO_MONS:
failStr = sText_CantThrowPokeBall_TwoMons;
cannotUse = TRUE;
break;
case BALL_THROW_UNABLE_NO_ROOM:
failStr = gText_BoxFull;
cannotUse = TRUE;
break;
case BALL_THROW_UNABLE_SEMI_INVULNERABLE:
failStr = sText_CantThrowPokeBall_SemiInvulnerable;
cannotUse = TRUE;
break;
case BALL_THROW_UNABLE_DISABLED_FLAG:
failStr = sText_CantThrowPokeBall_Disabled;
cannotUse = TRUE;
break;
}
}
// Max Mushrooms
if (battleUsage == EFFECT_ITEM_INCREASE_ALL_STATS)
{
u32 i;
for (i = 1; i < NUM_STATS; i++)
break;
case EFFECT_ITEM_INCREASE_ALL_STATS:
for (i = STAT_ATK; i < NUM_STATS; i++)
{
if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL))
{
cannotUse++;
cannotUse = TRUE;
break;
}
}
break;
case EFFECT_ITEM_RESTORE_HP:
if (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
cannotUse = TRUE;
break;
case EFFECT_ITEM_CURE_STATUS:
if (!((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId))
|| (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId))))
cannotUse = TRUE;
break;
case EFFECT_ITEM_HEAL_AND_CURE_STATUS:
if ((hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
&& !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId))
|| (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId))))
cannotUse = TRUE;
break;
case EFFECT_ITEM_REVIVE:
if (hp != 0)
cannotUse = TRUE;
break;
case EFFECT_ITEM_RESTORE_PP:
if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP)
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i));
break;
}
if (i == MAX_MON_MOVES)
cannotUse = TRUE;
}
else if (GetMonData(mon, MON_DATA_PP1 + gPartyMenu.data1) == CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + gPartyMenu.data1), GetMonData(mon, MON_DATA_PP_BONUSES), gPartyMenu.data1))
{
cannotUse = TRUE;
}
break;
}

if (failStr != NULL)
StringExpandPlaceholders(gStringVar4, failStr);
else
StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect);

return cannotUse;
}

void ItemUseInBattle_BagMenu(u8 taskId)
{
if (CannotUseBagBattleItem(gSpecialVar_ItemId))
if (CannotUseItemsInBattle(gSpecialVar_ItemId, NULL))
{
if (!InBattlePyramid())
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage);
Expand Down
64 changes: 2 additions & 62 deletions src/party_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,6 @@ static bool8 SetUpFieldMove_Dive(void);
void TryItemHoldFormChange(struct Pokemon *mon);
static void ShowMoveSelectWindow(u8 slot);
static void Task_HandleWhichMoveInput(u8 taskId);
static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon);

// static const data
#include "data/party_menu.h"
Expand Down Expand Up @@ -4557,70 +4556,11 @@ static bool8 IsItemFlute(u16 item)
return FALSE;
}

static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon)
{
u8 i;
u8 cannotUse = FALSE;
u16 battleUsage = ItemId_GetBattleUsage(itemId);
u16 hp = GetMonData(mon, MON_DATA_HP);

// Embargo Check
if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO)
|| (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO))
{
return FALSE;
}
// Items that restore HP (Potions, Sitrus Berry, etc.)
if (battleUsage == EFFECT_ITEM_RESTORE_HP && (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)))
{
cannotUse++;
}
// Items that cure status (Burn Heal, Awakening, etc.)
if (battleUsage == EFFECT_ITEM_CURE_STATUS
&& !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId))
|| (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId))))
{
cannotUse++;
}
// Items that restore HP and cure status (Full Restore)
if (battleUsage == EFFECT_ITEM_HEAL_AND_CURE_STATUS
&& (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
&& !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId))
|| (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId))))
{
cannotUse++;
}
// Items that revive a party member
if (battleUsage == EFFECT_ITEM_REVIVE && hp != 0)
{
cannotUse++;
}
// Items that restore PP (Elixir, Ether, Leppa Berry)
if (battleUsage == EFFECT_ITEM_RESTORE_PP)
{
if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP)
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i));
break;
}
if (i == MAX_MON_MOVES)
cannotUse++;
}
else if (GetMonData(mon, MON_DATA_PP1 + gPartyMenu.data1) == CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + gPartyMenu.data1), GetMonData(mon, MON_DATA_PP_BONUSES), gPartyMenu.data1))
{
cannotUse++;
}
}
return cannotUse;
}

// Battle scripts called in HandleAction_UseItem
void ItemUseCB_BattleScript(u8 taskId, TaskFunc task)
{
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon))
if (CannotUseItemsInBattle(gSpecialVar_ItemId, mon))
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
Expand Down Expand Up @@ -5129,7 +5069,7 @@ static void TryUseItemOnMove(u8 taskId)
// In battle, set appropriate variables to be used in battle script.
if (gMain.inBattle)
{
if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon))
if (CannotUseItemsInBattle(gSpecialVar_ItemId, mon))
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
Expand Down

0 comments on commit 58b03cb

Please sign in to comment.