From df7a284822fc6267f0241cbe634822f1fdfcd44a Mon Sep 17 00:00:00 2001 From: Duncan Date: Wed, 17 Mar 2021 08:04:41 +0000 Subject: [PATCH] Entity type 2: Remove sprite_identifier (#14334) * Start changing the underlying type * Further work * Complete refactor * Further cleanup * Remove pointless check * Increment network and plugin versions * Add defaults * Further defaults * Fix test paint * Update replays --- CMakeLists.txt | 4 +- openrct2.proj | 4 +- .../interface/ViewportInteraction.cpp | 66 +++-- src/openrct2/Game.cpp | 2 +- src/openrct2/GameStateSnapshots.cpp | 229 ++++++++--------- src/openrct2/GameStateSnapshots.h | 3 +- src/openrct2/actions/PeepPickupAction.cpp | 4 +- src/openrct2/interface/InteractiveConsole.cpp | 2 +- src/openrct2/interface/Viewport.cpp | 6 +- src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/paint/sprite/Paint.Sprite.cpp | 21 +- src/openrct2/peep/Guest.cpp | 3 +- src/openrct2/peep/Peep.cpp | 8 +- src/openrct2/peep/Staff.cpp | 3 +- src/openrct2/rct1/S4Importer.cpp | 4 - src/openrct2/rct2/S6Exporter.cpp | 53 +++- src/openrct2/rct2/S6Importer.cpp | 65 ++++- src/openrct2/ride/Vehicle.cpp | 2 +- src/openrct2/scripting/ScEntity.hpp | 92 ++++--- src/openrct2/scripting/ScMap.hpp | 17 +- src/openrct2/scripting/ScriptEngine.cpp | 2 +- src/openrct2/world/Balloon.cpp | 3 +- src/openrct2/world/Duck.cpp | 3 +- src/openrct2/world/Fountain.cpp | 4 +- src/openrct2/world/MoneyEffect.cpp | 3 +- src/openrct2/world/Particle.cpp | 6 +- src/openrct2/world/Sprite.cpp | 235 ++++-------------- src/openrct2/world/SpriteBase.h | 6 +- test/testpaint/Compat.cpp | 7 +- test/tests/S6ImportExportTests.cpp | 77 +++--- 30 files changed, 435 insertions(+), 501 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d8be726b4..65584a8008 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,8 +48,8 @@ set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip") set(OBJECTS_SHA1 "c38af45d51a6e440386180feacf76c64720b6ac5") -set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.32/replays.zip") -set(REPLAYS_SHA1 "45843591A8C6739CA1D60899B7E54FC0792EF896") +set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.33/replays.zip") +set(REPLAYS_SHA1 "6D600B756B49461CEA4F8206EA18C17AA6F2AF7B") 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 7760c0227b..9bb0780e8d 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -48,8 +48,8 @@ 304d13a126c15bf2c86ff13b81a2f2cc1856ac8d https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip c38af45d51a6e440386180feacf76c64720b6ac5 - https://github.com/OpenRCT2/replays/releases/download/v0.0.32/replays.zip - 45843591A8C6739CA1D60899B7E54FC0792EF896 + https://github.com/OpenRCT2/replays/releases/download/v0.0.33/replays.zip + 6D600B756B49461CEA4F8206EA18C17AA6F2AF7B diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 7d3b641bc5..60a35dca0a 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -86,9 +86,9 @@ InteractionInfo ViewportInteractionGetItemLeft(const ScreenCoordsXY& screenCoord switch (info.SpriteType) { case ViewportInteractionItem::Entity: - switch (sprite->sprite_identifier) + switch (sprite->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: { auto vehicle = sprite->As(); if (vehicle != nullptr && vehicle->ride_subtype != RIDE_ENTRY_INDEX_NULL) @@ -97,7 +97,8 @@ InteractionInfo ViewportInteractionGetItemLeft(const ScreenCoordsXY& screenCoord info.SpriteType = ViewportInteractionItem::None; } break; - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: { auto peep = sprite->As(); if (peep != nullptr) @@ -110,9 +111,7 @@ InteractionInfo ViewportInteractionGetItemLeft(const ScreenCoordsXY& screenCoord } } break; - case SpriteIdentifier::Misc: - case SpriteIdentifier::Litter: - case SpriteIdentifier::Null: + default: break; } break; @@ -176,54 +175,45 @@ bool ViewportInteractionLeftClick(const ScreenCoordsXY& screenCoords) case ViewportInteractionItem::Entity: { auto entity = info.Entity; - switch (entity->sprite_identifier) + switch (entity->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: { auto intent = Intent(WD_VEHICLE); intent.putExtra(INTENT_EXTRA_VEHICLE, entity); context_open_intent(&intent); break; } - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: { auto intent = Intent(WC_PEEP); intent.putExtra(INTENT_EXTRA_PEEP, entity); context_open_intent(&intent); break; } - case SpriteIdentifier::Misc: + case EntityType::Balloon: + { if (game_is_not_paused()) { - auto miscEntity = entity->As(); - if (miscEntity == nullptr) + auto balloonPress = BalloonPressAction(entity->sprite_index); + GameActions::Execute(&balloonPress); + } + } + break; + case EntityType::Duck: + { + if (game_is_not_paused()) + { + auto duck = entity->As(); + if (duck != nullptr) { - break; - } - switch (miscEntity->SubType) - { - case MiscEntityType::Balloon: - { - auto balloonPress = BalloonPressAction(entity->sprite_index); - GameActions::Execute(&balloonPress); - } - break; - case MiscEntityType::Duck: - { - auto duck = entity->As(); - if (duck != nullptr) - { - duck_press(duck); - } - } - break; - default: - break; + duck_press(duck); } } - break; - case SpriteIdentifier::Litter: - case SpriteIdentifier::Null: + } + break; + default: break; } return true; @@ -270,7 +260,7 @@ InteractionInfo ViewportInteractionGetItemRight(const ScreenCoordsXY& screenCoor case ViewportInteractionItem::Entity: { auto sprite = info.Entity; - if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || sprite->sprite_identifier != SpriteIdentifier::Vehicle) + if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || sprite->Type != EntityType::Vehicle) { info.SpriteType = ViewportInteractionItem::None; return info; @@ -541,7 +531,7 @@ bool ViewportInteractionRightClick(const ScreenCoordsXY& screenCoords) case ViewportInteractionItem::Entity: { auto entity = info.Entity; - if (entity->sprite_identifier == SpriteIdentifier::Vehicle) + if (entity->Type == EntityType::Vehicle) { auto vehicle = entity->As(); if (vehicle == nullptr) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index fbff40169e..23482c5ea4 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -591,7 +591,7 @@ void reset_all_sprite_quadrant_placements() for (size_t i = 0; i < MAX_ENTITIES; i++) { auto* spr = GetEntity(i); - if (spr != nullptr && spr->sprite_identifier != SpriteIdentifier::Null) + if (spr != nullptr && spr->Type != EntityType::Null) { spr->MoveTo({ spr->x, spr->y, spr->z }); } diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp index ad0ce9a415..7d3808f392 100644 --- a/src/openrct2/GameStateSnapshots.cpp +++ b/src/openrct2/GameStateSnapshots.cpp @@ -50,7 +50,7 @@ struct GameStateSnapshot_t for (size_t i = 0; i < numSprites; i++) { auto entity = getEntity(i); - if (entity == nullptr || entity->misc.sprite_identifier == SpriteIdentifier::Null) + if (entity == nullptr || entity->misc.Type == EntityType::Null) continue; indexTable.push_back(static_cast(i)); } @@ -77,45 +77,40 @@ struct GameStateSnapshot_t } auto& sprite = *entity; - ds << sprite.misc.sprite_identifier; + ds << sprite.misc.Type; - switch (sprite.misc.sprite_identifier) + switch (sprite.misc.Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: ds << reinterpret_cast(sprite.vehicle); break; - case SpriteIdentifier::Peep: - ds << reinterpret_cast(sprite.peep); + case EntityType::Guest: + ds << reinterpret_cast(sprite.peep); break; - case SpriteIdentifier::Litter: + case EntityType::Staff: + ds << reinterpret_cast(sprite.peep); + break; + case EntityType::Litter: ds << reinterpret_cast(sprite.litter); break; - case SpriteIdentifier::Misc: - { - ds << sprite.misc.SubType; - switch (sprite.misc.SubType) - { - case MiscEntityType::MoneyEffect: - ds << reinterpret_cast(sprite.money_effect); - break; - case MiscEntityType::Balloon: - ds << reinterpret_cast(sprite.balloon); - break; - case MiscEntityType::Duck: - ds << reinterpret_cast(sprite.duck); - break; - case MiscEntityType::JumpingFountainWater: - ds << reinterpret_cast(sprite.jumping_fountain); - break; - case MiscEntityType::SteamParticle: - ds << reinterpret_cast(sprite.steam_particle); - break; - default: - break; - } + case EntityType::MoneyEffect: + ds << reinterpret_cast(sprite.money_effect); break; - } - case SpriteIdentifier::Null: + case EntityType::Balloon: + ds << reinterpret_cast(sprite.balloon); + break; + case EntityType::Duck: + ds << reinterpret_cast(sprite.duck); + break; + case EntityType::JumpingFountain: + ds << reinterpret_cast(sprite.jumping_fountain); + break; + case EntityType::SteamParticle: + ds << reinterpret_cast(sprite.steam_particle); + break; + case EntityType::Null: + break; + default: break; } } @@ -177,7 +172,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots for (auto& sprite : spriteList) { // By default they don't exist. - sprite.misc.sprite_identifier = SpriteIdentifier::Null; + sprite.misc.Type = EntityType::Null; } snapshot.SerialiseSprites([&spriteList](const size_t index) { return &spriteList[index]; }, MAX_ENTITIES, false); @@ -200,7 +195,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteDataCommon( const SpriteBase& spriteBase, const SpriteBase& spriteCmp, GameStateSpriteChange_t& changeData) const { - COMPARE_FIELD(SpriteBase, sprite_identifier); + COMPARE_FIELD(SpriteBase, Type); COMPARE_FIELD(SpriteBase, sprite_index); COMPARE_FIELD(SpriteBase, flags); COMPARE_FIELD(SpriteBase, x); @@ -408,6 +403,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteDataMoneyEffect( const MoneyEffect& spriteBase, const MoneyEffect& spriteCmp, GameStateSpriteChange_t& changeData) const { + CompareSpriteDataMisc(spriteBase, spriteCmp, changeData); COMPARE_FIELD(MoneyEffect, MoveDelay); COMPARE_FIELD(MoneyEffect, NumMovements); COMPARE_FIELD(MoneyEffect, Vertical); @@ -419,6 +415,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteDataSteamParticle( const SteamParticle& spriteBase, const SteamParticle& spriteCmp, GameStateSpriteChange_t& changeData) const { + CompareSpriteDataMisc(spriteBase, spriteCmp, changeData); COMPARE_FIELD(SteamParticle, time_to_move); } @@ -426,6 +423,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots const VehicleCrashParticle& spriteBase, const VehicleCrashParticle& spriteCmp, GameStateSpriteChange_t& changeData) const { + CompareSpriteDataMisc(spriteBase, spriteCmp, changeData); COMPARE_FIELD(VehicleCrashParticle, time_to_live); for (int i = 0; i < 2; i++) { @@ -442,6 +440,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteDataDuck(const Duck& spriteBase, const Duck& spriteCmp, GameStateSpriteChange_t& changeData) const { + CompareSpriteDataMisc(spriteBase, spriteCmp, changeData); COMPARE_FIELD(Duck, target_x); COMPARE_FIELD(Duck, target_y); COMPARE_FIELD(Duck, state); @@ -450,6 +449,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteDataBalloon( const Balloon& spriteBase, const Balloon& spriteCmp, GameStateSpriteChange_t& changeData) const { + CompareSpriteDataMisc(spriteBase, spriteCmp, changeData); COMPARE_FIELD(Balloon, popped); COMPARE_FIELD(Balloon, time_to_move); COMPARE_FIELD(Balloon, colour); @@ -458,6 +458,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteDataJumpingFountain( const JumpingFountain& spriteBase, const JumpingFountain& spriteCmp, GameStateSpriteChange_t& changeData) const { + CompareSpriteDataMisc(spriteBase, spriteCmp, changeData); COMPARE_FIELD(JumpingFountain, NumTicksAlive); COMPARE_FIELD(JumpingFountain, FountainFlags); COMPARE_FIELD(JumpingFountain, TargetX); @@ -475,55 +476,49 @@ struct GameStateSnapshots final : public IGameStateSnapshots void CompareSpriteData(const rct_sprite& spriteBase, const rct_sprite& spriteCmp, GameStateSpriteChange_t& changeData) const { CompareSpriteDataCommon(spriteBase.misc, spriteCmp.misc, changeData); - if (spriteBase.misc.sprite_identifier == spriteCmp.misc.sprite_identifier) + if (spriteBase.misc.Type == spriteCmp.misc.Type) { - switch (spriteBase.misc.sprite_identifier) + switch (spriteBase.misc.Type) { - case SpriteIdentifier::Peep: + case EntityType::Guest: CompareSpriteDataPeep(spriteBase.peep, spriteCmp.peep, changeData); break; - case SpriteIdentifier::Vehicle: + case EntityType::Staff: + CompareSpriteDataPeep(spriteBase.peep, spriteCmp.peep, changeData); + break; + case EntityType::Vehicle: CompareSpriteDataVehicle(spriteBase.vehicle, spriteCmp.vehicle, changeData); break; - case SpriteIdentifier::Litter: + case EntityType::Litter: CompareSpriteDataLitter(spriteBase.litter, spriteCmp.litter, changeData); break; - case SpriteIdentifier::Misc: - // This is not expected to happen, as misc sprites do not constitute sprite checksum - CompareSpriteDataMisc(spriteBase.misc, spriteCmp.misc, changeData); - switch (spriteBase.misc.SubType) - { - case MiscEntityType::SteamParticle: - CompareSpriteDataSteamParticle(spriteBase.steam_particle, spriteCmp.steam_particle, changeData); - break; - case MiscEntityType::MoneyEffect: - CompareSpriteDataMoneyEffect(spriteBase.money_effect, spriteCmp.money_effect, changeData); - break; - case MiscEntityType::CrashedVehicleParticle: - CompareSpriteDataVehicleCrashParticle( - spriteBase.crashed_vehicle_particle, spriteCmp.crashed_vehicle_particle, changeData); - break; - case MiscEntityType::ExplosionCloud: - case MiscEntityType::CrashSplash: - case MiscEntityType::ExplosionFlare: - // MiscEntity - break; - case MiscEntityType::JumpingFountainWater: - case MiscEntityType::JumpingFountainSnow: - CompareSpriteDataJumpingFountain( - spriteBase.jumping_fountain, spriteCmp.jumping_fountain, changeData); - break; - case MiscEntityType::Balloon: - CompareSpriteDataBalloon(spriteBase.balloon, spriteCmp.balloon, changeData); - break; - case MiscEntityType::Duck: - CompareSpriteDataDuck(spriteBase.duck, spriteCmp.duck, changeData); - break; - default: - break; - } + case EntityType::SteamParticle: + CompareSpriteDataSteamParticle(spriteBase.steam_particle, spriteCmp.steam_particle, changeData); break; - case SpriteIdentifier::Null: + case EntityType::MoneyEffect: + CompareSpriteDataMoneyEffect(spriteBase.money_effect, spriteCmp.money_effect, changeData); + break; + case EntityType::CrashedVehicleParticle: + CompareSpriteDataVehicleCrashParticle( + spriteBase.crashed_vehicle_particle, spriteCmp.crashed_vehicle_particle, changeData); + break; + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + CompareSpriteDataMisc(spriteBase.misc, spriteCmp.misc, changeData); + break; + case EntityType::JumpingFountain: + CompareSpriteDataJumpingFountain(spriteBase.jumping_fountain, spriteCmp.jumping_fountain, changeData); + break; + case EntityType::Balloon: + CompareSpriteDataBalloon(spriteBase.balloon, spriteCmp.balloon, changeData); + break; + case EntityType::Duck: + CompareSpriteDataDuck(spriteBase.duck, spriteCmp.duck, changeData); + break; + case EntityType::Null: + break; + default: break; } } @@ -548,30 +543,21 @@ struct GameStateSnapshots final : public IGameStateSnapshots const rct_sprite& spriteBase = spritesBase[i]; const rct_sprite& spriteCmp = spritesCmp[i]; - 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; + changeData.entityType = spriteBase.misc.Type; - if (spriteBase.misc.sprite_identifier == SpriteIdentifier::Null - && spriteCmp.misc.sprite_identifier != SpriteIdentifier::Null) + if (spriteBase.misc.Type == EntityType::Null && spriteCmp.misc.Type != EntityType::Null) { // Sprite was added. changeData.changeType = GameStateSpriteChange_t::ADDED; - changeData.spriteIdentifier = spriteCmp.misc.sprite_identifier; + changeData.entityType = spriteCmp.misc.Type; } - else if ( - spriteBase.misc.sprite_identifier != SpriteIdentifier::Null - && spriteCmp.misc.sprite_identifier == SpriteIdentifier::Null) + else if (spriteBase.misc.Type != EntityType::Null && spriteCmp.misc.Type == EntityType::Null) { // Sprite was removed. changeData.changeType = GameStateSpriteChange_t::REMOVED; - changeData.spriteIdentifier = spriteBase.misc.sprite_identifier; + changeData.entityType = spriteBase.misc.Type; } - else if ( - spriteBase.misc.sprite_identifier == SpriteIdentifier::Null - && spriteCmp.misc.sprite_identifier == SpriteIdentifier::Null) + else if (spriteBase.misc.Type == EntityType::Null && spriteCmp.misc.Type == EntityType::Null) { // Do nothing. changeData.changeType = GameStateSpriteChange_t::EQUAL; @@ -595,45 +581,40 @@ struct GameStateSnapshots final : public IGameStateSnapshots return res; } - static const char* GetSpriteIdentifierName(SpriteIdentifier spriteIdentifier, MiscEntityType miscIdentifier) + static const char* GetEntityTypeName(EntityType type) { - switch (spriteIdentifier) + switch (type) { - case SpriteIdentifier::Null: + case EntityType::Null: return "Null"; - case SpriteIdentifier::Peep: - return "Peep"; - case SpriteIdentifier::Vehicle: + case EntityType::Guest: + return "Guest"; + case EntityType::Staff: + return "Staff"; + case EntityType::Vehicle: return "Vehicle"; - case SpriteIdentifier::Litter: + case EntityType::Litter: return "Litter"; - case SpriteIdentifier::Misc: - switch (miscIdentifier) - { - case MiscEntityType::SteamParticle: - return "Misc: Steam Particle"; - case MiscEntityType::MoneyEffect: - return "Misc: Money effect"; - case MiscEntityType::CrashedVehicleParticle: - return "Misc: Crash Vehicle Particle"; - case MiscEntityType::ExplosionCloud: - return "Misc: Explosion Cloud"; - case MiscEntityType::CrashSplash: - return "Misc: Crash Splash"; - case MiscEntityType::ExplosionFlare: - return "Misc: Explosion Flare"; - case MiscEntityType::JumpingFountainWater: - return "Misc: Jumping fountain water"; - case MiscEntityType::Balloon: - return "Misc: Balloon"; - case MiscEntityType::Duck: - return "Misc: Duck"; - case MiscEntityType::JumpingFountainSnow: - return "Misc: Jumping fountain snow"; - default: - break; - } - return "Misc"; + case EntityType::SteamParticle: + return "Misc: Steam Particle"; + case EntityType::MoneyEffect: + return "Misc: Money effect"; + case EntityType::CrashedVehicleParticle: + return "Misc: Crash Vehicle Particle"; + case EntityType::ExplosionCloud: + return "Misc: Explosion Cloud"; + case EntityType::CrashSplash: + return "Misc: Crash Splash"; + case EntityType::ExplosionFlare: + return "Misc: Explosion Flare"; + case EntityType::JumpingFountain: + return "Misc: Jumping fountain"; + case EntityType::Balloon: + return "Misc: Balloon"; + case EntityType::Duck: + return "Misc: Duck"; + default: + break; } return "Unknown"; } @@ -662,7 +643,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots if (change.changeType == GameStateSpriteChange_t::EQUAL) continue; - const char* typeName = GetSpriteIdentifierName(change.spriteIdentifier, change.miscIdentifier); + const char* typeName = GetEntityTypeName(change.entityType); if (change.changeType == GameStateSpriteChange_t::ADDED) { diff --git a/src/openrct2/GameStateSnapshots.h b/src/openrct2/GameStateSnapshots.h index 383522a769..a155167313 100644 --- a/src/openrct2/GameStateSnapshots.h +++ b/src/openrct2/GameStateSnapshots.h @@ -39,8 +39,7 @@ struct GameStateSpriteChange_t }; uint8_t changeType; - SpriteIdentifier spriteIdentifier; - MiscEntityType miscIdentifier; + EntityType entityType; uint32_t spriteIndex; std::vector diffs; diff --git a/src/openrct2/actions/PeepPickupAction.cpp b/src/openrct2/actions/PeepPickupAction.cpp index 49b422cdcf..cc4f490975 100644 --- a/src/openrct2/actions/PeepPickupAction.cpp +++ b/src/openrct2/actions/PeepPickupAction.cpp @@ -48,7 +48,7 @@ GameActions::Result::Ptr PeepPickupAction::Query() const } auto* const peep = TryGetEntity(_spriteId); - if (!peep || peep->sprite_identifier != SpriteIdentifier::Peep) + if (peep == nullptr) { log_error("Failed to pick up peep for sprite %d", _spriteId); return MakeResult(GameActions::Status::InvalidParameters, STR_ERR_CANT_PLACE_PERSON_HERE); @@ -106,7 +106,7 @@ GameActions::Result::Ptr PeepPickupAction::Query() const GameActions::Result::Ptr PeepPickupAction::Execute() const { Peep* const peep = TryGetEntity(_spriteId); - if (!peep || peep->sprite_identifier != SpriteIdentifier::Peep) + if (peep == nullptr) { log_error("Failed to pick up peep for sprite %d", _spriteId); return MakeResult(GameActions::Status::InvalidParameters, STR_ERR_CANT_PLACE_PERSON_HERE); diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index 891ed9b7fa..3008675078 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1585,7 +1585,7 @@ static int32_t cc_mp_desync(InteractiveConsole& console, const arguments_t& argv for (int i = 0; i < MAX_ENTITIES; i++) { auto* sprite = GetEntity(i); - if (sprite == nullptr || sprite->sprite_identifier == SpriteIdentifier::Null) + if (sprite == nullptr || sprite->Type == EntityType::Null) continue; auto peep = sprite->As(); diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 42bee34297..81929de14f 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -668,7 +668,7 @@ void viewport_update_smart_sprite_follow(rct_window* window) window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; } - else if (entity->sprite_identifier == SpriteIdentifier::Peep) + else if (entity->Type == EntityType::Guest || entity->Type == EntityType::Staff) { Peep* peep = TryGetEntity(window->viewport_smart_follow_sprite); if (peep == nullptr) @@ -684,11 +684,11 @@ void viewport_update_smart_sprite_follow(rct_window* window) else if (peep->AssignedPeepType == PeepType::Staff) viewport_update_smart_staff_follow(window, peep); } - else if (entity->sprite_identifier == SpriteIdentifier::Vehicle) + else if (entity->Type == EntityType::Vehicle) { viewport_update_smart_vehicle_follow(window); } - else if (entity->sprite_identifier == SpriteIdentifier::Misc || entity->sprite_identifier == SpriteIdentifier::Litter) + else if (entity->Type != EntityType::Null) { window->viewport_focus_sprite.sprite_id = window->viewport_smart_follow_sprite; window->viewport_target_sprite = window->viewport_smart_follow_sprite; diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index bed98f680a..632e9ff58e 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -36,7 +36,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 "2" +#define NETWORK_STREAM_VERSION "3" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; diff --git a/src/openrct2/paint/sprite/Paint.Sprite.cpp b/src/openrct2/paint/sprite/Paint.Sprite.cpp index c27bb3c055..c3a4f41201 100644 --- a/src/openrct2/paint/sprite/Paint.Sprite.cpp +++ b/src/openrct2/paint/sprite/Paint.Sprite.cpp @@ -56,7 +56,7 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t continue; } } - else if (spr->sprite_identifier != SpriteIdentifier::Litter) + else if (spr->Type != EntityType::Litter) { continue; } @@ -100,9 +100,9 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t session->SpritePosition.y = spr->y; session->InteractionType = ViewportInteractionItem::Entity; - switch (spr->sprite_identifier) + switch (spr->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: vehicle_paint(session, spr->As(), image_direction); #ifdef __ENABLE_LIGHTFX__ if (lightfx_for_vehicles_is_available()) @@ -111,14 +111,23 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t } #endif break; - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: peep_paint(session, spr->As(), image_direction); break; - case SpriteIdentifier::Misc: + case EntityType::SteamParticle: + case EntityType::MoneyEffect: + case EntityType::CrashedVehicleParticle: + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + case EntityType::JumpingFountain: + case EntityType::Balloon: + case EntityType::Duck: // TODO: Update misc_paint to take a specific sprite type misc_paint(session, spr->As(), image_direction); break; - case SpriteIdentifier::Litter: + case EntityType::Litter: litter_paint(session, spr->As(), image_direction); break; default: diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp index 6b3f319790..04023261f4 100644 --- a/src/openrct2/peep/Guest.cpp +++ b/src/openrct2/peep/Guest.cpp @@ -232,8 +232,7 @@ bool loc_690FD0(Peep* peep, uint8_t* rideToView, uint8_t* rideSeatToView, TileEl template<> bool SpriteBase::Is() const { - auto peep = As(); - return peep && peep->AssignedPeepType == PeepType::Guest; + return Type == EntityType::Guest; } bool Guest::GuestHasValidXY() const diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index bc3732d941..5c73b231ae 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -318,7 +318,7 @@ const bool gSpriteTypeToSlowWalkMap[] = { template<> bool SpriteBase::Is() const { - return sprite_identifier == SpriteIdentifier::Peep; + return Type == EntityType::Guest || Type == EntityType::Staff; } uint8_t Peep::GetNextDirection() const @@ -411,7 +411,7 @@ void peep_update_all() { peep_128_tick_update(peep, i); // 128 tick can delete so double check its not deleted - if (peep->sprite_identifier == SpriteIdentifier::Peep) + if (peep->Type == EntityType::Guest) { peep->Update(); } @@ -430,7 +430,7 @@ void peep_update_all() { peep_128_tick_update(staff, i); // 128 tick can delete so double check its not deleted - if (staff->sprite_identifier == SpriteIdentifier::Peep) + if (staff->Type == EntityType::Staff) { staff->Update(); } @@ -839,7 +839,7 @@ void peep_sprite_remove(Peep* peep) window_close_by_number(WC_PEEP, peep->sprite_index); - window_close_by_number(WC_FIRE_PROMPT, EnumValue(peep->sprite_identifier)); + window_close_by_number(WC_FIRE_PROMPT, EnumValue(peep->Type)); // Needed for invalidations after sprite removal bool wasGuest = peep->AssignedPeepType == PeepType::Guest; diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index f52e0f8887..ef12d2a72f 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -74,8 +74,7 @@ const uint16_t MAX_LITTER_DISTANCE = 3 * COORDS_XY_STEP; template<> bool SpriteBase::Is() const { - auto peep = As(); - return peep && peep->AssignedPeepType == PeepType::Staff; + return Type == EntityType::Staff; } /** diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index e81b819e4b..e049646206 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1160,7 +1160,6 @@ private: uint8_t vehicleEntryIndex = RCT1::GetVehicleSubEntryIndex(src->vehicle_type); - dst->sprite_identifier = SpriteIdentifier::Vehicle; dst->ride = src->ride; dst->ride_subtype = RCTEntryIndexToOpenRCT2EntryIndex(ride->subtype); @@ -1412,7 +1411,6 @@ private: void ImportPeep(Peep* dst, rct1_peep* src) { - dst->sprite_identifier = SpriteIdentifier::Peep; // Peep vs. staff (including which kind) dst->SpriteType = RCT1::GetPeepSpriteType(src->sprite_type); dst->Action = static_cast(src->action); @@ -1658,7 +1656,6 @@ private: const auto* srcLitter = &sprite.litter; Litter* litter = CreateEntity(); - litter->sprite_identifier = srcLitter->sprite_identifier; litter->SubType = LitterType(srcLitter->type); litter->x = srcLitter->x; @@ -1726,7 +1723,6 @@ private: log_warning("SV4 has too many misc entities. No more misc entities will be imported!"); break; } - dst->sprite_identifier = src->sprite_identifier; dst->SubType = MiscEntityType(src->type); dst->flags = src->flags; dst->sprite_direction = src->sprite_direction; diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index ccbc07497b..0c7bb0af68 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -990,9 +990,9 @@ void S6Exporter::RebuildEntityLinks() constexpr RCT12EntityLinkListOffset GetRCT2LinkListOffset(const SpriteBase* src) { RCT12EntityLinkListOffset output = RCT12EntityLinkListOffset::Free; - switch (src->sprite_identifier) + switch (src->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: { auto veh = src->As(); if (veh && veh->IsHead()) @@ -1005,13 +1005,22 @@ constexpr RCT12EntityLinkListOffset GetRCT2LinkListOffset(const SpriteBase* src) } } break; - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: output = RCT12EntityLinkListOffset::Peep; break; - case SpriteIdentifier::Misc: + case EntityType::SteamParticle: + case EntityType::MoneyEffect: + case EntityType::CrashedVehicleParticle: + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + case EntityType::JumpingFountain: + case EntityType::Balloon: + case EntityType::Duck: output = RCT12EntityLinkListOffset::Misc; break; - case SpriteIdentifier::Litter: + case EntityType::Litter: output = RCT12EntityLinkListOffset::Litter; break; default: @@ -1020,9 +1029,41 @@ constexpr RCT12EntityLinkListOffset GetRCT2LinkListOffset(const SpriteBase* src) return output; } +constexpr SpriteIdentifier GetRCT2SpriteIdentifier(const SpriteBase* src) +{ + SpriteIdentifier output = SpriteIdentifier::Null; + switch (src->Type) + { + case EntityType::Vehicle: + output = SpriteIdentifier::Vehicle; + break; + case EntityType::Guest: + case EntityType::Staff: + output = SpriteIdentifier::Peep; + break; + case EntityType::SteamParticle: + case EntityType::MoneyEffect: + case EntityType::CrashedVehicleParticle: + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + case EntityType::JumpingFountain: + case EntityType::Balloon: + case EntityType::Duck: + output = SpriteIdentifier::Misc; + break; + case EntityType::Litter: + output = SpriteIdentifier::Litter; + break; + default: + break; + } + return output; +} + void S6Exporter::ExportEntityCommonProperties(RCT12SpriteBase* dst, const SpriteBase* src) { - dst->sprite_identifier = src->sprite_identifier; + dst->sprite_identifier = GetRCT2SpriteIdentifier(src); dst->linked_list_type_offset = GetRCT2LinkListOffset(src); dst->next_in_quadrant = SPRITE_INDEX_NULL; dst->sprite_height_negative = src->sprite_height_negative; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index e73f8dd97e..2f73fea4c1 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1678,9 +1678,72 @@ public: dst->creationTick = src->creationTick; } + constexpr EntityType GetEntityTypeFromRCT2Sprite(const RCT12SpriteBase* src) + { + EntityType output = EntityType::Null; + switch (src->sprite_identifier) + { + case SpriteIdentifier::Vehicle: + output = EntityType::Vehicle; + break; + case SpriteIdentifier::Peep: + if (PeepType(static_cast(src)->peep_type) == PeepType::Guest) + { + output = EntityType::Guest; + } + else + { + output = EntityType::Staff; + } + break; + case SpriteIdentifier::Misc: + + switch (MiscEntityType(src->type)) + { + case MiscEntityType::SteamParticle: + output = EntityType::SteamParticle; + break; + case MiscEntityType::MoneyEffect: + output = EntityType::MoneyEffect; + break; + case MiscEntityType::CrashedVehicleParticle: + output = EntityType::CrashedVehicleParticle; + break; + case MiscEntityType::ExplosionCloud: + output = EntityType::ExplosionCloud; + break; + case MiscEntityType::CrashSplash: + output = EntityType::CrashSplash; + break; + case MiscEntityType::ExplosionFlare: + output = EntityType::ExplosionFlare; + break; + case MiscEntityType::JumpingFountainWater: + case MiscEntityType::JumpingFountainSnow: + output = EntityType::JumpingFountain; + break; + case MiscEntityType::Balloon: + output = EntityType::Balloon; + break; + case MiscEntityType::Duck: + output = EntityType::Duck; + break; + default: + break; + } + break; + case SpriteIdentifier::Litter: + output = EntityType::Litter; + break; + default: + break; + } + return output; + } + void ImportSpriteCommonProperties(SpriteBase* dst, const RCT12SpriteBase* src) { - dst->sprite_identifier = src->sprite_identifier; + dst->Type = GetEntityTypeFromRCT2Sprite(src); dst->sprite_height_negative = src->sprite_height_negative; dst->sprite_index = src->sprite_index; dst->flags = src->flags; diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index db3d3b9b70..ed8680f580 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -734,7 +734,7 @@ static const struct template<> bool SpriteBase::Is() const { - return sprite_identifier == SpriteIdentifier::Vehicle; + return Type == EntityType::Vehicle; } static bool vehicle_move_info_valid( diff --git a/src/openrct2/scripting/ScEntity.hpp b/src/openrct2/scripting/ScEntity.hpp index d5cb5aa1aa..210a42b69e 100644 --- a/src/openrct2/scripting/ScEntity.hpp +++ b/src/openrct2/scripting/ScEntity.hpp @@ -51,50 +51,37 @@ namespace OpenRCT2::Scripting auto entity = GetEntity(); if (entity != nullptr) { - switch (entity->sprite_identifier) + switch (entity->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: return "car"; - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: return "peep"; - case SpriteIdentifier::Misc: - { - auto misc = entity->As(); - if (misc == nullptr) - { - return "unknown"; - } - switch (misc->SubType) - { - case MiscEntityType::SteamParticle: - return "steam_particle"; - case MiscEntityType::MoneyEffect: - return "money_effect"; - case MiscEntityType::CrashedVehicleParticle: - return "crashed_vehicle_particle"; - case MiscEntityType::ExplosionCloud: - return "explosion_cloud"; - case MiscEntityType::CrashSplash: - return "crash_splash"; - case MiscEntityType::ExplosionFlare: - return "explosion_flare"; - case MiscEntityType::JumpingFountainWater: - return "jumping_fountain_water"; - case MiscEntityType::Balloon: - return "balloon"; - case MiscEntityType::Duck: - return "duck"; - case MiscEntityType::JumpingFountainSnow: - return "jumping_fountain_snow"; - default: - break; - } - } - break; - case SpriteIdentifier::Litter: + case EntityType::SteamParticle: + return "steam_particle"; + case EntityType::MoneyEffect: + return "money_effect"; + case EntityType::CrashedVehicleParticle: + return "crashed_vehicle_particle"; + case EntityType::ExplosionCloud: + return "explosion_cloud"; + case EntityType::CrashSplash: + return "crash_splash"; + case EntityType::ExplosionFlare: + return "explosion_flare"; + case EntityType::Balloon: + return "balloon"; + case EntityType::Duck: + return "duck"; + case EntityType::JumpingFountain: + return "jumping_fountain"; + case EntityType::Litter: return "litter"; - case SpriteIdentifier::Null: + case EntityType::Null: return "unknown"; + default: + break; } } return "unknown"; @@ -155,17 +142,18 @@ namespace OpenRCT2::Scripting if (entity != nullptr) { entity->Invalidate(); - switch (entity->sprite_identifier) + switch (entity->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: duk_error(ctx, DUK_ERR_ERROR, "Removing a vehicle is currently unsupported."); break; - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: { - auto peep = static_cast(entity); + auto peep = entity->As(); // We can't remove a single peep from a ride at the moment as this can cause complications with the // vehicle car having an unsupported peep capacity. - if (peep->State == PeepState::OnRide || peep->State == PeepState::EnteringRide) + if (peep == nullptr || peep->State == PeepState::OnRide || peep->State == PeepState::EnteringRide) { duk_error(ctx, DUK_ERR_ERROR, "Removing a peep that is on a ride is currently unsupported."); } @@ -175,11 +163,21 @@ namespace OpenRCT2::Scripting } break; } - case SpriteIdentifier::Misc: - case SpriteIdentifier::Litter: + case EntityType::SteamParticle: + case EntityType::MoneyEffect: + case EntityType::CrashedVehicleParticle: + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + case EntityType::JumpingFountain: + case EntityType::Balloon: + case EntityType::Duck: + case EntityType::Litter: sprite_remove(entity); break; - case SpriteIdentifier::Null: + case EntityType::Null: + break; + default: break; } } diff --git a/src/openrct2/scripting/ScMap.hpp b/src/openrct2/scripting/ScMap.hpp index 04d3fadba8..15543290a6 100644 --- a/src/openrct2/scripting/ScMap.hpp +++ b/src/openrct2/scripting/ScMap.hpp @@ -89,7 +89,7 @@ namespace OpenRCT2::Scripting { auto spriteId = static_cast(id); auto sprite = GetEntity(spriteId); - if (sprite != nullptr && sprite->sprite_identifier != SpriteIdentifier::Null) + if (sprite != nullptr && sprite->Type != EntityType::Null) { return GetEntityAsDukValue(sprite); } @@ -169,17 +169,14 @@ namespace OpenRCT2::Scripting DukValue GetEntityAsDukValue(const SpriteBase* sprite) const { auto spriteId = sprite->sprite_index; - switch (sprite->sprite_identifier) + switch (sprite->Type) { - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: return GetObjectAsDukValue(_context, std::make_shared(spriteId)); - case SpriteIdentifier::Peep: - { - if (sprite->Is()) - return GetObjectAsDukValue(_context, std::make_shared(spriteId)); - else - return GetObjectAsDukValue(_context, std::make_shared(spriteId)); - } + case EntityType::Staff: + return GetObjectAsDukValue(_context, std::make_shared(spriteId)); + case EntityType::Guest: + return GetObjectAsDukValue(_context, std::make_shared(spriteId)); default: return GetObjectAsDukValue(_context, std::make_shared(spriteId)); } diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 00f167150c..5411420390 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -44,7 +44,7 @@ using namespace OpenRCT2; using namespace OpenRCT2::Scripting; -static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 24; +static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 25; struct ExpressionStringifier final { diff --git a/src/openrct2/world/Balloon.cpp b/src/openrct2/world/Balloon.cpp index 7f909027b2..d2fe6239a7 100644 --- a/src/openrct2/world/Balloon.cpp +++ b/src/openrct2/world/Balloon.cpp @@ -16,8 +16,7 @@ template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::Balloon; + return Type == EntityType::Balloon; } void Balloon::Update() diff --git a/src/openrct2/world/Duck.cpp b/src/openrct2/world/Duck.cpp index 267c1bf132..034a025f82 100644 --- a/src/openrct2/world/Duck.cpp +++ b/src/openrct2/world/Duck.cpp @@ -68,8 +68,7 @@ static constexpr const uint8_t * DuckAnimations[] = template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::Duck; + return Type == EntityType::Duck; } bool Duck::IsFlying() diff --git a/src/openrct2/world/Fountain.cpp b/src/openrct2/world/Fountain.cpp index 365021c8ea..01b7f65d66 100644 --- a/src/openrct2/world/Fountain.cpp +++ b/src/openrct2/world/Fountain.cpp @@ -72,9 +72,7 @@ const uint8_t _fountainPatternFlags[] = { template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc - && (misc->SubType == MiscEntityType::JumpingFountainSnow || misc->SubType == MiscEntityType::JumpingFountainWater); + return Type == EntityType::JumpingFountain; } void JumpingFountain::StartAnimation(const int32_t newType, const CoordsXY& newLoc, const TileElement* tileElement) diff --git a/src/openrct2/world/MoneyEffect.cpp b/src/openrct2/world/MoneyEffect.cpp index 6449f08ba5..fca0c2a082 100644 --- a/src/openrct2/world/MoneyEffect.cpp +++ b/src/openrct2/world/MoneyEffect.cpp @@ -20,8 +20,7 @@ static constexpr const CoordsXY _moneyEffectMoveOffset[] = { { 1, -1 }, { 1, 1 } template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::MoneyEffect; + return Type == EntityType::MoneyEffect; } /** diff --git a/src/openrct2/world/Particle.cpp b/src/openrct2/world/Particle.cpp index e01d2dfcb5..420eb13afc 100644 --- a/src/openrct2/world/Particle.cpp +++ b/src/openrct2/world/Particle.cpp @@ -16,14 +16,12 @@ template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::CrashedVehicleParticle; + return Type == EntityType::CrashedVehicleParticle; } template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::CrashSplash; + return Type == EntityType::CrashSplash; } /** * diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index a3f12d6341..f0747d4c95 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -75,30 +75,41 @@ template<> bool SpriteBase::Is() const template<> bool SpriteBase::Is() const { - return sprite_identifier == SpriteIdentifier::Litter; + return Type == EntityType::Litter; } template<> bool SpriteBase::Is() const { - return sprite_identifier == SpriteIdentifier::Misc; + switch (Type) + { + case EntityType::SteamParticle: + case EntityType::MoneyEffect: + case EntityType::CrashedVehicleParticle: + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + case EntityType::JumpingFountain: + case EntityType::Balloon: + case EntityType::Duck: + return true; + default: + return false; + } } template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::SteamParticle; + return Type == EntityType::SteamParticle; } template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::ExplosionFlare; + return Type == EntityType::ExplosionFlare; } template<> bool SpriteBase::Is() const { - auto* misc = As(); - return misc && misc->SubType == MiscEntityType::ExplosionCloud; + return Type == EntityType::ExplosionCloud; } uint16_t GetEntityListCount(EntityType type) @@ -152,43 +163,29 @@ void SpriteBase::Invalidate() return; int32_t maxZoom = 0; - switch (sprite_identifier) + switch (Type) { - case SpriteIdentifier::Vehicle: - case SpriteIdentifier::Peep: + case EntityType::Vehicle: + case EntityType::Guest: + case EntityType::Staff: maxZoom = 2; break; - case SpriteIdentifier::Misc: - { - auto* misc = As(); - if (misc == nullptr) - { - return; - } - switch (misc->SubType) - { - case MiscEntityType::CrashedVehicleParticle: - case MiscEntityType::JumpingFountainWater: - case MiscEntityType::JumpingFountainSnow: - maxZoom = 0; - break; - case MiscEntityType::Duck: - maxZoom = 1; - break; - case MiscEntityType::SteamParticle: - case MiscEntityType::MoneyEffect: - case MiscEntityType::ExplosionCloud: - case MiscEntityType::CrashSplash: - case MiscEntityType::ExplosionFlare: - case MiscEntityType::Balloon: - maxZoom = 2; - break; - default: - break; - } - } - break; - case SpriteIdentifier::Litter: + case EntityType::CrashedVehicleParticle: + case EntityType::JumpingFountain: + maxZoom = 0; + break; + case EntityType::Duck: + maxZoom = 1; + break; + case EntityType::SteamParticle: + case EntityType::MoneyEffect: + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + case EntityType::Balloon: + maxZoom = 2; + break; + case EntityType::Litter: maxZoom = 0; break; default: @@ -198,71 +195,6 @@ void SpriteBase::Invalidate() viewports_invalidate(sprite_left, sprite_top, sprite_right, sprite_bottom, maxZoom); } -constexpr EntityType EntityBaseToEntityType(const SpriteBase& base) -{ - EntityType type = EntityType::Count; - switch (base.sprite_identifier) - { - case SpriteIdentifier::Vehicle: - type = EntityType::Vehicle; - break; - case SpriteIdentifier::Peep: - if (base.Is()) - { - type = EntityType::Guest; - } - else - { - type = EntityType::Staff; - } - break; - case SpriteIdentifier::Misc: - if (base.Is()) - { - type = EntityType::SteamParticle; - } - else if (base.Is()) - { - type = EntityType::MoneyEffect; - } - else if (base.Is()) - { - type = EntityType::CrashedVehicleParticle; - } - else if (base.Is()) - { - type = EntityType::ExplosionCloud; - } - else if (base.Is()) - { - type = EntityType::CrashSplash; - } - else if (base.Is()) - { - type = EntityType::ExplosionFlare; - } - else if (base.Is()) - { - type = EntityType::JumpingFountain; - } - else if (base.Is()) - { - type = EntityType::Balloon; - } - else if (base.Is()) - { - type = EntityType::Duck; - } - break; - case SpriteIdentifier::Litter: - type = EntityType::Litter; - break; - default: - break; - } - return type; -} - constexpr SpriteIdentifier EntityTypeToSpriteIdentifier(const EntityType type) { switch (type) @@ -285,6 +217,7 @@ constexpr SpriteIdentifier EntityTypeToSpriteIdentifier(const EntityType type) case EntityType::Balloon: case EntityType::Duck: return SpriteIdentifier::Misc; + case EntityType::Null: case EntityType::Count: return SpriteIdentifier::Null; } @@ -302,14 +235,13 @@ void RebuildEntityLists() for (auto& ent : _spriteList) { - if (ent.misc.sprite_identifier == SpriteIdentifier::Null) + if (ent.misc.Type == EntityType::Null) { _freeIdList.push_back(ent.misc.sprite_index); } else { - auto listId = EntityBaseToEntityType(ent.misc); - gEntityLists[EnumValue(listId)].push_back(ent.misc.sprite_index); + gEntityLists[EnumValue(ent.misc.Type)].push_back(ent.misc.sprite_index); } } // List needs to be back to front to simplify removing @@ -337,7 +269,7 @@ void reset_sprite_list() continue; } - spr->sprite_identifier = SpriteIdentifier::Null; + spr->Type = EntityType::Null; spr->sprite_index = i; _spriteFlashingList[i] = false; @@ -363,7 +295,7 @@ void reset_sprite_spatial_index() for (size_t i = 0; i < MAX_ENTITIES; i++) { auto* spr = GetEntity(i); - if (spr != nullptr && spr->sprite_identifier != SpriteIdentifier::Null) + if (spr != nullptr && spr->Type != EntityType::Null) { SpriteSpatialInsert(spr, { spr->x, spr->y }); } @@ -394,8 +326,7 @@ rct_sprite_checksum sprite_checksum() { // TODO create a way to copy only the specific type auto sprite = GetEntity(i); - if (sprite != nullptr && sprite->sprite_identifier != SpriteIdentifier::Null - && sprite->sprite_identifier != SpriteIdentifier::Misc) + if (sprite != nullptr && sprite->Type != EntityType::Null && !sprite->Is()) { // Upconvert it to rct_sprite so that the full size is copied. auto copy = *reinterpret_cast(sprite); @@ -447,7 +378,7 @@ static void sprite_reset(SpriteBase* sprite) std::memset(sprite, 0, sizeof(rct_sprite)); sprite->sprite_index = sprite_index; - sprite->sprite_identifier = SpriteIdentifier::Null; + sprite->Type = EntityType::Null; } /** @@ -472,8 +403,7 @@ void sprite_clear_all_unused() static constexpr uint16_t MAX_MISC_SPRITES = 300; static void AddToEntityList(SpriteBase* entity) { - auto listId = EntityBaseToEntityType(*entity); - auto& list = gEntityLists[EnumValue(listId)]; + auto& list = gEntityLists[EnumValue(entity->Type)]; // Entity list must be in sprite_index order to prevent desync issues list.insert(std::lower_bound(std::begin(list), std::end(list), entity->sprite_index), entity->sprite_index); } @@ -486,8 +416,7 @@ static void AddToFreeList(uint16_t index) static void RemoveFromEntityList(SpriteBase* entity) { - auto listId = EntityBaseToEntityType(*entity); - auto& list = gEntityLists[EnumValue(listId)]; + auto& list = gEntityLists[EnumValue(entity->Type)]; auto ptr = std::lower_bound(std::begin(list), std::end(list), entity->sprite_index); if (ptr != std::end(list) && *ptr == entity->sprite_index) { @@ -507,70 +436,6 @@ uint16_t GetMiscEntityCount() return count; } -static void SetLegacyFields(SpriteBase& base, EntityType type) -{ - auto spriteIdentifier = EntityTypeToSpriteIdentifier(type); - base.sprite_identifier = spriteIdentifier; - switch (spriteIdentifier) - { - case SpriteIdentifier::Peep: - { - Peep* peep = base.As(); - if (peep != nullptr) - { - if (type == EntityType::Guest) - { - peep->AssignedPeepType = PeepType::Guest; - } - else - { - peep->AssignedPeepType = PeepType::Staff; - } - } - break; - } - case SpriteIdentifier::Misc: - { - MiscEntity* misc = base.As(); - switch (type) - { - case EntityType::SteamParticle: - misc->SubType = MiscEntityType::SteamParticle; - break; - case EntityType::MoneyEffect: - misc->SubType = MiscEntityType::MoneyEffect; - break; - case EntityType::CrashedVehicleParticle: - misc->SubType = MiscEntityType::CrashedVehicleParticle; - break; - case EntityType::ExplosionCloud: - misc->SubType = MiscEntityType::ExplosionCloud; - break; - case EntityType::CrashSplash: - misc->SubType = MiscEntityType::CrashSplash; - break; - case EntityType::ExplosionFlare: - misc->SubType = MiscEntityType::ExplosionFlare; - break; - case EntityType::JumpingFountain: - misc->SubType = MiscEntityType::JumpingFountainWater; - break; - case EntityType::Balloon: - misc->SubType = MiscEntityType::Balloon; - break; - case EntityType::Duck: - misc->SubType = MiscEntityType::Duck; - break; - default: - break; - } - break; - } - default: - break; - } -} - rct_sprite* create_sprite(EntityType type) { if (_freeIdList.size() == 0) @@ -603,7 +468,7 @@ rct_sprite* create_sprite(EntityType type) // may contain garbage and cause a desync later on. sprite_reset(sprite); - SetLegacyFields(*sprite, type); + sprite->Type = type; AddToEntityList(sprite); sprite->x = LOCATION_NULL; @@ -1009,7 +874,7 @@ void EntityTweener::PostTick() void EntityTweener::RemoveEntity(SpriteBase* entity) { - if (entity->sprite_identifier != SpriteIdentifier::Peep && entity->sprite_identifier != SpriteIdentifier::Vehicle) + if (!entity->Is() && !entity->Is()) { // Only peeps and vehicles are tweened, bail if type is incorrect. return; diff --git a/src/openrct2/world/SpriteBase.h b/src/openrct2/world/SpriteBase.h index 4e997ca6bc..75231355ec 100644 --- a/src/openrct2/world/SpriteBase.h +++ b/src/openrct2/world/SpriteBase.h @@ -3,7 +3,6 @@ #include "../common.h" struct CoordsXYZ; -enum class SpriteIdentifier : uint8_t; enum class EntityType : uint8_t { @@ -20,12 +19,13 @@ enum class EntityType : uint8_t JumpingFountain, Balloon, Duck, - Count + Count, + Null = 255 }; struct SpriteBase { - SpriteIdentifier sprite_identifier; + EntityType Type; // Height from centre of sprite to bottom uint8_t sprite_height_negative; uint16_t sprite_index; diff --git a/test/testpaint/Compat.cpp b/test/testpaint/Compat.cpp index e819989d88..a6b7bf93d8 100644 --- a/test/testpaint/Compat.cpp +++ b/test/testpaint/Compat.cpp @@ -154,18 +154,17 @@ template<> bool SpriteBase::Is() const template<> bool SpriteBase::Is() const { - return sprite_identifier == SpriteIdentifier::Peep; + return Type == EntityType::Guest || Type == EntityType::Staff; } template<> bool SpriteBase::Is() const { - auto peep = As(); - return peep && peep->AssignedPeepType == PeepType::Guest; + return Type == EntityType::Guest; } template<> bool SpriteBase::Is() const { - return sprite_identifier == SpriteIdentifier::Vehicle; + return Type == EntityType::Vehicle; } SpriteBase* get_sprite(size_t sprite_idx) diff --git a/test/tests/S6ImportExportTests.cpp b/test/tests/S6ImportExportTests.cpp index 1efc50d4cf..a3e9ab94f7 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].misc.sprite_identifier = SpriteIdentifier::Null; + res->sprites[spriteIdx].misc.Type = EntityType::Null; else res->sprites[spriteIdx] = *sprite; } @@ -130,7 +130,7 @@ 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(sprite_index); COMPARE_FIELD(flags); COMPARE_FIELD(x); @@ -347,11 +347,13 @@ static void CompareSpriteDataLitter(const Litter& left, const Litter& right) static void CompareSpriteDataSteamParticle(const SteamParticle& left, const SteamParticle& right) { + COMPARE_FIELD(SubType); COMPARE_FIELD(time_to_move); } static void CompareSpriteDataMoneyEffect(const MoneyEffect& left, const MoneyEffect& right) { + COMPARE_FIELD(SubType); COMPARE_FIELD(MoveDelay); COMPARE_FIELD(NumMovements); COMPARE_FIELD(Vertical); @@ -362,6 +364,7 @@ static void CompareSpriteDataMoneyEffect(const MoneyEffect& left, const MoneyEff static void CompareSpriteDataCrashedVehicleParticle(const VehicleCrashParticle& left, const VehicleCrashParticle& right) { + COMPARE_FIELD(SubType); COMPARE_FIELD(time_to_live); for (size_t i = 0; i < std::size(left.colour); i++) { @@ -378,6 +381,7 @@ static void CompareSpriteDataCrashedVehicleParticle(const VehicleCrashParticle& static void CompareSpriteDataJumpingFountain(const JumpingFountain& left, const JumpingFountain& right) { + COMPARE_FIELD(SubType); COMPARE_FIELD(NumTicksAlive); COMPARE_FIELD(FountainFlags); COMPARE_FIELD(TargetX); @@ -387,6 +391,7 @@ static void CompareSpriteDataJumpingFountain(const JumpingFountain& left, const static void CompareSpriteDataBalloon(const Balloon& left, const Balloon& right) { + COMPARE_FIELD(SubType); COMPARE_FIELD(popped); COMPARE_FIELD(time_to_move); COMPARE_FIELD(colour); @@ -394,6 +399,7 @@ static void CompareSpriteDataBalloon(const Balloon& left, const Balloon& right) static void CompareSpriteDataDuck(const Duck& left, const Duck& right) { + COMPARE_FIELD(SubType); COMPARE_FIELD(target_x); COMPARE_FIELD(target_y); COMPARE_FIELD(state); @@ -402,47 +408,46 @@ static void CompareSpriteDataDuck(const Duck& left, const Duck& right) static void CompareSpriteData(const rct_sprite& left, const rct_sprite& right) { CompareSpriteDataCommon(left.misc, right.misc); - if (left.misc.sprite_identifier == right.misc.sprite_identifier) + if (left.misc.Type == right.misc.Type) { - switch (left.misc.sprite_identifier) + switch (left.misc.Type) { - case SpriteIdentifier::Peep: + case EntityType::Guest: + case EntityType::Staff: CompareSpriteDataPeep(left.peep, right.peep); break; - case SpriteIdentifier::Vehicle: + case EntityType::Vehicle: CompareSpriteDataVehicle(left.vehicle, right.vehicle); break; - case SpriteIdentifier::Litter: + case EntityType::Litter: CompareSpriteDataLitter(left.litter, right.litter); break; - case SpriteIdentifier::Misc: - COMPARE_FIELD(misc.SubType); - switch (left.misc.SubType) - { - case MiscEntityType::SteamParticle: - CompareSpriteDataSteamParticle(left.steam_particle, right.steam_particle); - break; - case MiscEntityType::MoneyEffect: - CompareSpriteDataMoneyEffect(left.money_effect, right.money_effect); - break; - case MiscEntityType::CrashedVehicleParticle: - CompareSpriteDataCrashedVehicleParticle(left.crashed_vehicle_particle, right.crashed_vehicle_particle); - break; - case MiscEntityType::JumpingFountainSnow: - case MiscEntityType::JumpingFountainWater: - CompareSpriteDataJumpingFountain(left.jumping_fountain, right.jumping_fountain); - break; - case MiscEntityType::Balloon: - CompareSpriteDataBalloon(left.balloon, right.balloon); - break; - case MiscEntityType::Duck: - CompareSpriteDataDuck(left.duck, right.duck); - break; - default: - break; - } + case EntityType::SteamParticle: + CompareSpriteDataSteamParticle(left.steam_particle, right.steam_particle); break; - case SpriteIdentifier::Null: + case EntityType::MoneyEffect: + CompareSpriteDataMoneyEffect(left.money_effect, right.money_effect); + break; + case EntityType::CrashedVehicleParticle: + CompareSpriteDataCrashedVehicleParticle(left.crashed_vehicle_particle, right.crashed_vehicle_particle); + break; + case EntityType::JumpingFountain: + CompareSpriteDataJumpingFountain(left.jumping_fountain, right.jumping_fountain); + break; + case EntityType::Balloon: + CompareSpriteDataBalloon(left.balloon, right.balloon); + break; + case EntityType::Duck: + CompareSpriteDataDuck(left.duck, right.duck); + break; + case EntityType::ExplosionCloud: + case EntityType::CrashSplash: + case EntityType::ExplosionFlare: + COMPARE_FIELD(misc.SubType); + break; + case EntityType::Null: + break; + default: break; } } @@ -462,8 +467,8 @@ static void CompareStates( for (size_t spriteIdx = 0; spriteIdx < MAX_ENTITIES; ++spriteIdx) { - if (importedState->sprites[spriteIdx].misc.sprite_identifier == SpriteIdentifier::Null - && exportedState->sprites[spriteIdx].misc.sprite_identifier == SpriteIdentifier::Null) + if (importedState->sprites[spriteIdx].misc.Type == EntityType::Null + && exportedState->sprites[spriteIdx].misc.Type == EntityType::Null) { continue; }