diff --git a/data/maps/MtChimney/scripts.inc b/data/maps/MtChimney/scripts.inc index 37fd2ccde7..cdff230d77 100644 --- a/data/maps/MtChimney/scripts.inc +++ b/data/maps/MtChimney/scripts.inc @@ -851,4 +851,3 @@ MtChimney_Text_SawyerRematchDefeat: MtChimney_Text_SawyerPostRematch: .string "Actually, it really is hot here.\n" .string "I'm overdressed for these parts.$" - diff --git a/data/maps/SlateportCity_OceanicMuseum_2F/scripts.inc b/data/maps/SlateportCity_OceanicMuseum_2F/scripts.inc index 70463728f3..c46099e39a 100644 --- a/data/maps/SlateportCity_OceanicMuseum_2F/scripts.inc +++ b/data/maps/SlateportCity_OceanicMuseum_2F/scripts.inc @@ -433,4 +433,3 @@ SlateportCity_OceanicMuseum_2F_Text_SSAnneReplica: .string "“S.S. ANNE\p" .string "“A replica of the luxury liner that\n" .string "circles the globe.”$" - diff --git a/data/scripts/battle_pike.inc b/data/scripts/battle_pike.inc index 2108becd06..c4612609b0 100644 --- a/data/scripts/battle_pike.inc +++ b/data/scripts/battle_pike.inc @@ -85,6 +85,7 @@ BattleFrontier_BattlePikeThreePathRoom_EventScript_RightRoomWarp:: end BattleFrontier_BattlePikeThreePathRoom_EventScript_RoomWarp:: + clearflag FLAG_SAFE_FOLLOWER_MOVEMENT pike_get PIKE_DATA_WIN_STREAK addvar VAR_RESULT, 1 pike_set PIKE_DATA_WIN_STREAK, VAR_RESULT diff --git a/include/constants/event_objects.h b/include/constants/event_objects.h index a0ca0063dc..eacd3b3a2a 100644 --- a/include/constants/event_objects.h +++ b/include/constants/event_objects.h @@ -331,11 +331,14 @@ #define LOCALID_NONE 0 #define LOCALID_CAMERA 127 #define LOCALID_BERRY_BLENDER_PLAYER_END 240 // This will use 5 (MAX_RFU_PLAYERS) IDs ending at 240, i.e. 236-240 +#define LOCALID_FOLLOWING_POKEMON 254 #define LOCALID_PLAYER 255 -#define OBJ_EVENT_ID_FOLLOWER 0xFE -#define OBJ_EVENT_ID_NPC_FOLLOWER 0xFD +#define OBJ_EVENT_ID_FOLLOWER 0xFE +#define OBJ_EVENT_ID_NPC_FOLLOWER 0xFD // Aliases for old names. "object event id" normally refers to an index into gObjectEvents, which these are not. +// Used for link player OWs in CreateLinkPlayerSprite +#define OBJ_EVENT_ID_DYNAMIC_BASE 0xF0 #define OBJ_EVENT_ID_CAMERA LOCALID_CAMERA #define OBJ_EVENT_ID_PLAYER LOCALID_PLAYER diff --git a/include/constants/flags.h b/include/constants/flags.h index 71a9116728..47a3b245e1 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1397,6 +1397,7 @@ #define FLAG_SYS_USE_FLASH (SYSTEM_FLAGS + 0x28) #define FLAG_SYS_USE_STRENGTH (SYSTEM_FLAGS + 0x29) +// Sets abnormal weather on maps that check for it #define FLAG_SYS_WEATHER_CTRL (SYSTEM_FLAGS + 0x2A) #define FLAG_SYS_CYCLING_ROAD (SYSTEM_FLAGS + 0x2B) #define FLAG_SYS_SAFARI_MODE (SYSTEM_FLAGS + 0x2C) diff --git a/include/event_object_movement.h b/include/event_object_movement.h index 51cc2c991c..a9d1e61277 100644 --- a/include/event_object_movement.h +++ b/include/event_object_movement.h @@ -182,7 +182,7 @@ u8 GetWalkInPlaceFasterMovementAction(u32); u8 GetWalkInPlaceFastMovementAction(u32); u8 GetWalkInPlaceNormalMovementAction(u32); u8 GetWalkInPlaceSlowMovementAction(u32); -u8 GetCollisionAtCoords(struct ObjectEvent *, s16 x, s16 y, u32 dir); +u8 GetCollisionAtCoords(struct ObjectEvent *objectEvent, s16 x, s16 y, u32 dir); u32 GetObjectObjectCollidesWith(struct ObjectEvent *objectEvent, s16 x, s16 y, bool32 addCoords); void MoveCoords(u8 direction, s16 *x, s16 *y); bool8 ObjectEventIsHeldMovementActive(struct ObjectEvent *objectEvent); diff --git a/include/field_effect_helpers.h b/include/field_effect_helpers.h index 0c97da4337..65dce3dfda 100644 --- a/include/field_effect_helpers.h +++ b/include/field_effect_helpers.h @@ -22,7 +22,7 @@ void StartRevealDisguise(struct ObjectEvent *objectEvent); void StartAshFieldEffect(s16 x, s16 y, u16 metatileId, s16 delay); void SetUpReflection(struct ObjectEvent *objectEvent, struct Sprite *sprite, bool8 stillReflection); void SetUpShadow(struct ObjectEvent *objectEvent); -u32 StartFieldEffectForObjectEvent(u8, struct ObjectEvent *objectEvent); +u32 StartFieldEffectForObjectEvent(u8 fieldEffectId, struct ObjectEvent *objectEvent); u8 FindTallGrassFieldEffectSpriteId(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y); void UpdateRayquazaSpotlightEffect(struct Sprite *sprite); void UpdateShadowFieldEffect(struct Sprite *sprite); diff --git a/include/follower_helper.h b/include/follower_helper.h index 54a2b4c12a..2960077696 100644 --- a/include/follower_helper.h +++ b/include/follower_helper.h @@ -70,7 +70,8 @@ enum MessageCondition #define MATCH_U16(type, value1, value2) {type, {.split = {.hw = value1, .b = value2}}} #define MATCH_U8(type, v1, v2, v3) {type, {.bytes = {v1, v2, v3}}} -#define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species) +#define MATCH_SPECIES(species) MATCH_U16(MSG_COND_SPECIES, species, 0) +#define MATCH_NOT_SPECIES(species) MATCH_U16(MSG_COND_SPECIES, species, 1) #define MATCH_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, 0) // Checks that follower has *neither* of the two types #define MATCH_NOT_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, TYPE_NONE | 1) @@ -118,6 +119,7 @@ enum ConditionalMessage COND_MSG_BURN, COND_MSG_DAY, COND_MSG_NIGHT, + COND_MSG_ABNORMAL_WEATHER, COND_MSG_COUNT, }; diff --git a/src/battle_transition.c b/src/battle_transition.c index fe7188203b..c43837a5a0 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -1048,6 +1048,9 @@ static void Task_BattleTransition(u8 taskId) static bool8 Transition_StartIntro(struct Task *task) { SetWeatherScreenFadeOut(); + // cause all shadow sprites to destroy themselves, + // freeing up sprite slots for the transition + gWeatherPtr->noShadows = TRUE; CpuCopy32(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); if (sTasks_Intro[task->tTransitionId] != NULL) { diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 361111ac4e..0c0d5b4694 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2335,7 +2335,12 @@ bool32 CheckMsgCondition(const struct MsgCondition *cond, struct Pokemon *mon, u switch (cond->type) { case MSG_COND_SPECIES: - return (cond->data.raw == species); + multi = cond->data.split.hw; + // if byte nonzero, invert; check != species! + if (cond->data.split.b) + return (cond->data.split.hw != species); + else + return (cond->data.split.hw == species); case MSG_COND_TYPE: multi = (SpeciesHasType(species, cond->data.bytes[0]) || SpeciesHasType(species, cond->data.bytes[1])); diff --git a/src/follower_helper.c b/src/follower_helper.c index e85289d1f7..474bd79fd7 100644 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -38,7 +38,7 @@ static const u8 sCondMsg16[] = _("{STR_VAR_1} doesn't want to get off\nthe boat static const u8* const sBoatTexts[] = {sCondMsg14, sCondMsg15, sCondMsg16, NULL}; static const u8 sCondMsg17[] = _("{STR_VAR_1} is listening to the\nsound of the machines."); static const u8* const sMachineTexts[] = {sCondMsg13, sCondMsg17, NULL}; -static const u8 sCondMsg18[] = _("Waah! your POKéMON suddenly splashed\nwater!"); +static const u8 sCondMsg18[] = _("Waah! Your POKéMON suddenly splashed\nwater!"); static const u8 sCondMsg19[] = _("Your POKéMON is blowing sand in the\nair!"); static const u8 sCondMsg20[] = _("{STR_VAR_1} is playing around,\nplucking bits of grass."); static const u8 sCondMsg21[] = _("Your POKéMON is happily looking at\nyour footprints!"); @@ -74,6 +74,7 @@ static const u8* const sDayTexts[] = {sCondMsg43, sCondMsg44, NULL}; static const u8 sCondMsg45[] = _("Your POKéMON is staring spellbound\nat the night sky!"); static const u8 sCondMsg46[] = _("Your POKéMON is happily gazing at\nthe beautiful, starry sky!"); static const u8* const sNightTexts[] = {sCondMsg45, sCondMsg46, NULL}; +static const u8 sCondMsg50[] = _("{STR_VAR_1} is disturbed by the\nabnormal weather!"); // See the struct definition in follower_helper.h for more info const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT] = @@ -378,6 +379,18 @@ const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT MATCH_TIME_OF_DAY(TIME_NIGHT), }, }, + [COND_MSG_ABNORMAL_WEATHER] = + { + .text = sCondMsg50, + .emotion = FOLLOWER_EMOTION_SURPRISE, + .conditions = + { + MATCH_MUSIC(MUS_ABNORMAL_WEATHER), + MATCH_NOT_SPECIES(SPECIES_KYOGRE), + MATCH_NOT_SPECIES(SPECIES_GROUDON), + MATCH_NOT_SPECIES(SPECIES_RAYQUAZA), + } + }, }; // Pool of "unconditional" follower messages diff --git a/src/palette.c b/src/palette.c index c4d65404d1..4054e007de 100644 --- a/src/palette.c +++ b/src/palette.c @@ -2,10 +2,12 @@ #include "palette.h" #include "util.h" #include "decompress.h" +#include "field_weather.h" #include "malloc.h" #include "menu.h" #include "gpu_regs.h" #include "task.h" +#include "constants/field_weather.h" #include "constants/rgb.h" enum @@ -718,26 +720,46 @@ static void UpdateBlendRegisters(void) { SetGpuReg(REG_OFFSET_BLDCNT, (u16)gPaletteFadeBlendCnt); SetGpuReg(REG_OFFSET_BLDY, gPaletteFade.y); - // If fade-out, also adjust BLDALPHA and DISPCNT - if (!gPaletteFade.yDec) + // if TGT2 enabled, also adjust BLDALPHA and DISPCNT + if (((u16)gPaletteFadeBlendCnt) & BLDCNT_TGT2_ALL) { u16 bldAlpha = GetGpuReg(REG_OFFSET_BLDALPHA); u8 tgt1 = BLDALPHA_TGT1(bldAlpha); u8 tgt2 = BLDALPHA_TGT2(bldAlpha); - u8 bldFade; + u8 mode = (gPaletteFadeBlendCnt & BLDCNT_EFFECT_EFF_MASK) == BLDCNT_EFFECT_LIGHTEN ? FADE_FROM_WHITE : FADE_FROM_BLACK; + if (!gPaletteFade.yDec) + mode++; - switch (gPaletteFadeBlendCnt & BLDCNT_EFFECT_EFF_MASK) + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); + + switch (mode) { - // FADE_TO_BLACK - case BLDCNT_EFFECT_DARKEN: - bldFade = BLDALPHA_TGT1(max(0, 16 - gPaletteFade.y)); - SetGpuReg(REG_OFFSET_BLDALPHA, - BLDALPHA_BLEND(min(tgt1, bldFade), min(tgt2, bldFade))); + case FADE_FROM_BLACK: + // increment each target until reaching weather's values + SetGpuReg( + REG_OFFSET_BLDALPHA, + BLDALPHA_BLEND( + min(++tgt1, gWeatherPtr->currBlendEVA), + min(++tgt2, gWeatherPtr->currBlendEVB) + ) + ); break; - // FADE_TO_WHITE - case BLDCNT_EFFECT_LIGHTEN: - SetGpuReg(REG_OFFSET_BLDALPHA, - BLDALPHA_BLEND(min(++tgt1, 31), min(++tgt2, 31))); + case FADE_TO_BLACK: + bldAlpha = BLDALPHA_TGT1(max(0, 16 - gPaletteFade.y)); + SetGpuReg( + REG_OFFSET_BLDALPHA, + BLDALPHA_BLEND(min(tgt1, bldAlpha), min(tgt2, bldAlpha)) + ); + break; + // Not handled; blend sprites will pop in, + // but the effect coming from white looks okay + // case FADE_FROM_WHITE: + // break; + case FADE_TO_WHITE: + SetGpuReg( + REG_OFFSET_BLDALPHA, + BLDALPHA_BLEND(min(++tgt1, 31), min(++tgt2, 31)) + ); // cause display to show white when finished // (otherwise blend-mode sprites will still be visible) if (gPaletteFade.hardwareFadeFinishing && gPaletteFade.y >= 16) @@ -745,10 +767,6 @@ static void UpdateBlendRegisters(void) break; } } - else - { - ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); - } if (gPaletteFade.hardwareFadeFinishing) { diff --git a/src/scrcmd.c b/src/scrcmd.c index 87bc8e6298..b5077420e3 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -839,6 +839,8 @@ bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx) switch (mode) { case FADE_FROM_BLACK: + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + break; case FADE_FROM_WHITE: // Restore last weather blend before fading in, // since BLDALPHA was modified by fade-out