diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 54f7faa47..09a56f526 100755 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,4 +1,7 @@ 725252905baf28dbb9298dd5fa0daaf0e804a455 afbb88d77ada8a636a318ec32b61b4ea849d85ab f861504cfc50941768286c0703d24ab0aaceb88e -ebbcb7d025cff716eec5008b5dd2b7d55aa8c3f3 \ No newline at end of file +ebbcb7d025cff716eec5008b5dd2b7d55aa8c3f3 +# 24759293+aarant@users.noreply.github.com +# meta: cleaned up spacing of lighting code +0ae5cb1e39f64955107707bbacd1d6dfc117fc01 diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 2207bd0d7..8a8a6076d 100755 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1347,7 +1347,7 @@ @ The specified id can be used to refer to the sprite again later with turnvobject. .macro createvobject graphicsId:req, id:req, x:req, y:req, elevation=3, direction=DIR_SOUTH .byte 0xaa - .byte \graphicsId + .2byte \graphicsId .byte \id .2byte \x .2byte \y diff --git a/data/maps/DesertRuins/map.json b/data/maps/DesertRuins/map.json index 55ef70ce3..c386a06a9 100755 --- a/data/maps/DesertRuins/map.json +++ b/data/maps/DesertRuins/map.json @@ -15,7 +15,7 @@ "connections": 0, "object_events": [ { - "graphics_id": "OBJ_EVENT_GFX_MON_BASE+SPECIES_REGIROCK", + "graphics_id": "OBJ_EVENT_GFX_SPECIES(REGIROCK)", "x": 8, "y": 3, "elevation": 3, diff --git a/data/maps/IslandCave/map.json b/data/maps/IslandCave/map.json index 87c7f1303..b580449e6 100755 --- a/data/maps/IslandCave/map.json +++ b/data/maps/IslandCave/map.json @@ -15,7 +15,7 @@ "connections": 0, "object_events": [ { - "graphics_id": "OBJ_EVENT_GFX_MON_BASE+SPECIES_REGICE", + "graphics_id": "OBJ_EVENT_GFX_SPECIES(REGICE)", "x": 8, "y": 3, "elevation": 3, diff --git a/data/maps/UnionRoom/scripts.inc b/data/maps/UnionRoom/scripts.inc index 8eaabc800..927c40618 100755 --- a/data/maps/UnionRoom/scripts.inc +++ b/data/maps/UnionRoom/scripts.inc @@ -107,4 +107,3 @@ UnionRoom_EventScript_Unused:: waitstate releaseall end - diff --git a/gflib/sprite.c b/gflib/sprite.c index 2e7bc759c..eb09e0359 100755 --- a/gflib/sprite.c +++ b/gflib/sprite.c @@ -1496,7 +1496,7 @@ void SetOamMatrixRotationScaling(u8 matrixNum, s16 xScale, s16 yScale, u16 rotat CopyOamMatrix(matrixNum, &matrix); } -u16 LoadSpriteSheet(const struct SpriteSheet *sheet) +static u16 LoadSpriteSheetWithOffset(const struct SpriteSheet *sheet, u32 offset) { s16 tileStart = AllocSpriteTiles(sheet->size / TILE_SIZE_4BPP); @@ -1507,11 +1507,16 @@ u16 LoadSpriteSheet(const struct SpriteSheet *sheet) else { AllocSpriteTileRange(sheet->tag, (u16)tileStart, sheet->size / TILE_SIZE_4BPP); - CpuSmartCopy16(sheet->data, (u8 *)OBJ_VRAM0 + TILE_SIZE_4BPP * tileStart, sheet->size); + CpuSmartCopy16(sheet->data, (u8 *)OBJ_VRAM0 + TILE_SIZE_4BPP * tileStart + offset, sheet->size - offset); return (u16)tileStart; } } +u16 LoadSpriteSheet(const struct SpriteSheet *sheet) +{ + return LoadSpriteSheetWithOffset(sheet, 0); +} + // Like LoadSpriteSheet, but checks if already loaded, and uses template image frames u16 LoadSpriteSheetByTemplate(const struct SpriteTemplate *template, u32 frame, s32 offset) { u16 tileStart; @@ -1521,10 +1526,10 @@ u16 LoadSpriteSheetByTemplate(const struct SpriteTemplate *template, u32 frame, return TAG_NONE; if ((tileStart = GetSpriteTileStartByTag(template->tileTag)) != TAG_NONE) // return if already loaded return tileStart; - sheet.data = template->images[frame].data - offset; + sheet.data = template->images[frame].data; sheet.size = template->images[frame].size; sheet.tag = template->tileTag; - return LoadSpriteSheet(&sheet); + return LoadSpriteSheetWithOffset(&sheet, offset); } void LoadSpriteSheets(const struct SpriteSheet *sheets) diff --git a/include/battle_tower.h b/include/battle_tower.h index 1ce55b5b4..993bf23c9 100755 --- a/include/battle_tower.h +++ b/include/battle_tower.h @@ -34,9 +34,9 @@ struct FacilityMon }; extern const u8 gTowerMaleFacilityClasses[43]; -extern const u8 gTowerMaleTrainerGfxIds[43]; +extern const u16 gTowerMaleTrainerGfxIds[43]; extern const u8 gTowerFemaleFacilityClasses[27]; -extern const u8 gTowerFemaleTrainerGfxIds[27]; +extern const u16 gTowerFemaleTrainerGfxIds[27]; extern const u16 gBattleFrontierHeldItems[]; extern const struct FacilityMon gBattleFrontierMons[]; extern const struct FacilityMon gBattleFrontierMonsSplit[]; diff --git a/include/constants/event_objects.h b/include/constants/event_objects.h index 04942b87a..d46f54705 100755 --- a/include/constants/event_objects.h +++ b/include/constants/event_objects.h @@ -281,6 +281,10 @@ #define OBJ_EVENT_GFX_SPECIES_BITS 11 #define OBJ_EVENT_GFX_SPECIES_MASK ((1 << OBJ_EVENT_GFX_SPECIES_BITS) - 1) +// Used to call a specific species' follower graphics. Useful for static encounters. +#define OBJ_EVENT_GFX_SPECIES(name) (SPECIES_##name + OBJ_EVENT_GFX_MON_BASE) +#define OBJ_EVENT_GFX_SPECIES_SHINY(name) (SPECIES_##name + OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) + #define OW_SPECIES(x) (((x)->graphicsId & OBJ_EVENT_GFX_SPECIES_MASK) - OBJ_EVENT_GFX_MON_BASE) #define OW_FORM(x) ((x)->graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS) @@ -324,6 +328,9 @@ #define OBJ_KIND_CLONE 255 // Exclusive to FRLG // Special object event local ids +// Used for link player OWs in CreateLinkPlayerSprite +#define OBJ_EVENT_ID_DYNAMIC_BASE 0xF0 + #define OBJ_EVENT_ID_PLAYER 0xFF #define OBJ_EVENT_ID_CAMERA 0x7F #define OBJ_EVENT_ID_FOLLOWER 0xFE diff --git a/include/constants/species.h b/include/constants/species.h index bb92081ae..077f3e5b3 100755 --- a/include/constants/species.h +++ b/include/constants/species.h @@ -469,6 +469,8 @@ #define NUM_SPECIES SPECIES_EGG +#define SPECIES_SHINY_TAG 500 + #define SPECIES_UNOWN_B (NUM_SPECIES + 1) #define SPECIES_UNOWN_C (SPECIES_UNOWN_B + 1) #define SPECIES_UNOWN_D (SPECIES_UNOWN_B + 2) diff --git a/include/data.h b/include/data.h index 99b695d72..ef1124280 100755 --- a/include/data.h +++ b/include/data.h @@ -3,7 +3,6 @@ #include "constants/moves.h" -#define SPECIES_SHINY_TAG 500 #define N_FOLLOWER_HAPPY_MESSAGES 31 #define N_FOLLOWER_NEUTRAL_MESSAGES 14 #define N_FOLLOWER_SAD_MESSAGES 3 diff --git a/include/follower_helper.h b/include/follower_helper.h index 86ac018d1..5b91619dc 100755 --- a/include/follower_helper.h +++ b/include/follower_helper.h @@ -65,7 +65,7 @@ struct FollowerMsgInfoExtended { #define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species) #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) +#define MATCH_NOT_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, TYPE_NONE | 1) #define MATCH_STATUS(status) MATCH_U24(MSG_COND_STATUS, status) #define MATCH_MAPSEC(mapsec) MATCH_U24(MSG_COND_MAPSEC, mapsec) #define MATCH_MAP_RAW(mapGroup, mapNum) MATCH_U8(MSG_COND_MAP, mapGroup, mapNum, 0) diff --git a/include/palette.h b/include/palette.h index fa41b2d0d..930499b87 100755 --- a/include/palette.h +++ b/include/palette.h @@ -14,6 +14,8 @@ #define PALETTE_FADE_STATUS_LOADING 0xFF #define PALETTES_BG 0x0000FFFF +// like PALETTES_BG but excludes UI pals [13, 15] +#define PALETTES_MAP 0x00001FFF #define PALETTES_OBJECTS 0xFFFF0000 #define PALETTES_ALL (PALETTES_BG | PALETTES_OBJECTS) @@ -24,6 +26,11 @@ #define OBJ_PLTT_ID(n) (OBJ_PLTT_OFFSET + PLTT_ID(n)) #define OBJ_PLTT_ID2(n) (PLTT_ID((n) + 16)) +// Used to determine whether a sprite palette tag +// should be excluded from time (and weather) blending +#define BLEND_IMMUNE_FLAG (1 << 15) +#define IS_BLEND_IMMUNE_TAG(tag) ((tag) & BLEND_IMMUNE_FLAG) + enum { FAST_FADE_IN_FROM_WHITE, diff --git a/src/battle_tower.c b/src/battle_tower.c index 4c0a61b51..3d63dda3a 100755 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -318,7 +318,7 @@ const u8 gTowerFemaleFacilityClasses[27] = FACILITY_CLASS_LEAF }; -const u8 gTowerMaleTrainerGfxIds[43] = +const u16 gTowerMaleTrainerGfxIds[43] = { OBJ_EVENT_GFX_HIKER, OBJ_EVENT_GFX_TUBER_M, @@ -365,7 +365,7 @@ const u8 gTowerMaleTrainerGfxIds[43] = OBJ_EVENT_GFX_MAXIE }; -const u8 gTowerFemaleTrainerGfxIds[27] = +const u16 gTowerFemaleTrainerGfxIds[27] = { OBJ_EVENT_GFX_WOMAN_2, OBJ_EVENT_GFX_TUBER_F, @@ -3674,7 +3674,7 @@ static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) u16 FacilityClassToGraphicsId(u8 facilityClass) { - u8 trainerObjectGfxId; + u16 trainerObjectGfxId; u8 i; // Search male classes. diff --git a/src/data/text/follower_messages.h b/src/data/text/follower_messages.h index 7678992f2..638df64d8 100755 --- a/src/data/text/follower_messages.h +++ b/src/data/text/follower_messages.h @@ -34,7 +34,7 @@ static const u8 sHappyMsg11[] = _("Your POKéMON has caught the scent of\nsmoke. static const u8 sHappyMsg12[] = _("{STR_VAR_1} is poking at your belly."); static const u8 sHappyMsg13[] = _("Your POKéMON stretched out its body\nand is relaxing."); static const u8 sHappyMsg14[] = _("{STR_VAR_1} looks like it wants to\nlead!"); -static const u8 sHappyMsg15[] = _("{STR_VAR_1} is doing it's best to\nkeep up with you."); +static const u8 sHappyMsg15[] = _("{STR_VAR_1} is doing its best to\nkeep up with you."); static const u8 sHappyMsg16[] = _("{STR_VAR_1} is happily cuddling up\nto you!"); static const u8 sHappyMsg17[] = _("{STR_VAR_1} is full of life!"); static const u8 sHappyMsg18[] = _("{STR_VAR_1} seems to be very happy!"); @@ -134,7 +134,7 @@ const struct FollowerMsgInfo gFollowerUpsetMessages[] = { // Unconditional angry messages static const u8 sAngryMsg00[] = _("{STR_VAR_1} let out a roar!"); -static const u8 sAngryMsg01[] = _("{STR_VAR_1} is making a face like\nits angry!"); +static const u8 sAngryMsg01[] = _("{STR_VAR_1} is making a face like\nit's angry!"); static const u8 sAngryMsg02[] = _("{STR_VAR_1} seems to be angry for\nsome reason."); static const u8 sAngryMsg03[] = _("Your POKéMON turned to face the\nother way, showing a defiant face."); static const u8 sAngryMsg04[] = _("{STR_VAR_1} cried out."); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 509e32eb8..35b4e69ea 100755 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1435,7 +1435,7 @@ u8 GetFirstInactiveObjectEventId(void) u8 GetObjectEventIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroupId) { - if (localId < OBJ_EVENT_ID_FOLLOWER) + if (localId < OBJ_EVENT_ID_DYNAMIC_BASE) return GetObjectEventIdByLocalIdAndMapInternal(localId, mapNum, mapGroupId); return GetObjectEventIdByLocalId(localId); @@ -1674,10 +1674,12 @@ u16 LoadSheetGraphicsInfo(const struct ObjectEventGraphicsInfo *info, u16 uuid, u32 sheetSpan = GetSpanPerImage(info->oam->shape, info->oam->size); u16 oldTiles = 0; u16 tileStart; + bool32 oldInvisible; if (tag == TAG_NONE) tag = COMP_OW_TILE_TAG_BASE + uuid; if (sprite) { + oldInvisible = sprite->invisible; oldTiles = sprite->sheetTileStart; sprite->sheetTileStart = 0; // mark unused // Note: If sprite was not allocated to use a sheet, @@ -1691,9 +1693,19 @@ u16 LoadSheetGraphicsInfo(const struct ObjectEventGraphicsInfo *info, u16 uuid, if (tileStart == TAG_NONE) { struct SpriteFrameImage image = {.size = info->size, .data = info->images->data}; struct SpriteTemplate template = {.tileTag = tag, .images = &image}; - if (oldTiles) - FieldEffectFreeTilesIfUnused(oldTiles); + // Load, then free, in order to avoid displaying garbage data + // before sprite's `sheetTileStart` is repointed tileStart = LoadCompressedSpriteSheetByTemplate(&template, TILE_SIZE_4BPP << sheetSpan); + if (oldTiles) { + FieldEffectFreeTilesIfUnused(oldTiles); + // We weren't able to load the sheet; + // retry (after having freed), and set sprite to invisible until done + if (tileStart <= 0) { + if (sprite) + sprite->invisible = TRUE; + tileStart = LoadCompressedSpriteSheetByTemplate(&template, TILE_SIZE_4BPP << sheetSpan); + } + } // sheet loaded; unload any *other* sheet for sprite } else if (oldTiles && oldTiles != tileStart) { FieldEffectFreeTilesIfUnused(oldTiles); @@ -1703,6 +1715,7 @@ u16 LoadSheetGraphicsInfo(const struct ObjectEventGraphicsInfo *info, u16 uuid, sprite->sheetTileStart = tileStart; sprite->sheetSpan = sheetSpan; sprite->usingSheet = TRUE; + sprite->invisible = oldInvisible; } // Going from sheet -> !sheet, reset tile number // (sheet stays loaded) @@ -1746,6 +1759,12 @@ static u8 TrySetupObjectEventSprite(const struct ObjectEventTemplate *objectEven spriteTemplate->tileTag = LoadSheetGraphicsInfo(graphicsInfo, objectEvent->graphicsId, NULL); #endif + if (objectEvent->graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) + { + objectEvent->shiny = TRUE; + objectEvent->graphicsId -= SPECIES_SHINY_TAG; + } + spriteId = CreateSprite(spriteTemplate, 0, 0, 0); if (spriteId == MAX_SPRITES) { @@ -2317,12 +2336,12 @@ bool32 CheckMsgCondition(const struct MsgCondition *cond, struct Pokemon *mon, u case MSG_COND_TYPE: multi = (SpeciesHasType(species, cond->data.bytes[0]) || SpeciesHasType(species, cond->data.bytes[1])); - // if bytes[2] == TYPE_NONE, + // if bytes[2] nonzero, // invert; check that mon has *neither* type! - if (cond->data.bytes[2] == 0) - return multi; - else + if (cond->data.bytes[2] != 0) return !multi; + else + return multi; break; case MSG_COND_STATUS: return (cond->data.raw & mon->status); @@ -2340,7 +2359,9 @@ bool32 CheckMsgCondition(const struct MsgCondition *cond, struct Pokemon *mon, u case MSG_COND_MUSIC: return (cond->data.raw == GetCurrentMapMusic()); case MSG_COND_TIME_OF_DAY: - return (cond->data.raw == gTimeOfDay); + // Must match time of day, have natural light on the map, + // and not have weather that obscures the sky + return (cond->data.raw == gTimeOfDay && MapHasNaturalLight(gMapHeader.mapType) && GetCurrentWeather() < WEATHER_RAIN); case MSG_COND_NEAR_MB: multi = FindMetatileBehaviorWithinRange( obj->currentCoords.x, obj->currentCoords.y, @@ -2392,9 +2413,11 @@ bool8 ScrFunc_getfolloweraction(struct ScriptContext *ctx) // Essentially a big [FOLLOWER_EMOTION_UPSET] = 15, [FOLLOWER_EMOTION_ANGRY] = 15, [FOLLOWER_EMOTION_PENSIVE] = 15, + [FOLLOWER_EMOTION_LOVE] = 0, [FOLLOWER_EMOTION_SURPRISE] = 10, [FOLLOWER_EMOTION_CURIOUS] = 10, [FOLLOWER_EMOTION_MUSIC] = 15, + [FOLLOWER_EMOTION_POISONED] = 0, }; u32 i, j; bool32 pickedCondition = FALSE; @@ -2422,7 +2445,7 @@ bool8 ScrFunc_getfolloweraction(struct ScriptContext *ctx) // Essentially a big if (GetCurrentWeather() == WEATHER_SUNNY_CLOUDS) condEmotes[condCount++] = (struct SpecialEmote) {.emotion=FOLLOWER_EMOTION_HAPPY, .index=31}; // Health & status-related - multi = mon->hp * 100 / mon->maxHP; + multi = SAFE_DIV(mon->hp * 100, mon->maxHP); if (multi < 20) { emotion_weight[FOLLOWER_EMOTION_SAD] = 30; condEmotes[condCount++] = (struct SpecialEmote) {.emotion=FOLLOWER_EMOTION_SAD, .index=4}; @@ -2974,6 +2997,8 @@ const struct ObjectEventGraphicsInfo *GetObjectEventGraphicsInfo(u16 graphicsId) if (graphicsId >= OBJ_EVENT_GFX_VARS && graphicsId <= OBJ_EVENT_GFX_VAR_F) graphicsId = VarGetObjectEventGraphicsId(graphicsId - OBJ_EVENT_GFX_VARS); + if (graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) + graphicsId -= SPECIES_SHINY_TAG; // graphicsId may contain mon form info if (graphicsId > OBJ_EVENT_GFX_SPECIES_MASK) { form = graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS; diff --git a/src/field_specials.c b/src/field_specials.c index 61db5b019..41228b636 100755 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -64,6 +64,7 @@ #include "constants/battle_frontier.h" #include "constants/weather.h" #include "constants/metatile_labels.h" +#include "constants/rgb.h" #include "palette.h" #include "constants/metatile_behaviors.h" #include "item.h" @@ -3448,7 +3449,7 @@ void SetDeoxysRockPalette(void) u32 paletteNum = IndexOfSpritePaletteTag(OBJ_EVENT_PAL_TAG_BIRTH_ISLAND_STONE); LoadPalette(&sDeoxysRockPalettes[(u8)VarGet(VAR_DEOXYS_ROCK_LEVEL)], OBJ_PLTT_ID(paletteNum), PLTT_SIZEOF(4)); // Set faded to all black, weather blending handled during fade-in - CpuFill16(0, &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], 32); + CpuFill16(RGB_BLACK, &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], PLTT_SIZE_4BPP); } void SetPCBoxToSendMon(u8 boxId) diff --git a/src/field_weather.c b/src/field_weather.c index 1b9bf0d14..4d92c8b4d 100755 --- a/src/field_weather.c +++ b/src/field_weather.c @@ -497,7 +497,7 @@ static void ApplyColorMap(u8 startPalIndex, u8 numPalettes, s8 colorMapIndex) { // don't blend special palettes immune to blending if (sPaletteColorMapTypes[curPalIndex] == COLOR_MAP_NONE || - (curPalIndex >= 16 && GetSpritePaletteTagByPaletteNum(curPalIndex - 16) >> 15)) + (curPalIndex >= 16 && IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(curPalIndex - 16)))) { // No palette change. palOffset += 16; @@ -686,7 +686,7 @@ static void ApplyFogBlend(u8 blendCoeff, u16 blendColor) CpuFastCopy(gPlttBufferUnfaded, gPlttBufferFaded, PLTT_BUFFER_SIZE * 2); UpdatePalettesWithTime(PALETTES_ALL); // Then blend tile palettes [0, 12] faded->faded with fadeIn color - BlendPalettesFine(0x1FFF, gPlttBufferFaded, gPlttBufferFaded, blendCoeff, blendColor); + BlendPalettesFine(PALETTES_MAP, gPlttBufferFaded, gPlttBufferFaded, blendCoeff, blendColor); // Do fog blending on marked sprite palettes for (curPalIndex = 16; curPalIndex < 32; curPalIndex++) { @@ -710,7 +710,7 @@ static bool8 LightenSpritePaletteInFog(u8 paletteIndex) { u16 i; - if (paletteIndex >= 16 && (GetSpritePaletteTagByPaletteNum(i - 16) >> 15)) // don't blend specialpalette tags + if (paletteIndex >= 16 && IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(paletteIndex - 16))) return FALSE; for (i = 0; i < gWeatherPtr->lightenedFogSpritePalsCount; i++) diff --git a/src/field_weather_effect.c b/src/field_weather_effect.c index 971bbbcdc..e68e619e3 100755 --- a/src/field_weather_effect.c +++ b/src/field_weather_effect.c @@ -1361,20 +1361,20 @@ static void DestroyFogHorizontalSprites(void); // Updates just the color of shadows to match special weather blending u8 UpdateShadowColor(u16 color) { - u8 paletteNum = IndexOfSpritePaletteTag(TAG_WEATHER_START); - u16 ALIGNED(4) tempBuffer[16]; - u16 blendedColor; - if (paletteNum != 0xFF) { - u16 index = (paletteNum+16)*16+SHADOW_COLOR_INDEX; - gPlttBufferUnfaded[index] = gPlttBufferFaded[index] = color; - // Copy to temporary buffer, blend, and keep just the shadow color index - CpuFastCopy(&gPlttBufferFaded[index-SHADOW_COLOR_INDEX], tempBuffer, 32); - UpdateSpritePaletteWithTime(paletteNum); - blendedColor = gPlttBufferFaded[index]; - CpuFastCopy(tempBuffer, &gPlttBufferFaded[index-SHADOW_COLOR_INDEX], 32); - gPlttBufferFaded[index] = blendedColor; - } - return paletteNum; + u8 paletteNum = IndexOfSpritePaletteTag(TAG_WEATHER_START); + u16 ALIGNED(4) tempBuffer[16]; + u16 blendedColor; + if (paletteNum < 16) { + u16 index = OBJ_PLTT_ID(paletteNum)+SHADOW_COLOR_INDEX; + gPlttBufferUnfaded[index] = gPlttBufferFaded[index] = color; + // Copy to temporary buffer, blend, and keep just the shadow color index + CpuFastCopy(&gPlttBufferFaded[index-SHADOW_COLOR_INDEX], tempBuffer, PLTT_SIZE_4BPP); + UpdateSpritePaletteWithTime(paletteNum); + blendedColor = gPlttBufferFaded[index]; + CpuFastCopy(tempBuffer, &gPlttBufferFaded[index-SHADOW_COLOR_INDEX], PLTT_SIZE_4BPP); + gPlttBufferFaded[index] = blendedColor; + } + return paletteNum; } void FogHorizontal_InitVars(void) diff --git a/src/follower_helper.c b/src/follower_helper.c index 1eb990b2e..14f0622e7 100755 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -55,7 +55,7 @@ static const u8* const sFearTexts[] = {sCondMsg29, sCondMsg30, NULL}; static const u8 sCondMsg31[] = _("{STR_VAR_1} is taking shelter in the\ngrass from the rain."); static const u8 sCondMsg32[] = _("{STR_VAR_1} seems very cold."); static const u8 sCondMsg33[] = _("{STR_VAR_1} is staring at the sea."); -static const u8 sCondMsg34[] = _("Your pokemon is staring intently at\nthe sea!"); +static const u8 sCondMsg34[] = _("Your POKéMON is staring intently at\nthe sea!"); static const u8 sCondMsg35[] = _("{STR_VAR_1} is looking at the\nsurging sea."); static const u8* const sSeaTexts[] = {sCondMsg33, sCondMsg34, sCondMsg35, NULL}; static const u8 sCondMsg36[] = _("{STR_VAR_1} is listening to the\nsound of the waterfall."); diff --git a/src/overworld.c b/src/overworld.c index 8affc0993..bed585499 100755 --- a/src/overworld.c +++ b/src/overworld.c @@ -12,6 +12,7 @@ #include "field_camera.h" #include "field_control_avatar.h" #include "field_effect.h" +#include "field_effect_helpers.h" #include "field_message_box.h" #include "field_player_avatar.h" #include "field_screen_effect.h" @@ -61,6 +62,7 @@ #include "wild_encounter.h" #include "frontier_util.h" #include "constants/abilities.h" +#include "constants/event_objects.h" #include "constants/layouts.h" #include "constants/map_types.h" #include "constants/region_map_sections.h" @@ -1535,9 +1537,9 @@ void CB1_Overworld(void) const struct BlendSettings gTimeOfDayBlend[] = { - [TIME_OF_DAY_NIGHT] = {.coeff = 10, .blendColor = TINT_NIGHT, .isTint = TRUE}, - [TIME_OF_DAY_TWILIGHT] = {.coeff = 4, .blendColor = 0xA8B0E0, .isTint = TRUE}, - [TIME_OF_DAY_DAY] = {.coeff = 0, .blendColor = 0}, + [TIME_OF_DAY_NIGHT] = {.coeff = 10, .blendColor = TINT_NIGHT, .isTint = TRUE}, + [TIME_OF_DAY_TWILIGHT] = {.coeff = 4, .blendColor = 0xA8B0E0, .isTint = TRUE}, + [TIME_OF_DAY_DAY] = {.coeff = 0, .blendColor = 0}, }; u8 UpdateTimeOfDay(void) { @@ -1585,8 +1587,12 @@ u8 UpdateTimeOfDay(void) { } bool8 MapHasNaturalLight(u8 mapType) { // Whether a map type is naturally lit/outside - return mapType == MAP_TYPE_TOWN || mapType == MAP_TYPE_CITY || mapType == MAP_TYPE_ROUTE - || mapType == MAP_TYPE_OCEAN_ROUTE; + return ( + mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_CITY + || mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_OCEAN_ROUTE + ); } // Update & mix day / night bg palettes (into unfaded) @@ -1598,7 +1604,7 @@ void UpdateAltBgPalettes(u16 palettes) { return; palettes &= ~((1 << NUM_PALS_IN_PRIMARY) - 1) | primary->swapPalettes; palettes &= ((1 << NUM_PALS_IN_PRIMARY) - 1) | (secondary->swapPalettes << NUM_PALS_IN_PRIMARY); - palettes &= 0x1FFE; // don't blend palette 0, [13,15] + palettes &= PALETTES_MAP ^ (1 << 0); // don't blend palette 0, [13,15] palettes >>= 1; // start at palette 1 if (!palettes) return; @@ -1615,40 +1621,42 @@ void UpdateAltBgPalettes(u16 palettes) { } void UpdatePalettesWithTime(u32 palettes) { - if (MapHasNaturalLight(gMapHeader.mapType)) { - u32 i; - u32 mask = 1 << 16; - if (palettes >= 0x10000) - for (i = 0; i < 16; i++, mask <<= 1) - if (GetSpritePaletteTagByPaletteNum(i) >> 15) // Don't blend special sprite palette tags - palettes &= ~(mask); + if (MapHasNaturalLight(gMapHeader.mapType)) { + u32 i; + u32 mask = 1 << 16; + if (palettes >= (1 << 16)) + for (i = 0; i < 16; i++, mask <<= 1) + if (IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(i))) + palettes &= ~(mask); - palettes &= 0xFFFF1FFF; // Don't blend UI BG palettes [13,15] + palettes &= PALETTES_MAP | PALETTES_OBJECTS; // Don't blend UI pals if (!palettes) - return; - TimeMixPalettes(palettes, - gPlttBufferUnfaded, - gPlttBufferFaded, - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], - currentTimeBlend.weight); - } + return; + TimeMixPalettes( + palettes, + gPlttBufferUnfaded, + gPlttBufferFaded, + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], + currentTimeBlend.weight + ); + } } u8 UpdateSpritePaletteWithTime(u8 paletteNum) { - if (MapHasNaturalLight(gMapHeader.mapType)) { - u16 offset; - if (GetSpritePaletteTagByPaletteNum(paletteNum) >> 15) - return paletteNum; - offset = (paletteNum + 16) << 4; - TimeMixPalettes(1, - gPlttBufferUnfaded + offset, - gPlttBufferFaded + offset, - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], - (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], - currentTimeBlend.weight); - } - return paletteNum; + if (MapHasNaturalLight(gMapHeader.mapType)) { + if (IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(paletteNum))) + return paletteNum; + TimeMixPalettes( + 1, + &gPlttBufferUnfaded[OBJ_PLTT_ID(paletteNum)], + &gPlttBufferFaded[OBJ_PLTT_ID(paletteNum)], + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time0], + (struct BlendSettings *)&gTimeOfDayBlend[currentTimeBlend.time1], + currentTimeBlend.weight + ); + } + return paletteNum; } static void OverworldBasic(void) @@ -1664,19 +1672,20 @@ static void OverworldBasic(void) DoScheduledBgTilemapCopiesToVram(); // Every minute if no palette fade is active, update TOD blending as needed if (!gPaletteFade.active && ++gTimeUpdateCounter >= 3600) { - struct TimeBlendSettings cachedBlend = { - .time0 = currentTimeBlend.time0, - .time1 = currentTimeBlend.time1, - .weight = currentTimeBlend.weight, - }; - gTimeUpdateCounter = 0; - UpdateTimeOfDay(); - if (cachedBlend.time0 != currentTimeBlend.time0 - || cachedBlend.time1 != currentTimeBlend.time1 - || cachedBlend.weight != currentTimeBlend.weight) { + struct TimeBlendSettings cachedBlend = { + .time0 = currentTimeBlend.time0, + .time1 = currentTimeBlend.time1, + .weight = currentTimeBlend.weight, + }; + gTimeUpdateCounter = 0; + UpdateTimeOfDay(); + if (cachedBlend.time0 != currentTimeBlend.time0 + || cachedBlend.time1 != currentTimeBlend.time1 + || cachedBlend.weight != currentTimeBlend.weight) + { UpdateAltBgPalettes(PALETTES_BG); UpdatePalettesWithTime(PALETTES_ALL); - } + } } } @@ -3429,6 +3438,8 @@ static void CreateLinkPlayerSprite(u8 linkPlayerId, u8 gameVersion) sprite->coordOffsetEnabled = TRUE; sprite->data[0] = linkPlayerId; objEvent->triggerGroundEffectsOnMove = 0; + objEvent->localId = OBJ_EVENT_ID_DYNAMIC_BASE + linkPlayerId; + SetUpShadow(objEvent, sprite); } } diff --git a/src/palette.c b/src/palette.c index 0093a4bf6..ddc068820 100755 --- a/src/palette.c +++ b/src/palette.c @@ -515,25 +515,25 @@ static u8 UpdateTimeOfDayPaletteFade(void) u32 i; u32 j = 1; for (i = 0; i < 16; i++, j <<= 1) { // Mask out palettes that should not be light blended - if ((selectedPalettes & j) && !(GetSpritePaletteTagByPaletteNum(i) >> 15)) - timePalettes |= j; + if ((selectedPalettes & j) && !IS_BLEND_IMMUNE_TAG(GetSpritePaletteTagByPaletteNum(i))) + timePalettes |= j; } } else { // tile palettes, don't blend [13, 15] - timePalettes = selectedPalettes & 0x1FFF; + timePalettes = selectedPalettes & PALETTES_MAP; } TimeMixPalettes(timePalettes, src, dst, gPaletteFade.bld0, gPaletteFade.bld1, gPaletteFade.weight); // palettes that were not blended above must be copied through if ((copyPalettes = ~timePalettes)) { - u16 * src1 = src; - u16 * dst1 = dst; - while (copyPalettes) { - if (copyPalettes & 1) - CpuFastCopy(src1, dst1, 32); - copyPalettes >>= 1; - src1 += 16; - dst1 += 16; - } + u16 * src1 = src; + u16 * dst1 = dst; + while (copyPalettes) { + if (copyPalettes & 1) + CpuFastCopy(src1, dst1, 32); + copyPalettes >>= 1; + src1 += 16; + dst1 += 16; + } } // Then, blend from faded->faded with native BlendPalettes @@ -1330,58 +1330,59 @@ void TintPalette_CustomTone(u16 *palette, u16 count, u16 rTone, u16 gTone, u16 b // Tints from Unfaded to Faded, using a 15-bit GBA color void TintPalette_RGB_Copy(u16 palOffset, u32 blendColor) { - s32 newR, newG, newB, rTone, gTone, bTone; - u16 * src = gPlttBufferUnfaded + palOffset; - u16 * dst = gPlttBufferFaded + palOffset; - u32 defaultBlendColor = DEFAULT_LIGHT_COLOR; - u16 *srcEnd = src + 16; - u16 altBlendIndices = *dst++ = *src++; // color 0 is copied through unchanged - u32 altBlendColor; - - newR = ((blendColor << 27) >> 27) << 3; - newG = ((blendColor << 22) >> 27) << 3; - newB = ((blendColor << 17) >> 27) << 3; - - if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend - // Note that bit 0 of altBlendIndices specifies color 1 - altBlendColor = src[14]; // color 15 - if (altBlendColor >> 15) { // Set alternate blend color - rTone = ((altBlendColor << 27) >> 27) << 3; - gTone = ((altBlendColor << 22) >> 27) << 3; - bTone = ((altBlendColor << 17) >> 27) << 3; - } else { // Set default blend color - rTone = ((defaultBlendColor << 27) >> 27) << 3; - gTone = ((defaultBlendColor << 22) >> 27) << 3; - bTone = ((defaultBlendColor << 17) >> 27) << 3; + s32 newR, newG, newB, rTone, gTone, bTone; + u16 * src = gPlttBufferUnfaded + palOffset; + u16 * dst = gPlttBufferFaded + palOffset; + u32 defaultBlendColor = DEFAULT_LIGHT_COLOR; + u16 *srcEnd = src + 16; + u16 altBlendIndices = *dst++ = *src++; // color 0 is copied through unchanged + u32 altBlendColor; + + newR = ((blendColor << 27) >> 27) << 3; + newG = ((blendColor << 22) >> 27) << 3; + newB = ((blendColor << 17) >> 27) << 3; + + if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend + // Note that bit 0 of altBlendIndices specifies color 1 + altBlendColor = src[14]; // color 15 + if (altBlendColor >> 15) { // Set alternate blend color + rTone = ((altBlendColor << 27) >> 27) << 3; + gTone = ((altBlendColor << 22) >> 27) << 3; + bTone = ((altBlendColor << 17) >> 27) << 3; + } else { // Set default blend color + rTone = ((defaultBlendColor << 27) >> 27) << 3; + gTone = ((defaultBlendColor << 22) >> 27) << 3; + bTone = ((defaultBlendColor << 17) >> 27) << 3; + } + } else { + altBlendIndices = 0; } - } else { - altBlendIndices = 0; - } - while (src != srcEnd) { - u32 srcColor = *src; - s32 r = (srcColor << 27) >> 27; - s32 g = (srcColor << 22) >> 27; - s32 b = (srcColor << 17) >> 27; - if (altBlendIndices & 1) { - r = (u16)((rTone * r)) >> 8; - g = (u16)((gTone * g)) >> 8; - b = (u16)((bTone * b)) >> 8; - } else { // Use provided blend color - r = (u16)((newR * r)) >> 8; - g = (u16)((newG * g)) >> 8; - b = (u16)((newB * b)) >> 8; + while (src != srcEnd) { + u32 srcColor = *src; + s32 r = (srcColor << 27) >> 27; + s32 g = (srcColor << 22) >> 27; + s32 b = (srcColor << 17) >> 27; + + if (altBlendIndices & 1) { + r = (u16)((rTone * r)) >> 8; + g = (u16)((gTone * g)) >> 8; + b = (u16)((bTone * b)) >> 8; + } else { // Use provided blend color + r = (u16)((newR * r)) >> 8; + g = (u16)((newG * g)) >> 8; + b = (u16)((newB * b)) >> 8; + } + if (r > 31) + r = 31; + if (g > 31) + g = 31; + if (b > 31) + b = 31; + src++; + *dst++ = RGB2(r, g, b); + altBlendIndices >>= 1; } - if (r > 31) - r = 31; - if (g > 31) - g = 31; - if (b > 31) - b = 31; - src++; - *dst++ = RGB2(r, g, b); - altBlendIndices >>= 1; - } } #define tCoeff data[0] diff --git a/src/palette_util.c b/src/palette_util.c index bcf8c3481..54549ffcc 100755 --- a/src/palette_util.c +++ b/src/palette_util.c @@ -385,8 +385,7 @@ void UpdatePulseBlend(struct PulseBlend *pulseBlend) if (--pulseBlendPalette->delayCounter == 0xFF) { pulseBlendPalette->delayCounter = pulseBlendPalette->pulseBlendSettings.delay; - // TODO: Optimize pulse blending - CpuFastCopy(gPlttBufferUnfaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, gPlttBufferFaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, 32); + CpuFastCopy(gPlttBufferUnfaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, gPlttBufferFaded + pulseBlendPalette->pulseBlendSettings.paletteOffset, PLTT_SIZE_4BPP); UpdatePalettesWithTime(1 << (pulseBlendPalette->pulseBlendSettings.paletteOffset >> 4)); // pulseBlendSettings has a numColors field, but it is only ever set to 16 (for mirage tower) // So, it's ok to use the fine blending here which blends the entire palette diff --git a/src/random.c b/src/random.c index d59314bd8..7789d850b 100755 --- a/src/random.c +++ b/src/random.c @@ -101,16 +101,16 @@ void ShuffleListU16(u16 *list, u16 count, u32 seed) u8 RandomWeightedIndex(u8 *weights, u8 length) { u32 i; - u16 random_value; + u16 randomValue; u16 weightSum = 0; for (i = 0; i < length; i++) weightSum += weights[i]; - random_value = Random() % weightSum; + randomValue = weightSum > 0 ? Random() % weightSum : 0; weightSum = 0; for (i = 0; i < length; i++) { weightSum += weights[i]; - if (random_value <= weightSum) + if (randomValue <= weightSum) return i; } } \ No newline at end of file diff --git a/src/scrcmd.c b/src/scrcmd.c index 678dc546e..a6730d9cb 100755 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1233,10 +1233,10 @@ bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx) bool8 ScrCmd_createvobject(struct ScriptContext *ctx) { - u16 graphicsId = ScriptReadByte(ctx); // Support u16 in createvobject + u16 graphicsId = ScriptReadHalfword(ctx); // Support u16 in createvobject u8 virtualObjId = ScriptReadByte(ctx); u16 x = VarGet(ScriptReadHalfword(ctx)); - u32 y = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); u8 elevation = ScriptReadByte(ctx); u8 direction = ScriptReadByte(ctx);