Merge remote-tracking branch '_merrp_origin/followers-expanded-id' into _RHH/pr/upcoming/merrpFollowers

# Conflicts:
#	src/event_object_movement.c
#	src/scrcmd.c
This commit is contained in:
Eduardo Quezada 2024-06-01 20:17:19 -04:00
commit 1359966a14
6 changed files with 30 additions and 15 deletions

View file

@ -1393,7 +1393,7 @@
@ The specified id can be used to refer to the sprite again later with turnvobject. @ 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 .macro createvobject graphicsId:req, id:req, x:req, y:req, elevation=3, direction=DIR_SOUTH
.byte 0xaa .byte 0xaa
.byte \graphicsId .2byte \graphicsId
.byte \id .byte \id
.2byte \x .2byte \x
.2byte \y .2byte \y

View file

@ -26,6 +26,7 @@ UnionRoom_OnResume:
end end
UnionRoom_OnTransition: UnionRoom_OnTransition:
setflag FLAG_TEMP_HIDE_FOLLOWER
end end
UnionRoom_EventScript_Player1:: UnionRoom_EventScript_Player1::
@ -106,4 +107,3 @@ UnionRoom_EventScript_Unused::
waitstate waitstate
releaseall releaseall
end end

View file

@ -69,7 +69,7 @@ struct FollowerMsgInfoExtended
#define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species) #define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species)
#define MATCH_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, 0) #define MATCH_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, 0)
// Checks that follower has *neither* of the two types // 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_STATUS(status) MATCH_U24(MSG_COND_STATUS, status)
#define MATCH_MAPSEC(mapsec) MATCH_U24(MSG_COND_MAPSEC, mapsec) #define MATCH_MAPSEC(mapsec) MATCH_U24(MSG_COND_MAPSEC, mapsec)
#define MATCH_MAP_RAW(mapGroup, mapNum) MATCH_U8(MSG_COND_MAP, mapGroup, mapNum, 0) #define MATCH_MAP_RAW(mapGroup, mapNum) MATCH_U8(MSG_COND_MAP, mapGroup, mapNum, 0)

View file

