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
This commit is contained in:
Duncan 2021-03-17 08:04:41 +00:00 committed by GitHub
parent 6ec379cd0e
commit df7a284822
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 435 additions and 501 deletions

View File

@ -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")

View File

@ -48,8 +48,8 @@
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip</ObjectsUrl>
<ObjectsSha1>c38af45d51a6e440386180feacf76c64720b6ac5</ObjectsSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.32/replays.zip</ReplaysUrl>
<ReplaysSha1>45843591A8C6739CA1D60899B7E54FC0792EF896</ReplaysSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.33/replays.zip</ReplaysUrl>
<ReplaysSha1>6D600B756B49461CEA4F8206EA18C17AA6F2AF7B</ReplaysSha1>
</PropertyGroup>
<ItemGroup>

View File

@ -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<Vehicle>();
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<Peep>();
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<MiscEntity>();
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<Duck>();
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<Duck>();
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<Vehicle>();
if (vehicle == nullptr)

View File

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

View File

@ -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<uint32_t>(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<uint8_t(&)[sizeof(Vehicle)]>(sprite.vehicle);
break;
case SpriteIdentifier::Peep:
ds << reinterpret_cast<uint8_t(&)[sizeof(Peep)]>(sprite.peep);
case EntityType::Guest:
ds << reinterpret_cast<uint8_t(&)[sizeof(Guest)]>(sprite.peep);
break;
case SpriteIdentifier::Litter:
case EntityType::Staff:
ds << reinterpret_cast<uint8_t(&)[sizeof(Staff)]>(sprite.peep);
break;
case EntityType::Litter:
ds << reinterpret_cast<uint8_t(&)[sizeof(Litter)]>(sprite.litter);
break;
case SpriteIdentifier::Misc:
{
ds << sprite.misc.SubType;
switch (sprite.misc.SubType)
{
case MiscEntityType::MoneyEffect:
ds << reinterpret_cast<uint8_t(&)[sizeof(MoneyEffect)]>(sprite.money_effect);
break;
case MiscEntityType::Balloon:
ds << reinterpret_cast<uint8_t(&)[sizeof(Balloon)]>(sprite.balloon);
break;
case MiscEntityType::Duck:
ds << reinterpret_cast<uint8_t(&)[sizeof(Duck)]>(sprite.duck);
break;
case MiscEntityType::JumpingFountainWater:
ds << reinterpret_cast<uint8_t(&)[sizeof(JumpingFountain)]>(sprite.jumping_fountain);
break;
case MiscEntityType::SteamParticle:
ds << reinterpret_cast<uint8_t(&)[sizeof(SteamParticle)]>(sprite.steam_particle);
break;
default:
break;
}
case EntityType::MoneyEffect:
ds << reinterpret_cast<uint8_t(&)[sizeof(MoneyEffect)]>(sprite.money_effect);
break;
}
case SpriteIdentifier::Null:
case EntityType::Balloon:
ds << reinterpret_cast<uint8_t(&)[sizeof(Balloon)]>(sprite.balloon);
break;
case EntityType::Duck:
ds << reinterpret_cast<uint8_t(&)[sizeof(Duck)]>(sprite.duck);
break;
case EntityType::JumpingFountain:
ds << reinterpret_cast<uint8_t(&)[sizeof(JumpingFountain)]>(sprite.jumping_fountain);
break;
case EntityType::SteamParticle:
ds << reinterpret_cast<uint8_t(&)[sizeof(SteamParticle)]>(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)
{

View File

@ -39,8 +39,7 @@ struct GameStateSpriteChange_t
};
uint8_t changeType;
SpriteIdentifier spriteIdentifier;
MiscEntityType miscIdentifier;
EntityType entityType;
uint32_t spriteIndex;
std::vector<Diff_t> diffs;

View File

@ -48,7 +48,7 @@ GameActions::Result::Ptr PeepPickupAction::Query() const
}
auto* const peep = TryGetEntity<Peep>(_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<Peep>(_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);

View File

@ -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<Peep>();

View File

@ -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<Peep>(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;

View File

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

View File

@ -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<Vehicle>(), 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<Peep>(), 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<MiscEntity>(), image_direction);
break;
case SpriteIdentifier::Litter:
case EntityType::Litter:
litter_paint(session, spr->As<Litter>(), image_direction);
break;
default:

View File

@ -232,8 +232,7 @@ bool loc_690FD0(Peep* peep, uint8_t* rideToView, uint8_t* rideSeatToView, TileEl
template<> bool SpriteBase::Is<Guest>() const
{
auto peep = As<Peep>();
return peep && peep->AssignedPeepType == PeepType::Guest;
return Type == EntityType::Guest;
}
bool Guest::GuestHasValidXY() const

View File

@ -318,7 +318,7 @@ const bool gSpriteTypeToSlowWalkMap[] = {
template<> bool SpriteBase::Is<Peep>() 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;

View File

@ -74,8 +74,7 @@ const uint16_t MAX_LITTER_DISTANCE = 3 * COORDS_XY_STEP;
template<> bool SpriteBase::Is<Staff>() const
{
auto peep = As<Peep>();
return peep && peep->AssignedPeepType == PeepType::Staff;
return Type == EntityType::Staff;
}
/**

View File

@ -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<PeepActionType>(src->action);
@ -1658,7 +1656,6 @@ private:
const auto* srcLitter = &sprite.litter;
Litter* litter = CreateEntity<Litter>();
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;

View File

@ -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<Vehicle>();
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;

View File

@ -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<const RCT2SpritePeep*>(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;

View File

@ -734,7 +734,7 @@ static const struct
template<> bool SpriteBase::Is<Vehicle>() const
{
return sprite_identifier == SpriteIdentifier::Vehicle;
return Type == EntityType::Vehicle;
}
static bool vehicle_move_info_valid(

View File

@ -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<MiscEntity>();
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<Peep*>(entity);
auto peep = entity->As<Peep>();
// 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;
}
}

View File

@ -89,7 +89,7 @@ namespace OpenRCT2::Scripting
{
auto spriteId = static_cast<uint16_t>(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<ScVehicle>(spriteId));
case SpriteIdentifier::Peep:
{
if (sprite->Is<Staff>())
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));
else
return GetObjectAsDukValue(_context, std::make_shared<ScGuest>(spriteId));
}
case EntityType::Staff:
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));
case EntityType::Guest:
return GetObjectAsDukValue(_context, std::make_shared<ScGuest>(spriteId));
default:
return GetObjectAsDukValue(_context, std::make_shared<ScEntity>(spriteId));
}

View File

@ -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
{

View File

@ -16,8 +16,7 @@
template<> bool SpriteBase::Is<Balloon>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::Balloon;
return Type == EntityType::Balloon;
}
void Balloon::Update()

View File

@ -68,8 +68,7 @@ static constexpr const uint8_t * DuckAnimations[] =
template<> bool SpriteBase::Is<Duck>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::Duck;
return Type == EntityType::Duck;
}
bool Duck::IsFlying()

View File

@ -72,9 +72,7 @@ const uint8_t _fountainPatternFlags[] = {
template<> bool SpriteBase::Is<JumpingFountain>() const
{
auto* misc = As<MiscEntity>();
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)

View File

@ -20,8 +20,7 @@ static constexpr const CoordsXY _moneyEffectMoveOffset[] = { { 1, -1 }, { 1, 1 }
template<> bool SpriteBase::Is<MoneyEffect>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::MoneyEffect;
return Type == EntityType::MoneyEffect;
}
/**

View File

@ -16,14 +16,12 @@
template<> bool SpriteBase::Is<VehicleCrashParticle>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::CrashedVehicleParticle;
return Type == EntityType::CrashedVehicleParticle;
}
template<> bool SpriteBase::Is<CrashSplashParticle>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::CrashSplash;
return Type == EntityType::CrashSplash;
}
/**
*

View File

@ -75,30 +75,41 @@ template<> bool SpriteBase::Is<SpriteBase>() const
template<> bool SpriteBase::Is<Litter>() const
{
return sprite_identifier == SpriteIdentifier::Litter;
return Type == EntityType::Litter;
}
template<> bool SpriteBase::Is<MiscEntity>() 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<SteamParticle>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::SteamParticle;
return Type == EntityType::SteamParticle;
}
template<> bool SpriteBase::Is<ExplosionFlare>() const
{
auto* misc = As<MiscEntity>();
return misc && misc->SubType == MiscEntityType::ExplosionFlare;
return Type == EntityType::ExplosionFlare;
}
template<> bool SpriteBase::Is<ExplosionCloud>() const
{
auto* misc = As<MiscEntity>();
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<MiscEntity>();
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<Guest>())
{
type = EntityType::Guest;
}
else
{
type = EntityType::Staff;
}
break;
case SpriteIdentifier::Misc:
if (base.Is<SteamParticle>())
{
type = EntityType::SteamParticle;
}
else if (base.Is<MoneyEffect>())
{
type = EntityType::MoneyEffect;
}
else if (base.Is<VehicleCrashParticle>())
{
type = EntityType::CrashedVehicleParticle;
}
else if (base.Is<ExplosionCloud>())
{
type = EntityType::ExplosionCloud;
}
else if (base.Is<CrashSplashParticle>())
{
type = EntityType::CrashSplash;
}
else if (base.Is<ExplosionFlare>())
{
type = EntityType::ExplosionFlare;
}
else if (base.Is<JumpingFountain>())
{
type = EntityType::JumpingFountain;
}
else if (base.Is<Balloon>())
{
type = EntityType::Balloon;
}
else if (base.Is<Duck>())
{
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<MiscEntity>())
{
// Upconvert it to rct_sprite so that the full size is copied.
auto copy = *reinterpret_cast<rct_sprite*>(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<Peep>();
if (peep != nullptr)
{
if (type == EntityType::Guest)
{
peep->AssignedPeepType = PeepType::Guest;
}
else
{
peep->AssignedPeepType = PeepType::Staff;
}
}
break;
}
case SpriteIdentifier::Misc:
{
MiscEntity* misc = base.As<MiscEntity>();
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<Peep>() && !entity->Is<Vehicle>())
{
// Only peeps and vehicles are tweened, bail if type is incorrect.
return;

View File

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

View File

@ -154,18 +154,17 @@ template<> bool SpriteBase::Is<SpriteBase>() const
template<> bool SpriteBase::Is<Peep>() const
{
return sprite_identifier == SpriteIdentifier::Peep;
return Type == EntityType::Guest || Type == EntityType::Staff;
}
template<> bool SpriteBase::Is<Guest>() const
{
auto peep = As<Peep>();
return peep && peep->AssignedPeepType == PeepType::Guest;
return Type == EntityType::Guest;
}
template<> bool SpriteBase::Is<Vehicle>() const
{
return sprite_identifier == SpriteIdentifier::Vehicle;
return Type == EntityType::Vehicle;
}
SpriteBase* get_sprite(size_t sprite_idx)

View File

@ -110,7 +110,7 @@ static std::unique_ptr<GameState_t> GetGameState(std::unique_ptr<IContext>& cont
{
rct_sprite* sprite = reinterpret_cast<rct_sprite*>(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<IContext>& 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;
}