diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 09af260a4b..34dc1a1d17 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1069,21 +1069,6 @@ private: } } - void FixRideVehicleLinks(const uint16_t* spriteIndexMap) - { - for (auto& ride : GetRideManager()) - { - for (uint8_t j = 0; j < std::size(ride.vehicles); j++) - { - uint16_t originalIndex = ride.vehicles[j]; - if (originalIndex != SPRITE_INDEX_NULL) - { - ride.vehicles[j] = spriteIndexMap[originalIndex]; - } - } - } - } - void ImportRideMeasurements() { for (const auto& src : _s4.ride_measurements) @@ -1117,155 +1102,19 @@ private: } } + void ImportEntity(const RCT12SpriteBase& src); + template void ImportEntity(const RCT12SpriteBase& src); + void ImportSprites() { - ImportVehicles(); - ImportPeeps(); - ImportLitter(); - ImportMiscSprites(); - } - - void ImportVehicles() - { - std::vector vehicles; - uint16_t spriteIndexMap[RCT1_MAX_SPRITES]; for (int i = 0; i < RCT1_MAX_SPRITES; i++) { - spriteIndexMap[i] = SPRITE_INDEX_NULL; - if (_s4.sprites[i].unknown.sprite_identifier == RCT12SpriteIdentifier::Vehicle) - { - rct1_vehicle* srcVehicle = &_s4.sprites[i].vehicle; - if (srcVehicle->x != LOCATION_NULL) - { - Vehicle* vehicle = CreateEntity(); - spriteIndexMap[i] = vehicle->sprite_index; - vehicles.push_back(vehicle); - - ImportVehicle(vehicle, srcVehicle); - } - } + ImportEntity(_s4.sprites[i].unknown); } - for (auto vehicle : vehicles) - { - FixVehicleLinks(vehicle, spriteIndexMap); - } - FixRideVehicleLinks(spriteIndexMap); + FixImportStaff(); } - void ImportVehicle(Vehicle* dst, rct1_vehicle* src) - { - const auto* ride = get_ride(src->ride); - if (ride == nullptr) - return; - - uint8_t vehicleEntryIndex = RCT1::GetVehicleSubEntryIndex(src->vehicle_type); - - dst->ride = src->ride; - dst->ride_subtype = RCTEntryIndexToOpenRCT2EntryIndex(ride->subtype); - - dst->vehicle_type = vehicleEntryIndex; - dst->SubType = Vehicle::Type(src->type); - dst->var_44 = src->var_44; - dst->remaining_distance = src->remaining_distance; - - // Properties from vehicle entry - dst->sprite_width = src->sprite_width; - dst->sprite_height_negative = src->sprite_height_negative; - dst->sprite_height_positive = src->sprite_height_positive; - dst->sprite_direction = src->sprite_direction; - - dst->sprite_left = src->sprite_left; - dst->sprite_top = src->sprite_top; - dst->sprite_right = src->sprite_right; - dst->sprite_bottom = src->sprite_bottom; - - dst->mass = src->mass; - dst->num_seats = src->num_seats; - dst->speed = src->speed; - dst->powered_acceleration = src->powered_acceleration; - dst->brake_speed = src->brake_speed; - - dst->velocity = src->velocity; - dst->acceleration = src->acceleration; - dst->SwingSprite = src->SwingSprite; - dst->SwingPosition = src->SwingPosition; - dst->SwingSpeed = src->SwingSpeed; - dst->restraints_position = src->restraints_position; - dst->spin_sprite = src->spin_sprite; - dst->sound_vector_factor = src->sound_vector_factor; - dst->spin_speed = src->spin_speed; - dst->sound2_flags = src->sound2_flags; - dst->sound1_id = OpenRCT2::Audio::SoundId::Null; - dst->sound2_id = OpenRCT2::Audio::SoundId::Null; - dst->var_C0 = src->var_C0; - dst->var_C4 = src->var_C4; - dst->animation_frame = src->animation_frame; - dst->var_C8 = src->var_C8; - dst->var_CA = src->var_CA; - dst->var_CE = src->var_CE; - dst->var_D3 = src->var_D3; - dst->scream_sound_id = OpenRCT2::Audio::SoundId::Null; - dst->vehicle_sprite_type = src->vehicle_sprite_type; - dst->bank_rotation = src->bank_rotation; - - // Seat rotation was not in RCT1 - dst->target_seat_rotation = DEFAULT_SEAT_ROTATION; - dst->seat_rotation = DEFAULT_SEAT_ROTATION; - - // Vehicle links (indexes converted later) - dst->prev_vehicle_on_ride = src->prev_vehicle_on_ride; - dst->next_vehicle_on_ride = src->next_vehicle_on_ride; - dst->next_vehicle_on_train = src->next_vehicle_on_train; - - // Guests (indexes converted later) - for (int i = 0; i < 32; i++) - { - uint16_t spriteIndex = src->peep[i]; - dst->peep[i] = spriteIndex; - if (spriteIndex != SPRITE_INDEX_NULL) - { - dst->peep_tshirt_colours[i] = RCT1::GetColour(src->peep_tshirt_colours[i]); - } - } - - Vehicle::Status statusSrc = Vehicle::Status::MovingToEndOfStation; - if (src->status <= static_cast(Vehicle::Status::StoppedByBlockBrakes)) - { - statusSrc = static_cast(src->status); - } - dst->status = statusSrc; - dst->TrackSubposition = VehicleTrackSubposition{ src->TrackSubposition }; - dst->TrackLocation = { src->track_x, src->track_y, src->track_z }; - dst->current_station = src->current_station; - if (src->boat_location.isNull() || ride->mode != RideMode::BoatHire || statusSrc != Vehicle::Status::TravellingBoat) - { - dst->BoatLocation.setNull(); - dst->SetTrackDirection(src->GetTrackDirection()); - dst->SetTrackType(RCT1TrackTypeToOpenRCT2(src->GetTrackType(), ride->type)); - } - else - { - dst->BoatLocation = TileCoordsXY{ src->boat_location.x, src->boat_location.y }.ToCoordsXY(); - dst->SetTrackDirection(0); - dst->SetTrackType(0); - } - dst->track_progress = src->track_progress; - dst->vertical_drop_countdown = src->vertical_drop_countdown; - dst->sub_state = src->sub_state; - dst->update_flags = src->update_flags; - - SetVehicleColours(dst, src); - - dst->mini_golf_current_animation = src->mini_golf_current_animation; - dst->mini_golf_flags = src->mini_golf_flags; - - dst->MoveTo({ src->x, src->y, src->z }); - - dst->num_peeps = src->num_peeps; - dst->next_free_seat = src->next_free_seat; - } - - void SetVehicleColours(Vehicle* dst, rct1_vehicle* src) + void SetVehicleColours(Vehicle* dst, const rct1_vehicle* src) { rct1_ride* srcRide = &_s4.rides[src->ride]; uint8_t vehicleTypeIndex = srcRide->vehicle_type; @@ -1313,80 +1162,8 @@ private: } } - void FixVehicleLinks(Vehicle* vehicle, const uint16_t* spriteIndexMap) + void FixImportStaff() { - if (vehicle->prev_vehicle_on_ride != SPRITE_INDEX_NULL) - { - vehicle->prev_vehicle_on_ride = spriteIndexMap[vehicle->prev_vehicle_on_ride]; - } - if (vehicle->next_vehicle_on_ride != SPRITE_INDEX_NULL) - { - vehicle->next_vehicle_on_ride = spriteIndexMap[vehicle->next_vehicle_on_ride]; - } - if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) - { - vehicle->next_vehicle_on_train = spriteIndexMap[vehicle->next_vehicle_on_train]; - } - } - - void FixVehiclePeepLinks(Vehicle* vehicle, const uint16_t* spriteIndexMap) - { - for (auto& peep : vehicle->peep) - { - peep = MapSpriteIndex(peep, spriteIndexMap); - } - } - - void ImportPeeps() - { - uint16_t spriteIndexMap[RCT1_MAX_SPRITES]; - for (size_t i = 0; i < RCT1_MAX_SPRITES; i++) - { - spriteIndexMap[i] = SPRITE_INDEX_NULL; - if (_s4.sprites[i].unknown.sprite_identifier == RCT12SpriteIdentifier::Peep) - { - rct1_peep* srcPeep = &_s4.sprites[i].peep; - Peep* peep = nullptr; - if (static_cast(srcPeep->type) == RCT12PeepType::Guest) - { - peep = CreateEntity(); - } - else - { - peep = CreateEntity(); - } - spriteIndexMap[i] = peep->sprite_index; - - ImportPeep(peep, srcPeep); - } - } - for (auto* vehicle : EntityList()) - { - FixVehiclePeepLinks(vehicle, spriteIndexMap); - } - - for (auto& ride : GetRideManager()) - { - FixRidePeepLinks(&ride, spriteIndexMap); - } - - for (auto peep : EntityList()) - { - FixPeepNextInQueue(peep, spriteIndexMap); - } - - // Fix the news items in advance - for (auto i = 0; i < News::MaxItems; i++) - { - rct12_news_item* newsItem = &_s4.messages[i]; - News::ItemType type = static_cast(newsItem->Type); - - if (type == News::ItemType::Peep || type == News::ItemType::PeepOnRide) - { - newsItem->Assoc = MapSpriteIndex(newsItem->Assoc, spriteIndexMap); - } - } - // The RCT2/OpenRCT2 structures are bigger than in RCT1, so initialise them to zero std::fill(std::begin(gStaffModes), std::end(gStaffModes), StaffMode::None); std::fill(std::begin(gStaffPatrolAreas), std::end(gStaffPatrolAreas), 0); @@ -1404,7 +1181,7 @@ private: staff_update_greyed_patrol_areas(); } - void ImportPeep(Peep* dst, rct1_peep* src) + void ImportPeep(Peep* dst, const rct1_peep* src) { // Peep vs. staff (including which kind) dst->SpriteType = RCT1::GetPeepSpriteType(src->sprite_type); @@ -1581,24 +1358,6 @@ private: } } - void FixRidePeepLinks(Ride* ride, const uint16_t* spriteIndexMap) - { - for (auto& station : ride->stations) - { - station.LastPeepInQueue = MapSpriteIndex(station.LastPeepInQueue, spriteIndexMap); - } - ride->mechanic = MapSpriteIndex(ride->mechanic, spriteIndexMap); - if (ride->type == RIDE_TYPE_SPIRAL_SLIDE) - { - ride->slide_peep = MapSpriteIndex(ride->slide_peep, spriteIndexMap); - } - } - - void FixPeepNextInQueue(Peep* peep, const uint16_t* spriteIndexMap) - { - peep->GuestNextInQueue = MapSpriteIndex(peep->GuestNextInQueue, spriteIndexMap); - } - void ImportStaffPatrolArea(Peep* staffmember) { // The patrol areas in RCT1 are encoded as follows, for coordinates x and y, separately for every staff member: @@ -1640,192 +1399,16 @@ private: } } - void ImportLitter() + void ImportEntityCommonProperties(SpriteBase* dst, const RCT12SpriteBase* src) { - for (auto& sprite : _s4.sprites) - { - if (sprite.unknown.sprite_identifier == RCT12SpriteIdentifier::Litter) - { - const auto* srcLitter = &sprite.litter; - - Litter* litter = CreateEntity(); - litter->SubType = LitterType(srcLitter->type); - - litter->x = srcLitter->x; - litter->y = srcLitter->y; - litter->z = srcLitter->z; - litter->sprite_direction = srcLitter->sprite_direction; - litter->sprite_width = srcLitter->sprite_width; - litter->sprite_height_positive = srcLitter->sprite_height_positive; - litter->sprite_height_negative = srcLitter->sprite_height_negative; - - litter->MoveTo({ srcLitter->x, srcLitter->y, srcLitter->z }); - } - } - } - - MiscEntity* CreateMiscFromType(RCT12MiscEntityType type) - { - MiscEntity* misc = nullptr; - switch (type) - { - case RCT12MiscEntityType::SteamParticle: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::MoneyEffect: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::CrashedVehicleParticle: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::ExplosionCloud: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::CrashSplash: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::ExplosionFlare: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::JumpingFountainWater: - case RCT12MiscEntityType::JumpingFountainSnow: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::Balloon: - misc = CreateEntity(); - break; - case RCT12MiscEntityType::Duck: - misc = CreateEntity(); - break; - default: - break; - } - return misc; - } - - void ImportMiscSprites() - { - for (auto& sprite : _s4.sprites) - { - if (sprite.unknown.sprite_identifier == RCT12SpriteIdentifier::Misc) - { - rct1_unk_sprite* src = &sprite.unknown; - MiscEntity* dst = CreateMiscFromType(RCT12MiscEntityType(src->type)); - if (dst == nullptr) - { - log_warning("SV4 has too many misc entities. No more misc entities will be imported!"); - break; - } - dst->flags = src->flags; - dst->sprite_direction = src->sprite_direction; - dst->sprite_width = src->sprite_width; - dst->sprite_height_negative = src->sprite_height_negative; - dst->sprite_height_positive = src->sprite_height_positive; - - dst->MoveTo({ src->x, src->y, src->z }); - - switch (static_cast(src->type)) - { - case RCT12MiscEntityType::SteamParticle: - ImportSteamParticle(dst->As(), reinterpret_cast(src)); - break; - case RCT12MiscEntityType::MoneyEffect: - ImportMoneyEffect(dst->As(), reinterpret_cast(src)); - break; - case RCT12MiscEntityType::CrashedVehicleParticle: - break; - case RCT12MiscEntityType::ExplosionCloud: - break; - case RCT12MiscEntityType::CrashSplash: - break; - case RCT12MiscEntityType::ExplosionFlare: - break; - case RCT12MiscEntityType::JumpingFountainWater: - ImportJumpingFountainWater( - dst->As(), reinterpret_cast(src)); - break; - case RCT12MiscEntityType::Balloon: - ImportBalloon(dst->As(), reinterpret_cast(src)); - break; - case RCT12MiscEntityType::Duck: - ImportDuck(dst->As(), reinterpret_cast(src)); - break; - default: - break; - } - - dst->MoveTo({ src->x, src->y, src->z }); - } - } - } - - void ImportMoneyEffect(MoneyEffect* dst, RCT12SpriteMoneyEffect* src) - { - if (dst == nullptr) - return; - dst->MoveDelay = src->move_delay; - dst->NumMovements = src->num_movements; - dst->Value = src->value; - dst->OffsetX = src->offset_x; - dst->Wiggle = src->wiggle; - } - - void ImportSteamParticle(SteamParticle* dst, RCT12SpriteSteamParticle* src) - { - if (dst == nullptr) - return; - dst->frame = src->frame; - } - - void ImportJumpingFountainWater(JumpingFountain* dst, RCT12SpriteJumpingFountain* src) - { - if (dst == nullptr) - return; - dst->FountainFlags = src->fountain_flags; - dst->Iteration = src->iteration; - dst->NumTicksAlive = src->num_ticks_alive; - dst->frame = src->frame; - dst->FountainType = JumpingFountainType::Water; - } - - void ImportBalloon(Balloon* dst, RCT12SpriteBalloon* src) - { - if (dst == nullptr) - return; - // Balloons were always blue in RCT1 without AA/LL - if (_gameVersion == FILE_VERSION_RCT1) - { - dst->colour = COLOUR_LIGHT_BLUE; - } - else - { - dst->colour = RCT1::GetColour(src->colour); - } - } - - void ImportDuck(Duck* dst, RCT12SpriteDuck* src) - { - if (dst == nullptr) - return; - dst->frame = src->frame; - dst->state = static_cast(src->state); - } - - uint16_t MapSpriteIndex(uint16_t originalSpriteIndex, const uint16_t* spriteIndexMap) - { - uint16_t newSpriteIndex = SPRITE_INDEX_NULL; - if (originalSpriteIndex != SPRITE_INDEX_NULL) - { - if (originalSpriteIndex >= RCT1_MAX_SPRITES) - { - log_warning("Incorrect sprite index: %d", originalSpriteIndex); - } - else - { - newSpriteIndex = spriteIndexMap[originalSpriteIndex]; - } - } - return newSpriteIndex; + dst->flags = src->flags; + dst->sprite_direction = src->sprite_direction; + dst->sprite_width = src->sprite_width; + dst->sprite_height_negative = src->sprite_height_negative; + dst->sprite_height_positive = src->sprite_height_positive; + dst->x = src->x; + dst->y = src->y; + dst->z = src->z; } void ImportPeepSpawns() @@ -3116,6 +2699,347 @@ private: } }; +// Very similar but not the same as S6Importer version (due to peeps) +constexpr EntityType GetEntityTypeFromRCT1Sprite(const RCT12SpriteBase& src) +{ + EntityType output = EntityType::Null; + switch (src.sprite_identifier) + { + case RCT12SpriteIdentifier::Vehicle: + output = EntityType::Vehicle; + break; + case RCT12SpriteIdentifier::Peep: + if (RCT12PeepType(static_cast(&src)->type) == RCT12PeepType::Guest) + { + output = EntityType::Guest; + } + else + { + output = EntityType::Staff; + } + break; + case RCT12SpriteIdentifier::Misc: + + switch (RCT12MiscEntityType(src.type)) + { + case RCT12MiscEntityType::SteamParticle: + output = EntityType::SteamParticle; + break; + case RCT12MiscEntityType::MoneyEffect: + output = EntityType::MoneyEffect; + break; + case RCT12MiscEntityType::CrashedVehicleParticle: + output = EntityType::CrashedVehicleParticle; + break; + case RCT12MiscEntityType::ExplosionCloud: + output = EntityType::ExplosionCloud; + break; + case RCT12MiscEntityType::CrashSplash: + output = EntityType::CrashSplash; + break; + case RCT12MiscEntityType::ExplosionFlare: + output = EntityType::ExplosionFlare; + break; + case RCT12MiscEntityType::JumpingFountainWater: + case RCT12MiscEntityType::JumpingFountainSnow: + output = EntityType::JumpingFountain; + break; + case RCT12MiscEntityType::Balloon: + output = EntityType::Balloon; + break; + case RCT12MiscEntityType::Duck: + output = EntityType::Duck; + break; + default: + break; + } + break; + case RCT12SpriteIdentifier::Litter: + output = EntityType::Litter; + break; + default: + break; + } + return output; +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + const auto* ride = get_ride(src->ride); + if (ride == nullptr) + return; + + uint8_t vehicleEntryIndex = RCT1::GetVehicleSubEntryIndex(src->vehicle_type); + + dst->ride = src->ride; + dst->ride_subtype = RCTEntryIndexToOpenRCT2EntryIndex(ride->subtype); + + dst->vehicle_type = vehicleEntryIndex; + dst->SubType = Vehicle::Type(src->type); + dst->var_44 = src->var_44; + dst->remaining_distance = src->remaining_distance; + + // Properties from vehicle entry + dst->sprite_width = src->sprite_width; + dst->sprite_height_negative = src->sprite_height_negative; + dst->sprite_height_positive = src->sprite_height_positive; + dst->sprite_direction = src->sprite_direction; + + dst->sprite_left = src->sprite_left; + dst->sprite_top = src->sprite_top; + dst->sprite_right = src->sprite_right; + dst->sprite_bottom = src->sprite_bottom; + + dst->mass = src->mass; + dst->num_seats = src->num_seats; + dst->speed = src->speed; + dst->powered_acceleration = src->powered_acceleration; + dst->brake_speed = src->brake_speed; + + dst->velocity = src->velocity; + dst->acceleration = src->acceleration; + dst->SwingSprite = src->SwingSprite; + dst->SwingPosition = src->SwingPosition; + dst->SwingSpeed = src->SwingSpeed; + dst->restraints_position = src->restraints_position; + dst->spin_sprite = src->spin_sprite; + dst->sound_vector_factor = src->sound_vector_factor; + dst->spin_speed = src->spin_speed; + dst->sound2_flags = src->sound2_flags; + dst->sound1_id = OpenRCT2::Audio::SoundId::Null; + dst->sound2_id = OpenRCT2::Audio::SoundId::Null; + dst->var_C0 = src->var_C0; + dst->var_C4 = src->var_C4; + dst->animation_frame = src->animation_frame; + dst->var_C8 = src->var_C8; + dst->var_CA = src->var_CA; + dst->var_CE = src->var_CE; + dst->var_D3 = src->var_D3; + dst->scream_sound_id = OpenRCT2::Audio::SoundId::Null; + dst->vehicle_sprite_type = src->vehicle_sprite_type; + dst->bank_rotation = src->bank_rotation; + + // Seat rotation was not in RCT1 + dst->target_seat_rotation = DEFAULT_SEAT_ROTATION; + dst->seat_rotation = DEFAULT_SEAT_ROTATION; + + // Vehicle links (indexes converted later) + dst->prev_vehicle_on_ride = src->prev_vehicle_on_ride; + dst->next_vehicle_on_ride = src->next_vehicle_on_ride; + dst->next_vehicle_on_train = src->next_vehicle_on_train; + + // Guests (indexes converted later) + for (int i = 0; i < 32; i++) + { + uint16_t spriteIndex = src->peep[i]; + dst->peep[i] = spriteIndex; + if (spriteIndex != SPRITE_INDEX_NULL) + { + dst->peep_tshirt_colours[i] = RCT1::GetColour(src->peep_tshirt_colours[i]); + } + } + + Vehicle::Status statusSrc = Vehicle::Status::MovingToEndOfStation; + if (src->status <= static_cast(Vehicle::Status::StoppedByBlockBrakes)) + { + statusSrc = static_cast(src->status); + } + dst->status = statusSrc; + dst->TrackSubposition = VehicleTrackSubposition{ src->TrackSubposition }; + dst->TrackLocation = { src->track_x, src->track_y, src->track_z }; + dst->current_station = src->current_station; + if (src->boat_location.isNull() || ride->mode != RideMode::BoatHire || statusSrc != Vehicle::Status::TravellingBoat) + { + dst->BoatLocation.setNull(); + dst->SetTrackDirection(src->GetTrackDirection()); + dst->SetTrackType(RCT1TrackTypeToOpenRCT2(src->GetTrackType(), ride->type)); + } + else + { + dst->BoatLocation = TileCoordsXY{ src->boat_location.x, src->boat_location.y }.ToCoordsXY(); + dst->SetTrackDirection(0); + dst->SetTrackType(0); + } + dst->track_progress = src->track_progress; + dst->vertical_drop_countdown = src->vertical_drop_countdown; + dst->sub_state = src->sub_state; + dst->update_flags = src->update_flags; + + SetVehicleColours(dst, src); + + dst->mini_golf_current_animation = src->mini_golf_current_animation; + dst->mini_golf_flags = src->mini_golf_flags; + + dst->MoveTo({ src->x, src->y, src->z }); + + dst->num_peeps = src->num_peeps; + dst->next_free_seat = src->next_free_seat; +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportPeep(dst, src); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportPeep(dst, src); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportEntityCommonProperties(dst, src); + + dst->SubType = LitterType(src->type); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + + ImportEntityCommonProperties(dst, src); + dst->frame = src->frame; +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + + ImportEntityCommonProperties(dst, src); + dst->MoveDelay = src->move_delay; + dst->NumMovements = src->num_movements; + dst->Value = src->value; + dst->OffsetX = src->offset_x; + dst->Wiggle = src->wiggle; +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportEntityCommonProperties(dst, src); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportEntityCommonProperties(dst, src); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportEntityCommonProperties(dst, src); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + ImportEntityCommonProperties(dst, src); +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + + ImportEntityCommonProperties(dst, src); + dst->FountainFlags = src->fountain_flags; + dst->Iteration = src->iteration; + dst->NumTicksAlive = src->num_ticks_alive; + dst->frame = src->frame; + dst->FountainType = JumpingFountainType::Water; +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + + ImportEntityCommonProperties(dst, src); + // Balloons were always blue in RCT1 without AA/LL + if (_gameVersion == FILE_VERSION_RCT1) + { + dst->colour = COLOUR_LIGHT_BLUE; + } + else + { + dst->colour = RCT1::GetColour(src->colour); + } +} + +template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) +{ + auto* dst = CreateEntityAt(srcBase.sprite_index); + auto* src = static_cast(&srcBase); + + ImportEntityCommonProperties(dst, src); + dst->frame = src->frame; + dst->state = static_cast(src->state); +} + +void S4Importer::ImportEntity(const RCT12SpriteBase& src) +{ + switch (GetEntityTypeFromRCT1Sprite(src)) + { + case EntityType::Vehicle: + ImportEntity(src); + break; + case EntityType::Guest: + ImportEntity(src); + break; + case EntityType::Staff: + ImportEntity(src); + break; + case EntityType::SteamParticle: + ImportEntity(src); + break; + case EntityType::MoneyEffect: + ImportEntity(src); + break; + case EntityType::CrashedVehicleParticle: + ImportEntity(src); + break; + case EntityType::ExplosionCloud: + ImportEntity(src); + break; + case EntityType::ExplosionFlare: + ImportEntity(src); + break; + case EntityType::CrashSplash: + ImportEntity(src); + break; + case EntityType::JumpingFountain: + ImportEntity(src); + break; + case EntityType::Balloon: + ImportEntity(src); + break; + case EntityType::Duck: + ImportEntity(src); + break; + case EntityType::Litter: + ImportEntity(src); + break; + default: + // Null elements do not need imported + break; + } +} + std::unique_ptr ParkImporter::CreateS4() { return std::make_unique();