2017-11-14 20:23:25 +01:00
|
|
|
#include "global.h"
|
|
|
|
#include "pokemon.h"
|
2018-05-19 11:53:22 +02:00
|
|
|
#include "battle.h"
|
2017-11-14 20:23:25 +01:00
|
|
|
#include "daycare.h"
|
|
|
|
#include "string_util.h"
|
|
|
|
#include "mail.h"
|
|
|
|
#include "pokemon_storage_system.h"
|
|
|
|
#include "event_data.h"
|
2017-12-05 19:27:33 +01:00
|
|
|
#include "random.h"
|
2017-11-14 20:23:25 +01:00
|
|
|
#include "main.h"
|
2017-11-14 23:25:07 +01:00
|
|
|
#include "egg_hatch.h"
|
2017-11-15 20:08:31 +01:00
|
|
|
#include "text.h"
|
|
|
|
#include "menu.h"
|
|
|
|
#include "international_string_util.h"
|
|
|
|
#include "script.h"
|
2018-12-24 00:02:29 +01:00
|
|
|
#include "strings.h"
|
2017-11-15 20:08:31 +01:00
|
|
|
#include "task.h"
|
|
|
|
#include "window.h"
|
2018-12-24 00:02:29 +01:00
|
|
|
#include "party_menu.h"
|
2017-11-15 20:08:31 +01:00
|
|
|
#include "list_menu.h"
|
2018-12-07 23:50:56 +01:00
|
|
|
#include "overworld.h"
|
2019-09-25 20:48:22 +02:00
|
|
|
#include "constants/items.h"
|
|
|
|
#include "constants/moves.h"
|
|
|
|
#include "constants/region_map_sections.h"
|
2017-11-14 20:23:25 +01:00
|
|
|
|
2021-06-01 23:14:45 +02:00
|
|
|
extern const struct Evolution gEvolutionTable[][EVOS_PER_MON];
|
2021-05-31 06:19:26 +02:00
|
|
|
|
2021-04-25 23:22:45 +02:00
|
|
|
static void ClearDaycareMonMail(struct DaycareMail *mail);
|
2017-11-15 22:12:18 +01:00
|
|
|
static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare);
|
|
|
|
static u8 GetDaycareCompatibilityScore(struct DayCare *daycare);
|
2021-06-18 06:15:45 +02:00
|
|
|
static void DaycarePrintMonInfo(u8 windowId, u32 daycareSlotId, u8 y);
|
2017-11-14 21:43:23 +01:00
|
|
|
|
|
|
|
// RAM buffers used to assist with BuildEggMoveset()
|
|
|
|
EWRAM_DATA static u16 sHatchedEggLevelUpMoves[EGG_LVL_UP_MOVES_ARRAY_COUNT] = {0};
|
2019-09-08 17:53:48 +02:00
|
|
|
EWRAM_DATA static u16 sHatchedEggFatherMoves[MAX_MON_MOVES] = {0};
|
|
|
|
EWRAM_DATA static u16 sHatchedEggFinalMoves[MAX_MON_MOVES] = {0};
|
2017-11-14 21:43:23 +01:00
|
|
|
EWRAM_DATA static u16 sHatchedEggEggMoves[EGG_MOVES_ARRAY_COUNT] = {0};
|
2019-09-08 17:53:48 +02:00
|
|
|
EWRAM_DATA static u16 sHatchedEggMotherMoves[MAX_MON_MOVES] = {0};
|
2017-11-14 20:23:25 +01:00
|
|
|
|
|
|
|
#include "data/pokemon/egg_moves.h"
|
|
|
|
|
2018-09-02 18:53:52 +02:00
|
|
|
static const struct WindowTemplate sDaycareLevelMenuWindowTemplate =
|
|
|
|
{
|
2018-10-27 00:53:07 +02:00
|
|
|
.bg = 0,
|
2018-09-02 18:53:52 +02:00
|
|
|
.tilemapLeft = 15,
|
|
|
|
.tilemapTop = 1,
|
|
|
|
.width = 14,
|
|
|
|
.height = 6,
|
|
|
|
.paletteNum = 15,
|
|
|
|
.baseBlock = 8
|
|
|
|
};
|
2017-11-15 22:12:18 +01:00
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// Indices here are assigned by Task_HandleDaycareLevelMenuInput to VAR_RESULT,
|
|
|
|
// which is copied to VAR_0x8004 and used as an index for GetDaycareCost
|
2017-11-15 22:12:18 +01:00
|
|
|
static const struct ListMenuItem sLevelMenuItems[] =
|
|
|
|
{
|
2019-12-05 21:33:36 +01:00
|
|
|
{gText_ExpandedPlaceholder_Empty, 0},
|
|
|
|
{gText_ExpandedPlaceholder_Empty, 1},
|
2019-09-25 20:48:22 +02:00
|
|
|
{gText_Exit, DAYCARE_LEVEL_MENU_EXIT}
|
2017-11-15 22:12:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct ListMenuTemplate sDaycareListMenuLevelTemplate =
|
|
|
|
{
|
|
|
|
.items = sLevelMenuItems,
|
2018-07-15 13:23:38 +02:00
|
|
|
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
|
|
|
|
.itemPrintFunc = DaycarePrintMonInfo,
|
2017-11-15 22:12:18 +01:00
|
|
|
.totalItems = 3,
|
|
|
|
.maxShowed = 3,
|
2018-03-03 14:58:41 +01:00
|
|
|
.windowId = 0,
|
2018-07-15 13:23:38 +02:00
|
|
|
.header_X = 0,
|
|
|
|
.item_X = 8,
|
2018-03-03 14:58:41 +01:00
|
|
|
.cursor_X = 0,
|
2017-11-15 22:12:18 +01:00
|
|
|
.upText_Y = 1,
|
2018-03-03 14:58:41 +01:00
|
|
|
.cursorPal = 2,
|
|
|
|
.fillValue = 1,
|
|
|
|
.cursorShadowPal = 3,
|
|
|
|
.lettersSpacing = 1,
|
2018-07-15 13:23:38 +02:00
|
|
|
.itemVerticalPadding = 0,
|
2018-03-02 16:34:31 +01:00
|
|
|
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
|
2021-10-30 22:47:37 +02:00
|
|
|
.fontId = FONT_NORMAL,
|
2017-12-16 00:08:23 +01:00
|
|
|
.cursorKind = 0
|
2017-11-15 22:12:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 *const sCompatibilityMessages[] =
|
|
|
|
{
|
|
|
|
gDaycareText_GetAlongVeryWell,
|
|
|
|
gDaycareText_GetAlong,
|
|
|
|
gDaycareText_DontLikeOther,
|
|
|
|
gDaycareText_PlayOther
|
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 sJapaneseEggNickname[] = _("タマゴ"); // "tamago" ("egg" in Japanese)
|
2017-11-14 21:43:23 +01:00
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
u8 *GetMonNickname2(struct Pokemon *mon, u8 *dest)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u8 nickname[POKEMON_NAME_LENGTH * 2];
|
|
|
|
|
|
|
|
GetMonData(mon, MON_DATA_NICKNAME, nickname);
|
2021-11-18 04:11:03 +01:00
|
|
|
return StringCopy_Nickname(dest, nickname);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
u8 *GetBoxMonNickname(struct BoxPokemon *mon, u8 *dest)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u8 nickname[POKEMON_NAME_LENGTH * 2];
|
|
|
|
|
|
|
|
GetBoxMonData(mon, MON_DATA_NICKNAME, nickname);
|
2021-11-18 04:11:03 +01:00
|
|
|
return StringCopy_Nickname(dest, nickname);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u8 CountPokemonInDaycare(struct DayCare *daycare)
|
|
|
|
{
|
|
|
|
u8 i, count;
|
|
|
|
count = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
{
|
|
|
|
if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) != 0)
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-10-23 16:55:46 +02:00
|
|
|
void InitDaycareMailRecordMixing(struct DayCare *daycare, struct RecordMixingDaycareMail *mixMail)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u8 i;
|
|
|
|
u8 numDaycareMons = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
{
|
|
|
|
if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) != SPECIES_NONE)
|
|
|
|
{
|
|
|
|
numDaycareMons++;
|
|
|
|
if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_HELD_ITEM) == ITEM_NONE)
|
2021-10-23 16:55:46 +02:00
|
|
|
mixMail->cantHoldItem[i] = FALSE;
|
2017-11-14 20:23:25 +01:00
|
|
|
else
|
2021-10-23 16:55:46 +02:00
|
|
|
mixMail->cantHoldItem[i] = TRUE;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-23 16:55:46 +02:00
|
|
|
// Daycare slot empty
|
|
|
|
mixMail->cantHoldItem[i] = TRUE;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-23 16:55:46 +02:00
|
|
|
mixMail->numDaycareMons = numDaycareMons;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static s8 Daycare_FindEmptySpot(struct DayCare *daycare)
|
|
|
|
{
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
{
|
2021-04-25 23:22:45 +02:00
|
|
|
if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) == SPECIES_NONE)
|
2017-11-14 20:23:25 +01:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon)
|
|
|
|
{
|
|
|
|
if (MonHasMail(mon))
|
|
|
|
{
|
|
|
|
u8 mailId;
|
|
|
|
|
2021-10-23 16:55:46 +02:00
|
|
|
StringCopy(daycareMon->mail.otName, gSaveBlock2Ptr->playerName);
|
2019-09-26 00:44:56 +02:00
|
|
|
GetMonNickname2(mon, daycareMon->mail.monName);
|
2018-05-26 00:25:36 +02:00
|
|
|
StripExtCtrlCodes(daycareMon->mail.monName);
|
2021-02-05 18:08:49 +01:00
|
|
|
daycareMon->mail.gameLanguage = GAME_LANGUAGE;
|
2018-05-26 00:25:36 +02:00
|
|
|
daycareMon->mail.monLanguage = GetMonData(mon, MON_DATA_LANGUAGE);
|
2017-11-14 20:23:25 +01:00
|
|
|
mailId = GetMonData(mon, MON_DATA_MAIL);
|
2018-05-26 00:25:36 +02:00
|
|
|
daycareMon->mail.message = gSaveBlock1Ptr->mail[mailId];
|
2017-11-14 20:23:25 +01:00
|
|
|
TakeMailFromMon(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
daycareMon->mon = mon->box;
|
|
|
|
BoxMonRestorePP(&daycareMon->mon);
|
|
|
|
daycareMon->steps = 0;
|
|
|
|
ZeroMonData(mon);
|
|
|
|
CompactPartySlots();
|
|
|
|
CalculatePlayerPartyCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void StorePokemonInEmptyDaycareSlot(struct Pokemon *mon, struct DayCare *daycare)
|
|
|
|
{
|
|
|
|
s8 slotId = Daycare_FindEmptySpot(daycare);
|
|
|
|
StorePokemonInDaycare(mon, &daycare->mons[slotId]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreSelectedPokemonInDaycare(void)
|
|
|
|
{
|
|
|
|
u8 monId = GetCursorSelectionMonId();
|
|
|
|
StorePokemonInEmptyDaycareSlot(&gPlayerParty[monId], &gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shifts the second daycare pokemon slot into the first slot.
|
|
|
|
static void ShiftDaycareSlots(struct DayCare *daycare)
|
|
|
|
{
|
|
|
|
// This condition is only satisfied when the player takes out the first pokemon from the daycare.
|
2019-09-26 00:05:12 +02:00
|
|
|
if (GetBoxMonData(&daycare->mons[1].mon, MON_DATA_SPECIES) != SPECIES_NONE
|
|
|
|
&& GetBoxMonData(&daycare->mons[0].mon, MON_DATA_SPECIES) == SPECIES_NONE)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
daycare->mons[0].mon = daycare->mons[1].mon;
|
|
|
|
ZeroBoxMonData(&daycare->mons[1].mon);
|
2017-11-14 20:23:25 +01:00
|
|
|
|
2019-09-26 00:05:12 +02:00
|
|
|
daycare->mons[0].mail = daycare->mons[1].mail;
|
|
|
|
daycare->mons[0].steps = daycare->mons[1].steps;
|
|
|
|
daycare->mons[1].steps = 0;
|
|
|
|
ClearDaycareMonMail(&daycare->mons[1].mail);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ApplyDaycareExperience(struct Pokemon *mon)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
bool8 firstMove;
|
|
|
|
u16 learnedMove;
|
|
|
|
|
2018-10-17 04:47:08 +02:00
|
|
|
for (i = 0; i < MAX_LEVEL; i++)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
// Add the mon's gained daycare experience level by level until it can't level up anymore.
|
|
|
|
if (TryIncrementMonLevel(mon))
|
|
|
|
{
|
|
|
|
// Teach the mon new moves it learned while in the daycare.
|
|
|
|
firstMove = TRUE;
|
|
|
|
while ((learnedMove = MonTryLearningNewMove(mon, firstMove)) != 0)
|
|
|
|
{
|
|
|
|
firstMove = FALSE;
|
2019-10-18 01:22:03 +02:00
|
|
|
if (learnedMove == MON_HAS_MAX_MOVES)
|
2017-11-14 20:23:25 +01:00
|
|
|
DeleteFirstMoveAndGiveMoveToMon(mon, gMoveToLearn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Re-calculate the mons stats at its new level.
|
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon)
|
|
|
|
{
|
|
|
|
u16 species;
|
|
|
|
u32 experience;
|
|
|
|
struct Pokemon pokemon;
|
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycareMon->mon, gStringVar1);
|
2017-11-14 20:23:25 +01:00
|
|
|
species = GetBoxMonData(&daycareMon->mon, MON_DATA_SPECIES);
|
|
|
|
BoxMonToMon(&daycareMon->mon, &pokemon);
|
|
|
|
|
2018-10-17 04:47:08 +02:00
|
|
|
if (GetMonData(&pokemon, MON_DATA_LEVEL) != MAX_LEVEL)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
experience = GetMonData(&pokemon, MON_DATA_EXP) + daycareMon->steps;
|
|
|
|
SetMonData(&pokemon, MON_DATA_EXP, &experience);
|
|
|
|
ApplyDaycareExperience(&pokemon);
|
|
|
|
}
|
|
|
|
|
|
|
|
gPlayerParty[PARTY_SIZE - 1] = pokemon;
|
2018-05-26 00:25:36 +02:00
|
|
|
if (daycareMon->mail.message.itemId)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
2021-10-23 16:55:46 +02:00
|
|
|
GiveMailToMon(&gPlayerParty[PARTY_SIZE - 1], &daycareMon->mail.message);
|
2018-05-26 00:25:36 +02:00
|
|
|
ClearDaycareMonMail(&daycareMon->mail);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ZeroBoxMonData(&daycareMon->mon);
|
|
|
|
daycareMon->steps = 0;
|
|
|
|
CompactPartySlots();
|
|
|
|
CalculatePlayerPartyCount();
|
|
|
|
return species;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u16 TakeSelectedPokemonMonFromDaycareShiftSlots(struct DayCare *daycare, u8 slotId)
|
|
|
|
{
|
|
|
|
u16 species = TakeSelectedPokemonFromDaycare(&daycare->mons[slotId]);
|
|
|
|
ShiftDaycareSlots(daycare);
|
|
|
|
return species;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 TakePokemonFromDaycare(void)
|
|
|
|
{
|
|
|
|
return TakeSelectedPokemonMonFromDaycareShiftSlots(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 GetLevelAfterDaycareSteps(struct BoxPokemon *mon, u32 steps)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
struct BoxPokemon tempMon = *mon;
|
|
|
|
|
|
|
|
u32 experience = GetBoxMonData(mon, MON_DATA_EXP) + steps;
|
|
|
|
SetBoxMonData(&tempMon, MON_DATA_EXP, &experience);
|
|
|
|
return GetLevelFromBoxMonExp(&tempMon);
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 GetNumLevelsGainedFromSteps(struct DaycareMon *daycareMon)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u8 levelBefore;
|
|
|
|
u8 levelAfter;
|
|
|
|
|
|
|
|
levelBefore = GetLevelFromBoxMonExp(&daycareMon->mon);
|
|
|
|
levelAfter = GetLevelAfterDaycareSteps(&daycareMon->mon, daycareMon->steps);
|
|
|
|
return levelAfter - levelBefore;
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 GetNumLevelsGainedForDaycareMon(struct DaycareMon *daycareMon)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u8 numLevelsGained = GetNumLevelsGainedFromSteps(daycareMon);
|
|
|
|
ConvertIntToDecimalStringN(gStringVar2, numLevelsGained, STR_CONV_MODE_LEFT_ALIGN, 2);
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycareMon->mon, gStringVar1);
|
2017-11-14 20:23:25 +01:00
|
|
|
return numLevelsGained;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32 GetDaycareCostForSelectedMon(struct DaycareMon *daycareMon)
|
|
|
|
{
|
|
|
|
u32 cost;
|
|
|
|
|
|
|
|
u8 numLevelsGained = GetNumLevelsGainedFromSteps(daycareMon);
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycareMon->mon, gStringVar1);
|
2017-11-14 20:23:25 +01:00
|
|
|
cost = 100 + 100 * numLevelsGained;
|
|
|
|
ConvertIntToDecimalStringN(gStringVar2, cost, STR_CONV_MODE_LEFT_ALIGN, 5);
|
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u16 GetDaycareCostForMon(struct DayCare *daycare, u8 slotId)
|
|
|
|
{
|
|
|
|
return GetDaycareCostForSelectedMon(&daycare->mons[slotId]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetDaycareCost(void)
|
|
|
|
{
|
|
|
|
gSpecialVar_0x8005 = GetDaycareCostForMon(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Debug_AddDaycareSteps(u16 numSteps)
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
gSaveBlock1Ptr->daycare.mons[0].steps += numSteps;
|
|
|
|
gSaveBlock1Ptr->daycare.mons[1].steps += numSteps;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetNumLevelsGainedFromDaycare(void)
|
|
|
|
{
|
|
|
|
if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004], MON_DATA_SPECIES) != 0)
|
|
|
|
return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004]);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-04-25 23:22:45 +02:00
|
|
|
static void ClearDaycareMonMail(struct DaycareMail *mail)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
|
2018-09-01 22:03:21 +02:00
|
|
|
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
|
2021-10-23 16:55:46 +02:00
|
|
|
mail->otName[i] = 0;
|
2017-11-14 20:23:25 +01:00
|
|
|
for (i = 0; i < POKEMON_NAME_LENGTH + 1; i++)
|
2018-05-26 00:25:36 +02:00
|
|
|
mail->monName[i] = 0;
|
2017-11-14 20:23:25 +01:00
|
|
|
|
2021-10-23 16:55:46 +02:00
|
|
|
ClearMail(&mail->message);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ClearDaycareMon(struct DaycareMon *daycareMon)
|
|
|
|
{
|
|
|
|
ZeroBoxMonData(&daycareMon->mon);
|
|
|
|
daycareMon->steps = 0;
|
2018-05-26 00:25:36 +02:00
|
|
|
ClearDaycareMonMail(&daycareMon->mail);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ClearAllDaycareData(struct DayCare *daycare)
|
|
|
|
{
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
ClearDaycareMon(&daycare->mons[i]);
|
|
|
|
|
|
|
|
daycare->offspringPersonality = 0;
|
|
|
|
daycare->stepCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determines what the species of an Egg would be based on the given species.
|
|
|
|
// It determines this by working backwards through the evolution chain of the
|
|
|
|
// given species.
|
2017-11-15 22:12:18 +01:00
|
|
|
static u16 GetEggSpecies(u16 species)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
bool8 found;
|
|
|
|
|
|
|
|
// Working backwards up to 5 times seems arbitrary, since the maximum number
|
|
|
|
// of times would only be 3 for 3-stage evolutions.
|
|
|
|
for (i = 0; i < EVOS_PER_MON; i++)
|
|
|
|
{
|
|
|
|
found = FALSE;
|
|
|
|
for (j = 1; j < NUM_SPECIES; j++)
|
|
|
|
{
|
|
|
|
for (k = 0; k < EVOS_PER_MON; k++)
|
|
|
|
{
|
2018-02-05 17:39:26 +01:00
|
|
|
if (gEvolutionTable[j][k].targetSpecies == species)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
species = j;
|
|
|
|
found = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == NUM_SPECIES)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return species;
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
static s32 GetParentToInheritNature(struct DayCare *daycare)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u32 species[DAYCARE_MON_COUNT];
|
2017-11-17 19:31:03 +01:00
|
|
|
s32 i;
|
|
|
|
s32 dittoCount;
|
2019-09-26 00:05:12 +02:00
|
|
|
s32 parent = -1;
|
2017-11-14 20:23:25 +01:00
|
|
|
|
|
|
|
// search for female gender
|
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
{
|
|
|
|
if (GetBoxMonGender(&daycare->mons[i].mon) == MON_FEMALE)
|
2019-09-25 20:48:22 +02:00
|
|
|
parent = i;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// search for ditto
|
|
|
|
for (dittoCount = 0, i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
{
|
|
|
|
species[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES);
|
|
|
|
if (species[i] == SPECIES_DITTO)
|
2019-09-25 20:48:22 +02:00
|
|
|
dittoCount++, parent = i;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// coin flip on ...two Dittos
|
2019-09-25 20:48:22 +02:00
|
|
|
if (dittoCount == DAYCARE_MON_COUNT)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
if (Random() >= USHRT_MAX / 2)
|
2019-09-26 00:05:12 +02:00
|
|
|
parent = 0;
|
2017-11-14 20:23:25 +01:00
|
|
|
else
|
2019-09-26 00:05:12 +02:00
|
|
|
parent = 1;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// Don't inherit nature if not holding Everstone
|
|
|
|
if (GetBoxMonData(&daycare->mons[parent].mon, MON_DATA_HELD_ITEM) != ITEM_EVERSTONE
|
2017-11-14 20:23:25 +01:00
|
|
|
|| Random() >= USHRT_MAX / 2)
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
return -1;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
return parent;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void _TriggerPendingDaycareEgg(struct DayCare *daycare)
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
s32 parent;
|
2017-11-14 20:23:25 +01:00
|
|
|
s32 natureTries = 0;
|
|
|
|
|
|
|
|
SeedRng2(gMain.vblankCounter2);
|
2019-09-25 20:48:22 +02:00
|
|
|
parent = GetParentToInheritNature(daycare);
|
2017-11-14 20:23:25 +01:00
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// don't inherit nature
|
|
|
|
if (parent < 0)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
daycare->offspringPersonality = (Random2() << 16) | ((Random() % 0xfffe) + 1);
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
2019-09-25 20:48:22 +02:00
|
|
|
// inherit nature
|
2017-11-14 20:23:25 +01:00
|
|
|
else
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
u8 wantedNature = GetNatureFromPersonality(GetBoxMonData(&daycare->mons[parent].mon, MON_DATA_PERSONALITY, NULL));
|
2017-11-14 20:23:25 +01:00
|
|
|
u32 personality;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
personality = (Random2() << 16) | (Random());
|
2017-11-14 20:23:25 +01:00
|
|
|
if (wantedNature == GetNatureFromPersonality(personality) && personality != 0)
|
2019-09-25 20:48:22 +02:00
|
|
|
break; // found a personality with the same nature
|
2017-11-14 20:23:25 +01:00
|
|
|
|
|
|
|
natureTries++;
|
|
|
|
} while (natureTries <= 2400);
|
|
|
|
|
|
|
|
daycare->offspringPersonality = personality;
|
|
|
|
}
|
|
|
|
|
|
|
|
FlagSet(FLAG_PENDING_DAYCARE_EGG);
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// Functionally unused
|
2017-11-14 20:23:25 +01:00
|
|
|
static void _TriggerPendingDaycareMaleEgg(struct DayCare *daycare)
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
daycare->offspringPersonality = (Random()) | (EGG_GENDER_MALE);
|
2017-11-14 20:23:25 +01:00
|
|
|
FlagSet(FLAG_PENDING_DAYCARE_EGG);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerPendingDaycareEgg(void)
|
|
|
|
{
|
|
|
|
_TriggerPendingDaycareEgg(&gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// Unused
|
2017-11-15 22:12:18 +01:00
|
|
|
static void TriggerPendingDaycareMaleEgg(void)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
_TriggerPendingDaycareMaleEgg(&gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Removes the selected index from the given IV list and shifts the remaining
|
|
|
|
// elements to the left.
|
2017-11-15 22:12:18 +01:00
|
|
|
static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
s32 i, j;
|
|
|
|
u8 temp[NUM_STATS];
|
|
|
|
|
2018-12-05 15:31:01 +01:00
|
|
|
ivs[selectedIv] = 0xFF;
|
2017-11-14 20:23:25 +01:00
|
|
|
for (i = 0; i < NUM_STATS; i++)
|
|
|
|
{
|
|
|
|
temp[i] = ivs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; i < NUM_STATS; i++)
|
|
|
|
{
|
2018-12-05 15:31:01 +01:00
|
|
|
if (temp[i] != 0xFF)
|
2017-11-14 20:23:25 +01:00
|
|
|
ivs[j++] = temp[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
u8 i;
|
2019-09-25 20:48:22 +02:00
|
|
|
u8 selectedIvs[INHERITED_IV_COUNT];
|
2017-11-14 20:23:25 +01:00
|
|
|
u8 availableIVs[NUM_STATS];
|
2019-09-26 00:44:56 +02:00
|
|
|
u8 whichParents[INHERITED_IV_COUNT];
|
2017-11-14 20:23:25 +01:00
|
|
|
u8 iv;
|
|
|
|
|
|
|
|
// Initialize a list of IV indices.
|
|
|
|
for (i = 0; i < NUM_STATS; i++)
|
|
|
|
{
|
|
|
|
availableIVs[i] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select the 3 IVs that will be inherited.
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < INHERITED_IV_COUNT; i++)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
// Randomly pick an IV from the available list and stop from being chosen again.
|
2020-12-09 23:45:27 +01:00
|
|
|
// BUG: Instead of removing the IV that was just picked, this
|
2020-11-15 23:24:19 +01:00
|
|
|
// removes position 0 (HP) then position 1 (DEF), then position 2. This is why HP and DEF
|
|
|
|
// have a lower chance to be inherited in Emerald and why the IV picked for inheritance can
|
2020-12-09 23:45:27 +01:00
|
|
|
// be repeated. Amusingly, FRLG and RS also got this wrong. They remove selectedIvs[i], which
|
2020-12-13 05:28:01 +01:00
|
|
|
// is not an index! This means that it can sometimes remove the wrong stat.
|
|
|
|
#ifndef BUGFIX
|
2020-12-09 23:45:27 +01:00
|
|
|
selectedIvs[i] = availableIVs[Random() % (NUM_STATS - i)];
|
|
|
|
RemoveIVIndexFromList(availableIVs, i);
|
2020-12-13 05:28:01 +01:00
|
|
|
#else
|
|
|
|
u8 index = Random() % (NUM_STATS - i);
|
|
|
|
selectedIvs[i] = availableIVs[index];
|
|
|
|
RemoveIVIndexFromList(availableIVs, index);
|
|
|
|
#endif
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Determine which parent each of the selected IVs should inherit from.
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < INHERITED_IV_COUNT; i++)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
whichParents[i] = Random() % DAYCARE_MON_COUNT;
|
2017-11-14 20:23:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set each of inherited IVs on the egg mon.
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < INHERITED_IV_COUNT; i++)
|
2017-11-14 20:23:25 +01:00
|
|
|
{
|
|
|
|
switch (selectedIvs[i])
|
|
|
|
{
|
|
|
|
case 0:
|
2019-09-26 00:44:56 +02:00
|
|
|
iv = GetBoxMonData(&daycare->mons[whichParents[i]].mon, MON_DATA_HP_IV);
|
2017-11-14 20:23:25 +01:00
|
|
|
SetMonData(egg, MON_DATA_HP_IV, &iv);
|
|
|
|
break;
|
|
|
|
case 1:
|
2019-09-26 00:44:56 +02:00
|
|
|
iv = GetBoxMonData(&daycare->mons[whichParents[i]].mon, MON_DATA_ATK_IV);
|
2017-11-14 20:23:25 +01:00
|
|
|
SetMonData(egg, MON_DATA_ATK_IV, &iv);
|
|
|
|
break;
|
|
|
|
case 2:
|
2019-09-26 00:44:56 +02:00
|
|
|
iv = GetBoxMonData(&daycare->mons[whichParents[i]].mon, MON_DATA_DEF_IV);
|
2017-11-14 20:23:25 +01:00
|
|
|
SetMonData(egg, MON_DATA_DEF_IV, &iv);
|
|
|
|
break;
|
|
|
|
case 3:
|
2019-09-26 00:44:56 +02:00
|
|
|
iv = GetBoxMonData(&daycare->mons[whichParents[i]].mon, MON_DATA_SPEED_IV);
|
2017-11-14 20:23:25 +01:00
|
|
|
SetMonData(egg, MON_DATA_SPEED_IV, &iv);
|
|
|
|
break;
|
|
|
|
case 4:
|
2019-09-26 00:44:56 +02:00
|
|
|
iv = GetBoxMonData(&daycare->mons[whichParents[i]].mon, MON_DATA_SPATK_IV);
|
2017-11-14 20:23:25 +01:00
|
|
|
SetMonData(egg, MON_DATA_SPATK_IV, &iv);
|
|
|
|
break;
|
|
|
|
case 5:
|
2019-09-26 00:44:56 +02:00
|
|
|
iv = GetBoxMonData(&daycare->mons[whichParents[i]].mon, MON_DATA_SPDEF_IV);
|
2017-11-14 20:23:25 +01:00
|
|
|
SetMonData(egg, MON_DATA_SPDEF_IV, &iv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-14 21:43:23 +01:00
|
|
|
// Counts the number of egg moves a pokemon learns and stores the moves in
|
|
|
|
// the given array.
|
|
|
|
static u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves)
|
|
|
|
{
|
|
|
|
u16 eggMoveIdx;
|
|
|
|
u16 numEggMoves;
|
|
|
|
u16 species;
|
|
|
|
u16 i;
|
|
|
|
|
|
|
|
numEggMoves = 0;
|
|
|
|
eggMoveIdx = 0;
|
|
|
|
species = GetMonData(pokemon, MON_DATA_SPECIES);
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gEggMoves) - 1; i++)
|
|
|
|
{
|
|
|
|
if (gEggMoves[i] == species + EGG_MOVES_SPECIES_OFFSET)
|
|
|
|
{
|
|
|
|
eggMoveIdx = i + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < EGG_MOVES_ARRAY_COUNT; i++)
|
|
|
|
{
|
|
|
|
if (gEggMoves[eggMoveIdx + i] > EGG_MOVES_SPECIES_OFFSET)
|
|
|
|
break;
|
|
|
|
|
|
|
|
eggMoves[i] = gEggMoves[eggMoveIdx + i];
|
|
|
|
numEggMoves++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numEggMoves;
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, struct BoxPokemon *mother)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
u16 numSharedParentMoves;
|
|
|
|
u32 numLevelUpMoves;
|
|
|
|
u16 numEggMoves;
|
|
|
|
u16 i, j;
|
|
|
|
|
|
|
|
numSharedParentMoves = 0;
|
2018-12-25 18:50:15 +01:00
|
|
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
sHatchedEggMotherMoves[i] = MOVE_NONE;
|
|
|
|
sHatchedEggFatherMoves[i] = MOVE_NONE;
|
|
|
|
sHatchedEggFinalMoves[i] = MOVE_NONE;
|
2017-11-14 21:43:23 +01:00
|
|
|
}
|
|
|
|
for (i = 0; i < EGG_MOVES_ARRAY_COUNT; i++)
|
2019-09-25 20:48:22 +02:00
|
|
|
sHatchedEggEggMoves[i] = MOVE_NONE;
|
2017-11-14 21:43:23 +01:00
|
|
|
for (i = 0; i < EGG_LVL_UP_MOVES_ARRAY_COUNT; i++)
|
2019-09-25 20:48:22 +02:00
|
|
|
sHatchedEggLevelUpMoves[i] = MOVE_NONE;
|
2017-11-14 21:43:23 +01:00
|
|
|
|
|
|
|
numLevelUpMoves = GetLevelUpMovesBySpecies(GetMonData(egg, MON_DATA_SPECIES), sHatchedEggLevelUpMoves);
|
2018-12-25 18:50:15 +01:00
|
|
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
sHatchedEggFatherMoves[i] = GetBoxMonData(father, MON_DATA_MOVE1 + i);
|
|
|
|
sHatchedEggMotherMoves[i] = GetBoxMonData(mother, MON_DATA_MOVE1 + i);
|
|
|
|
}
|
|
|
|
|
|
|
|
numEggMoves = GetEggMoves(egg, sHatchedEggEggMoves);
|
|
|
|
|
2018-12-25 18:50:15 +01:00
|
|
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
if (sHatchedEggFatherMoves[i] != MOVE_NONE)
|
|
|
|
{
|
|
|
|
for (j = 0; j < numEggMoves; j++)
|
|
|
|
{
|
|
|
|
if (sHatchedEggFatherMoves[i] == sHatchedEggEggMoves[j])
|
|
|
|
{
|
2019-10-18 01:22:03 +02:00
|
|
|
if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == MON_HAS_MAX_MOVES)
|
2017-11-14 21:43:23 +01:00
|
|
|
DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFatherMoves[i]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-12-25 18:50:15 +01:00
|
|
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
if (sHatchedEggFatherMoves[i] != MOVE_NONE)
|
|
|
|
{
|
|
|
|
for (j = 0; j < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; j++)
|
|
|
|
{
|
2018-02-05 17:39:26 +01:00
|
|
|
if (sHatchedEggFatherMoves[i] == ItemIdToBattleMoveId(ITEM_TM01_FOCUS_PUNCH + j) && CanMonLearnTMHM(egg, j))
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
2019-10-18 01:22:03 +02:00
|
|
|
if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == MON_HAS_MAX_MOVES)
|
2017-11-14 21:43:23 +01:00
|
|
|
DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFatherMoves[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-25 18:50:15 +01:00
|
|
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
if (sHatchedEggFatherMoves[i] == MOVE_NONE)
|
|
|
|
break;
|
2018-12-25 18:50:15 +01:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
if (sHatchedEggFatherMoves[i] == sHatchedEggMotherMoves[j] && sHatchedEggFatherMoves[i] != MOVE_NONE)
|
|
|
|
sHatchedEggFinalMoves[numSharedParentMoves++] = sHatchedEggFatherMoves[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-25 18:50:15 +01:00
|
|
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
if (sHatchedEggFinalMoves[i] == MOVE_NONE)
|
|
|
|
break;
|
|
|
|
for (j = 0; j < numLevelUpMoves; j++)
|
|
|
|
{
|
|
|
|
if (sHatchedEggLevelUpMoves[j] != MOVE_NONE && sHatchedEggFinalMoves[i] == sHatchedEggLevelUpMoves[j])
|
|
|
|
{
|
2019-10-18 01:22:03 +02:00
|
|
|
if (GiveMoveToMon(egg, sHatchedEggFinalMoves[i]) == MON_HAS_MAX_MOVES)
|
2017-11-14 21:43:23 +01:00
|
|
|
DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFinalMoves[i]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void RemoveEggFromDayCare(struct DayCare *daycare)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
daycare->offspringPersonality = 0;
|
|
|
|
daycare->stepCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RejectEggFromDayCare(void)
|
|
|
|
{
|
|
|
|
RemoveEggFromDayCare(&gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void AlterEggSpeciesWithIncenseItem(u16 *species, struct DayCare *daycare)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
u16 motherItem, fatherItem;
|
|
|
|
if (*species == SPECIES_WYNAUT || *species == SPECIES_AZURILL)
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM);
|
|
|
|
fatherItem = GetBoxMonData(&daycare->mons[1].mon, MON_DATA_HELD_ITEM);
|
2017-11-14 21:43:23 +01:00
|
|
|
if (*species == SPECIES_WYNAUT && motherItem != ITEM_LAX_INCENSE && fatherItem != ITEM_LAX_INCENSE)
|
|
|
|
{
|
|
|
|
*species = SPECIES_WOBBUFFET;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*species == SPECIES_AZURILL && motherItem != ITEM_SEA_INCENSE && fatherItem != ITEM_SEA_INCENSE)
|
|
|
|
{
|
|
|
|
*species = SPECIES_MARILL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void GiveVoltTackleIfLightBall(struct Pokemon *mon, struct DayCare *daycare)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
u32 motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM);
|
|
|
|
u32 fatherItem = GetBoxMonData(&daycare->mons[1].mon, MON_DATA_HELD_ITEM);
|
2017-11-14 21:43:23 +01:00
|
|
|
|
|
|
|
if (motherItem == ITEM_LIGHT_BALL || fatherItem == ITEM_LIGHT_BALL)
|
|
|
|
{
|
2019-10-18 01:22:03 +02:00
|
|
|
if (GiveMoveToMon(mon, MOVE_VOLT_TACKLE) == MON_HAS_MAX_MOVES)
|
2017-11-14 21:43:23 +01:00
|
|
|
DeleteFirstMoveAndGiveMoveToMon(mon, MOVE_VOLT_TACKLE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parentSlots)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
u16 i;
|
2019-09-25 20:48:22 +02:00
|
|
|
u16 species[DAYCARE_MON_COUNT];
|
2017-11-14 21:43:23 +01:00
|
|
|
u16 eggSpecies;
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
species[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES);
|
|
|
|
if (species[i] == SPECIES_DITTO)
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
parentSlots[0] = i ^ 1;
|
|
|
|
parentSlots[1] = i;
|
2017-11-14 21:43:23 +01:00
|
|
|
}
|
|
|
|
else if (GetBoxMonGender(&daycare->mons[i].mon) == MON_FEMALE)
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
parentSlots[0] = i;
|
|
|
|
parentSlots[1] = i ^ 1;
|
2017-11-14 21:43:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-26 00:05:12 +02:00
|
|
|
eggSpecies = GetEggSpecies(species[parentSlots[0]]);
|
2019-09-25 20:48:22 +02:00
|
|
|
if (eggSpecies == SPECIES_NIDORAN_F && daycare->offspringPersonality & EGG_GENDER_MALE)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
eggSpecies = SPECIES_NIDORAN_M;
|
|
|
|
}
|
2019-09-25 20:48:22 +02:00
|
|
|
if (eggSpecies == SPECIES_ILLUMISE && daycare->offspringPersonality & EGG_GENDER_MALE)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
eggSpecies = SPECIES_VOLBEAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make Ditto the "mother" slot if the other daycare mon is male.
|
2019-09-26 00:05:12 +02:00
|
|
|
if (species[parentSlots[1]] == SPECIES_DITTO && GetBoxMonGender(&daycare->mons[parentSlots[0]].mon) != MON_FEMALE)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
u8 ditto = parentSlots[1];
|
|
|
|
parentSlots[1] = parentSlots[0];
|
|
|
|
parentSlots[0] = ditto;
|
2017-11-14 21:43:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return eggSpecies;
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
static void _GiveEggFromDaycare(struct DayCare *daycare)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
struct Pokemon egg;
|
|
|
|
u16 species;
|
2019-09-25 20:48:22 +02:00
|
|
|
u8 parentSlots[DAYCARE_MON_COUNT];
|
2017-11-14 21:43:23 +01:00
|
|
|
bool8 isEgg;
|
|
|
|
|
|
|
|
species = DetermineEggSpeciesAndParentSlots(daycare, parentSlots);
|
|
|
|
AlterEggSpeciesWithIncenseItem(&species, daycare);
|
|
|
|
SetInitialEggData(&egg, species, daycare);
|
|
|
|
InheritIVs(&egg, daycare);
|
2019-09-26 00:05:12 +02:00
|
|
|
BuildEggMoveset(&egg, &daycare->mons[parentSlots[1]].mon, &daycare->mons[parentSlots[0]].mon);
|
2017-11-14 21:43:23 +01:00
|
|
|
|
|
|
|
if (species == SPECIES_PICHU)
|
|
|
|
GiveVoltTackleIfLightBall(&egg, daycare);
|
|
|
|
|
|
|
|
isEgg = TRUE;
|
|
|
|
SetMonData(&egg, MON_DATA_IS_EGG, &isEgg);
|
|
|
|
gPlayerParty[PARTY_SIZE - 1] = egg;
|
|
|
|
CompactPartySlots();
|
|
|
|
CalculatePlayerPartyCount();
|
|
|
|
RemoveEggFromDayCare(daycare);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateEgg(struct Pokemon *mon, u16 species, bool8 setHotSpringsLocation)
|
|
|
|
{
|
|
|
|
u8 metLevel;
|
|
|
|
u16 ball;
|
|
|
|
u8 language;
|
|
|
|
u8 metLocation;
|
|
|
|
u8 isEgg;
|
|
|
|
|
2021-01-07 23:13:14 +01:00
|
|
|
CreateMon(mon, species, EGG_HATCH_LEVEL, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0);
|
2017-11-14 21:43:23 +01:00
|
|
|
metLevel = 0;
|
|
|
|
ball = ITEM_POKE_BALL;
|
|
|
|
language = LANGUAGE_JAPANESE;
|
|
|
|
SetMonData(mon, MON_DATA_POKEBALL, &ball);
|
|
|
|
SetMonData(mon, MON_DATA_NICKNAME, sJapaneseEggNickname);
|
|
|
|
SetMonData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].eggCycles);
|
|
|
|
SetMonData(mon, MON_DATA_MET_LEVEL, &metLevel);
|
|
|
|
SetMonData(mon, MON_DATA_LANGUAGE, &language);
|
|
|
|
if (setHotSpringsLocation)
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
metLocation = METLOC_SPECIAL_EGG;
|
2017-11-14 21:43:23 +01:00
|
|
|
SetMonData(mon, MON_DATA_MET_LOCATION, &metLocation);
|
|
|
|
}
|
|
|
|
|
|
|
|
isEgg = TRUE;
|
|
|
|
SetMonData(mon, MON_DATA_IS_EGG, &isEgg);
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare)
|
2017-11-14 21:43:23 +01:00
|
|
|
{
|
|
|
|
u32 personality;
|
|
|
|
u16 ball;
|
|
|
|
u8 metLevel;
|
|
|
|
u8 language;
|
|
|
|
|
|
|
|
personality = daycare->offspringPersonality;
|
2021-01-07 23:13:14 +01:00
|
|
|
CreateMon(mon, species, EGG_HATCH_LEVEL, USE_RANDOM_IVS, TRUE, personality, OT_ID_PLAYER_ID, 0);
|
2017-11-14 21:43:23 +01:00
|
|
|
metLevel = 0;
|
|
|
|
ball = ITEM_POKE_BALL;
|
|
|
|
language = LANGUAGE_JAPANESE;
|
|
|
|
SetMonData(mon, MON_DATA_POKEBALL, &ball);
|
|
|
|
SetMonData(mon, MON_DATA_NICKNAME, sJapaneseEggNickname);
|
|
|
|
SetMonData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].eggCycles);
|
|
|
|
SetMonData(mon, MON_DATA_MET_LEVEL, &metLevel);
|
|
|
|
SetMonData(mon, MON_DATA_LANGUAGE, &language);
|
|
|
|
}
|
2017-11-14 20:23:25 +01:00
|
|
|
|
2017-11-14 21:43:23 +01:00
|
|
|
void GiveEggFromDaycare(void)
|
|
|
|
{
|
|
|
|
_GiveEggFromDaycare(&gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
2017-11-14 23:25:07 +01:00
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
static bool8 TryProduceOrHatchEgg(struct DayCare *daycare)
|
2017-11-14 23:25:07 +01:00
|
|
|
{
|
|
|
|
u32 i, validEggs = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
|
|
|
{
|
2018-12-15 23:58:47 +01:00
|
|
|
if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SANITY_HAS_SPECIES))
|
2017-11-14 23:25:07 +01:00
|
|
|
daycare->mons[i].steps++, validEggs++;
|
|
|
|
}
|
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
// Check if an egg should be produced
|
2019-09-26 00:05:12 +02:00
|
|
|
if (daycare->offspringPersonality == 0 && validEggs == DAYCARE_MON_COUNT && (daycare->mons[1].steps & 0xFF) == 0xFF)
|
2017-11-14 23:25:07 +01:00
|
|
|
{
|
2021-02-05 07:27:11 +01:00
|
|
|
u8 compatibility = GetDaycareCompatibilityScore(daycare);
|
|
|
|
if (compatibility > (Random() * 100u) / USHRT_MAX)
|
2017-11-14 23:25:07 +01:00
|
|
|
TriggerPendingDaycareEgg();
|
|
|
|
}
|
|
|
|
|
2020-05-27 22:41:23 +02:00
|
|
|
// Try to hatch Egg
|
2019-09-26 00:44:56 +02:00
|
|
|
if (++daycare->stepCounter == 255)
|
2017-11-14 23:25:07 +01:00
|
|
|
{
|
2020-05-27 22:41:23 +02:00
|
|
|
u32 eggCycles;
|
|
|
|
u8 toSub = GetEggCyclesToSubtract();
|
2017-11-14 23:25:07 +01:00
|
|
|
|
|
|
|
for (i = 0; i < gPlayerPartyCount; i++)
|
|
|
|
{
|
|
|
|
if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
|
|
|
|
continue;
|
2018-12-15 23:58:47 +01:00
|
|
|
if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_IS_BAD_EGG))
|
2017-11-14 23:25:07 +01:00
|
|
|
continue;
|
|
|
|
|
2020-05-27 22:41:23 +02:00
|
|
|
eggCycles = GetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP);
|
|
|
|
if (eggCycles != 0)
|
2017-11-14 23:25:07 +01:00
|
|
|
{
|
2020-05-27 22:41:23 +02:00
|
|
|
if (eggCycles >= toSub)
|
|
|
|
eggCycles -= toSub;
|
2017-11-14 23:25:07 +01:00
|
|
|
else
|
2020-05-27 22:41:23 +02:00
|
|
|
eggCycles -= 1;
|
2017-11-14 23:25:07 +01:00
|
|
|
|
2020-05-27 22:41:23 +02:00
|
|
|
SetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP, &eggCycles);
|
2017-11-14 23:25:07 +01:00
|
|
|
}
|
2021-08-25 00:59:32 +02:00
|
|
|
else
|
2017-11-14 23:25:07 +01:00
|
|
|
{
|
|
|
|
gSpecialVar_0x8004 = i;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
return FALSE;
|
2017-11-14 23:25:07 +01:00
|
|
|
}
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2018-10-17 04:47:08 +02:00
|
|
|
bool8 ShouldEggHatch(void)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
return TryProduceOrHatchEgg(&gSaveBlock1Ptr->daycare);
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool8 IsEggPending(struct DayCare *daycare)
|
|
|
|
{
|
|
|
|
return (daycare->offspringPersonality != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// gStringVar1 = first mon's nickname
|
|
|
|
// gStringVar2 = second mon's nickname
|
|
|
|
// gStringVar3 = first mon trainer's name
|
2017-11-15 22:12:18 +01:00
|
|
|
static void _GetDaycareMonNicknames(struct DayCare *daycare)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
u8 text[12];
|
2019-09-26 00:05:12 +02:00
|
|
|
if (GetBoxMonData(&daycare->mons[0].mon, MON_DATA_SPECIES) != 0)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycare->mons[0].mon, gStringVar1);
|
2019-09-26 00:05:12 +02:00
|
|
|
GetBoxMonData(&daycare->mons[0].mon, MON_DATA_OT_NAME, text);
|
2017-11-15 20:08:31 +01:00
|
|
|
StringCopy(gStringVar3, text);
|
|
|
|
}
|
|
|
|
|
2019-09-26 00:05:12 +02:00
|
|
|
if (GetBoxMonData(&daycare->mons[1].mon, MON_DATA_SPECIES) != 0)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycare->mons[1].mon, gStringVar2);
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
u16 GetSelectedMonNicknameAndSpecies(void)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&gPlayerParty[GetCursorSelectionMonId()].box, gStringVar1);
|
2017-11-15 20:08:31 +01:00
|
|
|
return GetBoxMonData(&gPlayerParty[GetCursorSelectionMonId()].box, MON_DATA_SPECIES);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetDaycareMonNicknames(void)
|
|
|
|
{
|
|
|
|
_GetDaycareMonNicknames(&gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetDaycareState(void)
|
|
|
|
{
|
|
|
|
u8 numMons;
|
|
|
|
if (IsEggPending(&gSaveBlock1Ptr->daycare))
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
return DAYCARE_EGG_WAITING;
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
numMons = CountPokemonInDaycare(&gSaveBlock1Ptr->daycare);
|
|
|
|
if (numMons != 0)
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
return numMons + 1; // DAYCARE_ONE_MON or DAYCARE_TWO_MONS
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
return DAYCARE_NO_MONS;
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 GetDaycarePokemonCount(void)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
u8 ret = CountPokemonInDaycare(&gSaveBlock1Ptr->daycare);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// Determine if the two given egg group lists contain any of the
|
|
|
|
// same egg groups.
|
2017-11-15 20:08:31 +01:00
|
|
|
static bool8 EggGroupsOverlap(u16 *eggGroups1, u16 *eggGroups2)
|
|
|
|
{
|
|
|
|
s32 i, j;
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < EGG_GROUPS_PER_MON; i++)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
for (j = 0; j < EGG_GROUPS_PER_MON; j++)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
if (eggGroups1[i] == eggGroups2[j])
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 GetDaycareCompatibilityScore(struct DayCare *daycare)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
u32 i;
|
2019-09-25 20:48:22 +02:00
|
|
|
u16 eggGroups[DAYCARE_MON_COUNT][EGG_GROUPS_PER_MON];
|
|
|
|
u16 species[DAYCARE_MON_COUNT];
|
|
|
|
u32 trainerIds[DAYCARE_MON_COUNT];
|
|
|
|
u32 genders[DAYCARE_MON_COUNT];
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
u32 personality;
|
|
|
|
|
|
|
|
species[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES);
|
|
|
|
trainerIds[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_OT_ID);
|
|
|
|
personality = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_PERSONALITY);
|
|
|
|
genders[i] = GetGenderFromSpeciesAndPersonality(species[i], personality);
|
|
|
|
eggGroups[i][0] = gBaseStats[species[i]].eggGroup1;
|
|
|
|
eggGroups[i][1] = gBaseStats[species[i]].eggGroup2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check unbreedable egg group
|
2019-09-26 00:05:12 +02:00
|
|
|
if (eggGroups[0][0] == EGG_GROUP_UNDISCOVERED || eggGroups[1][0] == EGG_GROUP_UNDISCOVERED)
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_INCOMPATIBLE;
|
2017-11-15 20:08:31 +01:00
|
|
|
// two Ditto can't breed
|
2019-09-26 00:05:12 +02:00
|
|
|
if (eggGroups[0][0] == EGG_GROUP_DITTO && eggGroups[1][0] == EGG_GROUP_DITTO)
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_INCOMPATIBLE;
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
// one parent is Ditto
|
2019-09-26 00:05:12 +02:00
|
|
|
if (eggGroups[0][0] == EGG_GROUP_DITTO || eggGroups[1][0] == EGG_GROUP_DITTO)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
if (trainerIds[0] == trainerIds[1])
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_LOW_COMPATIBILITY;
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2021-02-05 07:27:11 +01:00
|
|
|
return PARENTS_MED_COMPATIBILITY;
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
2019-09-25 20:48:22 +02:00
|
|
|
// neither parent is Ditto
|
2017-11-15 20:08:31 +01:00
|
|
|
else
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
if (genders[0] == genders[1])
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_INCOMPATIBLE;
|
2019-09-26 00:05:12 +02:00
|
|
|
if (genders[0] == MON_GENDERLESS || genders[1] == MON_GENDERLESS)
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_INCOMPATIBLE;
|
2019-09-26 00:05:12 +02:00
|
|
|
if (!EggGroupsOverlap(eggGroups[0], eggGroups[1]))
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_INCOMPATIBLE;
|
|
|
|
|
2019-09-26 00:05:12 +02:00
|
|
|
if (species[0] == species[1])
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
if (trainerIds[0] == trainerIds[1])
|
2021-02-05 07:27:11 +01:00
|
|
|
return PARENTS_MED_COMPATIBILITY; // same species, same trainer
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2021-02-05 07:27:11 +01:00
|
|
|
return PARENTS_MAX_COMPATIBILITY; // same species, different trainers
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
if (trainerIds[0] != trainerIds[1])
|
2021-02-05 07:27:11 +01:00
|
|
|
return PARENTS_MED_COMPATIBILITY; // different species, different trainers
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
return PARENTS_LOW_COMPATIBILITY; // different species, same trainer
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 GetDaycareCompatibilityScoreFromSave(void)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
return GetDaycareCompatibilityScore(&gSaveBlock1Ptr->daycare);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetDaycareCompatibilityString(void)
|
|
|
|
{
|
|
|
|
u8 whichString;
|
|
|
|
u8 relationshipScore;
|
|
|
|
|
|
|
|
relationshipScore = GetDaycareCompatibilityScoreFromSave();
|
|
|
|
whichString = 0;
|
2019-09-25 20:48:22 +02:00
|
|
|
if (relationshipScore == PARENTS_INCOMPATIBLE)
|
2017-11-15 20:08:31 +01:00
|
|
|
whichString = 3;
|
2019-09-25 20:48:22 +02:00
|
|
|
if (relationshipScore == PARENTS_LOW_COMPATIBILITY)
|
2017-11-15 20:08:31 +01:00
|
|
|
whichString = 2;
|
2021-02-05 07:27:11 +01:00
|
|
|
if (relationshipScore == PARENTS_MED_COMPATIBILITY)
|
2017-11-15 20:08:31 +01:00
|
|
|
whichString = 1;
|
2021-02-05 07:27:11 +01:00
|
|
|
if (relationshipScore == PARENTS_MAX_COMPATIBILITY)
|
2017-11-15 20:08:31 +01:00
|
|
|
whichString = 0;
|
|
|
|
|
|
|
|
StringCopy(gStringVar4, sCompatibilityMessages[whichString]);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio)
|
|
|
|
{
|
|
|
|
u8 i;
|
2019-09-25 20:48:22 +02:00
|
|
|
u8 symbolsCount[GENDER_COUNT];
|
|
|
|
symbolsCount[MALE] = symbolsCount[FEMALE] = 0;
|
2017-11-15 20:08:31 +01:00
|
|
|
|
|
|
|
for (i = 0; name[i] != EOS; i++)
|
|
|
|
{
|
|
|
|
if (name[i] == CHAR_MALE)
|
2019-09-25 20:48:22 +02:00
|
|
|
symbolsCount[MALE]++;
|
2017-11-15 20:08:31 +01:00
|
|
|
if (name[i] == CHAR_FEMALE)
|
2019-09-25 20:48:22 +02:00
|
|
|
symbolsCount[FEMALE]++;
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:48:22 +02:00
|
|
|
if (genderRatio == MON_MALE && symbolsCount[MALE] != 0 && symbolsCount[FEMALE] == 0)
|
2017-11-15 20:08:31 +01:00
|
|
|
return TRUE;
|
2019-09-25 20:48:22 +02:00
|
|
|
if (genderRatio == MON_FEMALE && symbolsCount[FEMALE] != 0 && symbolsCount[MALE] == 0)
|
2017-11-15 20:08:31 +01:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u8 *AppendGenderSymbol(u8 *name, u8 gender)
|
|
|
|
{
|
|
|
|
if (gender == MON_MALE)
|
|
|
|
{
|
|
|
|
if (!NameHasGenderSymbol(name, MON_MALE))
|
|
|
|
return StringAppend(name, gText_MaleSymbol4);
|
|
|
|
}
|
|
|
|
else if (gender == MON_FEMALE)
|
|
|
|
{
|
|
|
|
if (!NameHasGenderSymbol(name, MON_FEMALE))
|
|
|
|
return StringAppend(name, gText_FemaleSymbol4);
|
|
|
|
}
|
|
|
|
|
|
|
|
return StringAppend(name, gText_GenderlessSymbol);
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static u8 *AppendMonGenderSymbol(u8 *name, struct BoxPokemon *boxMon)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
return AppendGenderSymbol(name, GetBoxMonGender(boxMon));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GetDaycareLevelMenuText(struct DayCare *daycare, u8 *dest)
|
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
u8 monNames[DAYCARE_MON_COUNT][20];
|
2017-11-15 20:08:31 +01:00
|
|
|
u8 i;
|
|
|
|
|
|
|
|
*dest = EOS;
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycare->mons[i].mon, monNames[i]);
|
2017-11-15 20:08:31 +01:00
|
|
|
AppendMonGenderSymbol(monNames[i], &daycare->mons[i].mon);
|
|
|
|
}
|
|
|
|
|
2019-09-26 00:05:12 +02:00
|
|
|
StringCopy(dest, monNames[0]);
|
2017-11-15 20:08:31 +01:00
|
|
|
StringAppend(dest, gText_NewLine2);
|
2019-09-26 00:05:12 +02:00
|
|
|
StringAppend(dest, monNames[1]);
|
2017-11-15 20:08:31 +01:00
|
|
|
StringAppend(dest, gText_NewLine2);
|
|
|
|
StringAppend(dest, gText_Exit4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GetDaycareLevelMenuLevelText(struct DayCare *daycare, u8 *dest)
|
|
|
|
{
|
|
|
|
u8 i;
|
|
|
|
u8 level;
|
|
|
|
u8 text[20];
|
|
|
|
|
|
|
|
*dest = EOS;
|
2019-09-25 20:48:22 +02:00
|
|
|
for (i = 0; i < DAYCARE_MON_COUNT; i++)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
StringAppend(dest, gText_Lv);
|
|
|
|
level = GetLevelAfterDaycareSteps(&daycare->mons[i].mon, daycare->mons[i].steps);
|
|
|
|
ConvertIntToDecimalStringN(text, level, STR_CONV_MODE_LEFT_ALIGN, 3);
|
|
|
|
StringAppend(dest, text);
|
|
|
|
StringAppend(dest, gText_NewLine2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void DaycareAddTextPrinter(u8 windowId, const u8 *text, u32 x, u32 y)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2018-11-06 17:44:48 +01:00
|
|
|
struct TextPrinterTemplate printer;
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2018-11-06 17:44:48 +01:00
|
|
|
printer.currentChar = text;
|
2017-11-15 20:08:31 +01:00
|
|
|
printer.windowId = windowId;
|
2021-10-30 22:47:37 +02:00
|
|
|
printer.fontId = FONT_NORMAL;
|
2017-11-15 20:08:31 +01:00
|
|
|
printer.x = x;
|
|
|
|
printer.y = y;
|
|
|
|
printer.currentX = x;
|
|
|
|
printer.currentY = y;
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
|
|
|
printer.unk = 0;
|
2018-11-06 18:30:21 +01:00
|
|
|
gTextFlags.useAlternateDownArrow = 0;
|
2017-11-15 20:08:31 +01:00
|
|
|
printer.letterSpacing = 0;
|
|
|
|
printer.lineSpacing = 1;
|
2018-01-25 22:25:35 +01:00
|
|
|
printer.fgColor = 2;
|
2017-11-15 20:08:31 +01:00
|
|
|
printer.bgColor = 1;
|
|
|
|
printer.shadowColor = 3;
|
|
|
|
|
2021-11-03 23:29:18 +01:00
|
|
|
AddTextPrinter(&printer, TEXT_SKIP_DRAW, NULL);
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
static void DaycarePrintMonNickname(struct DayCare *daycare, u8 windowId, u32 daycareSlotId, u32 y)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
u8 nickname[POKEMON_NAME_LENGTH * 2];
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2019-09-26 00:44:56 +02:00
|
|
|
GetBoxMonNickname(&daycare->mons[daycareSlotId].mon, nickname);
|
|
|
|
AppendMonGenderSymbol(nickname, &daycare->mons[daycareSlotId].mon);
|
|
|
|
DaycareAddTextPrinter(windowId, nickname, 8, y);
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void DaycarePrintMonLvl(struct DayCare *daycare, u8 windowId, u32 daycareSlotId, u32 y)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
|
|
|
u8 level;
|
|
|
|
u32 x;
|
|
|
|
u8 lvlText[12];
|
|
|
|
u8 intText[8];
|
|
|
|
|
|
|
|
StringCopy(lvlText, gText_Lv);
|
|
|
|
level = GetLevelAfterDaycareSteps(&daycare->mons[daycareSlotId].mon, daycare->mons[daycareSlotId].steps);
|
|
|
|
ConvertIntToDecimalStringN(intText, level, STR_CONV_MODE_LEFT_ALIGN, 3);
|
|
|
|
StringAppend(lvlText, intText);
|
2021-10-30 22:47:37 +02:00
|
|
|
x = GetStringRightAlignXOffset(FONT_NORMAL, lvlText, 112);
|
2017-11-15 20:08:31 +01:00
|
|
|
DaycareAddTextPrinter(windowId, lvlText, x, y);
|
|
|
|
}
|
|
|
|
|
2021-06-18 06:15:45 +02:00
|
|
|
static void DaycarePrintMonInfo(u8 windowId, u32 daycareSlotId, u8 y)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2017-11-15 22:12:18 +01:00
|
|
|
if (daycareSlotId < (unsigned) DAYCARE_MON_COUNT)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:44:56 +02:00
|
|
|
DaycarePrintMonNickname(&gSaveBlock1Ptr->daycare, windowId, daycareSlotId, y);
|
2017-11-15 20:08:31 +01:00
|
|
|
DaycarePrintMonLvl(&gSaveBlock1Ptr->daycare, windowId, daycareSlotId, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define tMenuListTaskId data[0]
|
|
|
|
#define tWindowId data[1]
|
|
|
|
|
2017-11-15 22:12:18 +01:00
|
|
|
static void Task_HandleDaycareLevelMenuInput(u8 taskId)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-02-02 11:04:38 +01:00
|
|
|
u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuListTaskId);
|
2017-11-15 20:08:31 +01:00
|
|
|
|
2020-11-03 02:02:39 +01:00
|
|
|
if (JOY_NEW(A_BUTTON))
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-02-02 11:04:38 +01:00
|
|
|
switch (input)
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-26 00:05:12 +02:00
|
|
|
case 0:
|
|
|
|
case 1:
|
2019-02-02 11:04:38 +01:00
|
|
|
gSpecialVar_Result = input;
|
2017-11-15 20:08:31 +01:00
|
|
|
break;
|
2019-09-25 20:48:22 +02:00
|
|
|
case DAYCARE_LEVEL_MENU_EXIT:
|
|
|
|
gSpecialVar_Result = DAYCARE_EXITED_LEVEL_MENU;
|
2017-11-15 20:08:31 +01:00
|
|
|
break;
|
|
|
|
}
|
2018-03-02 16:34:31 +01:00
|
|
|
DestroyListMenuTask(gTasks[taskId].tMenuListTaskId, NULL, NULL);
|
2019-02-22 07:40:11 +01:00
|
|
|
ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE);
|
2017-11-15 20:08:31 +01:00
|
|
|
RemoveWindow(gTasks[taskId].tWindowId);
|
|
|
|
DestroyTask(taskId);
|
|
|
|
EnableBothScriptContexts();
|
|
|
|
}
|
2020-11-03 02:02:39 +01:00
|
|
|
else if (JOY_NEW(B_BUTTON))
|
2017-11-15 20:08:31 +01:00
|
|
|
{
|
2019-09-25 20:48:22 +02:00
|
|
|
gSpecialVar_Result = DAYCARE_EXITED_LEVEL_MENU;
|
2018-03-02 16:34:31 +01:00
|
|
|
DestroyListMenuTask(gTasks[taskId].tMenuListTaskId, NULL, NULL);
|
2019-02-22 07:40:11 +01:00
|
|
|
ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE);
|
2017-11-15 20:08:31 +01:00
|
|
|
RemoveWindow(gTasks[taskId].tWindowId);
|
|
|
|
DestroyTask(taskId);
|
|
|
|
EnableBothScriptContexts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShowDaycareLevelMenu(void)
|
|
|
|
{
|
|
|
|
struct ListMenuTemplate menuTemplate;
|
|
|
|
u8 windowId;
|
|
|
|
u8 listMenuTaskId;
|
|
|
|
u8 daycareMenuTaskId;
|
|
|
|
|
|
|
|
windowId = AddWindow(&sDaycareLevelMenuWindowTemplate);
|
2019-02-22 07:40:11 +01:00
|
|
|
DrawStdWindowFrame(windowId, FALSE);
|
2017-11-15 20:08:31 +01:00
|
|
|
|
|
|
|
menuTemplate = sDaycareListMenuLevelTemplate;
|
2018-03-03 14:58:41 +01:00
|
|
|
menuTemplate.windowId = windowId;
|
2017-11-15 20:08:31 +01:00
|
|
|
listMenuTaskId = ListMenuInit(&menuTemplate, 0, 0);
|
|
|
|
|
2021-11-03 20:29:18 +01:00
|
|
|
CopyWindowToVram(windowId, COPYWIN_FULL);
|
2017-11-15 20:08:31 +01:00
|
|
|
|
|
|
|
daycareMenuTaskId = CreateTask(Task_HandleDaycareLevelMenuInput, 3);
|
|
|
|
gTasks[daycareMenuTaskId].tMenuListTaskId = listMenuTaskId;
|
|
|
|
gTasks[daycareMenuTaskId].tWindowId = windowId;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef tMenuListTaskId
|
|
|
|
#undef tWindowId
|
|
|
|
|
|
|
|
void ChooseSendDaycareMon(void)
|
|
|
|
{
|
2019-10-18 01:22:03 +02:00
|
|
|
ChooseMonForDaycare();
|
2018-02-14 00:58:22 +01:00
|
|
|
gMain.savedCallback = CB2_ReturnToField;
|
2017-11-15 20:08:31 +01:00
|
|
|
}
|