diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8142f9c1d9..5475cfb535 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,8 +44,8 @@ set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip")
set(OBJECTS_SHA1 "151424d24b1d49a167932b58319bedaa6ec368e9")
-set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.23/replays.zip")
-set(REPLAYS_SHA1 "AC67B93731B6246A31D9A8B01A6CA12AE98AE0D1")
+set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.24/replays.zip")
+set(REPLAYS_SHA1 "58AD8B2D2A804D2FEE787597A2A4DEADBF4D2A65")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests")
diff --git a/openrct2.proj b/openrct2.proj
index d63e4ba8d0..39029076fb 100644
--- a/openrct2.proj
+++ b/openrct2.proj
@@ -48,8 +48,8 @@
304d13a126c15bf2c86ff13b81a2f2cc1856ac8d
https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip
151424d24b1d49a167932b58319bedaa6ec368e9
- https://github.com/OpenRCT2/replays/releases/download/v0.0.23/replays.zip
- AC67B93731B6246A31D9A8B01A6CA12AE98AE0D1
+ https://github.com/OpenRCT2/replays/releases/download/v0.0.24/replays.zip
+ 58AD8B2D2A804D2FEE787597A2A4DEADBF4D2A65
diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp
index 81cfa0c624..50c90ea026 100644
--- a/src/openrct2-ui/interface/ViewportInteraction.cpp
+++ b/src/openrct2-ui/interface/ViewportInteraction.cpp
@@ -195,7 +195,7 @@ bool ViewportInteractionLeftClick(const ScreenCoordsXY& screenCoords)
case SpriteIdentifier::Misc:
if (game_is_not_paused())
{
- switch (static_cast(entity->type))
+ switch (entity->As()->SubType)
{
case MiscEntityType::Balloon:
{
diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp
index f6acacd7bc..3b7a5df130 100644
--- a/src/openrct2-ui/windows/TitleCommandEditor.cpp
+++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp
@@ -657,10 +657,10 @@ static void window_title_command_editor_tool_down(
}
else if (litter != nullptr)
{
- if (litter->type < std::size(litterNames))
+ if (litter->SubType < std::size(litterNames))
{
validSprite = true;
- format_string(_command.SpriteName, USER_STRING_MAX_LENGTH, litterNames[litter->type], nullptr);
+ format_string(_command.SpriteName, USER_STRING_MAX_LENGTH, litterNames[litter->SubType], nullptr);
}
}
else if (balloon != nullptr)
diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp
index 65dfc2e32b..7a97cbee0a 100644
--- a/src/openrct2/GameStateSnapshots.cpp
+++ b/src/openrct2/GameStateSnapshots.cpp
@@ -49,7 +49,7 @@ struct GameStateSnapshot_t
for (size_t i = 0; i < numSprites; i++)
{
auto entity = getEntity(i);
- if (entity == nullptr || entity->generic.sprite_identifier == SpriteIdentifier::Null)
+ if (entity == nullptr || entity->misc.sprite_identifier == SpriteIdentifier::Null)
continue;
indexTable.push_back(static_cast(i));
}
@@ -76,9 +76,9 @@ struct GameStateSnapshot_t
}
auto& sprite = *entity;
- ds << sprite.generic.sprite_identifier;
+ ds << sprite.misc.sprite_identifier;
- switch (sprite.generic.sprite_identifier)
+ switch (sprite.misc.sprite_identifier)
{
case SpriteIdentifier::Vehicle:
ds << reinterpret_cast(sprite.vehicle);
@@ -91,8 +91,8 @@ struct GameStateSnapshot_t
break;
case SpriteIdentifier::Misc:
{
- ds << sprite.generic.type;
- switch (static_cast(sprite.generic.type))
+ ds << sprite.misc.SubType;
+ switch (sprite.misc.SubType)
{
case MiscEntityType::MoneyEffect:
ds << reinterpret_cast(sprite.money_effect);
@@ -176,7 +176,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots
for (auto& sprite : spriteList)
{
// By default they don't exist.
- sprite.generic.sprite_identifier = SpriteIdentifier::Null;
+ sprite.misc.sprite_identifier = SpriteIdentifier::Null;
}
snapshot.SerialiseSprites([&spriteList](const size_t index) { return &spriteList[index]; }, MAX_SPRITES, false);
@@ -200,7 +200,6 @@ struct GameStateSnapshots final : public IGameStateSnapshots
const SpriteBase& spriteBase, const SpriteBase& spriteCmp, GameStateSpriteChange_t& changeData) const
{
COMPARE_FIELD(SpriteBase, sprite_identifier);
- COMPARE_FIELD(SpriteBase, type);
COMPARE_FIELD(SpriteBase, next_in_quadrant);
COMPARE_FIELD(SpriteBase, next);
COMPARE_FIELD(SpriteBase, previous);
@@ -469,18 +468,19 @@ struct GameStateSnapshots final : public IGameStateSnapshots
COMPARE_FIELD(JumpingFountain, Iteration);
}
- void CompareSpriteDataGeneric(
- const SpriteGeneric& spriteBase, const SpriteGeneric& spriteCmp, GameStateSpriteChange_t& changeData) const
+ void CompareSpriteDataMisc(
+ const MiscEntity& spriteBase, const MiscEntity& spriteCmp, GameStateSpriteChange_t& changeData) const
{
- COMPARE_FIELD(SpriteGeneric, frame);
+ COMPARE_FIELD(MiscEntity, SubType);
+ COMPARE_FIELD(MiscEntity, frame);
}
void CompareSpriteData(const rct_sprite& spriteBase, const rct_sprite& spriteCmp, GameStateSpriteChange_t& changeData) const
{
- CompareSpriteDataCommon(spriteBase.generic, spriteCmp.generic, changeData);
- if (spriteBase.generic.sprite_identifier == spriteCmp.generic.sprite_identifier)
+ CompareSpriteDataCommon(spriteBase.misc, spriteCmp.misc, changeData);
+ if (spriteBase.misc.sprite_identifier == spriteCmp.misc.sprite_identifier)
{
- switch (spriteBase.generic.sprite_identifier)
+ switch (spriteBase.misc.sprite_identifier)
{
case SpriteIdentifier::Peep:
CompareSpriteDataPeep(spriteBase.peep, spriteCmp.peep, changeData);
@@ -493,8 +493,8 @@ struct GameStateSnapshots final : public IGameStateSnapshots
break;
case SpriteIdentifier::Misc:
// This is not expected to happen, as misc sprites do not constitute sprite checksum
- CompareSpriteDataGeneric(spriteBase.generic, spriteCmp.generic, changeData);
- switch (static_cast(spriteBase.generic.type))
+ CompareSpriteDataMisc(spriteBase.misc, spriteCmp.misc, changeData);
+ switch (spriteBase.misc.SubType)
{
case MiscEntityType::SteamParticle:
CompareSpriteDataSteamParticle(spriteBase.steam_particle, spriteCmp.steam_particle, changeData);
@@ -509,7 +509,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots
case MiscEntityType::ExplosionCloud:
case MiscEntityType::CrashSplash:
case MiscEntityType::ExplosionFlare:
- // SpriteGeneric
+ // MiscEntity
break;
case MiscEntityType::JumpingFountainWater:
case MiscEntityType::JumpingFountainSnow:
@@ -550,27 +550,30 @@ struct GameStateSnapshots final : public IGameStateSnapshots
const rct_sprite& spriteBase = spritesBase[i];
const rct_sprite& spriteCmp = spritesCmp[i];
- changeData.spriteIdentifier = spriteBase.generic.sprite_identifier;
- changeData.miscIdentifier = spriteBase.generic.type;
+ changeData.spriteIdentifier = spriteBase.misc.sprite_identifier;
+ // This will be nonsense information for all types apart from MiscEntities.
+ // This is not an issue though as only MiscEntities will use this field in GetSpriteIdentifierName
+ // TODO: Don't do this.
+ changeData.miscIdentifier = spriteBase.misc.SubType;
- if (spriteBase.generic.sprite_identifier == SpriteIdentifier::Null
- && spriteCmp.generic.sprite_identifier != SpriteIdentifier::Null)
+ if (spriteBase.misc.sprite_identifier == SpriteIdentifier::Null
+ && spriteCmp.misc.sprite_identifier != SpriteIdentifier::Null)
{
// Sprite was added.
changeData.changeType = GameStateSpriteChange_t::ADDED;
- changeData.spriteIdentifier = spriteCmp.generic.sprite_identifier;
+ changeData.spriteIdentifier = spriteCmp.misc.sprite_identifier;
}
else if (
- spriteBase.generic.sprite_identifier != SpriteIdentifier::Null
- && spriteCmp.generic.sprite_identifier == SpriteIdentifier::Null)
+ spriteBase.misc.sprite_identifier != SpriteIdentifier::Null
+ && spriteCmp.misc.sprite_identifier == SpriteIdentifier::Null)
{
// Sprite was removed.
changeData.changeType = GameStateSpriteChange_t::REMOVED;
- changeData.spriteIdentifier = spriteBase.generic.sprite_identifier;
+ changeData.spriteIdentifier = spriteBase.misc.sprite_identifier;
}
else if (
- spriteBase.generic.sprite_identifier == SpriteIdentifier::Null
- && spriteCmp.generic.sprite_identifier == SpriteIdentifier::Null)
+ spriteBase.misc.sprite_identifier == SpriteIdentifier::Null
+ && spriteCmp.misc.sprite_identifier == SpriteIdentifier::Null)
{
// Do nothing.
changeData.changeType = GameStateSpriteChange_t::EQUAL;
@@ -655,8 +658,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots
if (change.changeType == GameStateSpriteChange_t::EQUAL)
continue;
- const char* typeName = GetSpriteIdentifierName(
- change.spriteIdentifier, static_cast(change.miscIdentifier));
+ const char* typeName = GetSpriteIdentifierName(change.spriteIdentifier, change.miscIdentifier);
if (change.changeType == GameStateSpriteChange_t::ADDED)
{
diff --git a/src/openrct2/GameStateSnapshots.h b/src/openrct2/GameStateSnapshots.h
index 01bc20bf2b..1b06fdb8ea 100644
--- a/src/openrct2/GameStateSnapshots.h
+++ b/src/openrct2/GameStateSnapshots.h
@@ -40,7 +40,7 @@ struct GameStateSpriteChange_t
uint8_t changeType;
SpriteIdentifier spriteIdentifier;
- uint8_t miscIdentifier;
+ MiscEntityType miscIdentifier;
uint32_t spriteIndex;
std::vector diffs;
diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp
index cee952ecfb..768df41ae4 100644
--- a/src/openrct2/network/NetworkBase.cpp
+++ b/src/openrct2/network/NetworkBase.cpp
@@ -34,7 +34,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
-#define NETWORK_STREAM_VERSION "9"
+#define NETWORK_STREAM_VERSION "10"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static Peep* _pickup_peep = nullptr;
diff --git a/src/openrct2/paint/sprite/Paint.Litter.cpp b/src/openrct2/paint/sprite/Paint.Litter.cpp
index a3eecc27ff..17a4218499 100644
--- a/src/openrct2/paint/sprite/Paint.Litter.cpp
+++ b/src/openrct2/paint/sprite/Paint.Litter.cpp
@@ -77,9 +77,9 @@ void litter_paint(paint_session* session, const Litter* litter, int32_t imageDir
imageDirection >>= 3;
// Some litter types have only 1 direction so remove
// anything that isn't required.
- imageDirection &= litter_sprites[litter->type].direction_mask;
+ imageDirection &= litter_sprites[litter->SubType].direction_mask;
- uint32_t image_id = imageDirection + litter_sprites[litter->type].base_id;
+ uint32_t image_id = imageDirection + litter_sprites[litter->SubType].base_id;
// In the following call to PaintAddImageAsParent, we add 4 (instead of 2) to the
// bound_box_offset_z to make sure litter is drawn on top of railways
diff --git a/src/openrct2/paint/sprite/Paint.Misc.cpp b/src/openrct2/paint/sprite/Paint.Misc.cpp
index 86628afdcb..8f2c51e805 100644
--- a/src/openrct2/paint/sprite/Paint.Misc.cpp
+++ b/src/openrct2/paint/sprite/Paint.Misc.cpp
@@ -29,11 +29,11 @@ const uint32_t vehicle_particle_base_sprites[] = {
/**
* rct2: 0x00672AC9
*/
-void misc_paint(paint_session* session, const SpriteBase* misc, int32_t imageDirection)
+void misc_paint(paint_session* session, const MiscEntity* misc, int32_t imageDirection)
{
rct_drawpixelinfo* dpi = &session->DPI;
- switch (static_cast(misc->type))
+ switch (misc->SubType)
{
case MiscEntityType::SteamParticle: // 0
{
@@ -134,9 +134,7 @@ void misc_paint(paint_session* session, const SpriteBase* misc, int32_t imageDir
isAntiClockwise = !isAntiClockwise;
}
- uint32_t baseImageId = (static_cast(jumpingFountain->type) == MiscEntityType::JumpingFountainSnow)
- ? 23037
- : 22973;
+ uint32_t baseImageId = (jumpingFountain->SubType == MiscEntityType::JumpingFountainSnow) ? 23037 : 22973;
uint32_t imageId = baseImageId + ebx * 16 + jumpingFountain->frame;
constexpr std::array antiClockWiseBoundingBoxes = { CoordsXY{ -COORDS_XY_STEP, -3 },
CoordsXY{ 0, -3 } };
diff --git a/src/openrct2/paint/sprite/Paint.Sprite.cpp b/src/openrct2/paint/sprite/Paint.Sprite.cpp
index 8b7961cb9b..be08dac38d 100644
--- a/src/openrct2/paint/sprite/Paint.Sprite.cpp
+++ b/src/openrct2/paint/sprite/Paint.Sprite.cpp
@@ -115,7 +115,7 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t
break;
case SpriteIdentifier::Misc:
// TODO: Update misc_paint to take a specific sprite type
- misc_paint(session, spr, image_direction);
+ misc_paint(session, spr->As(), image_direction);
break;
case SpriteIdentifier::Litter:
litter_paint(session, spr->As(), image_direction);
diff --git a/src/openrct2/paint/sprite/Paint.Sprite.h b/src/openrct2/paint/sprite/Paint.Sprite.h
index 4a54db2af5..9638184780 100644
--- a/src/openrct2/paint/sprite/Paint.Sprite.h
+++ b/src/openrct2/paint/sprite/Paint.Sprite.h
@@ -17,7 +17,7 @@ struct paint_session;
void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t y);
-void misc_paint(paint_session* session, const SpriteBase* misc, int32_t imageDirection);
+void misc_paint(paint_session* session, const MiscEntity* misc, int32_t imageDirection);
void litter_paint(paint_session* session, const Litter* litter, int32_t imageDirection);
void peep_paint(paint_session* session, const Peep* peep, int32_t imageDirection);
diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp
index c4e0b130b5..bfee63950d 100644
--- a/src/openrct2/peep/Guest.cpp
+++ b/src/openrct2/peep/Guest.cpp
@@ -5076,13 +5076,13 @@ void Guest::UpdateWalking()
{
if ((0xFFFF & scenario_rand()) <= 4096)
{
- static constexpr const uint8_t litter_types[] = {
+ static constexpr const LitterType litter_types[] = {
LITTER_TYPE_EMPTY_CAN,
LITTER_TYPE_RUBBISH,
LITTER_TYPE_EMPTY_BURGER_BOX,
LITTER_TYPE_EMPTY_CUP,
};
- int32_t litterType = litter_types[scenario_rand() & 0x3];
+ auto litterType = litter_types[scenario_rand() & 0x3];
int32_t litterX = x + (scenario_rand() & 0x7) - 3;
int32_t litterY = y + (scenario_rand() & 0x7) - 3;
Direction litterDirection = (scenario_rand() & 0x3);
@@ -5097,13 +5097,13 @@ void Guest::UpdateWalking()
&& ((0xFFFF & scenario_rand()) <= 4096))
{
int32_t container = bitscanforward(GetEmptyContainerFlags());
- int32_t litterType = 0;
+ LitterType litterType = LITTER_TYPE_SICK;
if (container != -1)
{
auto item = static_cast(container);
RemoveItem(item);
- litterType = GetShopItemDescriptor(item).LitterType;
+ litterType = LitterType(GetShopItemDescriptor(item).LitterType);
}
WindowInvalidateFlags |= PEEP_INVALIDATE_PEEP_INVENTORY;
@@ -5672,7 +5672,8 @@ void Guest::UpdateUsingBin()
UpdateSpriteType();
continue;
}
- uint8_t litterType = GetShopItemDescriptor(item).LitterType;
+
+ LitterType litterType = LitterType(GetShopItemDescriptor(item).LitterType);
int32_t litterX = x + (scenario_rand() & 7) - 3;
int32_t litterY = y + (scenario_rand() & 7) - 3;
diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp
index e566ba0bc6..09771a3908 100644
--- a/src/openrct2/peep/Peep.cpp
+++ b/src/openrct2/peep/Peep.cpp
@@ -2640,7 +2640,7 @@ static void peep_footpath_move_forward(Peep* peep, const CoordsXYE& coords, bool
continue;
litter_count++;
- if (litter->type != LITTER_TYPE_SICK && litter->type != LITTER_TYPE_SICK_ALT)
+ if (litter->SubType != LITTER_TYPE_SICK && litter->SubType != LITTER_TYPE_SICK_ALT)
continue;
litter_count--;
diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp
index ec3b829ca1..788328f5bf 100644
--- a/src/openrct2/rct1/S4Importer.cpp
+++ b/src/openrct2/rct1/S4Importer.cpp
@@ -1170,7 +1170,7 @@ private:
dst->ride_subtype = RCTEntryIndexToOpenRCT2EntryIndex(ride->subtype);
dst->vehicle_type = vehicleEntryIndex;
- dst->type = src->type;
+ dst->SubType = Vehicle::Type(src->type);
dst->var_44 = src->var_44;
dst->remaining_distance = src->remaining_distance;
@@ -1651,7 +1651,7 @@ private:
Litter* litter = reinterpret_cast(create_sprite(SpriteIdentifier::Litter));
litter->sprite_identifier = srcLitter->sprite_identifier;
- litter->type = srcLitter->type;
+ litter->SubType = LitterType(srcLitter->type);
litter->x = srcLitter->x;
litter->y = srcLitter->y;
@@ -1673,14 +1673,14 @@ private:
if (sprite.unknown.sprite_identifier == SpriteIdentifier::Misc)
{
rct1_unk_sprite* src = &sprite.unknown;
- SpriteGeneric* dst = reinterpret_cast(create_sprite(SpriteIdentifier::Misc));
+ MiscEntity* dst = reinterpret_cast(create_sprite(SpriteIdentifier::Misc));
if (dst == nullptr)
{
log_warning("SV4 has too many misc entities. No more misc entities will be imported!");
break;
}
dst->sprite_identifier = src->sprite_identifier;
- dst->type = src->type;
+ dst->SubType = MiscEntityType(src->type);
dst->flags = src->flags;
dst->sprite_direction = src->sprite_direction;
dst->sprite_width = src->sprite_width;
diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp
index 1349bdcd36..070c19df9f 100644
--- a/src/openrct2/rct2/S6Exporter.cpp
+++ b/src/openrct2/rct2/S6Exporter.cpp
@@ -963,10 +963,10 @@ void S6Exporter::ExportSprites()
void S6Exporter::ExportSprite(RCT2Sprite* dst, const rct_sprite* src)
{
std::memset(dst, 0, sizeof(rct_sprite));
- switch (src->generic.sprite_identifier)
+ switch (src->misc.sprite_identifier)
{
case SpriteIdentifier::Null:
- ExportSpriteCommonProperties(&dst->unknown, &src->generic);
+ ExportSpriteCommonProperties(&dst->unknown, &src->misc);
break;
case SpriteIdentifier::Vehicle:
ExportSpriteVehicle(&dst->vehicle, &src->vehicle);
@@ -975,14 +975,14 @@ void S6Exporter::ExportSprite(RCT2Sprite* dst, const rct_sprite* src)
ExportSpritePeep(&dst->peep, &src->peep);
break;
case SpriteIdentifier::Misc:
- ExportSpriteMisc(&dst->unknown, &src->generic);
+ ExportSpriteMisc(&dst->unknown, &src->misc);
break;
case SpriteIdentifier::Litter:
ExportSpriteLitter(&dst->litter, &src->litter);
break;
default:
- ExportSpriteCommonProperties(&dst->unknown, &src->generic);
- log_warning("Sprite identifier %d can not be exported.", src->generic.sprite_identifier);
+ ExportSpriteCommonProperties(&dst->unknown, &src->misc);
+ log_warning("Sprite identifier %d can not be exported.", src->misc.sprite_identifier);
break;
}
}
@@ -990,7 +990,6 @@ void S6Exporter::ExportSprite(RCT2Sprite* dst, const rct_sprite* src)
void S6Exporter::ExportSpriteCommonProperties(RCT12SpriteBase* dst, const SpriteBase* src)
{
dst->sprite_identifier = src->sprite_identifier;
- dst->type = src->type;
dst->next_in_quadrant = src->next_in_quadrant;
dst->next = src->next;
dst->previous = src->previous;
@@ -1015,6 +1014,7 @@ void S6Exporter::ExportSpriteVehicle(RCT2SpriteVehicle* dst, const Vehicle* src)
const auto* ride = src->GetRide();
ExportSpriteCommonProperties(dst, static_cast(src));
+ dst->type = EnumValue(src->SubType);
dst->vehicle_sprite_type = src->vehicle_sprite_type;
dst->bank_rotation = src->bank_rotation;
dst->remaining_distance = src->remaining_distance;
@@ -1248,10 +1248,11 @@ void S6Exporter::ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src)
dst->item_standard_flags = static_cast(src->GetItemFlags());
}
-void S6Exporter::ExportSpriteMisc(RCT12SpriteBase* cdst, const SpriteBase* csrc)
+void S6Exporter::ExportSpriteMisc(RCT12SpriteBase* cdst, const MiscEntity* csrc)
{
ExportSpriteCommonProperties(cdst, csrc);
- switch (static_cast(cdst->type))
+ cdst->type = EnumValue(csrc->SubType);
+ switch (csrc->SubType)
{
case MiscEntityType::SteamParticle:
{
@@ -1295,7 +1296,7 @@ void S6Exporter::ExportSpriteMisc(RCT12SpriteBase* cdst, const SpriteBase* csrc)
case MiscEntityType::ExplosionFlare:
case MiscEntityType::CrashSplash:
{
- auto src = static_cast(csrc);
+ auto src = static_cast(csrc);
auto dst = static_cast(cdst);
dst->frame = src->frame;
break;
@@ -1343,6 +1344,7 @@ void S6Exporter::ExportSpriteMisc(RCT12SpriteBase* cdst, const SpriteBase* csrc)
void S6Exporter::ExportSpriteLitter(RCT12SpriteLitter* dst, const Litter* src)
{
ExportSpriteCommonProperties(dst, src);
+ dst->type = EnumValue(src->SubType);
dst->creationTick = src->creationTick;
}
diff --git a/src/openrct2/rct2/S6Exporter.h b/src/openrct2/rct2/S6Exporter.h
index 85b45d0660..2a492b98bf 100644
--- a/src/openrct2/rct2/S6Exporter.h
+++ b/src/openrct2/rct2/S6Exporter.h
@@ -51,7 +51,7 @@ public:
void ExportSpriteCommonProperties(RCT12SpriteBase* dst, const SpriteBase* src);
void ExportSpriteVehicle(RCT2SpriteVehicle* dst, const Vehicle* src);
void ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src);
- void ExportSpriteMisc(RCT12SpriteBase* dst, const SpriteBase* src);
+ void ExportSpriteMisc(RCT12SpriteBase* dst, const MiscEntity* src);
void ExportSpriteLitter(RCT12SpriteLitter* dst, const Litter* src);
private:
diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp
index 1b08ed6726..94d51f3e7a 100644
--- a/src/openrct2/rct2/S6Importer.cpp
+++ b/src/openrct2/rct2/S6Importer.cpp
@@ -1318,7 +1318,7 @@ public:
ImportSpritePeep(&dst->peep, &src->peep);
break;
case SpriteIdentifier::Misc:
- ImportSpriteMisc(&dst->generic, &src->unknown);
+ ImportSpriteMisc(&dst->misc, &src->unknown);
break;
case SpriteIdentifier::Litter:
ImportSpriteLitter(&dst->litter, &src->litter);
@@ -1335,6 +1335,7 @@ public:
const auto& ride = _s6.rides[src->ride];
ImportSpriteCommonProperties(static_cast(dst), src);
+ dst->SubType = Vehicle::Type(src->type);
dst->vehicle_sprite_type = src->vehicle_sprite_type;
dst->bank_rotation = src->bank_rotation;
dst->remaining_distance = src->remaining_distance;
@@ -1530,10 +1531,11 @@ public:
dst->FavouriteRideRating = src->favourite_ride_rating;
}
- void ImportSpriteMisc(SpriteBase* cdst, const RCT12SpriteBase* csrc)
+ void ImportSpriteMisc(MiscEntity* cdst, const RCT12SpriteBase* csrc)
{
ImportSpriteCommonProperties(cdst, csrc);
- switch (static_cast(cdst->type))
+ cdst->SubType = MiscEntityType(csrc->type);
+ switch (cdst->SubType)
{
case MiscEntityType::SteamParticle:
{
@@ -1578,7 +1580,7 @@ public:
case MiscEntityType::CrashSplash:
{
auto src = static_cast(csrc);
- auto dst = static_cast(cdst);
+ auto dst = static_cast(cdst);
dst->frame = src->frame;
break;
}
@@ -1616,7 +1618,7 @@ public:
break;
}
default:
- log_warning("Misc. sprite type %d can not be imported.", cdst->type);
+ log_warning("Misc. sprite type %d can not be imported.", cdst->SubType);
break;
}
}
@@ -1624,13 +1626,13 @@ public:
void ImportSpriteLitter(Litter* dst, const RCT12SpriteLitter* src)
{
ImportSpriteCommonProperties(dst, src);
+ dst->SubType = LitterType(src->type);
dst->creationTick = src->creationTick;
}
void ImportSpriteCommonProperties(SpriteBase* dst, const RCT12SpriteBase* src)
{
dst->sprite_identifier = src->sprite_identifier;
- dst->type = src->type;
dst->next_in_quadrant = src->next_in_quadrant;
dst->next = src->next;
dst->previous = src->previous;
diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp
index 56a759c84b..aefad80cf5 100644
--- a/src/openrct2/ride/CableLift.cpp
+++ b/src/openrct2/ride/CableLift.cpp
@@ -32,7 +32,7 @@ Vehicle* cable_lift_segment_create(
{
ride.cable_lift = current->sprite_index;
}
- current->type = static_cast(head ? Vehicle::Type::Head : Vehicle::Type::Tail);
+ current->SubType = head ? Vehicle::Type::Head : Vehicle::Type::Tail;
current->var_44 = var_44;
current->remaining_distance = remaining_distance;
current->sprite_width = 10;
diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp
index e93935811d..43cf590c25 100644
--- a/src/openrct2/ride/Ride.cpp
+++ b/src/openrct2/ride/Ride.cpp
@@ -4403,7 +4403,7 @@ static Vehicle* vehicle_create_car(
vehicle->ride_subtype = ride->subtype;
vehicle->vehicle_type = vehicleEntryIndex;
- vehicle->type = static_cast(carIndex == 0 ? Vehicle::Type::Head : Vehicle::Type::Tail);
+ vehicle->SubType = carIndex == 0 ? Vehicle::Type::Head : Vehicle::Type::Tail;
vehicle->var_44 = ror32(vehicleEntry->spacing, 10) & 0xFFFF;
auto edx = vehicleEntry->spacing >> 1;
*remainingDistance -= edx;
diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp
index 3540c817cd..eeca788f8f 100644
--- a/src/openrct2/ride/Vehicle.cpp
+++ b/src/openrct2/ride/Vehicle.cpp
@@ -7239,7 +7239,7 @@ static void steam_particle_create(const CoordsXYZ& coords)
steam->sprite_height_negative = 18;
steam->sprite_height_positive = 16;
steam->sprite_identifier = SpriteIdentifier::Misc;
- steam->type = EnumValue(MiscEntityType::SteamParticle);
+ steam->SubType = MiscEntityType::SteamParticle;
steam->frame = 256;
steam->time_to_move = 0;
steam->MoveTo(coords);
diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h
index 69f1757bff..91364cd072 100644
--- a/src/openrct2/ride/Vehicle.h
+++ b/src/openrct2/ride/Vehicle.h
@@ -198,6 +198,7 @@ struct Vehicle : SpriteBase
StoppedByBlockBrakes
};
+ Type SubType;
uint8_t vehicle_sprite_type;
uint8_t bank_rotation;
int32_t remaining_distance;
@@ -312,7 +313,7 @@ struct Vehicle : SpriteBase
constexpr bool IsHead() const
{
- return type == static_cast(Vehicle::Type::Head);
+ return SubType == Vehicle::Type::Head;
}
void Update();
Vehicle* GetHead();
diff --git a/src/openrct2/scripting/ScEntity.hpp b/src/openrct2/scripting/ScEntity.hpp
index a2a7d79f0c..d59794b132 100644
--- a/src/openrct2/scripting/ScEntity.hpp
+++ b/src/openrct2/scripting/ScEntity.hpp
@@ -57,7 +57,13 @@ namespace OpenRCT2::Scripting
case SpriteIdentifier::Peep:
return "peep";
case SpriteIdentifier::Misc:
- switch (static_cast(entity->type))
+ {
+ auto misc = entity->As();
+ if (misc == nullptr)
+ {
+ return "unknown";
+ }
+ switch (misc->SubType)
{
case MiscEntityType::SteamParticle:
return "steam_particle";
@@ -82,7 +88,8 @@ namespace OpenRCT2::Scripting
default:
break;
}
- break;
+ }
+ break;
case SpriteIdentifier::Litter:
return "litter";
case SpriteIdentifier::Null:
diff --git a/src/openrct2/scripting/ScMap.hpp b/src/openrct2/scripting/ScMap.hpp
index 69b5ecaec8..3d7ac0de6f 100644
--- a/src/openrct2/scripting/ScMap.hpp
+++ b/src/openrct2/scripting/ScMap.hpp
@@ -99,11 +99,11 @@ namespace OpenRCT2::Scripting
std::vector getAllEntities(const std::string& type) const
{
EntityListId targetList{};
- uint8_t targetType{};
+ MiscEntityType targetType{};
if (type == "balloon")
{
targetList = EntityListId::Misc;
- targetType = EnumValue(MiscEntityType::Balloon);
+ targetType = MiscEntityType::Balloon;
}
if (type == "car")
{
@@ -116,7 +116,7 @@ namespace OpenRCT2::Scripting
else if (type == "duck")
{
targetList = EntityListId::Misc;
- targetType = EnumValue(MiscEntityType::Duck);
+ targetType = MiscEntityType::Duck;
}
else if (type == "peep")
{
@@ -130,26 +130,26 @@ namespace OpenRCT2::Scripting
std::vector result;
for (auto sprite : EntityList(targetList))
{
- // Only the misc list checks the type property
- if (targetList != EntityListId::Misc || sprite->type == targetType)
+ if (targetList == EntityListId::Peep)
{
- if (targetList == EntityListId::Peep)
- {
- if (sprite->Is())
- result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index)));
- else
- result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index)));
- }
- else if (targetList == EntityListId::TrainHead)
- {
- for (auto carId = sprite->sprite_index; carId != SPRITE_INDEX_NULL;)
- {
- auto car = GetEntity(carId);
- result.push_back(GetObjectAsDukValue(_context, std::make_shared(carId)));
- carId = car->next_vehicle_on_train;
- }
- }
+ if (sprite->Is())
+ result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index)));
else
+ result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index)));
+ }
+ else if (targetList == EntityListId::TrainHead)
+ {
+ for (auto carId = sprite->sprite_index; carId != SPRITE_INDEX_NULL;)
+ {
+ auto car = GetEntity(carId);
+ result.push_back(GetObjectAsDukValue(_context, std::make_shared(carId)));
+ carId = car->next_vehicle_on_train;
+ }
+ }
+ else if (targetList == EntityListId::Misc)
+ {
+ auto* misc = sprite->As();
+ if (misc && misc->SubType == targetType)
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index)));
}
diff --git a/src/openrct2/world/Balloon.cpp b/src/openrct2/world/Balloon.cpp
index 327c526561..bdb00a6abc 100644
--- a/src/openrct2/world/Balloon.cpp
+++ b/src/openrct2/world/Balloon.cpp
@@ -16,7 +16,8 @@
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::Balloon;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::Balloon;
}
void Balloon::Update()
@@ -84,9 +85,9 @@ void create_balloon(const CoordsXYZ& balloonPos, int32_t colour, bool isPopped)
rct_sprite* sprite = create_sprite(SpriteIdentifier::Misc);
if (sprite == nullptr)
return;
- sprite->generic.sprite_identifier = SpriteIdentifier::Misc;
- sprite->generic.type = EnumValue(MiscEntityType::Balloon);
- auto balloon = sprite->generic.As();
+ sprite->misc.sprite_identifier = SpriteIdentifier::Misc;
+ sprite->misc.SubType = MiscEntityType::Balloon;
+ auto balloon = sprite->misc.As();
if (balloon == nullptr)
return; // can never happen
diff --git a/src/openrct2/world/Duck.cpp b/src/openrct2/world/Duck.cpp
index 8103f4b0bd..af8167f502 100644
--- a/src/openrct2/world/Duck.cpp
+++ b/src/openrct2/world/Duck.cpp
@@ -68,7 +68,8 @@ static constexpr const uint8_t * DuckAnimations[] =
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::Duck;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::Duck;
}
bool Duck::IsFlying()
@@ -290,9 +291,9 @@ void create_duck(const CoordsXY& pos)
targetPos.x += offsetXY;
targetPos.y += offsetXY;
- sprite->generic.sprite_identifier = SpriteIdentifier::Misc;
- sprite->generic.type = EnumValue(MiscEntityType::Duck);
- auto duck = sprite->generic.As();
+ sprite->misc.sprite_identifier = SpriteIdentifier::Misc;
+ sprite->misc.SubType = MiscEntityType::Duck;
+ auto duck = sprite->misc.As();
if (duck == nullptr)
return; // can never happen
duck->sprite_width = 9;
diff --git a/src/openrct2/world/Fountain.cpp b/src/openrct2/world/Fountain.cpp
index 7f4f503021..33fc38d85b 100644
--- a/src/openrct2/world/Fountain.cpp
+++ b/src/openrct2/world/Fountain.cpp
@@ -72,9 +72,9 @@ const uint8_t _fountainPatternFlags[] = {
template<> bool SpriteBase::Is() const
{
- const auto miscType = static_cast(type);
- return sprite_identifier == SpriteIdentifier::Misc
- && (miscType == MiscEntityType::JumpingFountainSnow || miscType == MiscEntityType::JumpingFountainWater);
+ auto* misc = As();
+ return misc
+ && (misc->SubType == MiscEntityType::JumpingFountainSnow || misc->SubType == MiscEntityType::JumpingFountainWater);
}
void JumpingFountain::StartAnimation(const int32_t newType, const CoordsXY& newLoc, const TileElement* tileElement)
@@ -140,8 +140,8 @@ void JumpingFountain::Create(
jumpingFountain->sprite_height_positive = 12;
jumpingFountain->sprite_identifier = SpriteIdentifier::Misc;
jumpingFountain->MoveTo(newLoc);
- jumpingFountain->type = newType == JUMPING_FOUNTAIN_TYPE_SNOW ? EnumValue(MiscEntityType::JumpingFountainSnow)
- : EnumValue(MiscEntityType::JumpingFountainWater);
+ jumpingFountain->SubType = newType == JUMPING_FOUNTAIN_TYPE_SNOW ? MiscEntityType::JumpingFountainSnow
+ : MiscEntityType::JumpingFountainWater;
jumpingFountain->NumTicksAlive = 0;
jumpingFountain->frame = 0;
}
@@ -162,7 +162,7 @@ void JumpingFountain::Update()
Invalidate();
frame++;
- switch (static_cast(type))
+ switch (SubType)
{
case MiscEntityType::JumpingFountainWater:
if (frame == 11 && (FountainFlags & FOUNTAIN_FLAG::FAST))
@@ -192,9 +192,8 @@ void JumpingFountain::Update()
int32_t JumpingFountain::GetType() const
{
- const int32_t fountainType = static_cast(type) == MiscEntityType::JumpingFountainSnow
- ? JUMPING_FOUNTAIN_TYPE_SNOW
- : JUMPING_FOUNTAIN_TYPE_WATER;
+ const int32_t fountainType = SubType == MiscEntityType::JumpingFountainSnow ? JUMPING_FOUNTAIN_TYPE_SNOW
+ : JUMPING_FOUNTAIN_TYPE_WATER;
return fountainType;
}
diff --git a/src/openrct2/world/Fountain.h b/src/openrct2/world/Fountain.h
index e48cb71b40..790e42898f 100644
--- a/src/openrct2/world/Fountain.h
+++ b/src/openrct2/world/Fountain.h
@@ -13,7 +13,7 @@
#include "Map.h"
#include "SpriteBase.h"
-struct JumpingFountain : SpriteGeneric
+struct JumpingFountain : MiscEntity
{
uint8_t NumTicksAlive;
uint8_t FountainFlags;
diff --git a/src/openrct2/world/MoneyEffect.cpp b/src/openrct2/world/MoneyEffect.cpp
index 842a4ae087..95d93c0820 100644
--- a/src/openrct2/world/MoneyEffect.cpp
+++ b/src/openrct2/world/MoneyEffect.cpp
@@ -20,7 +20,8 @@ static constexpr const CoordsXY _moneyEffectMoveOffset[] = { { 1, -1 }, { 1, 1 }
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::MoneyEffect;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::MoneyEffect;
}
/**
@@ -43,7 +44,7 @@ void MoneyEffect::CreateAt(money32 value, const CoordsXYZ& effectPos, bool verti
moneyEffect->sprite_height_positive = 30;
moneyEffect->sprite_identifier = SpriteIdentifier::Misc;
moneyEffect->MoveTo(effectPos);
- moneyEffect->type = EnumValue(MiscEntityType::MoneyEffect);
+ moneyEffect->SubType = MiscEntityType::MoneyEffect;
moneyEffect->NumMovements = 0;
moneyEffect->MoveDelay = 0;
diff --git a/src/openrct2/world/Particle.cpp b/src/openrct2/world/Particle.cpp
index 74d3ac3256..7c3bbcf9de 100644
--- a/src/openrct2/world/Particle.cpp
+++ b/src/openrct2/world/Particle.cpp
@@ -16,13 +16,14 @@
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc
- && static_cast(type) == MiscEntityType::CrashedVehicleParticle;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::CrashedVehicleParticle;
}
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::CrashSplash;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::CrashSplash;
}
/**
*
@@ -40,7 +41,7 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, const CoordsXYZ
sprite->sprite_height_positive = 8;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(vehiclePos);
- sprite->type = EnumValue(MiscEntityType::CrashedVehicleParticle);
+ sprite->SubType = MiscEntityType::CrashedVehicleParticle;
sprite->frame = (scenario_rand() & 0xFF) * 12;
sprite->time_to_live = (scenario_rand() & 0x7F) + 140;
@@ -121,7 +122,7 @@ void VehicleCrashParticle::Update()
*/
void crash_splash_create(const CoordsXYZ& splashPos)
{
- SpriteGeneric* sprite = &create_sprite(SpriteIdentifier::Misc)->generic;
+ MiscEntity* sprite = &create_sprite(SpriteIdentifier::Misc)->misc;
if (sprite != nullptr)
{
sprite->sprite_width = 33;
@@ -129,7 +130,7 @@ void crash_splash_create(const CoordsXYZ& splashPos)
sprite->sprite_height_positive = 16;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(splashPos + CoordsXYZ{ 0, 0, 3 });
- sprite->type = EnumValue(MiscEntityType::CrashSplash);
+ sprite->SubType = MiscEntityType::CrashSplash;
sprite->frame = 0;
}
}
diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp
index 35976e6e11..902bde4808 100644
--- a/src/openrct2/world/Sprite.cpp
+++ b/src/openrct2/world/Sprite.cpp
@@ -60,19 +60,27 @@ template<> bool SpriteBase::Is() const
return sprite_identifier == SpriteIdentifier::Litter;
}
+template<> bool SpriteBase::Is() const
+{
+ return sprite_identifier == SpriteIdentifier::Misc;
+}
+
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::SteamParticle;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::SteamParticle;
}
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::ExplosionFlare;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::ExplosionFlare;
}
template<> bool SpriteBase::Is() const
{
- return sprite_identifier == SpriteIdentifier::Misc && static_cast(type) == MiscEntityType::ExplosionCloud;
+ auto* misc = As();
+ return misc && misc->SubType == MiscEntityType::ExplosionCloud;
}
uint16_t GetEntityListCount(EntityListId list)
@@ -97,7 +105,7 @@ std::string rct_sprite_checksum::ToString() const
SpriteBase* try_get_sprite(size_t spriteIndex)
{
- return spriteIndex >= MAX_SPRITES ? nullptr : &_spriteList[spriteIndex].generic;
+ return spriteIndex >= MAX_SPRITES ? nullptr : &_spriteList[spriteIndex].misc;
}
SpriteBase* get_sprite(size_t spriteIndex)
@@ -128,7 +136,13 @@ void SpriteBase::Invalidate()
maxZoom = 2;
break;
case SpriteIdentifier::Misc:
- switch (static_cast(type))
+ {
+ auto* misc = As();
+ if (misc == nullptr)
+ {
+ return;
+ }
+ switch (misc->SubType)
{
case MiscEntityType::CrashedVehicleParticle:
case MiscEntityType::JumpingFountainWater:
@@ -149,7 +163,8 @@ void SpriteBase::Invalidate()
default:
break;
}
- break;
+ }
+ break;
case SpriteIdentifier::Litter:
maxZoom = 0;
break;
@@ -283,19 +298,19 @@ rct_sprite_checksum sprite_checksum()
auto copy = *reinterpret_cast(sprite);
// Only required for rendering/invalidation, has no meaning to the game state.
- copy.generic.sprite_left = copy.generic.sprite_right = copy.generic.sprite_top = copy.generic.sprite_bottom = 0;
- copy.generic.sprite_width = copy.generic.sprite_height_negative = copy.generic.sprite_height_positive = 0;
+ copy.misc.sprite_left = copy.misc.sprite_right = copy.misc.sprite_top = copy.misc.sprite_bottom = 0;
+ copy.misc.sprite_width = copy.misc.sprite_height_negative = copy.misc.sprite_height_positive = 0;
// Next in quadrant might be a misc sprite, set first non-misc sprite in quadrant.
- while (auto* nextSprite = GetEntity(copy.generic.next_in_quadrant))
+ while (auto* nextSprite = GetEntity(copy.misc.next_in_quadrant))
{
if (nextSprite->sprite_identifier == SpriteIdentifier::Misc)
- copy.generic.next_in_quadrant = nextSprite->next_in_quadrant;
+ copy.misc.next_in_quadrant = nextSprite->next_in_quadrant;
else
break;
}
- if (copy.generic.Is())
+ if (copy.misc.Is())
{
// Name is pointer and will not be the same across clients
copy.peep.Name = {};
@@ -548,7 +563,7 @@ void SteamParticle::Update()
*/
void sprite_misc_explosion_cloud_create(const CoordsXYZ& cloudPos)
{
- SpriteGeneric* sprite = &create_sprite(SpriteIdentifier::Misc)->generic;
+ MiscEntity* sprite = &create_sprite(SpriteIdentifier::Misc)->misc;
if (sprite != nullptr)
{
sprite->sprite_width = 44;
@@ -556,7 +571,7 @@ void sprite_misc_explosion_cloud_create(const CoordsXYZ& cloudPos)
sprite->sprite_height_positive = 34;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(cloudPos + CoordsXYZ{ 0, 0, 4 });
- sprite->type = EnumValue(MiscEntityType::ExplosionCloud);
+ sprite->SubType = MiscEntityType::ExplosionCloud;
sprite->frame = 0;
}
}
@@ -581,7 +596,7 @@ void ExplosionCloud::Update()
*/
void sprite_misc_explosion_flare_create(const CoordsXYZ& flarePos)
{
- SpriteGeneric* sprite = &create_sprite(SpriteIdentifier::Misc)->generic;
+ MiscEntity* sprite = &create_sprite(SpriteIdentifier::Misc)->misc;
if (sprite != nullptr)
{
sprite->sprite_width = 25;
@@ -589,7 +604,7 @@ void sprite_misc_explosion_flare_create(const CoordsXYZ& flarePos)
sprite->sprite_height_positive = 8;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(flarePos + CoordsXYZ{ 0, 0, 4 });
- sprite->type = EnumValue(MiscEntityType::ExplosionFlare);
+ sprite->SubType = MiscEntityType::ExplosionFlare;
sprite->frame = 0;
}
}
@@ -612,9 +627,9 @@ void ExplosionFlare::Update()
*
* rct2: 0x006731CD
*/
-static void sprite_misc_update(SpriteBase* sprite)
+static void sprite_misc_update(MiscEntity* sprite)
{
- switch (static_cast(sprite->type))
+ switch (sprite->SubType)
{
case MiscEntityType::SteamParticle:
sprite->As()->Update();
@@ -655,7 +670,7 @@ static void sprite_misc_update(SpriteBase* sprite)
*/
void sprite_misc_update_all()
{
- for (auto entity : EntityList(EntityListId::Misc))
+ for (auto entity : EntityList(EntityListId::Misc))
{
sprite_misc_update(entity);
}
@@ -816,7 +831,7 @@ static bool litter_can_be_at(const CoordsXYZ& mapPos)
*
* rct2: 0x0067375D
*/
-void litter_create(const CoordsXYZD& litterPos, int32_t type)
+void litter_create(const CoordsXYZD& litterPos, LitterType type)
{
if (gCheatsDisableLittering)
return;
@@ -857,7 +872,7 @@ void litter_create(const CoordsXYZD& litterPos, int32_t type)
litter->sprite_height_negative = 6;
litter->sprite_height_positive = 3;
litter->sprite_identifier = SpriteIdentifier::Litter;
- litter->type = type;
+ litter->SubType = type;
litter->MoveTo(offsetLitterPos);
litter->creationTick = gScenarioTicks;
}
diff --git a/src/openrct2/world/Sprite.h b/src/openrct2/world/Sprite.h
index 9febd2a5d4..a90787080d 100644
--- a/src/openrct2/world/Sprite.h
+++ b/src/openrct2/world/Sprite.h
@@ -39,12 +39,15 @@ enum class EntityListId : uint8_t
Count,
};
+enum LitterType : uint8_t;
+
struct Litter : SpriteBase
{
+ LitterType SubType;
uint32_t creationTick;
};
-struct Balloon : SpriteGeneric
+struct Balloon : MiscEntity
{
uint16_t popped;
uint8_t time_to_move;
@@ -55,7 +58,7 @@ struct Balloon : SpriteGeneric
void Press();
};
-struct Duck : SpriteGeneric
+struct Duck : MiscEntity
{
enum class DuckState : uint8_t
{
@@ -82,7 +85,7 @@ private:
void UpdateFlyAway();
};
-struct MoneyEffect : SpriteBase
+struct MoneyEffect : MiscEntity
{
uint16_t MoveDelay;
uint8_t NumMovements;
@@ -97,7 +100,7 @@ struct MoneyEffect : SpriteBase
std::pair GetStringId() const;
};
-struct VehicleCrashParticle : SpriteGeneric
+struct VehicleCrashParticle : MiscEntity
{
uint16_t time_to_live;
uint8_t colour[2];
@@ -112,22 +115,22 @@ struct VehicleCrashParticle : SpriteGeneric
void Update();
};
-struct ExplosionFlare : SpriteGeneric
+struct ExplosionFlare : MiscEntity
{
void Update();
};
-struct ExplosionCloud : SpriteGeneric
+struct ExplosionCloud : MiscEntity
{
void Update();
};
-struct CrashSplashParticle : SpriteGeneric
+struct CrashSplashParticle : MiscEntity
{
void Update();
};
-struct SteamParticle : SpriteGeneric
+struct SteamParticle : MiscEntity
{
uint16_t time_to_move;
@@ -142,7 +145,7 @@ struct SteamParticle : SpriteGeneric
union rct_sprite
{
uint8_t pad_00[0x200];
- SpriteGeneric generic;
+ MiscEntity misc;
Peep peep;
Litter litter;
Vehicle vehicle;
@@ -192,7 +195,7 @@ enum
SPRITE_FLAGS_PEEP_FLASHING = 1 << 9, // Deprecated: Use sprite_set_flashing/sprite_get_flashing instead.
};
-enum
+enum LitterType : uint8_t
{
LITTER_TYPE_SICK,
LITTER_TYPE_SICK_ALT,
@@ -240,7 +243,7 @@ void sprite_clear_all_unused();
void sprite_misc_update_all();
void sprite_set_coordinates(const CoordsXYZ& spritePos, SpriteBase* sprite);
void sprite_remove(SpriteBase* sprite);
-void litter_create(const CoordsXYZD& litterPos, int32_t type);
+void litter_create(const CoordsXYZD& litterPos, LitterType type);
void litter_remove_at(const CoordsXYZ& litterPos);
uint16_t remove_floating_sprites();
void sprite_misc_explosion_cloud_create(const CoordsXYZ& cloudPos);
diff --git a/src/openrct2/world/SpriteBase.h b/src/openrct2/world/SpriteBase.h
index ba34452bb2..fe006ad493 100644
--- a/src/openrct2/world/SpriteBase.h
+++ b/src/openrct2/world/SpriteBase.h
@@ -9,7 +9,6 @@ enum class SpriteIdentifier : uint8_t;
struct SpriteBase
{
SpriteIdentifier sprite_identifier;
- uint8_t type;
uint16_t next_in_quadrant;
uint16_t next;
uint16_t previous;
@@ -47,7 +46,9 @@ struct SpriteBase
}
};
-struct SpriteGeneric : SpriteBase
+enum class MiscEntityType : uint8_t;
+struct MiscEntity : SpriteBase
{
+ MiscEntityType SubType;
uint16_t frame;
};
diff --git a/test/tests/S6ImportExportTests.cpp b/test/tests/S6ImportExportTests.cpp
index e2c2814d97..a37a71f409 100644
--- a/test/tests/S6ImportExportTests.cpp
+++ b/test/tests/S6ImportExportTests.cpp
@@ -110,7 +110,7 @@ static std::unique_ptr GetGameState(std::unique_ptr& cont
{
rct_sprite* sprite = reinterpret_cast(GetEntity(spriteIdx));
if (sprite == nullptr)
- res->sprites[spriteIdx].generic.sprite_identifier = SpriteIdentifier::Null;
+ res->sprites[spriteIdx].misc.sprite_identifier = SpriteIdentifier::Null;
else
res->sprites[spriteIdx] = *sprite;
}
@@ -131,7 +131,6 @@ static void AdvanceGameTicks(uint32_t ticks, std::unique_ptr& context)
static void CompareSpriteDataCommon(const SpriteBase& left, const SpriteBase& right)
{
COMPARE_FIELD(sprite_identifier);
- COMPARE_FIELD(type);
COMPARE_FIELD(next_in_quadrant);
COMPARE_FIELD(next);
COMPARE_FIELD(previous);
@@ -271,6 +270,7 @@ static void CompareSpriteDataPeep(const Peep& left, const Peep& right)
static void CompareSpriteDataVehicle(const Vehicle& left, const Vehicle& right)
{
+ COMPARE_FIELD(SubType);
COMPARE_FIELD(vehicle_sprite_type);
COMPARE_FIELD(bank_rotation);
COMPARE_FIELD(remaining_distance);
@@ -345,6 +345,7 @@ static void CompareSpriteDataVehicle(const Vehicle& left, const Vehicle& right)
static void CompareSpriteDataLitter(const Litter& left, const Litter& right)
{
+ COMPARE_FIELD(SubType);
COMPARE_FIELD(creationTick);
}
@@ -404,10 +405,10 @@ static void CompareSpriteDataDuck(const Duck& left, const Duck& right)
static void CompareSpriteData(const rct_sprite& left, const rct_sprite& right)
{
- CompareSpriteDataCommon(left.generic, right.generic);
- if (left.generic.sprite_identifier == right.generic.sprite_identifier)
+ CompareSpriteDataCommon(left.misc, right.misc);
+ if (left.misc.sprite_identifier == right.misc.sprite_identifier)
{
- switch (left.generic.sprite_identifier)
+ switch (left.misc.sprite_identifier)
{
case SpriteIdentifier::Peep:
CompareSpriteDataPeep(left.peep, right.peep);
@@ -419,7 +420,8 @@ static void CompareSpriteData(const rct_sprite& left, const rct_sprite& right)
CompareSpriteDataLitter(left.litter, right.litter);
break;
case SpriteIdentifier::Misc:
- switch (static_cast(left.generic.type))
+ COMPARE_FIELD(misc.SubType);
+ switch (left.misc.SubType)
{
case MiscEntityType::SteamParticle:
CompareSpriteDataSteamParticle(left.steam_particle, right.steam_particle);
@@ -464,8 +466,8 @@ static void CompareStates(
for (size_t spriteIdx = 0; spriteIdx < MAX_SPRITES; ++spriteIdx)
{
- if (importedState->sprites[spriteIdx].generic.sprite_identifier == SpriteIdentifier::Null
- && exportedState->sprites[spriteIdx].generic.sprite_identifier == SpriteIdentifier::Null)
+ if (importedState->sprites[spriteIdx].misc.sprite_identifier == SpriteIdentifier::Null
+ && exportedState->sprites[spriteIdx].misc.sprite_identifier == SpriteIdentifier::Null)
{
continue;
}