summaryrefslogtreecommitdiff
path: root/arm9/src/use_item_on_mon.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/src/use_item_on_mon.c')
-rw-r--r--arm9/src/use_item_on_mon.c719
1 files changed, 719 insertions, 0 deletions
diff --git a/arm9/src/use_item_on_mon.c b/arm9/src/use_item_on_mon.c
new file mode 100644
index 00000000..9e11e4bf
--- /dev/null
+++ b/arm9/src/use_item_on_mon.c
@@ -0,0 +1,719 @@
+#include "global.h"
+#include "pokemon.h"
+#include "heap.h"
+#include "itemtool.h"
+#include "move_data.h"
+#include "party.h"
+#include "use_item_on_mon.h"
+#include "constants/moves.h"
+
+#pragma thumb on
+
+BOOL CanUseItemOnPokemon(struct Pokemon * pokemon, u16 itemId, s32 moveId, u32 heap_id)
+{
+ s32 atkEv;
+ s32 defEv;
+ s32 speedEv;
+ s32 spAtkEv;
+ s32 spDefEv;
+ s32 hpEv;
+ u32 hp;
+ struct ItemData * itemData;
+ u32 status;
+
+ itemData = LoadItemDataOrGfx(itemId, ITEMDATA_DATA, heap_id);
+
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PARTY_USE) != 1)
+ {
+ FreeToHeap(itemData);
+ return FALSE;
+ }
+ status = GetMonData(pokemon, MON_DATA_STATUS, NULL);
+ // slp
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SLP_HEAL) && (status & MON_STATUS_SLP_MASK))
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ // psn
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PSN_HEAL) && (status & (MON_STATUS_PSN_MASK | MON_STATUS_TOX_MASK)))
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ // brn
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_BRN_HEAL) && (status & MON_STATUS_BRN_MASK))
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ // frz
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRZ_HEAL) && (status & MON_STATUS_FRZ_MASK))
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ // prz
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PRZ_HEAL) && (status & MON_STATUS_PRZ_MASK))
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ hp = GetMonData(pokemon, MON_DATA_HP, NULL);
+ if ((GetItemAttr_PreloadedItemData(itemData, ITEMATTR_REVIVE) || GetItemAttr_PreloadedItemData(itemData, ITEMATTR_REVIVE_ALL)) && !GetItemAttr_PreloadedItemData(itemData, ITEMATTR_LEVEL_UP))
+ {
+ if (hp == 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_RESTORE) &&hp != 0 && hp < GetMonData(pokemon, MON_DATA_MAXHP, NULL))
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_LEVEL_UP) && GetMonData(pokemon, MON_DATA_LEVEL, NULL) < MAX_LEVEL)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_EVOLVE) && GetMonEvolution(NULL, pokemon, 3, itemId, NULL) != SPECIES_NONE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_UP) || GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_MAX))
+ {
+ if (GetMonData(pokemon, MON_DATA_MOVE1PPUP + moveId, NULL) < 3 && WazaGetMaxPp((u16)GetMonData(pokemon, MON_DATA_MOVE1 + moveId, NULL), 0) >= 5)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_RESTORE) && MonMoveCanRestorePP(pokemon, moveId) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_RESTORE_ALL))
+ {
+ for (int i = 0; i < MON_MOVES; i++)
+ {
+ if (MonMoveCanRestorePP(pokemon, i) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ hpEv = (s32)GetMonData(pokemon, MON_DATA_HP_EV, NULL);
+ atkEv = (s32)GetMonData(pokemon, MON_DATA_ATK_EV, NULL);
+ defEv = (s32)GetMonData(pokemon, MON_DATA_DEF_EV, NULL);
+ speedEv = (s32)GetMonData(pokemon, MON_DATA_SPEED_EV, NULL);
+ spAtkEv = (s32)GetMonData(pokemon, MON_DATA_SPATK_EV, NULL);
+ spDefEv = (s32)GetMonData(pokemon, MON_DATA_SPDEF_EV, NULL);
+ if (GetMonData(pokemon, MON_DATA_SPECIES, NULL) != SPECIES_SHEDINJA && GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_EV_UP))
+ {
+ s32 dHpEv = (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_EV_UP_PARAM);
+ if (dHpEv > 0)
+ {
+ if (hpEv < MAX_EV && (hpEv + atkEv + defEv + speedEv + spAtkEv + spDefEv) < MAX_EV_SUM)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (dHpEv < 0)
+ {
+ if (hpEv > 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ else if (CanItemModFriendship(pokemon, itemData) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_ATK_EV_UP))
+ {
+ s32 dAtkEv = (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_ATK_EV_UP_PARAM);
+ if (dAtkEv > 0)
+ {
+ if (atkEv < MAX_EV && (hpEv + atkEv + defEv + speedEv + spAtkEv + spDefEv) < MAX_EV_SUM)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (dAtkEv < 0)
+ {
+ if (atkEv > 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ else if (CanItemModFriendship(pokemon, itemData) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_DEF_EV_UP))
+ {
+ s32 dDefEv = (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_DEF_EV_UP_PARAM);
+ if (dDefEv > 0)
+ {
+ if (defEv < MAX_EV && (hpEv + atkEv + defEv + speedEv + spAtkEv + spDefEv) < MAX_EV_SUM)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (dDefEv < 0)
+ {
+ if (defEv > 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ else if (CanItemModFriendship(pokemon, itemData) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPEED_EV_UP))
+ {
+ s32 dSpeedEv = (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPEED_EV_UP_PARAM);
+ if (dSpeedEv > 0)
+ {
+ if (speedEv < MAX_EV && (hpEv + atkEv + defEv + speedEv + spAtkEv + spDefEv) < MAX_EV_SUM)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (dSpeedEv < 0)
+ {
+ if (speedEv > 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ else if (CanItemModFriendship(pokemon, itemData) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPATK_EV_UP))
+ {
+ s32 dSpAtkEv = (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPATK_EV_UP_PARAM);
+ if (dSpAtkEv > 0)
+ {
+ if (spAtkEv < MAX_EV && (hpEv + atkEv + defEv + speedEv + spAtkEv + spDefEv) < MAX_EV_SUM)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (dSpAtkEv < 0)
+ {
+ if (spAtkEv > 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ else if (CanItemModFriendship(pokemon, itemData) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPDEF_EV_UP))
+ {
+
+ s32 dSpDefEv = (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPDEF_EV_UP_PARAM);
+ if (dSpDefEv > 0)
+ {
+ if (spDefEv < MAX_EV && (hpEv + atkEv + defEv + speedEv + spAtkEv + spDefEv) < MAX_EV_SUM)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ else if (dSpDefEv < 0)
+ {
+ if (spDefEv > 0)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ else if (CanItemModFriendship(pokemon, itemData) == TRUE)
+ {
+ FreeToHeap(itemData);
+ return TRUE;
+ }
+ }
+ }
+ FreeToHeap(itemData);
+ return FALSE;
+}
+
+BOOL CanUseItemOnMonInParty(struct PlayerParty * party, u16 itemId, s32 partyIdx, s32 moveIdx, u32 heap_id)
+{
+ struct Pokemon * pokemon = GetPartyMonByIndex(party, partyIdx);
+ return CanUseItemOnPokemon(pokemon, itemId, moveIdx, heap_id);
+}
+
+BOOL UseItemOnPokemon(struct Pokemon * pokemon, u16 itemId, s32 moveIdx, u16 location, u32 heap_id)
+{
+ s32 stack_data[8];
+#define sp6C stack_data[7]
+#define sp68 stack_data[6]
+#define sp64 stack_data[5]
+#define sp60 stack_data[4]
+#define sp5C stack_data[3]
+#define sp58 stack_data[2]
+#define sp54 stack_data[1]
+#define sp50 stack_data[0]
+ BOOL hadEffect;
+ BOOL effectFound;
+
+ struct ItemData * itemData = LoadItemDataOrGfx(itemId, ITEMDATA_DATA, heap_id);
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PARTY_USE) != 1)
+ {
+ FreeToHeap(itemData);
+ return FALSE;
+ }
+ hadEffect = FALSE;
+ effectFound = FALSE;
+ {
+ sp54 = sp50 = (int)GetMonData(pokemon, MON_DATA_STATUS, NULL);
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SLP_HEAL))
+ {
+ sp54 &= ~MON_STATUS_SLP_MASK;
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PSN_HEAL))
+ {
+ sp54 &= ~(MON_STATUS_PSN_MASK | MON_STATUS_TOX_MASK | 0xF00);
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_BRN_HEAL))
+ {
+ sp54 &= ~MON_STATUS_BRN_MASK;
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRZ_HEAL))
+ {
+ sp54 &= ~MON_STATUS_FRZ_MASK;
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PRZ_HEAL))
+ {
+ sp54 &= ~MON_STATUS_PRZ_MASK;
+ effectFound = TRUE;
+ }
+ if (sp50 != sp54)
+ {
+ SetMonData(pokemon, MON_DATA_STATUS, &sp54);
+ hadEffect = TRUE;
+ }
+ }
+ {
+ sp50 = (int)GetMonData(pokemon, MON_DATA_HP, NULL);
+ sp54 = (int)GetMonData(pokemon, MON_DATA_MAXHP, NULL);
+ if ((GetItemAttr_PreloadedItemData(itemData, ITEMATTR_REVIVE) || GetItemAttr_PreloadedItemData(itemData, ITEMATTR_REVIVE_ALL)) && GetItemAttr_PreloadedItemData(itemData, ITEMATTR_LEVEL_UP))
+ {
+ if (sp50 == 0)
+ {
+ RestoreMonHPBy(pokemon, (u32)sp50, (u32)sp54, GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_RESTORE_PARAM));
+ hadEffect = TRUE;
+ }
+ effectFound = TRUE;
+ }
+ else if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_RESTORE))
+ {
+ if (sp50 < sp54)
+ {
+ RestoreMonHPBy(pokemon, (u32)sp50, (u32)sp54, GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_RESTORE_PARAM));
+ hadEffect = TRUE;
+ }
+ effectFound = TRUE;
+ }
+ sp58 = (s32)GetMonData(pokemon, MON_DATA_LEVEL, NULL);
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_LEVEL_UP))
+ {
+ if (sp58 < MAX_LEVEL)
+ {
+ AddMonData(pokemon, MON_DATA_EXPERIENCE, (int)CalcMonExpToNextLevel(pokemon));
+ CalcMonLevelAndStats(pokemon);
+ if (sp50 == 0)
+ {
+ sp5C = (s32)GetMonData(pokemon, MON_DATA_MAXHP, NULL);
+ RestoreMonHPBy(pokemon, (u32)sp50, (u32)sp5C, (u32)(sp5C - sp54));
+ }
+ hadEffect = TRUE;
+ }
+ effectFound = TRUE;
+ }
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_EVOLVE))
+ effectFound = TRUE;
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_UP))
+ {
+ if (BoostMonMovePpUpBy(pokemon, moveIdx, 1) == TRUE)
+ hadEffect = TRUE;
+ effectFound = TRUE;
+ }
+ else if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_MAX))
+ {
+ if (BoostMonMovePpUpBy(pokemon, moveIdx, 3) == TRUE)
+ hadEffect = TRUE;
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_RESTORE))
+ {
+ if (MonMoveRestorePP(pokemon, moveIdx, (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_RESTORE_PARAM)) == 1)
+ hadEffect = TRUE;
+ effectFound = TRUE;
+ }
+ else if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_RESTORE_ALL))
+ {
+ sp50 = 0;
+ for (; sp50 < MON_MOVES; sp50++)
+ {
+ if (MonMoveRestorePP(pokemon, sp50, (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_PP_RESTORE_PARAM)) == 1)
+ hadEffect = TRUE;
+ }
+ effectFound = TRUE;
+ }
+ {
+ sp50 = (s32)GetMonData(pokemon, MON_DATA_HP_EV, NULL);
+ sp54 = (s32)GetMonData(pokemon, MON_DATA_ATK_EV, NULL);
+ sp58 = (s32)GetMonData(pokemon, MON_DATA_DEF_EV, NULL);
+ sp5C = (s32)GetMonData(pokemon, MON_DATA_SPEED_EV, NULL);
+ sp60 = (s32)GetMonData(pokemon, MON_DATA_SPATK_EV, NULL);
+ sp64 = (s32)GetMonData(pokemon, MON_DATA_SPDEF_EV, NULL);
+ if (GetMonData(pokemon, MON_DATA_SPECIES, NULL) != SPECIES_SHEDINJA &&GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_EV_UP))
+ {
+ sp6C = (int)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_HP_EV_UP_PARAM);
+ sp68 = TryModEV(sp50, sp54 + sp58 + sp5C + sp60 + sp64, sp6C);
+ if (sp68 != -1)
+ {
+ sp50 = sp68;
+ SetMonData(pokemon, MON_DATA_HP_EV, &sp50);
+ CalcMonLevelAndStats(pokemon);
+ hadEffect = TRUE;
+ }
+ if (sp6C > 0)
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_ATK_EV_UP))
+ {
+ sp6C = (int)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_ATK_EV_UP_PARAM);
+ sp68 = TryModEV(sp54, sp50 + sp58 + sp5C + sp60 + sp64, sp6C);
+ if (sp68 != -1)
+ {
+ sp54 = sp68;
+ SetMonData(pokemon, MON_DATA_ATK_EV, &sp54);
+ CalcMonLevelAndStats(pokemon);
+ hadEffect = TRUE;
+ }
+ if (sp6C > 0)
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_DEF_EV_UP))
+ {
+ sp6C = (int)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_DEF_EV_UP_PARAM);
+ sp68 = TryModEV(sp58, sp50 + sp54 + sp5C + sp60 + sp64, sp6C);
+ if (sp68 != -1)
+ {
+ sp58 = sp68;
+ SetMonData(pokemon, MON_DATA_DEF_EV, &sp58);
+ CalcMonLevelAndStats(pokemon);
+ hadEffect = TRUE;
+ }
+ if (sp6C > 0)
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPEED_EV_UP))
+ {
+ sp6C = (int)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPEED_EV_UP_PARAM);
+ sp68 = TryModEV(sp5C, sp50 + sp54 + sp58 + sp60 + sp64, sp6C);
+ if (sp68 != -1)
+ {
+ sp5C = sp68;
+ SetMonData(pokemon, MON_DATA_SPEED_EV, &sp5C);
+ CalcMonLevelAndStats(pokemon);
+ hadEffect = TRUE;
+ }
+ if (sp6C > 0)
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPATK_EV_UP))
+ {
+ sp6C = (int)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPATK_EV_UP_PARAM);
+ sp68 = TryModEV(sp60, sp50 + sp54 + sp58 + sp5C + sp64, sp6C);
+ if (sp68 != -1)
+ {
+ sp60 = sp68;
+ SetMonData(pokemon, MON_DATA_SPATK_EV, &sp60);
+ CalcMonLevelAndStats(pokemon);
+ hadEffect = TRUE;
+ }
+ if (sp6C > 0)
+ effectFound = TRUE;
+ }
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPDEF_EV_UP))
+ {
+ sp6C = (int)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_SPDEF_EV_UP_PARAM);
+ sp68 = TryModEV(sp64, sp50 + sp54 + sp58 + sp5C + sp60, sp6C);
+ if (sp68 != -1)
+ {
+ sp64 = sp68;
+ SetMonData(pokemon, MON_DATA_SPDEF_EV, &sp64);
+ CalcMonLevelAndStats(pokemon);
+ hadEffect = TRUE;
+ }
+ if (sp6C > 0)
+ effectFound = TRUE;
+ }
+ }
+ if (hadEffect == FALSE && effectFound == TRUE)
+ {
+ FreeToHeap(itemData);
+ return FALSE;
+ }
+ {
+ sp50 = (s32)GetMonData(pokemon, MON_DATA_FRIENDSHIP, NULL);
+ if (sp50 < 100)
+ {
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_LO))
+ {
+ DoItemFriendshipMod(pokemon, sp50, (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_LO_PARAM), location, heap_id);
+ FreeToHeap(itemData);
+ return hadEffect;
+ }
+ }
+ else if (sp50 >= 100 && sp50 < 200)
+ {
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_MED))
+ {
+ DoItemFriendshipMod(pokemon, sp50, (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_MED_PARAM), location, heap_id);
+ FreeToHeap(itemData);
+ return hadEffect;
+ }
+ }
+ else if (sp50 >= 200 && sp50 <= 255)
+ {
+ if (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_HI))
+ {
+ DoItemFriendshipMod(pokemon, sp50, (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_HI_PARAM), location, heap_id);
+ FreeToHeap(itemData);
+ return hadEffect;
+ }
+ }
+ }
+ FreeToHeap(itemData);
+ return hadEffect;
+}
+#undef sp6C
+#undef sp68
+#undef sp64
+#undef sp60
+#undef sp5C
+#undef sp58
+#undef sp54
+#undef sp50
+
+BOOL UseItemOnMonInParty(struct PlayerParty * party, u16 itemId, s32 partyIdx, s32 moveIdx, u16 location, u32 heap_id)
+{
+ struct Pokemon * pokemon = GetPartyMonByIndex(party, partyIdx);
+ return UseItemOnPokemon(pokemon, itemId, moveIdx, location, heap_id);
+}
+
+u8 MonMoveCanRestorePP(struct Pokemon * pokemon, s32 moveIdx)
+{
+ u16 move_id = (u16)GetMonData(pokemon, MON_DATA_MOVE1 + moveIdx, NULL);
+ if (move_id == MOVE_NONE)
+ return FALSE;
+ u8 pp = (u8)GetMonData(pokemon, MON_DATA_MOVE1PP + moveIdx, NULL);
+ u8 ppUp = (u8)GetMonData(pokemon, MON_DATA_MOVE1PPUP + moveIdx, NULL);
+ return (u8)(pp < WazaGetMaxPp(move_id, ppUp));
+}
+
+BOOL MonMoveRestorePP(struct Pokemon * pokemon, s32 moveIdx, s32 ppRestore)
+{
+ u16 move_id;
+ u8 pp;
+ u8 maxPp;
+ s32 ppAttr;
+ s32 ppUpAttr;
+
+ move_id = (u16)GetMonData(pokemon, MON_DATA_MOVE1 + moveIdx, NULL);
+ if (move_id == MOVE_NONE)
+ return FALSE;
+ ppAttr = MON_DATA_MOVE1PP + moveIdx;
+ pp = (u8)GetMonData(pokemon, ppAttr, NULL);
+ ppUpAttr = MON_DATA_MOVE1PPUP + moveIdx;
+ maxPp = WazaGetMaxPp(move_id, (u8)GetMonData(pokemon, ppUpAttr, NULL));
+ if (pp < maxPp)
+ {
+ if (ppRestore == PP_RESTORE_ALL)
+ pp = maxPp;
+ else
+ {
+ pp += ppRestore;
+ if (pp > maxPp)
+ pp = maxPp;
+ }
+ SetMonData(pokemon, ppAttr, &pp);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL BoostMonMovePpUpBy(struct Pokemon * pokemon, s32 moveIdx, u32 nPpUp)
+{
+ u16 move;
+ u8 pp, ppUp, maxPp, newMaxPp;
+ s32 ppUpAttr;
+ s32 ppAttr;
+
+ ppUpAttr = MON_DATA_MOVE1PPUP + moveIdx;
+ ppUp = (u8)GetMonData(pokemon, ppUpAttr, NULL);
+ if (ppUp == 3)
+ return FALSE;
+ move = (u16)GetMonData(pokemon, MON_DATA_MOVE1 + moveIdx, NULL);
+ if (WazaGetMaxPp(move, 0) < 5)
+ return FALSE;
+ ppAttr = MON_DATA_MOVE1PP + moveIdx;
+ pp = (u8)GetMonData(pokemon, ppAttr, NULL);
+ maxPp = WazaGetMaxPp(move, ppUp);
+ if (ppUp + nPpUp > 3)
+ ppUp = 3;
+ else
+ ppUp = (u8)(ppUp + nPpUp);
+ newMaxPp = WazaGetMaxPp(move, ppUp);
+ pp = (u8)(pp + newMaxPp - maxPp);
+ SetMonData(pokemon, ppUpAttr, &ppUp);
+ SetMonData(pokemon, ppAttr, &pp);
+ return TRUE;
+}
+
+void RestoreMonHPBy(struct Pokemon * pokemon, u32 hp, u32 maxHp, u32 restoration)
+{
+ if (maxHp == 1)
+ restoration = 1;
+ else if (restoration == HP_RESTORE_ALL)
+ restoration = maxHp;
+ else if (restoration == HP_RESTORE_HALF)
+ restoration = maxHp / 2;
+ else if (restoration == HP_RESTORE_QTR)
+ restoration = maxHp / 4;
+ if (hp + restoration > maxHp)
+ hp = maxHp;
+ else
+ hp = hp + restoration;
+ SetMonData(pokemon, MON_DATA_HP, &hp);
+}
+
+s32 TryModEV(s32 ev, s32 evSum, s32 by)
+{
+ if (ev == 0 && by < 0)
+ return -1;
+ if (ev >= MAX_EV && by > 0)
+ return -1;
+ if (ev + evSum >= MAX_EV_SUM && by > 0)
+ return -1;
+ ev += by;
+ if (ev > MAX_EV)
+ ev = MAX_EV;
+ else if (ev < 0)
+ ev = 0;
+ if (ev + evSum > MAX_EV_SUM)
+ ev = MAX_EV_SUM - evSum;
+ return ev;
+}
+
+BOOL CanItemModFriendship(struct Pokemon * pokemon, struct ItemData * itemData)
+{
+ s32 friendship = (s32)GetMonData(pokemon, MON_DATA_FRIENDSHIP, NULL);
+ if (friendship >= 255)
+ return FALSE;
+ if (friendship < 100)
+ {
+ return (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_LO) && (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_LO_PARAM) > 0);
+ }
+ if (friendship >= 100 && friendship < 200)
+ {
+ return (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_MED) && (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_MED_PARAM) > 0);
+ }
+ if (friendship >= 200 && friendship < 255)
+ {
+ return (GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_HI) && (s32)GetItemAttr_PreloadedItemData(itemData, ITEMATTR_FRIENDSHIP_MOD_HI_PARAM) > 0);
+ }
+ return FALSE;
+}
+
+BOOL DoItemFriendshipMod(struct Pokemon * pokemon, s32 friendship, s32 mod, u16 location, u32 heap_id)
+{
+ if (friendship == 255 && mod > 0)
+ return FALSE;
+ if (friendship == 0 && mod < 0)
+ return FALSE;
+ if (mod > 0)
+ {
+ if (GetItemAttr((u16)GetMonData(pokemon, MON_DATA_HELD_ITEM, NULL), ITEMATTR_HOLD_EFFECT, heap_id) == HOLD_EFFECT_FRIENDSHIP_UP)
+ mod = mod * 150 / 100;
+ if (GetMonData(pokemon, MON_DATA_POKEBALL, NULL) == ITEM_LUXURY_BALL)
+ mod++;
+ if (location == GetMonData(pokemon, MON_DATA_EGG_MET_LOCATION, NULL))
+ mod++;
+ }
+ mod += friendship;
+ if (mod > 255)
+ mod = 255;
+ if (mod < 0)
+ mod = 0;
+ SetMonData(pokemon, MON_DATA_FRIENDSHIP, &mod);
+ return TRUE;
+}
+
+void HealParty(struct PlayerParty * party)
+{
+ u32 sp8;
+ s32 nmons;
+ s32 i;
+ s32 j;
+
+ nmons = GetPartyCount(party);
+ for (i = 0; i < nmons; i++)
+ {
+ struct Pokemon * pokemon = GetPartyMonByIndex(party, i);
+ if (GetMonData(pokemon, MON_DATA_SPECIES_EXISTS, NULL))
+ {
+ sp8 = GetMonData(pokemon, MON_DATA_MAXHP, NULL);
+ SetMonData(pokemon, MON_DATA_HP, &sp8);
+
+ sp8 = 0;
+ SetMonData(pokemon, MON_DATA_STATUS, &sp8);
+
+ for (j = 0; j < MON_MOVES; j++)
+ {
+ if (MonMoveCanRestorePP(pokemon, j) == 1)
+ MonMoveRestorePP(pokemon, j, PP_RESTORE_ALL);
+ }
+ }
+ }
+}