@ -1507,11 +1507,13 @@ u16 LoadSheetGraphicsInfo(const struct ObjectEventGraphicsInfo *info, u16 uuid,
u32 sheetSpan = GetSpanPerImage(info->oam->shape, info->oam->size); u32 sheetSpan = GetSpanPerImage(info->oam->shape, info->oam->size);
u16 oldTiles = 0; u16 oldTiles = 0;
u16 tileStart; u16 tileStart;
bool32 oldInvisible;
if (tag == TAG_NONE) if (tag == TAG_NONE)
tag = COMP_OW_TILE_TAG_BASE + uuid; tag = COMP_OW_TILE_TAG_BASE + uuid;
if (sprite) if (sprite)
{ {
oldInvisible = sprite->invisible;
oldTiles = sprite->sheetTileStart; oldTiles = sprite->sheetTileStart;
sprite->sheetTileStart = 0; // mark unused sprite->sheetTileStart = 0; // mark unused
// Note: If sprite was not allocated to use a sheet, // 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 SpriteFrameImage image = {.size = info->size, .data = info->images->data};
struct SpriteTemplate template = {.tileTag = tag, .images = &image}; struct SpriteTemplate template = {.tileTag = tag, .images = &image};
if (oldTiles) // Load, then free, in order to avoid displaying garbage data
FieldEffectFreeTilesIfUnused(oldTiles); // before sprite's `sheetTileStart` is repointed
tileStart = LoadCompressedSpriteSheetByTemplate(&template, TILE_SIZE_4BPP << sheetSpan); 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 // sheet loaded; unload any *other* sheet for sprite
} }
else if (oldTiles && oldTiles != tileStart) else if (oldTiles && oldTiles != tileStart)
@ -1541,6 +1553,7 @@ u16 LoadSheetGraphicsInfo(const struct ObjectEventGraphicsInfo *info, u16 uuid,
sprite->sheetTileStart = tileStart; sprite->sheetTileStart = tileStart;
sprite->sheetSpan = sheetSpan; sprite->sheetSpan = sheetSpan;
sprite->usingSheet = TRUE; sprite->usingSheet = TRUE;
sprite->invisible = oldInvisible;
} }
// Going from sheet -> !sheet, reset tile number // Going from sheet -> !sheet, reset tile number
// (sheet stays loaded) // (sheet stays loaded)
@ -2184,12 +2197,12 @@ bool32 CheckMsgCondition(const struct MsgCondition *cond, struct Pokemon *mon, u
case MSG_COND_TYPE: case MSG_COND_TYPE:
multi = (SpeciesHasType(species, cond->data.bytes[0]) || multi = (SpeciesHasType(species, cond->data.bytes[0]) ||
SpeciesHasType(species, cond->data.bytes[1])); SpeciesHasType(species, cond->data.bytes[1]));
// if bytes[2] == TYPE_NONE, // if bytes[2] nonzero,
// invert; check that mon has *neither* type! // invert; check that mon has *neither* type!
if (cond->data.bytes[2] == 0) if (cond->data.bytes[2] != 0)
return multi;
else
return !multi; return !multi;
else
return multi;
break; break;
case MSG_COND_STATUS: case MSG_COND_STATUS:
return (cond->data.raw & mon->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_UPSET] = 15,
[FOLLOWER_EMOTION_ANGRY] = 15, [FOLLOWER_EMOTION_ANGRY] = 15,
[FOLLOWER_EMOTION_PENSIVE] = 15, [FOLLOWER_EMOTION_PENSIVE] = 15,
[FOLLOWER_EMOTION_LOVE] = 0,
[FOLLOWER_EMOTION_SURPRISE] = 10, [FOLLOWER_EMOTION_SURPRISE] = 10,
[FOLLOWER_EMOTION_CURIOUS] = 10, [FOLLOWER_EMOTION_CURIOUS] = 10,
[FOLLOWER_EMOTION_MUSIC] = 15, [FOLLOWER_EMOTION_MUSIC] = 15,
[FOLLOWER_EMOTION_POISONED] = 0,
}; };
u32 i, j; u32 i, j;
bool32 pickedCondition = FALSE; bool32 pickedCondition = FALSE;
@ -2303,7 +2318,7 @@ void GetFollowerAction(struct ScriptContext *ctx) // Essentially a big switch fo
if (GetCurrentWeather() == WEATHER_SUNNY_CLOUDS) if (GetCurrentWeather() == WEATHER_SUNNY_CLOUDS)
condEmotes[condCount++] = (struct SpecialEmote) {.emotion = FOLLOWER_EMOTION_HAPPY, .index = 31}; condEmotes[condCount++] = (struct SpecialEmote) {.emotion = FOLLOWER_EMOTION_HAPPY, .index = 31};
// Health & status-related // Health & status-related
multi = mon->hp * 100 / mon->maxHP; multi = SAFE_DIV(mon->hp * 100, mon->maxHP);
if (multi < 20) if (multi < 20)
{ {
emotion_weight[FOLLOWER_EMOTION_SAD] = 30; emotion_weight[FOLLOWER_EMOTION_SAD] = 30;

View file

@ -244,16 +244,16 @@ const void *RandomElementArrayDefault(enum RandomTag tag, const void *array, siz
u8 RandomWeightedIndex(u8 *weights, u8 length) u8 RandomWeightedIndex(u8 *weights, u8 length)
{ {
u32 i; u32 i;
u16 random_value; u16 randomValue;
u16 weightSum = 0; u16 weightSum = 0;
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
weightSum += weights[i]; weightSum += weights[i];
random_value = Random() % weightSum; randomValue = weightSum > 0 ? Random() % weightSum : 0;
weightSum = 0; weightSum = 0;
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
{ {
weightSum += weights[i]; weightSum += weights[i];
if (random_value <= weightSum) if (randomValue <= weightSum)
return i; return i;
} }
return 0; return 0;

View file

@ -1217,10 +1217,10 @@ bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx)
bool8 ScrCmd_createvobject(struct ScriptContext *ctx) bool8 ScrCmd_createvobject(struct ScriptContext *ctx)
{ {
u16 graphicsId = ScriptReadByte(ctx); u16 graphicsId = ScriptReadHalfword(ctx);
u8 virtualObjId = ScriptReadByte(ctx); u8 virtualObjId = ScriptReadByte(ctx);
u16 x = VarGet(ScriptReadHalfword(ctx)); u16 x = VarGet(ScriptReadHalfword(ctx));
u32 y = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx));
u8 elevation = ScriptReadByte(ctx); u8 elevation = ScriptReadByte(ctx);
u8 direction = ScriptReadByte(ctx); u8 direction = ScriptReadByte(ctx);