From 3af93bdfeefcf50eb4b86a8f7646235a8d4a1032 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:28:05 +0200 Subject: [PATCH] FRLG+ whiteout message (#4967) * FRLG whiteout message + post whiteout event --- data/event_scripts.s | 73 +++++++++++ include/config/overworld.h | 1 + include/constants/heal_locations.h | 1 + include/event_scripts.h | 2 + include/field_screen_effect.h | 1 + include/heal_location.h | 4 + include/strings.h | 4 + src/data/heal_locations_pkm_center.h | 175 +++++++++++++++++++++++++++ src/field_screen_effect.c | 114 +++++++++++++++++ src/heal_location.c | 69 +++++++++++ src/overworld.c | 17 ++- src/strings.c | 2 + 12 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 src/data/heal_locations_pkm_center.h diff --git a/data/event_scripts.s b/data/event_scripts.s index 07eafe1c35ea..d4393ac9d473 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -587,6 +587,37 @@ EventScript_WhiteOut:: goto EventScript_ResetMrBriney end +EventScript_AfterWhiteOutHeal:: + lockall + msgbox gText_FirstShouldRestoreMonsHealth + call EventScript_PkmnCenterNurse_TakeAndHealPkmn + call_if_unset FLAG_DEFEATED_RUSTBORO_GYM, EventScript_AfterWhiteOutHealMsgPreRoxanne + call_if_set FLAG_DEFEATED_RUSTBORO_GYM, EventScript_AfterWhiteOutHealMsg + applymovement VAR_LAST_TALKED, Movement_PkmnCenterNurse_Bow + waitmovement 0 + fadedefaultbgm + releaseall + end + +EventScript_AfterWhiteOutHealMsgPreRoxanne:: + msgbox gText_MonsHealedShouldBuyPotions + return + +EventScript_AfterWhiteOutHealMsg:: + msgbox gText_MonsHealed + return + +EventScript_AfterWhiteOutMomHeal:: + lockall + applymovement LOCALID_MOM, Common_Movement_WalkInPlaceFasterDown + waitmovement 0 + msgbox gText_HadQuiteAnExperienceTakeRest + call Common_EventScript_OutOfCenterPartyHeal + msgbox gText_MomExplainHPGetPotions + fadedefaultbgm + releaseall + end + EventScript_ResetMrBriney:: goto_if_eq VAR_BRINEY_LOCATION, 1, EventScript_MoveMrBrineyToHouse goto_if_eq VAR_BRINEY_LOCATION, 2, EventScript_MoveMrBrineyToDewford @@ -887,6 +918,48 @@ gText_PlayerWhitedOut:: .string "{PLAYER} is out of usable\n" .string "POKéMON!\p{PLAYER} whited out!$" +gText_FirstShouldRestoreMonsHealth:: + .string "First, you should restore your\n" + .string "POKéMON to full health.$" + +gText_MonsHealedShouldBuyPotions:: + .string "Your POKéMON have been healed\n" + .string "to perfect health.\p" + .string "If your POKéMON's energy, HP,\n" + .string "is down, please come see us.\p" + .string "If you're planning to go far in the\n" + .string "field, you should buy some POTIONS\l" + .string "at the POKéMON MART.\p" + .string "We hope you excel!$" + +gText_MonsHealed:: + .string "Your POKéMON have been healed\n" + .string "to perfect health.\p" + .string "We hope you excel!$" + +gText_HadQuiteAnExperienceTakeRest:: + .string "MOM: {PLAYER}!\n" + .string "Welcome home.\p" + .string "It sounds like you had quite\n" + .string "an experience.\p" + .string "Maybe you should take a quick\n" + .string "rest.$" + +gText_MomExplainHPGetPotions:: + .string "MOM: Oh, good! You and your\n" + .string "POKéMON are looking great.\p" + .string "I just heard from PROF. BIRCH.\p" + .string "He said that POKéMON's energy is\n" + .string "measured in HP.\p" + .string "If your POKéMON lose their HP,\n" + .string "you can restore them at any\l" + .string "POKéMON CENTER.\p" + .string "If you're going to travel far away,\n" + .string "the smart TRAINER stocks up on\l" + .string "POTIONS at the POKéMON MART.\p" + .string "Make me proud, honey!\p" + .string "Take care!$" + gText_RegisteredTrainerinPokeNav:: .string "Registered {STR_VAR_1} {STR_VAR_2}\n" .string "in the POKéNAV.$" diff --git a/include/config/overworld.h b/include/config/overworld.h index b6664269960c..b47cef5c5082 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -8,6 +8,7 @@ #define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all. #define OW_DOUBLE_APPROACH_WITH_ONE_MON FALSE // If enabled, you can be spotted by two trainers at the same time even if you only have one eligible Pokémon in your party. #define OW_HIDE_REPEAT_MAP_POPUP FALSE // If enabled, map popups will not appear if entering a map with the same Map Section Id as the last. +#define OW_FRLG_WHITEOUT FALSE // If enabled, shows an additional whiteout message and post whiteout event script with healing NPC. // These generational defines only make a distinction for Berries and the OW_PC_MOVE_ORDER #define GEN_6_XY GEN_6 diff --git a/include/constants/heal_locations.h b/include/constants/heal_locations.h index d3dd8f1f1748..217594d0b7f2 100644 --- a/include/constants/heal_locations.h +++ b/include/constants/heal_locations.h @@ -24,5 +24,6 @@ #define HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE 20 #define HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR 21 #define HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST 22 +#define HEAL_LOCATION_COUNT 23 #endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H diff --git a/include/event_scripts.h b/include/event_scripts.h index fa0bfe5c6ecd..7c35e991c252 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -620,6 +620,8 @@ extern const u8 EventScript_SelectWithoutRegisteredItem[]; // overworld extern const u8 EventScript_WhiteOut[]; +extern const u8 EventScript_AfterWhiteOutMomHeal[]; +extern const u8 EventScript_AfterWhiteOutHeal[]; extern const u8 EventScript_ResetMrBriney[]; extern const u8 EventScript_DoLinkRoomExit[]; extern const u8 CableClub_EventScript_TooBusyToNotice[]; diff --git a/include/field_screen_effect.h b/include/field_screen_effect.h index 6dc9b077d219..9b3aa6229e5f 100644 --- a/include/field_screen_effect.h +++ b/include/field_screen_effect.h @@ -16,6 +16,7 @@ void FieldCB_ReturnToFieldWirelessLink(void); void FieldCB_DefaultWarpExit(void); void FieldCB_WarpExitFadeFromBlack(void); void FieldCB_WarpExitFadeFromWhite(void); +void FieldCB_RushInjuredPokemonToCenter(void); bool8 FieldCB_ReturnToFieldOpenStartMenu(void); void ReturnToFieldOpenStartMenu(void); void FieldCB_ReturnToFieldNoScript(void); diff --git a/include/heal_location.h b/include/heal_location.h index 46f0d785ab7a..8c4ebae96508 100644 --- a/include/heal_location.h +++ b/include/heal_location.h @@ -10,7 +10,11 @@ struct HealLocation }; u32 GetHealLocationIndexByMap(u16 mapGroup, u16 mapNum); +u32 GetHealLocationIndexByWarpData(struct WarpData *warp); const struct HealLocation *GetHealLocationByMap(u16 mapGroup, u16 mapNum); const struct HealLocation *GetHealLocation(u32 index); +bool32 IsLastHealLocationPlayerHouse(); +void SetWhiteoutRespawnWarpAndHealerNPC(struct WarpData * warp); +u32 GetHealNpcLocalId(u32 healLocationId); #endif // GUARD_HEAL_LOCATION_H diff --git a/include/strings.h b/include/strings.h index 2963eb96d15c..ec175ab251d0 100644 --- a/include/strings.h +++ b/include/strings.h @@ -3046,4 +3046,8 @@ extern const u8 gText_PlantBerry[]; extern const u8 gText_AM[]; extern const u8 gText_PM[]; +// FRLG whiteout +extern const u8 gText_PlayerScurriedToCenter[]; +extern const u8 gText_PlayerScurriedBackHome[]; + #endif // GUARD_STRINGS_H diff --git a/src/data/heal_locations_pkm_center.h b/src/data/heal_locations_pkm_center.h new file mode 100644 index 000000000000..58be0be05ed6 --- /dev/null +++ b/src/data/heal_locations_pkm_center.h @@ -0,0 +1,175 @@ +#define DEFAULT_POKEMON_CENTER_COORDS .x = 7, .y = 4 + +static const struct HealLocation sHealLocationsPokemonCenter[HEAL_LOCATION_COUNT - 1] = +{ + [HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE_2F - 1] = + { + .group = MAP_GROUP(LITTLEROOT_TOWN_BRENDANS_HOUSE_1F), + .map = MAP_NUM(LITTLEROOT_TOWN_BRENDANS_HOUSE_1F), + .x = 2, + .y = 7, + }, + [HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE_2F - 1] = + { + .group = MAP_GROUP(LITTLEROOT_TOWN_MAYS_HOUSE_1F), + .map = MAP_NUM(LITTLEROOT_TOWN_MAYS_HOUSE_1F), + .x = 8, + .y = 7, + }, + [HEAL_LOCATION_PETALBURG_CITY - 1] = + { + .group = MAP_GROUP(PETALBURG_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(PETALBURG_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_SLATEPORT_CITY - 1] = + { + .group = MAP_GROUP(SLATEPORT_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(SLATEPORT_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_MAUVILLE_CITY - 1] = + { + .group = MAP_GROUP(MAUVILLE_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(MAUVILLE_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_RUSTBORO_CITY - 1] = + { + .group = MAP_GROUP(RUSTBORO_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(RUSTBORO_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_FORTREE_CITY - 1] = + { + .group = MAP_GROUP(FORTREE_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(FORTREE_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_LILYCOVE_CITY - 1] = + { + .group = MAP_GROUP(LILYCOVE_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(LILYCOVE_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_MOSSDEEP_CITY - 1] = + { + .group = MAP_GROUP(MOSSDEEP_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(MOSSDEEP_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_SOOTOPOLIS_CITY - 1] = + { + .group = MAP_GROUP(SOOTOPOLIS_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(SOOTOPOLIS_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_EVER_GRANDE_CITY - 1] = + { + .group = MAP_GROUP(EVER_GRANDE_CITY_POKEMON_CENTER_1F), + .map = MAP_NUM(EVER_GRANDE_CITY_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE - 1] = + { + .group = MAP_GROUP(LITTLEROOT_TOWN_BRENDANS_HOUSE_1F), + .map = MAP_NUM(LITTLEROOT_TOWN_BRENDANS_HOUSE_1F), + .x = 2, + .y = 7, + }, + [HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE - 1] = + { + .group = MAP_GROUP(LITTLEROOT_TOWN_MAYS_HOUSE_1F), + .map = MAP_NUM(LITTLEROOT_TOWN_MAYS_HOUSE_1F), + .x = 8, + .y = 7, + }, + [HEAL_LOCATION_OLDALE_TOWN - 1] = + { + .group = MAP_GROUP(OLDALE_TOWN_POKEMON_CENTER_1F), + .map = MAP_NUM(OLDALE_TOWN_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_DEWFORD_TOWN - 1] = + { + .group = MAP_GROUP(DEWFORD_TOWN_POKEMON_CENTER_1F), + .map = MAP_NUM(DEWFORD_TOWN_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_LAVARIDGE_TOWN - 1] = + { + .group = MAP_GROUP(LAVARIDGE_TOWN_POKEMON_CENTER_1F), + .map = MAP_NUM(LAVARIDGE_TOWN_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_FALLARBOR_TOWN - 1] = + { + .group = MAP_GROUP(FALLARBOR_TOWN_POKEMON_CENTER_1F), + .map = MAP_NUM(FALLARBOR_TOWN_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_VERDANTURF_TOWN - 1] = + { + .group = MAP_GROUP(VERDANTURF_TOWN_POKEMON_CENTER_1F), + .map = MAP_NUM(VERDANTURF_TOWN_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_PACIFIDLOG_TOWN - 1] = + { + .group = MAP_GROUP(PACIFIDLOG_TOWN_POKEMON_CENTER_1F), + .map = MAP_NUM(PACIFIDLOG_TOWN_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, + [HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE - 1] = + { + .group = MAP_GROUP(EVER_GRANDE_CITY_POKEMON_LEAGUE_1F), + .map = MAP_NUM(EVER_GRANDE_CITY_POKEMON_LEAGUE_1F), + .x = 3, + .y = 4, + }, + [HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR - 1] = + { + .group = MAP_GROUP(SOUTHERN_ISLAND_EXTERIOR), + .map = MAP_NUM(SOUTHERN_ISLAND_EXTERIOR), + .x = 15, + .y = 20, + }, + [HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST - 1] = + { + .group = MAP_GROUP(BATTLE_FRONTIER_POKEMON_CENTER_1F), + .map = MAP_NUM(BATTLE_FRONTIER_POKEMON_CENTER_1F), + DEFAULT_POKEMON_CENTER_COORDS, + }, +}; + +#undef DEFAULT_POKEMON_CENTER_COORDS + +// localIds can be found in the generated events.inc file for the specific heal location map +// e.g. for OldaleTown_PokemonCenter1F/events.inc the following entry gets generated: +// object_event 1, OBJ_EVENT_GFX_NURSE, 7, 2, 3, MOVEMENT_TYPE_FACE_DOWN, 0, 0, TRAINER_TYPE_NONE, 0, OldaleTown_PokemonCenter_1F_EventScript_Nurse, 0 +// In this case the localId is 1. +static const u8 sHealNpcLocalId[HEAL_LOCATION_COUNT - 1] = +{ + [HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE_2F - 1] = 1, + [HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE_2F - 1] = 1, + [HEAL_LOCATION_PETALBURG_CITY - 1] = 1, + [HEAL_LOCATION_SLATEPORT_CITY - 1] = 1, + [HEAL_LOCATION_MAUVILLE_CITY - 1] = 1, + [HEAL_LOCATION_RUSTBORO_CITY - 1] = 1, + [HEAL_LOCATION_FORTREE_CITY - 1] = 1, + [HEAL_LOCATION_LILYCOVE_CITY - 1] = 1, + [HEAL_LOCATION_MOSSDEEP_CITY - 1] = 1, + [HEAL_LOCATION_SOOTOPOLIS_CITY - 1] = 1, + [HEAL_LOCATION_EVER_GRANDE_CITY - 1] = 1, + [HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE - 1] = 1, + [HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE - 1] = 1, + [HEAL_LOCATION_OLDALE_TOWN - 1] = 1, + [HEAL_LOCATION_DEWFORD_TOWN - 1] = 1, + [HEAL_LOCATION_LAVARIDGE_TOWN - 1] = 1, + [HEAL_LOCATION_FALLARBOR_TOWN - 1] = 1, + [HEAL_LOCATION_VERDANTURF_TOWN - 1] = 1, + [HEAL_LOCATION_PACIFIDLOG_TOWN - 1] = 1, + [HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE - 1] = 1, + [HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR - 1] = 0, // no heal npc + [HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST - 1] = 1, +}; diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 9338fe183d17..e39a0c6c1f78 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -7,11 +7,13 @@ #include "field_effect.h" #include "event_object_lock.h" #include "event_object_movement.h" +#include "event_scripts.h" #include "field_player_avatar.h" #include "field_screen_effect.h" #include "field_special_scene.h" #include "field_weather.h" #include "gpu_regs.h" +#include "heal_location.h" #include "io_reg.h" #include "link.h" #include "link_rfu.h" @@ -26,10 +28,13 @@ #include "script.h" #include "sound.h" #include "start_menu.h" +#include "strings.h" +#include "string_util.h" #include "task.h" #include "text.h" #include "constants/event_object_movement.h" #include "constants/event_objects.h" +#include "constants/heal_locations.h" #include "constants/songs.h" #include "constants/rgb.h" #include "trainer_hill.h" @@ -1274,3 +1279,112 @@ static void Task_EnableScriptAfterMusicFade(u8 taskId) ScriptContext_Enable(); } } + +static const struct WindowTemplate sWindowTemplate_WhiteoutText = +{ + .bg = 0, + .tilemapLeft = 0, + .tilemapTop = 5, + .width = 30, + .height = 11, + .paletteNum = 15, + .baseBlock = 1, +}; + +static const u8 sWhiteoutTextColors[] = { TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY }; + +#define tState data[0] +#define tWindowId data[1] +#define tPrintState data[2] +#define tIsPlayerHouse data[3] + +static bool32 PrintWhiteOutRecoveryMessage(u8 taskId, const u8 *text, u32 x, u32 y) +{ + u32 windowId = gTasks[taskId].tWindowId; + + switch (gTasks[taskId].tPrintState) + { + case 0: + FillWindowPixelBuffer(windowId, PIXEL_FILL(0)); + StringExpandPlaceholders(gStringVar4, text); + AddTextPrinterParameterized4(windowId, FONT_NORMAL, x, y, 1, 0, sWhiteoutTextColors, 1, gStringVar4); + gTextFlags.canABSpeedUpPrint = FALSE; + gTasks[taskId].tPrintState = 1; + break; + case 1: + RunTextPrinters(); + if (!IsTextPrinterActive(windowId)) + { + gTasks[taskId].tPrintState = 0; + return TRUE; + } + break; + } + return FALSE; +} + +enum { + FRLG_WHITEOUT_ENTER_MSG_SCREEN, + FRLG_WHITEOUT_PRINT_MSG, + FRLG_WHITEOUT_LEAVE_MSG_SCREEN, + FRLG_WHITEOUT_HEAL_SCRIPT, +}; + +static void Task_RushInjuredPokemonToCenter(u8 taskId) +{ + u32 windowId; + + switch (gTasks[taskId].tState) + { + case FRLG_WHITEOUT_ENTER_MSG_SCREEN: + windowId = AddWindow(&sWindowTemplate_WhiteoutText); + gTasks[taskId].tWindowId = windowId; + Menu_LoadStdPalAt(BG_PLTT_ID(15)); + FillWindowPixelBuffer(windowId, PIXEL_FILL(0)); + PutWindowTilemap(windowId); + CopyWindowToVram(windowId, COPYWIN_FULL); + + gTasks[taskId].tIsPlayerHouse = IsLastHealLocationPlayerHouse(); + gTasks[taskId].tState = FRLG_WHITEOUT_PRINT_MSG; + break; + case FRLG_WHITEOUT_PRINT_MSG: + { + const u8 *recoveryMessage = gTasks[taskId].tIsPlayerHouse == TRUE ? gText_PlayerScurriedBackHome : gText_PlayerScurriedToCenter; + if (PrintWhiteOutRecoveryMessage(taskId, recoveryMessage, 2, 8)) + { + ObjectEventTurn(&gObjectEvents[gPlayerAvatar.objectEventId], DIR_NORTH); + gTasks[taskId].tState = FRLG_WHITEOUT_LEAVE_MSG_SCREEN; + } + break; + } + case FRLG_WHITEOUT_LEAVE_MSG_SCREEN: + windowId = gTasks[taskId].tWindowId; + ClearWindowTilemap(windowId); + CopyWindowToVram(windowId, COPYWIN_MAP); + RemoveWindow(windowId); + FillPalBufferBlack(); + FadeInFromBlack(); + gTasks[taskId].tState = FRLG_WHITEOUT_HEAL_SCRIPT; + break; + case FRLG_WHITEOUT_HEAL_SCRIPT: + if (WaitForWeatherFadeIn() == TRUE) + { + DestroyTask(taskId); + if (gTasks[taskId].tIsPlayerHouse) + ScriptContext_SetupScript(EventScript_AfterWhiteOutMomHeal); + else + ScriptContext_SetupScript(EventScript_AfterWhiteOutHeal); + } + break; + } +} + +void FieldCB_RushInjuredPokemonToCenter(void) +{ + u8 taskId; + + LockPlayerFieldControls(); + FillPalBufferBlack(); + taskId = CreateTask(Task_RushInjuredPokemonToCenter, 10); + gTasks[taskId].tState = FRLG_WHITEOUT_ENTER_MSG_SCREEN; +} diff --git a/src/heal_location.c b/src/heal_location.c index 0ab5540346f3..7193ea338e10 100644 --- a/src/heal_location.c +++ b/src/heal_location.c @@ -1,8 +1,11 @@ #include "global.h" +#include "event_data.h" #include "heal_location.h" #include "constants/heal_locations.h" +#include "constants/maps.h" #include "data/heal_locations.h" +#include "data/heal_locations_pkm_center.h" u32 GetHealLocationIndexByMap(u16 mapGroup, u16 mapNum) { @@ -26,6 +29,20 @@ const struct HealLocation *GetHealLocationByMap(u16 mapGroup, u16 mapNum) return &sHealLocations[index - 1]; } +u32 GetHealLocationIndexByWarpData(struct WarpData *warp) +{ + u32 i; + for (i = 0; i < ARRAY_COUNT(sHealLocations); i++) + { + if (sHealLocations[i].group == warp->mapGroup + && sHealLocations[i].map == warp->mapNum + && sHealLocations[i].x == warp->x + && sHealLocations[i].y == warp->y) + return i + 1; + } + return HEAL_LOCATION_NONE; +} + const struct HealLocation *GetHealLocation(u32 index) { if (index == HEAL_LOCATION_NONE) @@ -35,3 +52,55 @@ const struct HealLocation *GetHealLocation(u32 index) else return &sHealLocations[index - 1]; } + +static bool32 IsLastHealLocation(u32 healLocation) +{ + const struct HealLocation *loc = GetHealLocation(healLocation); + const struct WarpData *warpData = &gSaveBlock1Ptr->lastHealLocation; + + return warpData->mapGroup == loc->group + && warpData->mapNum == loc->map + && warpData->warpId == WARP_ID_NONE + && warpData->x == loc->x + && warpData->y == loc->y; +} + +bool32 IsLastHealLocationPlayerHouse() +{ + if (IsLastHealLocation(HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE) + || IsLastHealLocation(HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE_2F) + || IsLastHealLocation(HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE) + || IsLastHealLocation(HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE_2F)) + return TRUE; + + return FALSE; +} + +u32 GetHealNpcLocalId(u32 healLocationId) +{ + if (healLocationId == HEAL_LOCATION_NONE || healLocationId >= HEAL_LOCATION_COUNT) + return 0; + + return sHealNpcLocalId[healLocationId - 1]; +} + +void SetWhiteoutRespawnWarpAndHealerNPC(struct WarpData *warp) +{ + u32 healLocationId = GetHealLocationIndexByWarpData(&gSaveBlock1Ptr->lastHealLocation); + u32 healNpcLocalId = GetHealNpcLocalId(healLocationId); + struct HealLocation pkmCenterHealLocation; + + if (!healNpcLocalId) + { + *(warp) = gSaveBlock1Ptr->lastHealLocation; + return; + } + + pkmCenterHealLocation = sHealLocationsPokemonCenter[healLocationId - 1]; + warp->mapGroup = pkmCenterHealLocation.group; + warp->mapNum = pkmCenterHealLocation.map; + warp->warpId = WARP_ID_NONE; + warp->x = pkmCenterHealLocation.x; + warp->y = pkmCenterHealLocation.y; + gSpecialVar_LastTalked = healNpcLocalId; +} diff --git a/src/overworld.c b/src/overworld.c index a9606578dcdc..babdfad7b6e9 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -689,9 +689,19 @@ void SetWarpDestinationToHealLocation(u8 healLocationId) SetWarpDestination(healLocation->group, healLocation->map, WARP_ID_NONE, healLocation->x, healLocation->y); } +static bool32 IsFRLGWhiteout(void) +{ + if (!OW_FRLG_WHITEOUT) + return FALSE; + return GetHealNpcLocalId(GetHealLocationIndexByWarpData(&gSaveBlock1Ptr->lastHealLocation)) > 0; +} + void SetWarpDestinationToLastHealLocation(void) { - sWarpDestination = gSaveBlock1Ptr->lastHealLocation; + if (IsFRLGWhiteout()) + SetWhiteoutRespawnWarpAndHealerNPC(&sWarpDestination); + else + sWarpDestination = gSaveBlock1Ptr->lastHealLocation; } void SetLastHealLocationWarp(u8 healLocationId) @@ -1611,7 +1621,10 @@ void CB2_WhiteOut(void) ResetInitialPlayerAvatarState(); ScriptContext_Init(); UnlockPlayerFieldControls(); - gFieldCallback = FieldCB_WarpExitFadeFromBlack; + if (IsFRLGWhiteout()) + gFieldCallback = FieldCB_RushInjuredPokemonToCenter; + else + gFieldCallback = FieldCB_WarpExitFadeFromBlack; state = 0; DoMapLoadLoop(&state); SetFieldVBlankCallback(); diff --git a/src/strings.c b/src/strings.c index 254378d37920..28ed992d43c8 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1295,6 +1295,8 @@ const u8 gText_Sorry[] = _("SORRY"); const u8 gText_YaySmileEmoji[] = _("YAY{EMOJI_BIGSMILE}"); const u8 gText_ThankYou[] = _("THANK YOU"); const u8 gText_ByeBye[] = _("BYE-BYE!"); +const u8 gText_PlayerScurriedToCenter[] = _("{PLAYER} scurried to a POKéMON CENTER,\nprotecting the exhausted and fainted\nPOKéMON from further harm…\p"); +const u8 gText_PlayerScurriedBackHome[] = _("{PLAYER} scurried back home, protecting\nthe exhausted and fainted POKéMON from\nfurther harm…\p"); const u8 gText_MatchCallSteven_Strategy[] = _("Attack the weak points!"); const u8 gText_MatchCallSteven_Pokemon[] = _("Ultimate STEEL POKéMON."); const u8 gText_MatchCallSteven_Intro1_BeforeMeteorFallsBattle[] = _("I'd climb even waterfalls");