diff --git a/asm/macros/event.inc b/asm/macros/event.inc index c64ae3e463..8a43011603 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1393,7 +1393,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/UnionRoom/scripts.inc b/data/maps/UnionRoom/scripts.inc index 8a9e7682a5..927c406184 100644 --- a/data/maps/UnionRoom/scripts.inc +++ b/data/maps/UnionRoom/scripts.inc @@ -26,6 +26,7 @@ UnionRoom_OnResume: end UnionRoom_OnTransition: + setflag FLAG_TEMP_HIDE_FOLLOWER end UnionRoom_EventScript_Player1:: @@ -106,4 +107,3 @@ UnionRoom_EventScript_Unused:: waitstate releaseall end - diff --git a/include/follower_helper.h b/include/follower_helper.h index 39d9fc04d4..27bf1f700e 100644 --- a/include/follower_helper.h +++ b/include/follower_helper.h @@ -69,7 +69,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/src/event_object_movement.c b/src/event_object_movement.c index f57c6ec19b..8e68390ecc 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1507,11 +1507,13 @@ 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, @@ -1526,9 +1528,19 @@ u16 LoadSheetGraphicsInfo(const struct ObjectEventGraphicsInfo *info, u16 uuid, { 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) @@ -1541,6 +1553,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) @@ -2184,12 +2197,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); @@ -2270,9 +2283,11 @@ void GetFollowerAction(struct ScriptContext *ctx) // Essentially a big switch fo [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; @@ -2303,7 +2318,7 @@ void GetFollowerAction(struct ScriptContext *ctx) // Essentially a big switch fo 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; diff --git a/src/random.c b/src/random.c index 9850df1aff..9d43ae3740 100644 --- a/src/random.c +++ b/src/random.c @@ -244,16 +244,16 @@ const void *RandomElementArrayDefault(enum RandomTag tag, const void *array, siz 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; } return 0; diff --git a/src/scrcmd.c b/src/scrcmd.c index c375696eae..fceea306f0 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1217,10 +1217,10 @@ bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx) bool8 ScrCmd_createvobject(struct ScriptContext *ctx) { - u16 graphicsId = ScriptReadByte(ctx); + u16 graphicsId = ScriptReadHalfword(ctx); 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);