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; }