diff --git a/include/constants/field_effects.h b/include/constants/field_effects.h index 0f00ac6533..84dbead76e 100644 --- a/include/constants/field_effects.h +++ b/include/constants/field_effects.h @@ -134,4 +134,8 @@ #define FLDEFF_TILE_TAG_SHADOW_LARGE 0x1302 #define FLDEFF_TILE_TAG_SHADOW_EXTRA_LARGE 0x1303 +// Duplicates of event_object_movement tags +#define FLDEFF_PAL_TAG_MAY 0x1110 // OBJ_EVENT_PAL_TAG_MAY +#define FLDEFF_PAL_TAG_BRENDAN 0x1100 // OBJ_EVENT_PAL_TAG_BRENDAN + #endif // GUARD_FIELD_EFFECT_CONSTANTS_H diff --git a/include/event_object_movement.h b/include/event_object_movement.h index 98e5fd784e..97f0105e27 100644 --- a/include/event_object_movement.h +++ b/include/event_object_movement.h @@ -116,6 +116,7 @@ void ObjectEventTurnByLocalIdAndMap(u8, u8, u8, u8); const struct ObjectEventGraphicsInfo *GetObjectEventGraphicsInfo(u8 graphicsId); void SetObjectInvisibility(u8, u8, u8, bool8); void FreeAndReserveObjectSpritePalettes(void); +u8 LoadObjectEventPalette(u16 paletteTag); void SetObjectEventSpritePosByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y); void ResetObjectSubpriority(u8, u8, u8); void SetObjectSubpriority(u8, u8, u8, u8); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 5eee4428a6..b4f3d7fa72 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1395,8 +1395,16 @@ static void RemoveObjectEventInternal(struct ObjectEvent *objectEvent) image.size = GetObjectEventGraphicsInfo(objectEvent->graphicsId)->size; gSprites[objectEvent->spriteId].images = ℑ paletteNum = gSprites[objectEvent->spriteId].oam.paletteNum; - DestroySprite(&gSprites[objectEvent->spriteId]); - FieldEffectFreePaletteIfUnused(paletteNum); + // It's possible that this function is called while the sprite pointed to `== sDummySprite`, i.e during map resume; + // In this case, don't free the palette as `paletteNum` is likely blank dummy data + if (!gSprites[objectEvent->spriteId].inUse && + !gSprites[objectEvent->spriteId].oam.paletteNum && + gSprites[objectEvent->spriteId].callback == SpriteCallbackDummy) { + DestroySprite(&gSprites[objectEvent->spriteId]); + } else { + DestroySprite(&gSprites[objectEvent->spriteId]); + FieldEffectFreePaletteIfUnused(paletteNum); + } } void RemoveAllObjectEventsExceptPlayer(void) diff --git a/src/field_effect.c b/src/field_effect.c index afc25f757c..545080093e 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -3123,6 +3123,7 @@ u8 FldEff_NPCFlyOut(void) sprite->oam.priority = 1; sprite->callback = SpriteCB_NPCFlyOut; sprite->data[1] = gFieldEffectArguments[0]; + sprite->oam.paletteNum = LoadObjectEventPalette(gSaveBlock2Ptr->playerGender ? FLDEFF_PAL_TAG_MAY : FLDEFF_PAL_TAG_BRENDAN); PlaySE(SE_M_FLY); return spriteId; } @@ -3303,6 +3304,7 @@ static u8 CreateFlyBirdSprite(void) sprite = &gSprites[spriteId]; sprite->oam.priority = 1; sprite->callback = SpriteCB_FlyBirdLeaveBall; + sprite->oam.paletteNum = LoadObjectEventPalette(gSaveBlock2Ptr->playerGender ? FLDEFF_PAL_TAG_MAY : FLDEFF_PAL_TAG_BRENDAN); return spriteId; } diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c index 91efae9e1a..18d76c3dc8 100755 --- a/src/field_effect_helpers.c +++ b/src/field_effect_helpers.c @@ -261,8 +261,8 @@ u8 CreateWarpArrowSprite(void) if (spriteId != MAX_SPRITES) { sprite = &gSprites[spriteId]; - // OBJ_EVENT_PAL_TAG_MAY : OBJ_EVENT_PAL_TAG_BRENDAN - sprite->oam.paletteNum = LoadObjectEventPalette(gSaveBlock2Ptr->playerGender ? 0x1110 : 0x1100); + // Can use either gender's palette, so try to use the one that should be loaded + sprite->oam.paletteNum = LoadObjectEventPalette(gSaveBlock2Ptr->playerGender ? FLDEFF_PAL_TAG_MAY : FLDEFF_PAL_TAG_BRENDAN); sprite->oam.priority = 1; sprite->coordOffsetEnabled = TRUE; sprite->invisible = TRUE; @@ -1163,6 +1163,8 @@ u32 FldEff_SurfBlob(void) sprite = &gSprites[spriteId]; sprite->coordOffsetEnabled = TRUE; sprite->tPlayerObjId = gFieldEffectArguments[2]; + // Can use either gender's palette, so try to use the one that should be loaded + sprite->oam.paletteNum = LoadObjectEventPalette(gSaveBlock2Ptr->playerGender ? FLDEFF_PAL_TAG_MAY : FLDEFF_PAL_TAG_BRENDAN); sprite->data[3] = -1; sprite->data[6] = -1; sprite->data[7] = -1;