-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Make Pokemon Not Heal When Going into PC
voloved edited this page Nov 4, 2023
·
3 revisions
By devolov
Goal: Make it so depositing a Pokemon into the PC doesn't heal them.
This hack was made for me because I allow accessing the PC from the PokeNav, but this can also have a purpose for difficulty hacks where healing is not free.
------------------------------ include/pokemon.h ------------------------------
index 377e03f30..28c8d0207 100644
@@ -11,8 +11,9 @@ enum {
MON_DATA_LANGUAGE,
MON_DATA_SANITY_IS_BAD_EGG,
MON_DATA_SANITY_HAS_SPECIES,
MON_DATA_SANITY_IS_EGG,
+ MON_DATA_IN_PC,
MON_DATA_OT_NAME,
MON_DATA_MARKINGS,
MON_DATA_CHECKSUM,
MON_DATA_ENCRYPT_SEPARATOR,
@@ -94,9 +95,8 @@ enum {
MON_DATA_SPEED2,
MON_DATA_SPATK2,
MON_DATA_SPDEF2,
MON_DATA_DEAD,
MON_DATA_NATURE,
MON_DATA_HIDDEN_NATURE,
+ MON_DATA_BOX_HP,
+ MON_DATA_BOX_AILMENT,
};
struct PokemonSubstruct0
{
@@ -106,10 +109,10 @@ struct PokemonSubstruct0
u32 experience;
u8 ppBonuses;
u8 friendship;
u8 hiddenNature:5; // This is from the Nature Mints hack (https://www.pokecommunity.com/showpost.php?p=10245635&postcount=191)
- u8 free_sub0:3;
- u8 filler;
+ u8 box_ailment:3; //Set to zero unless pokemon is in the box
+ u8 box_hp; //Set to zero unless pokemon is in the box, then it's set to the HP is maxHP is <256 o/w currHP/maxHP * 255
};
struct PokemonSubstruct1
{
@@ -200,13 +203,14 @@ struct BoxPokemon
u8 isBadEgg:1;
u8 hasSpecies:1;
u8 isEgg:1;
u8 blockBoxRS:1; // Unused, but Pokémon Box Ruby & Sapphire will refuse to deposit a Pokémon with this flag set
- u8 unused:4;
+ u8 unused:3;
+ u8 inPC:1; //Used to retain save compatibility for Pokemon that existed in the PC before adding the "Make Pokemon Not Heal When Going into PC" hack
u8 otName[PLAYER_NAME_LENGTH];
u8 markings;
u16 checksum;
u16 unknown;
union
{
u32 raw[(NUM_SUBSTRUCT_BYTES * 4) / 4]; // *4 because there are 4 substructs, /4 because it's u32, not u8
----------------------- include/pokemon_storage_system.h -----------------------
index bdf2e8ef1..a42fd3ff7 100644
@@ -73,6 +73,9 @@ void SetWaldaPhrase(const u8 *src);
bool32 IsWaldaPhraseEmpty(void);
void CB2_ReturnToPokeStorage(void);
void EnterPokeStorage(u8 boxOption);
+u16 GetHPFromBoxHP(struct Pokemon *mon);
+u32 GetStatusFromBoxStatus(struct Pokemon *mon);
#endif // GUARD_POKEMON_STORAGE_SYSTEM_H
-------------------------------- src/pokemon.c --------------------------------
index 602960a2f..76a1486da 100644
@@ -3844,8 +3844,11 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
break;
case MON_DATA_SANITY_IS_EGG:
retVal = boxMon->isEgg;
break;
+ case MON_DATA_IN_PC:
+ retVal = boxMon->inPC;
+ break;
case MON_DATA_OT_NAME:
{
retVal = 0;
@@ -4111,8 +4114,14 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
break; // Tail end of case MON_DATA_NATURE
case MON_DATA_HIDDEN_NATURE:
retVal = substruct0->hiddenNature;
break;
+ case MON_DATA_BOX_HP:
+ retVal = substruct0->box_hp;
+ break;
+ case MON_DATA_BOX_AILMENT:
+ retVal = substruct0->box_ailment;
+ break;
default:
break;
}
@@ -4231,8 +4240,11 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
break;
case MON_DATA_SANITY_IS_EGG:
SET8(boxMon->isEgg);
break;
+ case MON_DATA_IN_PC:
+ SET8(boxMon->inPC);
+ break;
case MON_DATA_OT_NAME:
{
s32 i;
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
@@ -4514,8 +4526,14 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
} // Tail end of case MON_DATA_NATURE
case MON_DATA_HIDDEN_NATURE:
SET8(substruct0->hiddenNature);
break;
+ case MON_DATA_BOX_HP:
+ SET8(substruct0->box_hp);
+ break;
+ case MON_DATA_BOX_AILMENT:
+ SET8(substruct0->box_ailment);
+ break;
default:
break;
}
------------------------- src/pokemon_storage_system.c -------------------------
index 77cf2f9ae..73c32e5d9 100644
@@ -21,8 +21,9 @@
#include "mon_markings.h"
#include "naming_screen.h"
#include "overworld.h"
#include "palette.h"
+#include "party_menu.h"
#include "pc_screen_effect.h"
#include "pokemon.h"
#include "pokemon_icon.h"
#include "pokemon_summary_screen.h"
@@ -35,10 +36,12 @@
#include "text_window.h"
#include "trig.h"
#include "walda_phrase.h"
#include "window.h"
+#include "constants/battle.h"
#include "constants/items.h"
#include "constants/moves.h"
+#include "constants/party_menu.h"
#include "constants/rgb.h"
#include "constants/songs.h"
/*
@@ -6366,17 +6369,107 @@ static void SetMovingMonData(u8 boxId, u8 position)
sMovingMonOrigBoxId = boxId;
sMovingMonOrigBoxPos = position;
}
+static u8 GetBoxHPFromHP(struct Pokemon *mon)
+{
+ u8 hp_box;
+ u16 hp_curr = GetMonData(mon, MON_DATA_HP);
+ u16 hp_max = GetMonData(mon, MON_DATA_MAX_HP);
+ if (hp_max <= 0xFF) // If the HP is small enough to fully fit into a u8, put in the precise value
+ hp_box = hp_curr;
+ else // Otherwise, round
+ hp_box = SAFE_DIV(0xFF * hp_curr, hp_max);
+ if(hp_curr != 0 && hp_box == 0) // to stop accidental fainting
+ hp_box = 1;
+ return hp_box;
+}
+
+u16 GetHPFromBoxHP(struct Pokemon *mon)
+{
+ u16 hp_curr;
+ u8 hp_box = GetMonData(mon, MON_DATA_BOX_HP);
+ u16 hp_max = GetMonData(mon, MON_DATA_MAX_HP);
+ if (hp_max <= 0xFF)
+ hp_curr = hp_box;
+ else
+ hp_curr = SAFE_DIV(hp_max * hp_box, 0xFF);
+ return hp_curr;
+}
+
+static u8 GetBoxStatusFromStatus(struct Pokemon *mon)
+{
+ u32 status = GetMonData(mon, MON_DATA_STATUS);
+ u8 ailment = GetAilmentFromStatus(status);
+ if (ailment > 7) //Chops off anything above what 3 bits can hold
+ ailment = 0;
+ return ailment;
+}
+
+u32 GetStatusFromBoxStatus(struct Pokemon *mon)
+{
+ u8 boxStatus = GetMonData(mon, MON_DATA_BOX_AILMENT);
+ u32 status;
+ switch (boxStatus)
+ {
+ case AILMENT_PSN:
+ status = STATUS1_POISON;
+ break;
+ case AILMENT_PRZ:
+ status = STATUS1_PARALYSIS;
+ break;
+ case AILMENT_SLP:
+ status = STATUS1_SLEEP_TURN(3);
+ break;
+ case AILMENT_FRZ:
+ status = STATUS1_FREEZE;
+ break;
+ case AILMENT_BRN:
+ status = STATUS1_BURN;
+ break;
+ default:
+ status = STATUS1_NONE;
+ break;
+ }
+ return status;
+}
+
static void SetPlacedMonData(u8 boxId, u8 position)
{
+ u32 hp;
+ u32 status;
+ u8 value;
if (boxId == TOTAL_BOXES_COUNT)
{
+ if(GetMonData(&sStorage->movingMon, MON_DATA_IN_PC))
+ {
+ hp = GetHPFromBoxHP(&sStorage->movingMon);
+ status = GetStatusFromBoxStatus(&sStorage->movingMon);
+ SetMonData(&sStorage->movingMon, MON_DATA_HP, &hp);
+ SetMonData(&sStorage->movingMon, MON_DATA_STATUS, &status);
+ }
+ else
+ MonRestorePP(&sStorage->movingMon);
+ value = 0;
+ SetBoxMonData(&sStorage->movingMon.box, MON_DATA_IN_PC, &value);
+ SetBoxMonData(&sStorage->movingMon.box, MON_DATA_BOX_HP, &value);
+ SetBoxMonData(&sStorage->movingMon.box, MON_DATA_BOX_AILMENT, &value);
gPlayerParty[position] = sStorage->movingMon;
}
else
{
- BoxMonRestorePP(&sStorage->movingMon.box);
+ value = TRUE;
+ hp = GetBoxHPFromHP(&sStorage->movingMon);
+ status = GetBoxStatusFromStatus(&sStorage->movingMon);
+ SetBoxMonData(&sStorage->movingMon.box, MON_DATA_IN_PC, &value);
+ SetBoxMonData(&sStorage->movingMon.box, MON_DATA_BOX_HP, &hp);
+ SetBoxMonData(&sStorage->movingMon.box, MON_DATA_BOX_AILMENT, &status);
SetBoxMonAt(boxId, position, &sStorage->movingMon.box);
}
}
@@ -6703,12 +6796,24 @@ static void LoadSavedMovingMon(void)
}
static void InitSummaryScreenData(void)
{
+ u16 hp;
+ u32 status;
if (sIsMonBeingMoved)
{
SaveMovingMon();
sStorage->summaryMon.mon = &sSavedMovingMon;
+ if (GetMonData(&sStorage->movingMon, MON_DATA_IN_PC) && sMovingMonOrigBoxId != TOTAL_BOXES_COUNT)
+ // If it did not come from the party
+ {
+ hp = GetHPFromBoxHP(&sStorage->movingMon);
+ status = GetStatusFromBoxStatus(&sStorage->movingMon);
+ SetMonData(sStorage->summaryMon.mon, MON_DATA_HP, &hp);
+ SetMonData(sStorage->summaryMon.mon, MON_DATA_STATUS, &status);
+ }
+ else
+ MonRestorePP(sStorage->summaryMon.mon);
sStorage->summaryStartPos = 0;
sStorage->summaryMaxPos = 0;
sStorage->summaryScreenMode = SUMMARY_MODE_NORMAL;
}
------------------------- src/pokemon_summary_screen.c -------------------------
index 8b6051561..63a2964fd 100644
@@ -1404,8 +1404,17 @@ static void CopyMonToSummaryStruct(struct Pokemon *mon)
else
{
struct BoxPokemon *boxMon = sMonSummaryScreen->monList.boxMons;
BoxMonToMon(&boxMon[sMonSummaryScreen->curMonIndex], mon);
+ if (GetMonData(mon, MON_DATA_IN_PC)) // If the Pokemon's summary is coming from the PC as a BoxMon
+ {
+ u16 hp = GetHPFromBoxHP(mon);
+ u32 status = GetStatusFromBoxStatus(mon);
+ SetMonData(mon, MON_DATA_HP, &hp);
+ SetMonData(mon, MON_DATA_STATUS, &status);
+ }
+ else
+ MonRestorePP(mon);
}
}
static bool8 ExtractMonDataToSummaryStruct(struct Pokemon *mon)