Skip to content

Commit

Permalink
Fixed givemon not respecting perfect IVs for species (#5873)
Browse files Browse the repository at this point in the history
  • Loading branch information
AsparagusEduardo authored Dec 26, 2024
1 parent 2c93529 commit 91c7bd9
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 29 deletions.
1 change: 1 addition & 0 deletions include/pokemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg);
u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg);
bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method);
u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove);
void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv);
bool32 SpeciesHasGenderDifferences(u16 species);
bool32 TryFormChange(u32 monId, u32 side, u16 method);
void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method);
Expand Down
21 changes: 0 additions & 21 deletions src/daycare.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,27 +590,6 @@ static void UNUSED TriggerPendingDaycareMaleEgg(void)
_TriggerPendingDaycareMaleEgg(&gSaveBlock1Ptr->daycare);
}

// Removes the selected index from the given IV list and shifts the remaining
// elements to the left.
static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv)
{
s32 i, j;
u8 temp[NUM_STATS];

ivs[selectedIv] = 0xFF;
for (i = 0; i < NUM_STATS; i++)
{
temp[i] = ivs[i];
}

j = 0;
for (i = 0; i < NUM_STATS; i++)
{
if (temp[i] != 0xFF)
ivs[j++] = temp[i];
}
}

static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare)
{
u16 motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM);
Expand Down
5 changes: 3 additions & 2 deletions src/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ static void EncryptBoxMon(struct BoxPokemon *boxMon);
static void DecryptBoxMon(struct BoxPokemon *boxMon);
static void Task_PlayMapChosenOrBattleBGM(u8 taskId);
static bool8 ShouldSkipFriendshipChange(void);
static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv);
void TrySpecialOverworldEvo();

EWRAM_DATA static u8 sLearningMoveTableID = 0;
Expand Down Expand Up @@ -6659,7 +6658,9 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove)
return 0;
}

static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv)
// Removes the selected index from the given IV list and shifts the remaining
// elements to the left.
void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv)
{
s32 i, j;
u8 temp[NUM_STATS];
Expand Down
49 changes: 43 additions & 6 deletions src/script_pokemon_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,12 +487,49 @@ void ScrCmd_createmon(struct ScriptContext *ctx)
u8 speedEv = PARSE_FLAG(8, 0);
u8 spAtkEv = PARSE_FLAG(9, 0);
u8 spDefEv = PARSE_FLAG(10, 0);
u8 hpIv = PARSE_FLAG(11, Random() % (MAX_PER_STAT_IVS + 1));
u8 atkIv = PARSE_FLAG(12, Random() % (MAX_PER_STAT_IVS + 1));
u8 defIv = PARSE_FLAG(13, Random() % (MAX_PER_STAT_IVS + 1));
u8 speedIv = PARSE_FLAG(14, Random() % (MAX_PER_STAT_IVS + 1));
u8 spAtkIv = PARSE_FLAG(15, Random() % (MAX_PER_STAT_IVS + 1));
u8 spDefIv = PARSE_FLAG(16, Random() % (MAX_PER_STAT_IVS + 1));
u8 hpIv = Random() % (MAX_PER_STAT_IVS + 1);
u8 atkIv = Random() % (MAX_PER_STAT_IVS + 1);
u8 defIv = Random() % (MAX_PER_STAT_IVS + 1);
u8 speedIv = Random() % (MAX_PER_STAT_IVS + 1);
u8 spAtkIv = Random() % (MAX_PER_STAT_IVS + 1);
u8 spDefIv = Random() % (MAX_PER_STAT_IVS + 1);

// Perfect IV calculation
u32 i;
u8 availableIVs[NUM_STATS];
u8 selectedIvs[NUM_STATS];
if (gSpeciesInfo[species].perfectIVCount != 0)
{
// Initialize a list of IV indices.
for (i = 0; i < NUM_STATS; i++)
availableIVs[i] = i;

// Select the IVs that will be perfected.
for (i = 0; i < NUM_STATS && i < gSpeciesInfo[species].perfectIVCount; i++)
{
u8 index = Random() % (NUM_STATS - i);
selectedIvs[i] = availableIVs[index];
RemoveIVIndexFromList(availableIVs, index);
}
for (i = 0; i < NUM_STATS && i < gSpeciesInfo[species].perfectIVCount; i++)
{
switch (selectedIvs[i])
{
case STAT_HP: hpIv = MAX_PER_STAT_IVS; break;
case STAT_ATK: atkIv = MAX_PER_STAT_IVS; break;
case STAT_DEF: defIv = MAX_PER_STAT_IVS; break;
case STAT_SPEED: speedIv = MAX_PER_STAT_IVS; break;
case STAT_SPATK: spAtkIv = MAX_PER_STAT_IVS; break;
case STAT_SPDEF: spDefIv = MAX_PER_STAT_IVS; break;
}
}
}
hpIv = PARSE_FLAG(11, hpIv);
atkIv = PARSE_FLAG(12, atkIv);
defIv = PARSE_FLAG(13, defIv);
speedIv = PARSE_FLAG(14, speedIv);
spAtkIv = PARSE_FLAG(15, spAtkIv);
spDefIv = PARSE_FLAG(16, spDefIv);
u16 move1 = PARSE_FLAG(17, MOVE_NONE);
u16 move2 = PARSE_FLAG(18, MOVE_NONE);
u16 move3 = PARSE_FLAG(19, MOVE_NONE);
Expand Down
44 changes: 44 additions & 0 deletions test/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,50 @@ TEST("givemon [simple]")
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_LEVEL), 100);
}

