summaryrefslogtreecommitdiff
path: root/arm9/src
diff options
context:
space:
mode:
authorCleverking2003 <30466983+Cleverking2003@users.noreply.github.com>2020-08-28 20:03:59 +0300
committerGitHub <noreply@github.com>2020-08-28 20:03:59 +0300
commit98d8b5afbffbd248d3d8bd1358f1f1b9ed0f4150 (patch)
treed92f5e462b64a05b45e08e00cd17790fabb54acf /arm9/src
parent186aa237dd5d843d119a3e0e1d404fe031f89dcf (diff)
parentcd2529e8855bdf5bb725b40524478cf197b27a62 (diff)
Merge pull request #271 from PikalaxALT/pikalax_work
player_data, daycare, use_item_on_mon, item_data.json
Diffstat (limited to 'arm9/src')
-rw-r--r--arm9/src/daycare.c114
-rw-r--r--arm9/src/itemtool.c220
-rw-r--r--arm9/src/nutdata.c3
-rw-r--r--arm9/src/player_data.c232
-rw-r--r--arm9/src/save_arrays.c14
-rw-r--r--arm9/src/scrcmd_18_c.c3
-rw-r--r--arm9/src/script_pokemon_util.c8
-rw-r--r--arm9/src/unk_020254B8.c114
-rw-r--r--arm9/src/use_item_on_mon.c719
9 files changed, 1304 insertions, 123 deletions
diff --git a/arm9/src/daycare.c b/arm9/src/daycare.c
new file mode 100644
index 00000000..eff25151
--- /dev/null
+++ b/arm9/src/daycare.c
@@ -0,0 +1,114 @@
+#include "global.h"
+#include "pokemon.h"
+#include "seals.h"
+#include "save_block_2.h"
+#include "daycare.h"
+
+#pragma thumb on
+
+u32 Sav2_DayCare_sizeof(void)
+{
+ return sizeof(struct DayCare);
+}
+
+void Sav2_DayCare_init(struct DayCare * daycare)
+{
+ memset(daycare, 0, sizeof(struct DayCare));
+ ZeroBoxMonData(&daycare->mons[0].mon);
+ ZeroBoxMonData(&daycare->mons[1].mon);
+ daycare->egg_pid = 0;
+ daycare->egg_cycles = 0;
+}
+
+struct DayCareMon * Sav2_DayCare_GetMonX(struct DayCare * daycare, s32 i)
+{
+ return &daycare->mons[i];
+}
+
+struct BoxPokemon * DayCareMon_GetBoxMon(struct DayCareMon * dcmon)
+{
+ return &dcmon->mon;
+}
+
+struct DayCareMail * DayCareMon_GetExtras(struct DayCareMon * dcmon)
+{
+ return &dcmon->mail;
+}
+
+u32 DayCareMon_GetSteps(struct DayCareMon * dcmon)
+{
+ return dcmon->steps;
+}
+
+struct SealStruct * DayCareMail_GetCapsule(struct DayCareMail * dcmail)
+{
+ return &dcmail->seal;
+}
+
+u32 Sav2_DayCare_GetEggPID(struct DayCare * daycare)
+{
+ return daycare->egg_pid;
+}
+
+u8 Sav2_DayCare_GetEggCycleCounter(struct DayCare * daycare)
+{
+ return daycare->egg_cycles;
+}
+
+void DayCareMon_SetSteps(struct DayCareMon * dcmon, u32 steps)
+{
+ dcmon->steps = steps;
+}
+
+void DayCareMon_AddSteps(struct DayCareMon * dcmon, u32 steps)
+{
+ dcmon->steps += steps;
+}
+
+void Sav2_DayCare_SetEggPID(struct DayCare * daycare, u32 pid)
+{
+ daycare->egg_pid = pid;
+}
+
+void Sav2_DayCare_SetEggCycleCounter(struct DayCare * daycare, u8 count)
+{
+ daycare->egg_cycles = count;
+}
+
+BOOL Sav2_DayCare_MasudaCheck(struct DayCare * daycare)
+{
+ // Checks if the pokemon come from different countries.
+ // Uses language as a proxy for country, even though it
+ // only accounts for European languages and Japanese.
+ // If true, shiny odds are increased (see overlay 05).
+ return GetBoxMonData(&daycare->mons[0].mon, MON_DATA_GAME_LANGUAGE, NULL) != GetBoxMonData(&daycare->mons[1].mon, MON_DATA_GAME_LANGUAGE, NULL);
+}
+
+void DayCareMon_Copy(struct DayCareMon * dest, const struct DayCareMon * src)
+{
+ *dest = *src;
+}
+
+void DayCareMon_Extras_init(struct DayCareMail * mail)
+{
+ int i;
+
+ for (i = 0; i < OT_NAME_LENGTH + 1; i++)
+ mail->ot_name[i] = 0;
+ for (i = 0; i < POKEMON_NAME_LENGTH + 1; i++)
+ mail->nickname[i] = 0;
+ mail->ot_name[0] = EOS;
+ mail->nickname[0] = EOS;
+}
+
+void DayCareMon_Init(struct DayCareMon * mon)
+{
+ ZeroBoxMonData(&mon->mon);
+ mon->steps = 0;
+ DayCareMon_Extras_init(&mon->mail);
+}
+
+struct DayCare * Sav2_DayCare_get(struct SaveBlock2 * sav2)
+{
+ return (struct DayCare *)SavArray_get(sav2, 8);
+}
diff --git a/arm9/src/itemtool.c b/arm9/src/itemtool.c
index 9cd7552d..75785ee8 100644
--- a/arm9/src/itemtool.c
+++ b/arm9/src/itemtool.c
@@ -786,141 +786,141 @@ u32 GetItemAttr_PreloadedItemData(struct ItemData * itemData, u32 attr)
{
switch (attr)
{
- case 0:
+ case ITEMATTR_PRICE:
return itemData->price;
- case 1:
+ case ITEMATTR_HOLD_EFFECT:
return itemData->holdEffect;
- case 2:
+ case ITEMATTR_HOLD_EFFECT_PARAM:
return itemData->holdEffectParam;
- case 3:
- return itemData->unk8_5;
- case 4:
- return itemData->unk8_6;
- case 5:
+ case ITEMATTR_PREVENT_TOSS:
+ return itemData->prevent_toss;
+ case ITEMATTR_SELECTABLE:
+ return itemData->selectable;
+ case ITEMATTR_POCKET:
return itemData->pocket;
- case 6:
+ case ITEMATTR_UNKA:
return itemData->unkA;
- case 7:
+ case ITEMATTR_UNKB:
return itemData->unkB;
- case 8:
+ case ITEMATTR_UNK4:
return itemData->unk4;
- case 9:
+ case ITEMATTR_UNK5:
return itemData->unk5;
- case 10:
+ case ITEMATTR_UNK6:
return itemData->unk6;
- case 11:
+ case ITEMATTR_NATURAL_GIFT_POWER:
return itemData->naturalGiftPower;
- case 12:
+ case ITEMATTR_UNK8_0:
return itemData->unk8_0;
- case 13:
+ case ITEMATTR_UNK8_B:
return itemData->unk8_B;
- case 14:
- return itemData->unkC;
+ case ITEMATTR_PARTY_USE:
+ return itemData->partyUse;
default:
- switch (itemData->unkC)
+ switch (itemData->partyUse)
{
case 0:
- return itemData->unkE.flat;
+ return itemData->partyUseParam.flat;
case 1:
- return GetItemAttrSub(&itemData->unkE.sub, attr);
+ return GetItemAttrSub(&itemData->partyUseParam.sub, attr);
default:
return 0;
}
}
}
-u32 GetItemAttrSub(struct ItemDataSub * sub, u32 attr)
+u32 GetItemAttrSub(struct ItemPartyUseParam * sub, u32 attr)
{
switch (attr)
{
- case 15:
- return sub->unk0_0;
- case 16:
- return sub->unk0_1;
- case 17:
- return sub->unk0_2;
- case 18:
- return sub->unk0_3;
- case 19:
- return sub->unk0_4;
- case 20:
- return sub->unk0_5;
- case 21:
- return sub->unk0_6;
- case 22:
- return sub->unk0_7;
- case 23:
- return sub->unk1_0;
- case 24:
- return sub->unk1_1;
- case 25:
- return sub->unk1_2;
- case 26:
- return sub->unk1_3;
- case 27:
- return sub->unk1_4;
- case 28:
- return sub->unk2_0;
- case 29:
- return sub->unk2_4;
- case 30:
- return sub->unk3_0;
- case 31:
- return sub->unk3_4;
- case 32:
- return sub->unk4_0;
- case 33:
- return sub->unk4_4;
- case 34:
- return sub->unk4_6;
- case 35:
- return sub->unk4_7;
- case 36:
- return sub->unk5_0;
- case 37:
- return sub->unk5_1;
- case 38:
- return sub->unk5_2;
- case 39:
- return sub->unk5_3;
- case 40:
- return sub->unk5_4;
- case 41:
- return sub->unk5_5;
- case 42:
- return sub->unk5_6;
- case 43:
- return sub->unk5_7;
- case 44:
- return sub->unk6_0;
- case 45:
- return sub->unk6_1;
- case 46:
- return sub->unk6_2;
- case 47:
- return sub->unk6_3;
- case 48:
- return sub->unk7;
- case 49:
- return sub->unk8;
- case 50:
- return sub->unk9;
- case 51:
- return sub->unkA;
- case 52:
- return sub->unkB;
- case 53:
- return sub->unkC;
- case 54:
- return sub->unkD;
- case 55:
- return sub->unkE;
- case 56:
- return sub->unkF;
- case 57:
- return sub->unk10;
- case 58:
- return sub->unk11;
+ case ITEMATTR_SLP_HEAL:
+ return sub->slp_heal;
+ case ITEMATTR_PSN_HEAL:
+ return sub->psn_heal;
+ case ITEMATTR_BRN_HEAL:
+ return sub->brn_heal;
+ case ITEMATTR_FRZ_HEAL:
+ return sub->frz_heal;
+ case ITEMATTR_PRZ_HEAL:
+ return sub->prz_heal;
+ case ITEMATTR_CFS_HEAL:
+ return sub->cfs_heal;
+ case ITEMATTR_INF_HEAL:
+ return sub->inf_heal;
+ case ITEMATTR_GUARD_SPEC:
+ return sub->guard_spec;
+ case ITEMATTR_REVIVE:
+ return sub->revive;
+ case ITEMATTR_REVIVE_ALL:
+ return sub->revive_all;
+ case ITEMATTR_LEVEL_UP:
+ return sub->level_up;
+ case ITEMATTR_EVOLVE:
+ return sub->evolve;
+ case ITEMATTR_ATK_STAGES:
+ return sub->atk_stages;
+ case ITEMATTR_DEF_STAGES:
+ return sub->def_stages;
+ case ITEMATTR_SPATK_STAGES:
+ return sub->spatk_stages;
+ case ITEMATTR_SPDEF_STAGES:
+ return sub->spdef_stages;
+ case ITEMATTR_SPEED_STAGES:
+ return sub->speed_stages;
+ case ITEMATTR_ACCURACY_STAGES:
+ return sub->accuracy_stages;
+ case ITEMATTR_CRITRATE_STAGES:
+ return sub->critrate_stages;
+ case ITEMATTR_PP_UP:
+ return sub->pp_up;
+ case ITEMATTR_PP_MAX:
+ return sub->pp_max;
+ case ITEMATTR_PP_RESTORE:
+ return sub->pp_restore;
+ case ITEMATTR_PP_RESTORE_ALL:
+ return sub->pp_restore_all;
+ case ITEMATTR_HP_RESTORE:
+ return sub->hp_restore;
+ case ITEMATTR_HP_EV_UP:
+ return sub->hp_ev_up;
+ case ITEMATTR_ATK_EV_UP:
+ return sub->atk_ev_up;
+ case ITEMATTR_DEF_EV_UP:
+ return sub->def_ev_up;
+ case ITEMATTR_SPEED_EV_UP:
+ return sub->speed_ev_up;
+ case ITEMATTR_SPATK_EV_UP:
+ return sub->spatk_ev_up;
+ case ITEMATTR_SPDEF_EV_UP:
+ return sub->spdef_ev_up;
+ case ITEMATTR_FRIENDSHIP_MOD_LO:
+ return sub->friendship_mod_lo;
+ case ITEMATTR_FRIENDSHIP_MOD_MED:
+ return sub->friendship_mod_med;
+ case ITEMATTR_FRIENDSHIP_MOD_HI:
+ return sub->friendship_mod_hi;
+ case ITEMATTR_HP_EV_UP_PARAM:
+ return sub->hp_ev_up_param;
+ case ITEMATTR_ATK_EV_UP_PARAM:
+ return sub->atk_ev_up_param;
+ case ITEMATTR_DEF_EV_UP_PARAM:
+ return sub->def_ev_up_param;
+ case ITEMATTR_SPEED_EV_UP_PARAM:
+ return sub->speed_ev_up_param;
+ case ITEMATTR_SPATK_EV_UP_PARAM:
+ return sub->spatk_ev_up_param;
+ case ITEMATTR_SPDEF_EV_UP_PARAM:
+ return sub->spdef_ev_up_param;
+ case ITEMATTR_HP_RESTORE_PARAM:
+ return sub->hp_restore_param;
+ case ITEMATTR_PP_RESTORE_PARAM:
+ return sub->pp_restore_param;
+ case ITEMATTR_FRIENDSHIP_MOD_LO_PARAM:
+ return sub->friendship_mod_lo_param;
+ case ITEMATTR_FRIENDSHIP_MOD_MED_PARAM:
+ return sub->friendship_mod_med_param;
+ case ITEMATTR_FRIENDSHIP_MOD_HI_PARAM:
+ return sub->friendship_mod_hi_param;
default:
return 0;
}
diff --git a/arm9/src/nutdata.c b/arm9/src/nutdata.c
index a8f916e2..27c600fa 100644
--- a/arm9/src/nutdata.c
+++ b/arm9/src/nutdata.c
@@ -1,7 +1,8 @@
#include "global.h"
#include "filesystem.h"
-#include "itemtool.h"
+#include "nutdata.h"
#include "msgdata.h"
+#include "constants/items.h"
#pragma thumb on
diff --git a/arm9/src/player_data.c b/arm9/src/player_data.c
new file mode 100644
index 00000000..ea5802aa
--- /dev/null
+++ b/arm9/src/player_data.c
@@ -0,0 +1,232 @@
+#include "global.h"
+#include "save_block_2.h"
+#include "player_data.h"
+#include "MI_memory.h"
+#include "heap.h"
+#include "string16.h"
+#include "options.h"
+#include "coins.h"
+
+#pragma thumb on
+
+void PlayerProfile_init(struct PlayerData * data);
+
+u32 Sav2_PlayerData_sizeof(void)
+{
+ return sizeof(struct PlayerDataSav);
+}
+
+void Sav2_PlayerData_init(struct PlayerDataSav * pds)
+{
+ MI_CpuClearFast(pds, sizeof(struct PlayerDataSav));
+ Options_init(&pds->options);
+ PlayerProfile_init(&pds->data);
+ InitCoins(&pds->coins);
+ InitIGT(&pds->igt);
+}
+
+struct PlayerData * Sav2_PlayerData_GetProfileAddr(struct SaveBlock2 * sav2)
+{
+ return &((struct PlayerDataSav *)SavArray_get(sav2, 1))->data;
+}
+
+struct Options * Sav2_PlayerData_GetOptionsAddr(struct SaveBlock2 * sav2)
+{
+ return &((struct PlayerDataSav *)SavArray_get(sav2, 1))->options;
+}
+
+u16 * Sav2_PlayerData_GetCoinsAddr(struct SaveBlock2 * sav2)
+{
+ return &((struct PlayerDataSav *)SavArray_get(sav2, 1))->coins;
+}
+
+struct IGT * Sav2_PlayerData_GetIGTAddr(struct SaveBlock2 * sav2)
+{
+ return &((struct PlayerDataSav *)SavArray_get(sav2, 1))->igt;
+}
+
+u32 PlayerProfile_sizeof(void)
+{
+ return sizeof(struct PlayerData);
+}
+
+struct PlayerData * PlayerProfile_new(u32 heap_id)
+{
+ struct PlayerData * ret = (struct PlayerData *)AllocFromHeap(heap_id, sizeof(struct PlayerData));
+ PlayerProfile_init(ret);
+ return ret;
+}
+
+void PlayerProfile_Copy(const struct PlayerData * src, struct PlayerData * dest)
+{
+ MI_CpuCopy8(src, dest, sizeof(struct PlayerData));
+}
+
+void PlayerProfile_init(struct PlayerData * data)
+{
+ memset(data, 0, sizeof(struct PlayerData));
+ data->language = LANGUAGE_ENGLISH;
+}
+
+void CopyPlayerName(u16 * dest, struct PlayerData * data)
+{
+ GF_ASSERT((s32)StringLength(data->playerName) < OT_NAME_LENGTH + 1);
+ CopyU16StringArray(dest, data->playerName);
+}
+
+void PlayerName_StringToFlat(struct PlayerData * data, struct String * str)
+{
+ CopyStringToU16Array(str, data->playerName, OT_NAME_LENGTH + 1);
+}
+
+u16 * PlayerProfile_GetNamePtr(struct PlayerData * data)
+{
+ return data->playerName;
+}
+
+void PlayerName_FlatToString(struct PlayerData * data, struct String * str)
+{
+ CopyU16ArrayToString(str, data->playerName);
+}
+
+struct String * PlayerProfile_GetPlayerName_NewString(struct PlayerData * data, u32 heap_id)
+{
+ struct String * str = String_ctor(OT_NAME_LENGTH + 1, heap_id);
+ PlayerName_FlatToString(data, str);
+ return str;
+}
+
+void PlayerProfile_SetTrainerID(struct PlayerData * data, u32 otid)
+{
+ data->playerId = otid;
+}
+
+u32 PlayerProfile_GetTrainerID(struct PlayerData * data)
+{
+ return data->playerId;
+}
+
+u16 PlayerProfile_GetTrainerID_VisibleHalf(struct PlayerData * data)
+{
+ return (u16)data->playerId;
+}
+
+void PlayerProfile_SetTrainerGender(struct PlayerData * data, u8 gender)
+{
+ data->gender = gender;
+}
+
+u32 PlayerProfile_GetTrainerGender(struct PlayerData * data)
+{
+ return data->gender;
+}
+
+BOOL PlayerProfile_TestBadgeFlag(struct PlayerData * data, u32 badgeno)
+{
+ return (data->badges & (1 << badgeno)) != 0;
+}
+
+void PlayerProfile_SetBadgeFlag(struct PlayerData * data, u32 badgeno)
+{
+ data->badges |= (1 << badgeno);
+}
+
+u32 PlayerProfile_CountBadges(struct PlayerData * data)
+{
+ u32 count;
+ u32 badges;
+ for (count = 0, badges = data->badges; badges != 0; badges >>= 1)
+ {
+ if (badges & 1)
+ count++;
+ }
+ return count;
+}
+
+u32 PlayerProfile_GetMoney(struct PlayerData * data)
+{
+ return data->money;
+}
+
+u32 PlayerProfile_SetMoney(struct PlayerData * data, u32 amount)
+{
+ if (amount > 999999)
+ amount = 999999;
+ data->money = amount;
+ return amount;
+}
+
+u8 PlayerProfile_GetAvatar(struct PlayerData * data)
+{
+ return data->avatar;
+}
+
+void PlayerProfile_SetAvatar(struct PlayerData * data, u8 avatar)
+{
+ data->avatar = avatar;
+}
+
+u32 PlayerProfile_AddMoney(struct PlayerData * data, u32 amount)
+{
+ if (amount > 999999)
+ data->money = 999999;
+ else
+ data->money += amount;
+ if (data->money > 999999)
+ data->money = 999999;
+ return data->money;
+}
+
+u32 PlayerProfile_SubMoney(struct PlayerData * data, u32 amount)
+{
+ if (data->money < amount)
+ data->money = 0;
+ else
+ data->money -= amount;
+ return data->money;
+}
+
+u8 PlayerProfile_GetVersion(struct PlayerData * data)
+{
+ return data->version;
+}
+
+void PlayerProfile_SetVersion(struct PlayerData * data, u8 a1)
+{
+ data->version = a1;
+}
+
+u8 PlayerProfile_GetLanguage(struct PlayerData * data)
+{
+ return data->language;
+}
+
+void PlayerProfile_SetLanguage(struct PlayerData * data, u8 language)
+{
+ data->language = language;
+}
+
+void PlayerProfile_SetGameClearFlag(struct PlayerData * data)
+{
+ data->gameCleared = 1;
+}
+
+BOOL PlayerProfile_GetGameClearFlag(struct PlayerData * data)
+{
+ return data->gameCleared;
+}
+
+void PlayerProfile_SetNatDexFlag(struct PlayerData * data)
+{
+ data->nationalDex = 1;
+}
+
+BOOL PlayerProfile_GetNatDexFlag(struct PlayerData * data)
+{
+ return data->nationalDex;
+}
+
+BOOL PlayerProfile_NameAndOTIDMatchPlayer(struct PlayerData * a, struct PlayerData * b)
+{
+ return !StringNotEqualN(a->playerName, b->playerName, OT_NAME_LENGTH) && a->playerId == b->playerId;
+}
diff --git a/arm9/src/save_arrays.c b/arm9/src/save_arrays.c
index 797539d2..bccdcc11 100644
--- a/arm9/src/save_arrays.c
+++ b/arm9/src/save_arrays.c
@@ -9,12 +9,12 @@
#include "poketch.h"
#include "hall_of_fame.h"
#include "unk_020286F8.h"
+#include "unk_020254B8.h"
+#include "daycare.h"
extern u32 FUN_0202AC20(void);
extern u32 FUN_02034D7C(void);
-extern u32 FUN_02023D64(void);
-extern u32 FUN_02023C40(void);
-extern u32 FUN_020254B8(void);
+extern u32 Sav2_Pokedex_sizeof(void);
extern u32 FUN_02024E64(void);
extern u32 FUN_02034D80(void);
extern u32 FUN_02025954(void);
@@ -40,9 +40,7 @@ extern u32 FUN_0202C0E0(void);
extern u32 FUN_02013B28(void);
extern void FUN_0202AC28(void *);
extern void FUN_02034D98(void *);
-extern void FUN_02024378(void *);
-extern void FUN_02023C48(void *);
-extern void FUN_020254CC(void *);
+extern void Sav2_Pokedex_init(void *);
extern void FUN_02024E6C(void *);
extern void FUN_02034D88(void *);
extern void FUN_0202597C(void *);
@@ -80,8 +78,8 @@ const struct SaveChunkHeader UNK_020EE700[] = {
{ 4, 0, (SAVSIZEFN)SavArray_Flags_sizeof, (SAVINITFN)SavArray_Flags_init },
{ 5, 0, (SAVSIZEFN)Sav2_Poketch_sizeof, (SAVINITFN)Sav2_Poketch_init },
{ 6, 0, (SAVSIZEFN)FUN_02034D7C, (SAVINITFN)FUN_02034D98 },
- { 7, 0, (SAVSIZEFN)FUN_02023D64, (SAVINITFN)FUN_02024378 },
- { 8, 0, (SAVSIZEFN)FUN_02023C40, (SAVINITFN)FUN_02023C48 },
+ { 7, 0, (SAVSIZEFN)Sav2_Pokedex_sizeof, (SAVINITFN)Sav2_Pokedex_init },
+ { 8, 0, (SAVSIZEFN)Sav2_DayCare_sizeof, (SAVINITFN)Sav2_DayCare_init },
{ 9, 0, (SAVSIZEFN)FUN_020254B8, (SAVINITFN)FUN_020254CC },
{ 10, 0, (SAVSIZEFN)FUN_02024E64, (SAVINITFN)FUN_02024E6C },
{ 11, 0, (SAVSIZEFN)FUN_02034D80, (SAVINITFN)FUN_02034D88 },
diff --git a/arm9/src/scrcmd_18_c.c b/arm9/src/scrcmd_18_c.c
index d2753587..b8bbbcdd 100644
--- a/arm9/src/scrcmd_18_c.c
+++ b/arm9/src/scrcmd_18_c.c
@@ -4,6 +4,7 @@
#include "save_block_2.h"
#include "unk_0204639C.h"
#include "map_header.h"
+#include "scrcmd.h"
extern u16 VarGet(struct UnkStruct_0204639C* arg, u16 wk);
extern u16 *GetVarPointer(struct UnkStruct_0204639C* arg, u16);
@@ -18,6 +19,6 @@ THUMB_FUNC BOOL ScrCmd_givemon(struct ScriptContext* ctx)
u16 item = VarGet(ctx->unk80, ScriptReadHalfword(ctx));
u16 * varPtr = GetVarPointer(ctx->unk80, ScriptReadHalfword(ctx));
struct PlayerParty * party = SavArray_PlayerParty_get((struct SaveBlock2 *) savePtr->unkC);
- *varPtr = GiveMon(11, (struct SaveBlock2 *) savePtr->unkC, species, level, item, mapSec, 12);
+ *varPtr = (u16)GiveMon(11, (struct SaveBlock2 *) savePtr->unkC, species, (u8)level, item, mapSec, 12);
return FALSE;
}
diff --git a/arm9/src/script_pokemon_util.c b/arm9/src/script_pokemon_util.c
index fccdb15e..a3518bf4 100644
--- a/arm9/src/script_pokemon_util.c
+++ b/arm9/src/script_pokemon_util.c
@@ -7,6 +7,7 @@
#include "unk_02015CC0.h"
#include "unk_0202C144.h"
#include "module_05.h"
+#include "script_pokemon_util.h"
#include "constants/items.h"
#include "constants/script_pokemon_util.h"
@@ -44,6 +45,7 @@ BOOL GiveMon(u32 heap_id, struct SaveBlock2 * sav2, u16 species, u8 level, u16 i
/* Seems to have something to do with Manaphy Egg*/
BOOL GiveEgg(u32 heapId, struct SaveBlock2 * sav2, u16 species, int level, int metLocIndex, int a3)
{
+#pragma unused(heapId)
struct PlayerData * data = Sav2_PlayerData_GetProfileAddr(sav2);
struct PlayerParty * party = SavArray_PlayerParty_get(sav2);
struct Pokemon * mon = AllocMonZeroed(32);
@@ -57,7 +59,7 @@ BOOL GiveEgg(u32 heapId, struct SaveBlock2 * sav2, u16 species, int level, int m
void PartyMonSetMoveInSlot(struct PlayerParty * party, int partySlot, int moveSlot, u16 move)
{
struct Pokemon * mon = GetPartyMonByIndex(party, partySlot);
- MonSetMoveInSlot(mon, move, moveSlot);
+ MonSetMoveInSlot(mon, move, (u8)moveSlot);
}
int GetIdxOfFirstPartyMonWithMove(struct PlayerParty * party, int move)
@@ -114,7 +116,7 @@ struct Pokemon * GetFirstAliveMonInParty_CrashIfNone(struct PlayerParty * party)
struct Pokemon * GetFirstNonEggInParty(struct PlayerParty * party)
{
u16 i;
- u16 partyCount = GetPartyCount(party);
+ u16 partyCount = (u16)GetPartyCount(party);
for (i = 0; i < partyCount; i++)
{
@@ -172,7 +174,7 @@ int ApplyPoisonStep(struct PlayerParty * party, int location)
if (hp == 1)
{
numHealed++;
- MonApplyFriendshipMod(mon, FRIENDSHIP_EVENT_HEAL_FIELD_PSN, location);
+ MonApplyFriendshipMod(mon, FRIENDSHIP_EVENT_HEAL_FIELD_PSN, (u32)location);
}
numPoisoned++;
}
diff --git a/arm9/src/unk_020254B8.c b/arm9/src/unk_020254B8.c
new file mode 100644
index 00000000..ed323965
--- /dev/null
+++ b/arm9/src/unk_020254B8.c
@@ -0,0 +1,114 @@
+#include "global.h"
+#include "string_util.h"
+#include "save_block_2.h"
+#include "heap.h"
+#include "unk_020254B8.h"
+
+#pragma thumb on
+
+u32 FUN_020254B8(void)
+{
+ return 16 * sizeof(struct UnkStruct_020254B8);
+}
+
+struct UnkStruct_020254B8 * FUN_020254C0(struct SaveBlock2 * sav2)
+{
+ return (struct UnkStruct_020254B8 *)SavArray_get(sav2, 9);
+}
+
+void FUN_020254CC(struct UnkStruct_020254B8 * arr)
+{
+ s32 i;
+
+ for (i = 0; i < 16; i++)
+ {
+ memset(&arr[i], 0, sizeof(struct UnkStruct_020254B8));
+ arr[i].field_00[0] = EOS;
+ }
+}
+
+u16 * FUN_020254F0(struct UnkStruct_020254B8 * arr, s32 i)
+{
+ return arr[i].field_00;
+}
+
+u8 FUN_020254F8(struct UnkStruct_020254B8 * unk, s32 i)
+{
+ return unk->field_68[i];
+}
+
+BOOL FUN_02025500(struct UnkStruct_020254B8 * a, struct UnkStruct_020254B8 * b)
+{
+ return !StringNotEqual(a->field_00, b->field_00) && a->field_10 == b->field_10;
+}
+
+void FUN_02025520(struct UnkStruct_020254B8 * sp0, struct UnkStruct_020254B8 * sp4, s32 n, u32 heap_id)
+{
+ s32 sp18[5];
+ s32 sp14;
+ struct UnkStruct_020254B8 * sp10;
+ s32 r12;
+ s32 spC;
+ s32 r4;
+ s32 r4_2;
+
+ // auto buffer = new UnkStruct_020254B8[16]
+ sp10 = AllocFromHeap(heap_id, 16 * sizeof(struct UnkStruct_020254B8));
+ FUN_020254CC(sp10);
+
+ // Look up each element of sp4 in sp0
+ for (sp14 = 0; sp14 < n; sp14++)
+ {
+ sp18[sp14] = -1;
+ for (r4_2 = 0; r4_2 < 16; r4_2++)
+ {
+ if (FUN_02025500(&sp0[r4_2], &sp4[sp14]))
+ sp18[sp14] = r4_2;
+ }
+ }
+
+ // Copy sp4 to buffer and mask matching entries in sp0
+ r4 = 0;
+ for (spC = 0; spC < n; spC++)
+ {
+ sp10[r4] = sp4[spC];
+ if (sp18[spC] >= 0)
+ sp0[sp18[spC]].field_00[0] = EOS;
+ r4++;
+ }
+
+ // Copy unmasked entries from sp0 to buffer
+ for (r12 = 0; r12 < 16; r12++)
+ {
+ if (sp0[r12].field_00[0] != EOS)
+ {
+ sp10[r4] = sp0[r12];
+ r4++;
+ if (r4 >= 16)
+ break;
+ }
+ }
+ // Copy buffer to sp0 and destroy buffer
+ memcpy(sp0, sp10, 16 * sizeof(struct UnkStruct_020254B8));
+ FreeToHeap(sp10);
+}
+
+s32 FUN_02025614(struct UnkStruct_020254B8 * a0, u32 a1)
+{
+ s32 i, j;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (a1 == a0[i].field_10)
+ return 1;
+ }
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ if (a1 == a0[i].field_18[j])
+ return i + 2;
+ }
+ }
+ return 0;
+}
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);
+ }
+ }
+ }
+}