diff --git a/include/daycare.h b/include/daycare.h index f9cda1d10..8b0ca8de5 100644 --- a/include/daycare.h +++ b/include/daycare.h @@ -29,5 +29,6 @@ void EggHatch(void); u8 GetEggStepsToSubtract(void); bool8 ShouldEggHatch(void); u8 GetEggCyclesToSubtract(void); +u8 GetEggMovesBySpecies(u16 species, u16 *eggMoves); #endif // GUARD_DAYCARE_H diff --git a/include/pokemon.h b/include/pokemon.h index b12ef05de..2511d95b2 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -694,9 +694,11 @@ void CalculateMonStats(struct Pokemon *mon); void BoxMonToMon(const struct BoxPokemon *src, struct Pokemon *dest); u8 GetLevelFromBoxMonExp(struct BoxPokemon *boxMon); u16 GiveMoveToMon(struct Pokemon *mon, u16 move); +u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move); void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot); void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot); +void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon); u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move); diff --git a/src/daycare.c b/src/daycare.c index 67b9937ef..d9fd1ed6e 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -1,4 +1,5 @@ #include "global.h" +#include "pokemon.h" #include "gflib.h" #include "data.h" #include "battle.h" @@ -61,6 +62,8 @@ static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare * static u8 GetDaycareCompatibilityScore(struct DayCare *daycare); static void DaycarePrintMonInfo(u8 windowId, u32 daycareSlotId, u8 y); static u8 ModifyBreedingScoreForOvalCharm(u8 score); +static u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves); +static u16 GetEggSpecies(u16 species); static void Task_EggHatch(u8 taskID); static void CB2_EggHatch_0(void); @@ -126,6 +129,24 @@ static const struct ListMenuTemplate sDaycareListMenuLevelTemplate = .cursorKind = 0 }; +static const struct { + u16 currSpecies; + u16 item; + u16 babySpecies; +} sIncenseBabyTable[] = +{ + // Regular offspring, Item, Incense Offspring + { SPECIES_WOBBUFFET, ITEM_LAX_INCENSE, SPECIES_WYNAUT }, + { SPECIES_MARILL, ITEM_SEA_INCENSE, SPECIES_AZURILL }, + { SPECIES_SNORLAX, ITEM_FULL_INCENSE, SPECIES_MUNCHLAX }, + { SPECIES_CHANSEY, ITEM_LUCK_INCENSE, SPECIES_HAPPINY }, + { SPECIES_MR_MIME, ITEM_ODD_INCENSE, SPECIES_MIME_JR }, + { SPECIES_CHIMECHO, ITEM_PURE_INCENSE, SPECIES_CHINGLING }, + { SPECIES_SUDOWOODO, ITEM_ROCK_INCENSE, SPECIES_BONSLY }, + { SPECIES_ROSELIA, ITEM_ROSE_INCENSE, SPECIES_BUDEW }, + { SPECIES_MANTINE, ITEM_WAVE_INCENSE, SPECIES_MANTYKE }, +}; + static const u8 *const sCompatibilityMessages[] = { gDaycareText_GetAlongVeryWell, @@ -425,6 +446,71 @@ static s8 Daycare_FindEmptySpot(struct DayCare *daycare) return -1; } +static void ClearHatchedEggMoves(void) +{ + u16 i; + + for (i = 0; i < EGG_MOVES_ARRAY_COUNT; i++) + sHatchedEggEggMoves[i] = MOVE_NONE; +} + +static void TransferEggMoves(void) +{ + u32 i, j, k, l; + u16 numEggMoves; + + for (i = 0; i < DAYCARE_MON_COUNT; i++) + { + u16 moveLearnerSpecies = GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[i].mon, MON_DATA_SPECIES); + u16 eggSpecies = GetEggSpecies(moveLearnerSpecies); + + if (!GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[i].mon, MON_DATA_SANITY_HAS_SPECIES)) + continue; + + // Prevent non-baby species from learning incense baby egg moves + if (P_INCENSE_BREEDING < GEN_9 && eggSpecies != moveLearnerSpecies) + { + for (j = 0; j < ARRAY_COUNT(sIncenseBabyTable); j++) + { + if (sIncenseBabyTable[j].babySpecies == eggSpecies) + { + eggSpecies = sIncenseBabyTable[j].currSpecies; + break; + } + } + } + + ClearHatchedEggMoves(); + numEggMoves = GetEggMovesBySpecies(eggSpecies, sHatchedEggEggMoves); + for (j = 0; j < numEggMoves; j++) + { + // Go through other Daycare mons + for (k = 0; k < DAYCARE_MON_COUNT; k++) + { + u16 moveTeacherSpecies = GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[k].mon, MON_DATA_SPECIES); + + if (k == i || !GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[k].mon, MON_DATA_SANITY_HAS_SPECIES)) + continue; + + // Check if you can inherit from them + if (GET_BASE_SPECIES_ID(moveTeacherSpecies) != GET_BASE_SPECIES_ID(moveLearnerSpecies) + && (P_EGG_MOVE_TRANSFER < GEN_9 || GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[i].mon, MON_DATA_HELD_ITEM) != ITEM_MIRROR_HERB) + ) + continue; + + for (l = 0; l < MAX_MON_MOVES; l++) + { + if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[k].mon, MON_DATA_MOVE1 + l) != sHatchedEggEggMoves[j]) + continue; + + if (GiveMoveToBoxMon(&gSaveBlock1Ptr->daycare.mons[i].mon, sHatchedEggEggMoves[j]) == MON_HAS_MAX_MOVES) + break; + } + } + } + } +} + static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon) { if (MonHasMail(mon)) @@ -433,20 +519,22 @@ static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycar StringCopy(daycareMon->mail.OT_name, gSaveBlock2Ptr->playerName); DayCare_GetMonNickname(mon, daycareMon->mail.monName); -// StripExtCtrlCodes(daycareMon->mail.monName); -// daycareMon->mail.gameLanguage = LANGUAGE_ENGLISH; -// daycareMon->mail.monLanguage = GetMonData(mon, MON_DATA_LANGUAGE); + StripExtCtrlCodes(daycareMon->mail.monName); + daycareMon->mail.gameLanguage = GAME_LANGUAGE; + daycareMon->mail.monLanguage = GetMonData(mon, MON_DATA_LANGUAGE); mailId = GetMonData(mon, MON_DATA_MAIL); daycareMon->mail.message = gSaveBlock1Ptr->mail[mailId]; TakeMailFromMon(mon); } daycareMon->mon = mon->box; - BoxMonRestorePP(&daycareMon->mon); daycareMon->steps = 0; ZeroMonData(mon); CompactPartySlots(); CalculatePlayerPartyCount(); + + if (P_EGG_MOVE_TRANSFER >= GEN_8) + TransferEggMoves(); } static void StorePokemonInEmptyDaycareSlot(struct Pokemon *mon, struct DayCare *daycare) @@ -960,6 +1048,24 @@ static u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves) return numEggMoves; } +u8 GetEggMovesBySpecies(u16 species, u16 *eggMoves) +{ + u16 numEggMoves; + const u16 *eggMoveLearnset; + u32 i; + + numEggMoves = 0; + eggMoveLearnset = GetSpeciesEggMoves(species); + + for (i = 0; eggMoveLearnset[i] != MOVE_UNAVAILABLE; i++) + { + eggMoves[i] = eggMoveLearnset[i]; + numEggMoves++; + } + + return numEggMoves; +} + static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, struct BoxPokemon *mother) { u16 numSharedParentMoves; @@ -974,8 +1080,7 @@ static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, stru sHatchedEggFatherMoves[i] = MOVE_NONE; sHatchedEggFinalMoves[i] = MOVE_NONE; } - for (i = 0; i < EGG_MOVES_ARRAY_COUNT; i++) - sHatchedEggEggMoves[i] = MOVE_NONE; + ClearHatchedEggMoves(); for (i = 0; i < EGG_LVL_UP_MOVES_ARRAY_COUNT; i++) sHatchedEggLevelUpMoves[i] = MOVE_NONE; @@ -988,6 +1093,29 @@ static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, stru numEggMoves = GetEggMoves(egg, sHatchedEggEggMoves); + if (P_MOTHER_EGG_MOVE_INHERITANCE >= GEN_6) + { + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (sHatchedEggMotherMoves[i] != MOVE_NONE) + { + for (j = 0; j < numEggMoves; j++) + { + if (sHatchedEggMotherMoves[i] == sHatchedEggEggMoves[j]) + { + if (GiveMoveToMon(egg, sHatchedEggMotherMoves[i]) == MON_HAS_MAX_MOVES) + DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggMotherMoves[i]); + break; + } + } + } + else + { + break; + } + } + } + for (i = 0; i < MAX_MON_MOVES; i++) { if (sHatchedEggFatherMoves[i] != MOVE_NONE) @@ -1007,21 +1135,26 @@ static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, stru break; } } - for (i = 0; i < MAX_MON_MOVES; i++) + + if (P_TM_INHERITANCE < GEN_6) { - if (sHatchedEggFatherMoves[i] != MOVE_NONE) + for (i = 0; i < MAX_MON_MOVES; i++) { - for (j = 0; j < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; j++) + if (sHatchedEggFatherMoves[i] != MOVE_NONE) { - u16 moveId = ItemIdToBattleMoveId(ITEM_TM01 + j); - if (sHatchedEggFatherMoves[i] == moveId && CanLearnTeachableMove(GetMonData(egg, MON_DATA_SPECIES_OR_EGG), j)) + for (j = 0; j < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; j++) { - if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == MON_HAS_MAX_MOVES) - DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFatherMoves[i]); + u16 moveId = ItemIdToBattleMoveId(ITEM_TM01 + j); + if (sHatchedEggFatherMoves[i] == moveId && CanLearnTeachableMove(GetMonData(egg, MON_DATA_SPECIES_OR_EGG), moveId)) + { + if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == MON_HAS_MAX_MOVES) + DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFatherMoves[i]); + } } } } } + for (i = 0; i < MAX_MON_MOVES; i++) { if (sHatchedEggFatherMoves[i] == MOVE_NONE) @@ -1060,24 +1193,6 @@ void RejectEggFromDayCare(void) RemoveEggFromDayCare(&gSaveBlock1Ptr->daycare); } -static const struct { - u16 currSpecies; - u16 item; - u16 babySpecies; -} sIncenseBabyTable[] = -{ - // Regular offspring, Item, Incense Offspring - { SPECIES_WOBBUFFET, ITEM_LAX_INCENSE, SPECIES_WYNAUT }, - { SPECIES_MARILL, ITEM_SEA_INCENSE, SPECIES_AZURILL }, - { SPECIES_SNORLAX, ITEM_FULL_INCENSE, SPECIES_MUNCHLAX }, - { SPECIES_CHANSEY, ITEM_LUCK_INCENSE, SPECIES_HAPPINY }, - { SPECIES_MR_MIME, ITEM_ODD_INCENSE, SPECIES_MIME_JR }, - { SPECIES_CHIMECHO, ITEM_PURE_INCENSE, SPECIES_CHINGLING }, - { SPECIES_SUDOWOODO, ITEM_ROCK_INCENSE, SPECIES_BONSLY }, - { SPECIES_ROSELIA, ITEM_ROSE_INCENSE, SPECIES_BUDEW }, - { SPECIES_MANTINE, ITEM_WAVE_INCENSE, SPECIES_MANTYKE }, -}; - #if P_INCENSE_BREEDING < GEN_9 static void AlterEggSpeciesWithIncenseItem(u16 *species, struct DayCare *daycare) { diff --git a/src/pokemon.c b/src/pokemon.c index 36d1861df..d9a9156c8 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -64,9 +64,6 @@ static EWRAM_DATA struct MonSpritesGfxManager *sMonSpritesGfxManager = NULL; static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); static bool8 IsPokemonStorageFull(void); static void EncryptBoxMon(struct BoxPokemon *boxMon); -static void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); -static void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon); -static u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); static u8 GetLevelFromMonExp(struct Pokemon *mon); static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon); static bool8 ShouldSkipFriendshipChange(void); @@ -1742,13 +1739,13 @@ u16 GiveMoveToMon(struct Pokemon *mon, u16 move) return GiveMoveToBoxMon(&mon->box, move); } -static u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) +u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) { s32 i; for (i = 0; i < MAX_MON_MOVES; i++) { u16 existingMove = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, NULL); - if (!existingMove) + if (existingMove == MOVE_NONE) { SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &move); SetBoxMonData(boxMon, MON_DATA_PP1 + i, &gMovesInfo[move].pp); @@ -1800,21 +1797,53 @@ void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot) mon->pp[slot] = gMovesInfo[move].pp; } -void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon) +void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon) //Credit: AsparagusEduardo { u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); s32 level = GetLevelFromBoxMonExp(boxMon); s32 i; + u16 moves[MAX_MON_MOVES] = {MOVE_NONE}; + u8 addedMoves = 0; const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); for (i = 0; learnset[i].move != LEVEL_UP_MOVE_END; i++) { + s32 j; + bool32 alreadyKnown = FALSE; + if (learnset[i].level > level) break; if (learnset[i].level == 0) continue; - if (GiveMoveToBoxMon(boxMon, learnset[i].move) == MON_HAS_MAX_MOVES) - DeleteFirstMoveAndGiveMoveToBoxMon(boxMon, learnset[i].move); + + for (j = 0; j < addedMoves; j++) + { + if (moves[j] == learnset[i].move) + { + alreadyKnown = TRUE; + break; + } + } + + if (!alreadyKnown) + { + if (addedMoves < MAX_MON_MOVES) + { + moves[addedMoves] = learnset[i].move; + addedMoves++; + } + else + { + for (j = 0; j < MAX_MON_MOVES - 1; j++) + moves[j] = moves[j + 1]; + moves[MAX_MON_MOVES - 1] = learnset[i].move; + } + } + } + for (i = 0; i < MAX_MON_MOVES; i++) + { + SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &moves[i]); + SetBoxMonData(boxMon, MON_DATA_PP1 + i, &gMovesInfo[moves[i]].pp); } } @@ -1905,33 +1934,6 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) return 0; } -static void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) -{ - s32 i; - u16 moves[MAX_MON_MOVES]; - u8 pp[MAX_MON_MOVES]; - u8 ppBonuses; - - for (i = 0; i < MAX_MON_MOVES - 1; i++) - { - moves[i] = GetBoxMonData(boxMon, MON_DATA_MOVE2 + i, NULL); - pp[i] = GetBoxMonData(boxMon, MON_DATA_PP2 + i, NULL); - } - - ppBonuses = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, NULL); - ppBonuses >>= 2; - moves[MAX_MON_MOVES - 1] = move; - pp[MAX_MON_MOVES - 1] = gMovesInfo[move].pp; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &moves[i]); - SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp[i]); - } - - SetBoxMonData(boxMon, MON_DATA_PP_BONUSES, &ppBonuses); -} - u8 CountAliveMonsInBattle(u8 caseId, u32 battler) { s32 i;