TEST("givemon respects perfectIVCount")
{
ZeroPlayerPartyMons();
u32 perfectIVs[6] = {0};

ASSUME(gSpeciesInfo[SPECIES_MEW].perfectIVCount == 3);
ASSUME(gSpeciesInfo[SPECIES_CELEBI].perfectIVCount == 3);
ASSUME(gSpeciesInfo[SPECIES_JIRACHI].perfectIVCount == 3);
ASSUME(gSpeciesInfo[SPECIES_MANAPHY].perfectIVCount == 3);
ASSUME(gSpeciesInfo[SPECIES_VICTINI].perfectIVCount == 3);
ASSUME(gSpeciesInfo[SPECIES_DIANCIE].perfectIVCount == 3);

RUN_OVERWORLD_SCRIPT(
givemon SPECIES_MEW, 100;
givemon SPECIES_CELEBI, 100;
givemon SPECIES_JIRACHI, 100;
givemon SPECIES_MANAPHY, 100;
givemon SPECIES_VICTINI, 100;
givemon SPECIES_DIANCIE, 100;
);

EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_MEW);
EXPECT_EQ(GetMonData(&gPlayerParty[1], MON_DATA_SPECIES), SPECIES_CELEBI);
EXPECT_EQ(GetMonData(&gPlayerParty[2], MON_DATA_SPECIES), SPECIES_JIRACHI);
EXPECT_EQ(GetMonData(&gPlayerParty[3], MON_DATA_SPECIES), SPECIES_MANAPHY);
EXPECT_EQ(GetMonData(&gPlayerParty[4], MON_DATA_SPECIES), SPECIES_VICTINI);
EXPECT_EQ(GetMonData(&gPlayerParty[5], MON_DATA_SPECIES), SPECIES_DIANCIE);
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_LEVEL), 100);
EXPECT_EQ(GetMonData(&gPlayerParty[1], MON_DATA_LEVEL), 100);
EXPECT_EQ(GetMonData(&gPlayerParty[2], MON_DATA_LEVEL), 100);
EXPECT_EQ(GetMonData(&gPlayerParty[3], MON_DATA_LEVEL), 100);
EXPECT_EQ(GetMonData(&gPlayerParty[4], MON_DATA_LEVEL), 100);
EXPECT_EQ(GetMonData(&gPlayerParty[5], MON_DATA_LEVEL), 100);
for (u32 j = 0; j < 6; j++)
{
for (u32 k = 0; k < NUM_STATS; k++)
{
if (GetMonData(&gPlayerParty[j], MON_DATA_HP_IV + k) == MAX_PER_STAT_IVS)
perfectIVs[j]++;
}
EXPECT_GE(perfectIVs[j], 3);
}
}

TEST("givemon [moves]")
{
ZeroPlayerPartyMons();
Expand Down

0 comments on commit 91c7bd9

Please sign in to comment.