diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 3bfc5f66cf..7d3b641bc5 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -707,7 +707,7 @@ struct PeepDistance template PeepDistance GetClosestPeep(const ScreenCoordsXY& viewportCoords, const int32_t maxDistance, PeepDistance goal) { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->sprite_left == LOCATION_NULL) continue; diff --git a/src/openrct2-ui/windows/GuestList.cpp b/src/openrct2-ui/windows/GuestList.cpp index 831cc2e363..d638064585 100644 --- a/src/openrct2-ui/windows/GuestList.cpp +++ b/src/openrct2-ui/windows/GuestList.cpp @@ -610,7 +610,7 @@ public: { _guestList.clear(); - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { sprite_set_flashing(peep, false); if (peep->OutsideOfPark) @@ -828,7 +828,7 @@ private: _lastFindGroupsWait = 320; _groups.clear(); - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; diff --git a/src/openrct2-ui/windows/Map.cpp b/src/openrct2-ui/windows/Map.cpp index b0c93171d6..41eb23f912 100644 --- a/src/openrct2-ui/windows/Map.cpp +++ b/src/openrct2-ui/windows/Map.cpp @@ -1102,12 +1102,12 @@ static uint8_t MapGetStaffFlashColour() static void window_map_paint_peep_overlay(rct_drawpixelinfo* dpi) { auto flashColour = MapGetGuestFlashColour(); - for (auto guest : EntityList(EntityListId::Peep)) + for (auto guest : EntityList()) { DrawMapPeepPixel(guest, flashColour, dpi); } flashColour = MapGetStaffFlashColour(); - for (auto staff : EntityList(EntityListId::Peep)) + for (auto staff : EntityList()) { DrawMapPeepPixel(staff, flashColour, dpi); } diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index dad2fb7e94..1610b5d09f 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -4093,7 +4093,7 @@ static void window_ride_maintenance_paint(rct_window* w, rct_drawpixelinfo* dpi) { stringId = STR_NO_MECHANICS_ARE_HIRED_MESSAGE; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->IsMechanic()) { diff --git a/src/openrct2-ui/windows/StaffList.cpp b/src/openrct2-ui/windows/StaffList.cpp index 788f5e0c4f..755c7e9751 100644 --- a/src/openrct2-ui/windows/StaffList.cpp +++ b/src/openrct2-ui/windows/StaffList.cpp @@ -189,7 +189,7 @@ public: if (window_find_by_class(WC_MAP) != nullptr) { gWindowMapFlashingFlags |= MapFlashingFlags::StaffListOpen; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { sprite_set_flashing(peep, false); if (peep->AssignedStaffType == GetSelectedStaffType()) @@ -483,7 +483,7 @@ public: { _staffList.clear(); - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { sprite_set_flashing(peep, false); if (peep->AssignedStaffType == GetSelectedStaffType()) @@ -559,7 +559,7 @@ private: Peep* closestPeep = nullptr; auto closestPeepDistance = std::numeric_limits::max(); - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->AssignedStaffType != GetSelectedStaffType()) continue; diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index ad20060873..38250eaa2d 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -21,6 +21,7 @@ #include "object/ObjectManager.h" #include "object/ObjectRepository.h" #include "ride/RideData.h" +#include "ride/TrainManager.h" #include "ride/Vehicle.h" #include "scenario/Scenario.h" #include "windows/Intent.h" @@ -202,7 +203,7 @@ void setup_in_use_selection_flags() } // Apply selected object status for hacked vehicles that may not have an associated ride - for (auto vehicle : EntityList(EntityListId::TrainHead)) + for (auto* vehicle : TrainManager::View()) { ObjectEntryIndex type = vehicle->ride_subtype; if (type != RIDE_ENTRY_INDEX_NULL) // cable lifts use index null. Ignore them @@ -210,7 +211,7 @@ void setup_in_use_selection_flags() Editor::SetSelectedObject(ObjectType::Ride, type, OBJECT_SELECTION_FLAG_SELECTED); } } - for (auto vehicle : EntityList(EntityListId::Vehicle)) + for (auto vehicle : EntityList()) { ObjectEntryIndex type = vehicle->ride_subtype; if (type != RIDE_ENTRY_INDEX_NULL) // cable lifts use index null. Ignore them diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 0301b2f91a..fbff40169e 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -410,7 +410,7 @@ void game_fix_save_vars() // Recalculates peep count after loading a save to fix corrupted files uint32_t guestCount = 0; { - for (auto guest : EntityList(EntityListId::Peep)) + for (auto guest : EntityList()) { if (!guest->OutsideOfPark) { @@ -425,7 +425,7 @@ void game_fix_save_vars() std::vector peepsToRemove; // Fix possibly invalid field values - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->CurrentRideStation >= MAX_STATIONS) { diff --git a/src/openrct2/actions/RideDemolishAction.cpp b/src/openrct2/actions/RideDemolishAction.cpp index 1a1f7d4e6e..b5b7dc8013 100644 --- a/src/openrct2/actions/RideDemolishAction.cpp +++ b/src/openrct2/actions/RideDemolishAction.cpp @@ -143,7 +143,7 @@ GameActions::Result::Ptr RideDemolishAction::DemolishRide(Ride* ride) const } } - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { uint8_t ride_id_bit = _rideIndex % 8; uint8_t ride_id_offset = _rideIndex / 8; diff --git a/src/openrct2/actions/SetCheatAction.cpp b/src/openrct2/actions/SetCheatAction.cpp index c07ca57822..79bea5407f 100644 --- a/src/openrct2/actions/SetCheatAction.cpp +++ b/src/openrct2/actions/SetCheatAction.cpp @@ -410,7 +410,7 @@ void SetCheatAction::FixVandalism() const void SetCheatAction::RemoveLitter() const { - for (auto litter : EntityList(EntityListId::Litter)) + for (auto litter : EntityList()) { sprite_remove(litter); } @@ -553,7 +553,7 @@ void SetCheatAction::GenerateGuests(int32_t count) const void SetCheatAction::SetGuestParameter(int32_t parameter, int32_t value) const { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { switch (parameter) { @@ -597,7 +597,7 @@ void SetCheatAction::SetGuestParameter(int32_t parameter, int32_t value) const void SetCheatAction::GiveObjectToGuests(int32_t object) const { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { switch (object) { @@ -661,7 +661,7 @@ void SetCheatAction::RemoveAllGuests() const // Do not use the FOR_ALL_PEEPS macro for this as next sprite index // will be fetched on a deleted guest. - for (auto guest : EntityList(EntityListId::Peep)) + for (auto guest : EntityList()) { guest->Remove(); } @@ -672,7 +672,7 @@ void SetCheatAction::RemoveAllGuests() const void SetCheatAction::SetStaffSpeed(uint8_t value) const { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { peep->Energy = value; peep->EnergyTarget = value; diff --git a/src/openrct2/actions/StaffHireNewAction.cpp b/src/openrct2/actions/StaffHireNewAction.cpp index 3edefece24..ff3a1d0f75 100644 --- a/src/openrct2/actions/StaffHireNewAction.cpp +++ b/src/openrct2/actions/StaffHireNewAction.cpp @@ -128,7 +128,7 @@ GameActions::Result::Ptr StaffHireNewAction::QueryExecute(bool execute) const return MakeResult(GameActions::Status::NoFreeElements, STR_TOO_MANY_STAFF_IN_GAME); } - Peep* newPeep = &(create_sprite(SpriteIdentifier::Peep)->peep); + Peep* newPeep = CreateEntity(); if (newPeep == nullptr) { // Too many peeps exist already. @@ -165,7 +165,7 @@ GameActions::Result::Ptr StaffHireNewAction::QueryExecute(bool execute) const { bool found = false; ++newStaffId; - for (auto searchPeep : EntityList(EntityListId::Peep)) + for (auto searchPeep : EntityList()) { if (static_cast(searchPeep->AssignedStaffType) != _staffType) continue; @@ -250,7 +250,7 @@ void StaffHireNewAction::AutoPositionNewStaff(Peep* newPeep) const // Count number of walking guests { - for (auto guest : EntityList(EntityListId::Peep)) + for (auto guest : EntityList()) { if (guest->State == PeepState::Walking) { @@ -269,7 +269,7 @@ void StaffHireNewAction::AutoPositionNewStaff(Peep* newPeep) const uint32_t rand = scenario_rand_max(count); Guest* chosenGuest = nullptr; - for (auto guest : EntityList(EntityListId::Peep)) + for (auto guest : EntityList()) { if (guest->State == PeepState::Walking) { diff --git a/src/openrct2/actions/StaffSetColourAction.cpp b/src/openrct2/actions/StaffSetColourAction.cpp index f41462a167..786754219a 100644 --- a/src/openrct2/actions/StaffSetColourAction.cpp +++ b/src/openrct2/actions/StaffSetColourAction.cpp @@ -56,7 +56,7 @@ GameActions::Result::Ptr StaffSetColourAction::Execute() const } // Update each staff member's uniform - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->AssignedStaffType == static_cast(_staffType)) { diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index c6456a5f5e..891ed9b7fa 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -436,7 +436,7 @@ static int32_t cc_staff(InteractiveConsole& console, const arguments_t& argv) { if (argv[0] == "list") { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { auto name = peep->GetName(); console.WriteFormatLine( @@ -1242,19 +1242,12 @@ static int32_t cc_show_limits(InteractiveConsole& console, [[maybe_unused]] cons int32_t rideCount = ride_get_count(); int32_t spriteCount = 0; - for (int32_t i = 1; i < static_cast(EntityListId::Count); ++i) + for (int32_t i = 0; i < static_cast(EntityType::Count); ++i) { - spriteCount += GetEntityListCount(EntityListId(i)); + spriteCount += GetEntityListCount(EntityType(i)); } - int32_t staffCount = 0; - for (int32_t i = 0; i < STAFF_MAX_COUNT; ++i) - { - if (gStaffModes[i] != StaffMode::None) - { - staffCount++; - } - } + int32_t staffCount = GetEntityListCount(EntityType::Staff); int32_t bannerCount = 0; for (BannerIndex i = 0; i < MAX_BANNERS; ++i) diff --git a/src/openrct2/management/Award.cpp b/src/openrct2/management/Award.cpp index 8f75a42507..4ff66df9dd 100644 --- a/src/openrct2/management/Award.cpp +++ b/src/openrct2/management/Award.cpp @@ -85,7 +85,7 @@ static bool award_is_deserved_most_untidy(int32_t activeAwardTypes) return false; uint32_t negativeCount = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -113,7 +113,7 @@ static bool award_is_deserved_most_tidy(int32_t activeAwardTypes) uint32_t positiveCount = 0; uint32_t negativeCount = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -192,7 +192,7 @@ static bool award_is_deserved_most_beautiful(int32_t activeAwardTypes) uint32_t positiveCount = 0; uint32_t negativeCount = 0; - auto list = EntityList(EntityListId::Peep); + auto list = EntityList(); for (auto peep : list) { if (peep->OutsideOfPark) @@ -234,7 +234,7 @@ static bool award_is_deserved_worst_value(int32_t activeAwardTypes) static bool award_is_deserved_safest([[maybe_unused]] int32_t activeAwardTypes) { auto peepsWhoDislikeVandalism = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -263,9 +263,9 @@ static bool award_is_deserved_best_staff(int32_t activeAwardTypes) if (activeAwardTypes & EnumToFlag(ParkAward::MostUntidy)) return false; - auto staff = EntityList(EntityListId::Peep); + auto staff = EntityList(); auto staffCount = std::distance(staff.begin(), staff.end()); - auto guests = EntityList(EntityListId::Peep); + auto guests = EntityList(); auto peepCount = std::distance(guests.begin(), guests.end()); return ((staffCount != 0) && staffCount >= 20 && staffCount >= peepCount / 32); @@ -304,7 +304,7 @@ static bool award_is_deserved_best_food(int32_t activeAwardTypes) // Count hungry peeps auto hungryPeeps = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -348,7 +348,7 @@ static bool award_is_deserved_worst_food(int32_t activeAwardTypes) // Count hungry peeps auto hungryPeeps = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -378,7 +378,7 @@ static bool award_is_deserved_best_restrooms([[maybe_unused]] int32_t activeAwar // Count number of guests who are thinking they need the restroom auto guestsWhoNeedRestroom = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -505,7 +505,7 @@ static bool award_is_deserved_most_confusing_layout([[maybe_unused]] int32_t act { uint32_t peepsCounted = 0; uint32_t peepsLost = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; diff --git a/src/openrct2/management/Finance.cpp b/src/openrct2/management/Finance.cpp index dd0cb1bddc..3de1af67f5 100644 --- a/src/openrct2/management/Finance.cpp +++ b/src/openrct2/management/Finance.cpp @@ -111,7 +111,7 @@ void finance_pay_wages() return; } - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { finance_payment(GetStaffWage(peep->AssignedStaffType) / 4, ExpenditureType::Wages); } @@ -242,7 +242,7 @@ void finance_update_daily_profit() if (!(gParkFlags & PARK_FLAGS_NO_MONEY)) { // Staff costs - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { current_profit -= GetStaffWage(peep->AssignedStaffType); } diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp index 826198e2ac..6b3f319790 100644 --- a/src/openrct2/peep/Guest.cpp +++ b/src/openrct2/peep/Guest.cpp @@ -2754,7 +2754,7 @@ static PeepThoughtType peep_assess_surroundings(int16_t centre_x, int16_t centre } } - for (auto litter : EntityList(EntityListId::Litter)) + for (auto litter : EntityList()) { int16_t dist_x = abs(litter->x - centre_x); int16_t dist_y = abs(litter->y - centre_y); @@ -5891,7 +5891,7 @@ static void peep_update_walking_break_scenery(Peep* peep) return; } - for (auto inner_peep : EntityList(EntityListId::Peep)) + for (auto inner_peep : EntityList()) { if (inner_peep->AssignedStaffType != StaffType::Security) continue; diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index bd3fa1d393..bc3732d941 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -384,7 +384,7 @@ Peep* try_get_guest(uint16_t spriteIndex) int32_t peep_get_staff_count() { - auto list = EntityList(EntityListId::Peep); + auto list = EntityList(); auto count = std::distance(list.begin(), list.end()); return count; @@ -401,7 +401,7 @@ void peep_update_all() int32_t i = 0; // Warning this loop can delete peeps - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (static_cast(i & 0x7F) != (gCurrentTicks & 0x7F)) { @@ -420,7 +420,7 @@ void peep_update_all() i++; } - for (auto staff : EntityList(EntityListId::Peep)) + for (auto staff : EntityList()) { if (static_cast(i & 0x7F) != (gCurrentTicks & 0x7F)) { @@ -1197,7 +1197,7 @@ void peep_problem_warnings_update() disgust_counter = 0, toilet_counter = 0, vandalism_counter = 0; uint8_t* warning_throttle = gPeepWarningThrottle; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark || peep->Thoughts[0].freshness > 5) continue; @@ -1375,7 +1375,7 @@ void peep_update_crowd_noise() // Count the number of peeps visible auto visiblePeeps = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->sprite_left == LOCATION_NULL) continue; @@ -1438,7 +1438,7 @@ void peep_update_crowd_noise() */ void peep_applause() { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->OutsideOfPark) continue; @@ -1466,7 +1466,7 @@ void peep_applause() */ void peep_update_days_in_queue() { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (!peep->OutsideOfPark && peep->State == PeepState::Queuing) { @@ -1611,7 +1611,7 @@ Peep* Peep::Generate(const CoordsXYZ& coords) if (GetNumFreeEntities() < 400) return nullptr; - Peep* peep = &create_sprite(SpriteIdentifier::Peep)->peep; + Peep* peep = CreateEntity(); peep->SpriteType = PeepSpriteType::Normal; peep->OutsideOfPark = true; peep->State = PeepState::Falling; diff --git a/src/openrct2/peep/Peep.h b/src/openrct2/peep/Peep.h index 5f43f0b2b3..52c7e69dac 100644 --- a/src/openrct2/peep/Peep.h +++ b/src/openrct2/peep/Peep.h @@ -785,6 +785,8 @@ private: struct Guest : Peep { + static constexpr auto cEntityType = EntityType::Guest; + public: void UpdateGuest(); void Tick128UpdateGuest(int32_t index); @@ -872,6 +874,8 @@ private: struct Staff : Peep { + static constexpr auto cEntityType = EntityType::Staff; + public: void UpdateStaff(uint32_t stepsToTake); void Tick128UpdateStaff(); diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index 6144d63794..f52e0f8887 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -149,7 +149,7 @@ void staff_update_greyed_patrol_areas() gStaffPatrolAreas[staffPatrolOffset + i] = 0; } - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (static_cast(peep->AssignedStaffType) == staff_type) { @@ -349,7 +349,7 @@ uint8_t Staff::GetValidPatrolDirections(const CoordsXY& loc) const */ void Staff::ResetStats() { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { peep->SetHireDate(gDateMonthsElapsed); peep->StaffLawnsMown = 0; @@ -424,7 +424,7 @@ Direction Staff::HandymanDirectionToNearestLitter() const { uint16_t nearestLitterDist = 0xFFFF; Litter* nearestLitter = nullptr; - for (auto litter : EntityList(EntityListId::Litter)) + for (auto litter : EntityList()) { uint16_t distance = abs(litter->x - x) + abs(litter->y - y) + abs(litter->z - z) * 4; @@ -961,7 +961,7 @@ bool Staff::DoMiscPathFinding() */ void Staff::EntertainerUpdateNearbyPeeps() const { - for (auto guest : EntityList(EntityListId::Peep)) + for (auto guest : EntityList()) { if (guest->x == LOCATION_NULL) continue; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 9debb11428..e81b819e4b 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1137,7 +1137,7 @@ private: rct1_vehicle* srcVehicle = &_s4.sprites[i].vehicle; if (srcVehicle->x != LOCATION_NULL) { - Vehicle* vehicle = reinterpret_cast(create_sprite(SpriteIdentifier::Vehicle)); + Vehicle* vehicle = CreateEntity(); spriteIndexMap[i] = vehicle->sprite_index; vehicles.push_back(vehicle); @@ -1347,7 +1347,15 @@ private: if (_s4.sprites[i].unknown.sprite_identifier == SpriteIdentifier::Peep) { rct1_peep* srcPeep = &_s4.sprites[i].peep; - Peep* peep = reinterpret_cast(create_sprite(SpriteIdentifier::Peep)); + Peep* peep = nullptr; + if (static_cast(srcPeep->type) == PeepType::Guest) + { + peep = CreateEntity(); + } + else + { + peep = CreateEntity(); + } spriteIndexMap[i] = peep->sprite_index; ImportPeep(peep, srcPeep); @@ -1368,7 +1376,7 @@ private: } { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { FixPeepNextInQueue(peep, spriteIndexMap); } @@ -1394,7 +1402,7 @@ private: gStaffModes[i] = static_cast(_s4.staff_modes[i]); } - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { ImportStaffPatrolArea(peep); } @@ -1649,7 +1657,7 @@ private: { const auto* srcLitter = &sprite.litter; - Litter* litter = reinterpret_cast(create_sprite(SpriteIdentifier::Litter)); + Litter* litter = CreateEntity(); litter->sprite_identifier = srcLitter->sprite_identifier; litter->SubType = LitterType(srcLitter->type); @@ -1666,6 +1674,45 @@ private: } } + MiscEntity* CreateMiscFromType(MiscEntityType type) + { + MiscEntity* misc = nullptr; + switch (type) + { + case MiscEntityType::SteamParticle: + misc = CreateEntity(); + break; + case MiscEntityType::MoneyEffect: + misc = CreateEntity(); + break; + case MiscEntityType::CrashedVehicleParticle: + misc = CreateEntity(); + break; + case MiscEntityType::ExplosionCloud: + misc = CreateEntity(); + break; + case MiscEntityType::CrashSplash: + misc = CreateEntity(); + break; + case MiscEntityType::ExplosionFlare: + misc = CreateEntity(); + break; + case MiscEntityType::JumpingFountainWater: + case MiscEntityType::JumpingFountainSnow: + misc = CreateEntity(); + break; + case MiscEntityType::Balloon: + misc = CreateEntity(); + break; + case MiscEntityType::Duck: + misc = CreateEntity(); + break; + default: + break; + } + return misc; + } + void ImportMiscSprites() { for (auto& sprite : _s4.sprites) @@ -1673,7 +1720,7 @@ private: if (sprite.unknown.sprite_identifier == SpriteIdentifier::Misc) { rct1_unk_sprite* src = &sprite.unknown; - MiscEntity* dst = reinterpret_cast(create_sprite(SpriteIdentifier::Misc)); + MiscEntity* dst = CreateMiscFromType(MiscEntityType(src->type)); if (dst == nullptr) { log_warning("SV4 has too many misc entities. No more misc entities will be imported!"); @@ -2965,7 +3012,7 @@ private: if (_s4.scenario_slot_index == SC_URBAN_PARK && _isScenario) { // First, make the queuing peep exit - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->State == PeepState::QueuingFront && peep->CurrentRide == 0) { diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index 888dfc0e1b..ccbc07497b 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -1392,59 +1392,55 @@ void S6Exporter::ExportEntities() entity.unknown.linked_list_type_offset = RCT12EntityLinkListOffset::Free; } - for (auto* entity : EntityList(EntityListId::Peep)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].peep, entity); } - for (auto* entity : EntityList(EntityListId::Peep)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].peep, entity); } - for (auto* entity : EntityList(EntityListId::Vehicle)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].vehicle, entity); } - for (auto* entity : EntityList(EntityListId::TrainHead)) - { - ExportEntity(&_s6.sprites[entity->sprite_index].vehicle, entity); - } - for (auto* entity : EntityList(EntityListId::Litter)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].litter, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].duck, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].steam_particle, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].money_effect, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].crashed_vehicle_particle, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].jumping_fountain, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].balloon, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].misc_particle, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].misc_particle, entity); } - for (auto* entity : EntityList(EntityListId::Misc)) + for (auto* entity : EntityList()) { ExportEntity(&_s6.sprites[entity->sprite_index].misc_particle, entity); } diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp index ad0ef54865..11d7b57fa6 100644 --- a/src/openrct2/ride/CableLift.cpp +++ b/src/openrct2/ride/CableLift.cpp @@ -24,7 +24,7 @@ Vehicle* cable_lift_segment_create( Ride& ride, int32_t x, int32_t y, int32_t z, int32_t direction, uint16_t var_44, int32_t remaining_distance, bool head) { - Vehicle* current = &(create_sprite(SpriteIdentifier::Vehicle)->vehicle); + Vehicle* current = CreateEntity(); current->ride = ride.id; current->ride_subtype = RIDE_ENTRY_INDEX_NULL; if (head) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 846180ae57..b3e042fead 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -362,7 +362,7 @@ void ride_update_favourited_stat() for (auto& ride : GetRideManager()) ride.guests_favourite = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->FavouriteRide != RIDE_ID_NULL) { @@ -1116,7 +1116,7 @@ void ride_remove_peeps(Ride* ride) } // Place all the guests at exit - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->State == PeepState::QueuingFront || peep->State == PeepState::EnteringRide || peep->State == PeepState::LeavingRide || peep->State == PeepState::OnRide) @@ -1151,7 +1151,7 @@ void ride_remove_peeps(Ride* ride) } } // Place all the staff at exit - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->State == PeepState::Fixing || peep->State == PeepState::Inspecting) { @@ -2732,7 +2732,7 @@ Peep* find_closest_mechanic(const CoordsXY& entrancePosition, int32_t forInspect Peep* closestMechanic = nullptr; uint32_t closestDistance = std::numeric_limits::max(); - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (!peep->IsMechanic()) continue; @@ -4050,7 +4050,7 @@ static void ride_set_start_finish_points(ride_id_t rideIndex, CoordsXYE* startEl */ static int32_t count_free_misc_sprite_slots() { - int32_t miscSpriteCount = GetEntityListCount(EntityListId::Misc); + int32_t miscSpriteCount = GetMiscEntityCount(); int32_t remainingSpriteCount = GetNumFreeEntities(); return std::max(0, miscSpriteCount + remainingSpriteCount - 300); } @@ -4093,7 +4093,7 @@ static Vehicle* vehicle_create_car( return nullptr; auto vehicleEntry = &rideEntry->vehicles[vehicleEntryIndex]; - auto vehicle = &create_sprite(SpriteIdentifier::Vehicle)->vehicle; + auto vehicle = CreateEntity(); if (vehicle == nullptr) return nullptr; @@ -5195,7 +5195,7 @@ int32_t ride_get_refund_price(const Ride* ride) */ void Ride::StopGuestsQueuing() { - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (peep->State != PeepState::Queuing) continue; diff --git a/src/openrct2/ride/TrainManager.cpp b/src/openrct2/ride/TrainManager.cpp index 8c5e2f970e..52b6e75028 100644 --- a/src/openrct2/ride/TrainManager.cpp +++ b/src/openrct2/ride/TrainManager.cpp @@ -32,6 +32,6 @@ namespace TrainManager View::View() { - vec = &GetEntityList(EntityListId::Vehicle); + vec = &GetEntityList(EntityType::Vehicle); } } // namespace TrainManager diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index c6ceaae2ff..db3d3b9b70 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -7237,7 +7237,7 @@ static void steam_particle_create(const CoordsXYZ& coords) auto surfaceElement = map_get_surface_element_at(coords); if (surfaceElement != nullptr && coords.z > surfaceElement->GetBaseZ()) { - SteamParticle* steam = &create_sprite(SpriteIdentifier::Misc)->steam_particle; + SteamParticle* steam = CreateEntity(); if (steam == nullptr) return; diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 25eb39bd3c..455e759687 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -53,6 +53,8 @@ constexpr const uint16_t VehicleTrackTypeMask = 0b1111111111111100; struct Vehicle : SpriteBase { + static constexpr auto cEntityType = EntityType::Vehicle; + enum class Type : uint8_t { Head, diff --git a/src/openrct2/scripting/ScMap.hpp b/src/openrct2/scripting/ScMap.hpp index 7cd865bd9e..04d3fadba8 100644 --- a/src/openrct2/scripting/ScMap.hpp +++ b/src/openrct2/scripting/ScMap.hpp @@ -100,16 +100,16 @@ namespace OpenRCT2::Scripting std::vector getAllEntities(const std::string& type) const { - EntityListId targetList{}; - MiscEntityType targetType{}; + std::vector result; if (type == "balloon") { - targetList = EntityListId::Misc; - targetType = MiscEntityType::Balloon; + for (auto sprite : EntityList()) + { + result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); + } } if (type == "car") { - std::vector result; for (auto trainHead : TrainManager::View()) { for (auto carId = trainHead->sprite_index; carId != SPRITE_INDEX_NULL;) @@ -119,45 +119,37 @@ namespace OpenRCT2::Scripting carId = car->next_vehicle_on_train; } } - return result; } else if (type == "litter") { - targetList = EntityListId::Litter; + for (auto sprite : EntityList()) + { + result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); + } } else if (type == "duck") { - targetList = EntityListId::Misc; - targetType = MiscEntityType::Duck; + for (auto sprite : EntityList()) + { + result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); + } } else if (type == "peep") { - targetList = EntityListId::Peep; + for (auto sprite : EntityList()) + { + result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); + } + for (auto sprite : EntityList()) + { + result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); + } } else { duk_error(_context, DUK_ERR_ERROR, "Invalid entity type."); } - std::vector result; - for (auto sprite : EntityList(targetList)) - { - if (targetList == EntityListId::Peep) - { - if (sprite->Is()) - result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); - else - result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); - } - else if (targetList == EntityListId::Misc) - { - auto* misc = sprite->As(); - if (misc && misc->SubType == targetType) - { - result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); - } - } - } return result; } diff --git a/src/openrct2/world/Balloon.cpp b/src/openrct2/world/Balloon.cpp index 54ef0e58a1..7f909027b2 100644 --- a/src/openrct2/world/Balloon.cpp +++ b/src/openrct2/world/Balloon.cpp @@ -82,11 +82,11 @@ void Balloon::Pop() void create_balloon(const CoordsXYZ& balloonPos, int32_t colour, bool isPopped) { - rct_sprite* sprite = create_sprite(SpriteIdentifier::Misc); + auto* sprite = CreateEntity(); if (sprite == nullptr) return; - sprite->misc.SubType = MiscEntityType::Balloon; - auto balloon = sprite->misc.As(); + sprite->SubType = MiscEntityType::Balloon; + auto balloon = sprite->As(); if (balloon == nullptr) return; // can never happen diff --git a/src/openrct2/world/Duck.cpp b/src/openrct2/world/Duck.cpp index 8414482932..267c1bf132 100644 --- a/src/openrct2/world/Duck.cpp +++ b/src/openrct2/world/Duck.cpp @@ -281,7 +281,7 @@ uint32_t Duck::GetFrameImage(int32_t direction) const void create_duck(const CoordsXY& pos) { - rct_sprite* sprite = create_sprite(SpriteIdentifier::Misc); + auto* sprite = CreateEntity(); if (sprite == nullptr) return; @@ -291,8 +291,8 @@ void create_duck(const CoordsXY& pos) targetPos.x += offsetXY; targetPos.y += offsetXY; - sprite->misc.SubType = MiscEntityType::Duck; - auto duck = sprite->misc.As(); + sprite->SubType = MiscEntityType::Duck; + auto duck = sprite->As(); if (duck == nullptr) return; // can never happen duck->sprite_width = 9; @@ -351,7 +351,7 @@ void duck_press(Duck* duck) void duck_remove_all() { - for (auto duck : EntityList(EntityListId::Misc)) + for (auto duck : EntityList()) { duck->Remove(); } diff --git a/src/openrct2/world/EntityList.h b/src/openrct2/world/EntityList.h index 6f2d61ea7c..481db15cb4 100644 --- a/src/openrct2/world/EntityList.h +++ b/src/openrct2/world/EntityList.h @@ -20,78 +20,17 @@ enum class EntityListId : uint8_t { - Free, - TrainHead, - Peep, - Misc, - Litter, - Vehicle, - Count, + Count = 6, }; -const std::list& GetEntityList(const EntityListId id); +const std::list& GetEntityList(const EntityType id); -uint16_t GetEntityListCount(EntityListId list); +uint16_t GetEntityListCount(EntityType list); +uint16_t GetMiscEntityCount(); uint16_t GetNumFreeEntities(); void RebuildEntityLists(); const std::vector& GetEntityTileList(const CoordsXY& spritePos); -template class EntityIterator -{ -private: - T* Entity = nullptr; - uint16_t NextEntityId = SPRITE_INDEX_NULL; - -public: - EntityIterator(const uint16_t _EntityId) - : NextEntityId(_EntityId) - { - ++(*this); - } - EntityIterator& operator++() - { - Entity = nullptr; - - while (NextEntityId != SPRITE_INDEX_NULL && Entity == nullptr) - { - auto baseEntity = GetEntity(NextEntityId); - if (!baseEntity) - { - NextEntityId = SPRITE_INDEX_NULL; - continue; - } - NextEntityId = baseEntity->*NextList; - Entity = baseEntity->template As(); - } - return *this; - } - - EntityIterator operator++(int) - { - EntityIterator retval = *this; - ++(*this); - return retval; - } - bool operator==(EntityIterator other) const - { - return Entity == other.Entity; - } - bool operator!=(EntityIterator other) const - { - return !(*this == other); - } - T* operator*() - { - return Entity; - } - // iterator traits - using difference_type = std::ptrdiff_t; - using value_type = T; - using pointer = const T*; - using reference = const T&; - using iterator_category = std::forward_iterator_tag; -}; - template class EntityTileIterator { private: @@ -222,8 +161,8 @@ private: const std::list& vec; public: - EntityList(EntityListId type) - : vec(GetEntityList(type)) + EntityList() + : vec(GetEntityList(T::cEntityType)) { } diff --git a/src/openrct2/world/Fountain.cpp b/src/openrct2/world/Fountain.cpp index 90f98185ca..365021c8ea 100644 --- a/src/openrct2/world/Fountain.cpp +++ b/src/openrct2/world/Fountain.cpp @@ -129,7 +129,7 @@ void JumpingFountain::StartAnimation(const int32_t newType, const CoordsXY& newL void JumpingFountain::Create( const int32_t newType, const CoordsXYZ& newLoc, const int32_t direction, const int32_t newFlags, const int32_t iteration) { - auto* jumpingFountain = reinterpret_cast(create_sprite(SpriteIdentifier::Misc)); + auto* jumpingFountain = CreateEntity(); if (jumpingFountain != nullptr) { jumpingFountain->Iteration = iteration; diff --git a/src/openrct2/world/Fountain.h b/src/openrct2/world/Fountain.h index 790e42898f..2454272282 100644 --- a/src/openrct2/world/Fountain.h +++ b/src/openrct2/world/Fountain.h @@ -15,6 +15,8 @@ struct JumpingFountain : MiscEntity { + static constexpr auto cEntityType = EntityType::JumpingFountain; + uint8_t NumTicksAlive; uint8_t FountainFlags; int16_t TargetX; diff --git a/src/openrct2/world/MoneyEffect.cpp b/src/openrct2/world/MoneyEffect.cpp index 20a9525f19..6449f08ba5 100644 --- a/src/openrct2/world/MoneyEffect.cpp +++ b/src/openrct2/world/MoneyEffect.cpp @@ -33,7 +33,7 @@ void MoneyEffect::CreateAt(money32 value, const CoordsXYZ& effectPos, bool verti if (value == MONEY(0, 00)) return; - MoneyEffect* moneyEffect = &create_sprite(SpriteIdentifier::Misc)->money_effect; + MoneyEffect* moneyEffect = CreateEntity(); if (moneyEffect == nullptr) return; diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index efb646c598..794a2d4850 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -383,7 +383,7 @@ int32_t Park::CalculateParkRating() const // Find the number of happy peeps and the number of peeps who can't find the park exit uint32_t happyGuestCount = 0; uint32_t lostGuestCount = 0; - for (auto peep : EntityList(EntityListId::Peep)) + for (auto peep : EntityList()) { if (!peep->OutsideOfPark) { @@ -466,7 +466,7 @@ int32_t Park::CalculateParkRating() const // Litter { int32_t litterCount = 0; - for (auto litter : EntityList(EntityListId::Litter)) + for (auto litter : EntityList()) { // Ignore recently dropped litter if (litter->creationTick - gScenarioTicks >= 7680) diff --git a/src/openrct2/world/Particle.cpp b/src/openrct2/world/Particle.cpp index 4c1ae4ab5a..e01d2dfcb5 100644 --- a/src/openrct2/world/Particle.cpp +++ b/src/openrct2/world/Particle.cpp @@ -31,7 +31,7 @@ template<> bool SpriteBase::Is() const */ void crashed_vehicle_particle_create(rct_vehicle_colour colours, const CoordsXYZ& vehiclePos) { - VehicleCrashParticle* sprite = &create_sprite(SpriteIdentifier::Misc)->crashed_vehicle_particle; + VehicleCrashParticle* sprite = CreateEntity(); if (sprite != nullptr) { sprite->colour[0] = colours.body_colour; @@ -121,7 +121,7 @@ void VehicleCrashParticle::Update() */ void crash_splash_create(const CoordsXYZ& splashPos) { - MiscEntity* sprite = &create_sprite(SpriteIdentifier::Misc)->misc; + auto* sprite = CreateEntity(); if (sprite != nullptr) { sprite->sprite_width = 33; diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index 8c31c37dab..a3f12d6341 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -27,7 +27,7 @@ #include static rct_sprite _spriteList[MAX_ENTITIES]; -static std::array, EnumValue(EntityListId::Count)> gEntityLists; +static std::array, EnumValue(EntityType::Count)> gEntityLists; static std::vector _freeIdList; static bool _spriteFlashingList[MAX_ENTITIES]; @@ -101,9 +101,9 @@ template<> bool SpriteBase::Is() const return misc && misc->SubType == MiscEntityType::ExplosionCloud; } -uint16_t GetEntityListCount(EntityListId list) +uint16_t GetEntityListCount(EntityType type) { - return static_cast(gEntityLists[static_cast(list)].size()); + return static_cast(gEntityLists[EnumValue(type)].size()); } uint16_t GetNumFreeEntities() @@ -197,27 +197,98 @@ void SpriteBase::Invalidate() viewports_invalidate(sprite_left, sprite_top, sprite_right, sprite_bottom, maxZoom); } -constexpr EntityListId EntityIdentifierToListId(const SpriteIdentifier type) + +constexpr EntityType EntityBaseToEntityType(const SpriteBase& base) { - EntityListId linkedListIndex = EntityListId::Free; - switch (type) + EntityType type = EntityType::Count; + switch (base.sprite_identifier) { case SpriteIdentifier::Vehicle: - linkedListIndex = EntityListId::Vehicle; + type = EntityType::Vehicle; break; case SpriteIdentifier::Peep: - linkedListIndex = EntityListId::Peep; + if (base.Is()) + { + type = EntityType::Guest; + } + else + { + type = EntityType::Staff; + } break; case SpriteIdentifier::Misc: - linkedListIndex = EntityListId::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: - linkedListIndex = EntityListId::Litter; + type = EntityType::Litter; break; default: break; } - return linkedListIndex; + return type; +} + +constexpr SpriteIdentifier EntityTypeToSpriteIdentifier(const EntityType type) +{ + switch (type) + { + case EntityType::Vehicle: + return SpriteIdentifier::Vehicle; + case EntityType::Guest: + return SpriteIdentifier::Peep; + case EntityType::Staff: + return SpriteIdentifier::Peep; + case EntityType::Litter: + return 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: + return SpriteIdentifier::Misc; + case EntityType::Count: + return SpriteIdentifier::Null; + } + return SpriteIdentifier::Null; } void RebuildEntityLists() @@ -237,7 +308,7 @@ void RebuildEntityLists() } else { - auto listId = EntityIdentifierToListId(ent.misc.sprite_identifier); + auto listId = EntityBaseToEntityType(ent.misc); gEntityLists[EnumValue(listId)].push_back(ent.misc.sprite_index); } } @@ -245,7 +316,7 @@ void RebuildEntityLists() std::sort(std::begin(_freeIdList), std::end(_freeIdList), std::greater()); } -const std::list& GetEntityList(const EntityListId id) +const std::list& GetEntityList(const EntityType id) { return gEntityLists[EnumValue(id)]; } @@ -401,7 +472,7 @@ void sprite_clear_all_unused() static constexpr uint16_t MAX_MISC_SPRITES = 300; static void AddToEntityList(SpriteBase* entity) { - auto listId = EntityIdentifierToListId(entity->sprite_identifier); + auto listId = EntityBaseToEntityType(*entity); auto& list = gEntityLists[EnumValue(listId)]; // 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); @@ -415,7 +486,7 @@ static void AddToFreeList(uint16_t index) static void RemoveFromEntityList(SpriteBase* entity) { - auto listId = EntityIdentifierToListId(entity->sprite_identifier); + auto listId = EntityBaseToEntityType(*entity); auto& list = gEntityLists[EnumValue(listId)]; auto ptr = std::lower_bound(std::begin(list), std::end(list), entity->sprite_index); if (ptr != std::end(list) && *ptr == entity->sprite_index) @@ -424,7 +495,83 @@ static void RemoveFromEntityList(SpriteBase* entity) } } -rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier) +uint16_t GetMiscEntityCount() +{ + uint16_t count = 0; + for (auto id : { EntityType::SteamParticle, EntityType::MoneyEffect, EntityType::CrashedVehicleParticle, + EntityType::ExplosionCloud, EntityType::CrashSplash, EntityType::ExplosionFlare, + EntityType::JumpingFountain, EntityType::Balloon, EntityType::Duck }) + { + count += GetEntityListCount(id); + } + 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) { @@ -432,12 +579,13 @@ rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier) return nullptr; } + auto spriteIdentifier = EntityTypeToSpriteIdentifier(type); if (spriteIdentifier == SpriteIdentifier::Misc) { // Misc sprites are commonly used for effects, if there are less than MAX_MISC_SPRITES // free it will fail to keep slots for more relevant sprites. // Also there can't be more than MAX_MISC_SPRITES sprites in this list. - uint16_t miscSlotsRemaining = MAX_MISC_SPRITES - GetEntityListCount(EntityListId::Misc); + uint16_t miscSlotsRemaining = MAX_MISC_SPRITES - GetMiscEntityCount(); if (miscSlotsRemaining >= _freeIdList.size()) { return nullptr; @@ -455,7 +603,7 @@ rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier) // may contain garbage and cause a desync later on. sprite_reset(sprite); - sprite->sprite_identifier = spriteIdentifier; + SetLegacyFields(*sprite, type); AddToEntityList(sprite); sprite->x = LOCATION_NULL; @@ -499,7 +647,7 @@ void SteamParticle::Update() */ void sprite_misc_explosion_cloud_create(const CoordsXYZ& cloudPos) { - MiscEntity* sprite = &create_sprite(SpriteIdentifier::Misc)->misc; + auto* sprite = CreateEntity(); if (sprite != nullptr) { sprite->sprite_width = 44; @@ -531,7 +679,7 @@ void ExplosionCloud::Update() */ void sprite_misc_explosion_flare_create(const CoordsXYZ& flarePos) { - MiscEntity* sprite = &create_sprite(SpriteIdentifier::Misc)->misc; + MiscEntity* sprite = CreateEntity(); if (sprite != nullptr) { sprite->sprite_width = 25; @@ -559,7 +707,7 @@ void ExplosionFlare::Update() template void MiscUpdateAllType() { - for (auto misc : EntityList(EntityListId::Misc)) + for (auto misc : EntityList()) { misc->Update(); } @@ -732,11 +880,11 @@ void litter_create(const CoordsXYZD& litterPos, LitterType type) if (!litter_can_be_at(offsetLitterPos)) return; - if (GetEntityListCount(EntityListId::Litter) >= 500) + if (GetEntityListCount(EntityType::Litter) >= 500) { Litter* newestLitter = nullptr; uint32_t newestLitterCreationTick = 0; - for (auto litter : EntityList(EntityListId::Litter)) + for (auto litter : EntityList()) { if (newestLitterCreationTick <= litter->creationTick) { @@ -752,7 +900,7 @@ void litter_create(const CoordsXYZD& litterPos, LitterType type) } } - Litter* litter = reinterpret_cast(create_sprite(SpriteIdentifier::Litter)); + Litter* litter = CreateEntity(); if (litter == nullptr) return; @@ -796,12 +944,12 @@ void litter_remove_at(const CoordsXYZ& litterPos) uint16_t remove_floating_sprites() { uint16_t removed = 0; - for (auto* balloon : EntityList(EntityListId::Misc)) + for (auto* balloon : EntityList()) { sprite_remove(balloon); removed++; } - for (auto* duck : EntityList(EntityListId::Misc)) + for (auto* duck : EntityList()) { if (duck->IsFlying()) { @@ -809,7 +957,7 @@ uint16_t remove_floating_sprites() removed++; } } - for (auto* money : EntityList(EntityListId::Misc)) + for (auto* money : EntityList()) { sprite_remove(money); removed++; @@ -817,9 +965,19 @@ uint16_t remove_floating_sprites() return removed; } -void EntityTweener::PopulateEntities(EntityListId id) +void EntityTweener::PopulateEntities() { - for (auto ent : EntityList(id)) + for (auto ent : EntityList()) + { + Entities.push_back(ent); + PrePos.emplace_back(ent->x, ent->y, ent->z); + } + for (auto ent : EntityList()) + { + Entities.push_back(ent); + PrePos.emplace_back(ent->x, ent->y, ent->z); + } + for (auto ent : EntityList()) { Entities.push_back(ent); PrePos.emplace_back(ent->x, ent->y, ent->z); @@ -830,8 +988,7 @@ void EntityTweener::PreTick() { Restore(); Reset(); - PopulateEntities(EntityListId::Peep); - PopulateEntities(EntityListId::Vehicle); + PopulateEntities(); } void EntityTweener::PostTick() diff --git a/src/openrct2/world/Sprite.h b/src/openrct2/world/Sprite.h index fde11c243c..b53f96b62a 100644 --- a/src/openrct2/world/Sprite.h +++ b/src/openrct2/world/Sprite.h @@ -30,12 +30,14 @@ enum LitterType : uint8_t; struct Litter : SpriteBase { + static constexpr auto cEntityType = EntityType::Litter; LitterType SubType; uint32_t creationTick; }; struct Balloon : MiscEntity { + static constexpr auto cEntityType = EntityType::Balloon; uint16_t popped; uint8_t time_to_move; uint8_t colour; @@ -47,6 +49,7 @@ struct Balloon : MiscEntity struct Duck : MiscEntity { + static constexpr auto cEntityType = EntityType::Duck; enum class DuckState : uint8_t { FlyToWater, @@ -74,6 +77,7 @@ private: struct MoneyEffect : MiscEntity { + static constexpr auto cEntityType = EntityType::MoneyEffect; uint16_t MoveDelay; uint8_t NumMovements; uint8_t Vertical; @@ -89,6 +93,7 @@ struct MoneyEffect : MiscEntity struct VehicleCrashParticle : MiscEntity { + static constexpr auto cEntityType = EntityType::CrashedVehicleParticle; uint16_t time_to_live; uint8_t colour[2]; uint16_t crashed_sprite_base; @@ -104,21 +109,25 @@ struct VehicleCrashParticle : MiscEntity struct ExplosionFlare : MiscEntity { + static constexpr auto cEntityType = EntityType::ExplosionFlare; void Update(); }; struct ExplosionCloud : MiscEntity { + static constexpr auto cEntityType = EntityType::ExplosionCloud; void Update(); }; struct CrashSplashParticle : MiscEntity { + static constexpr auto cEntityType = EntityType::CrashSplash; void Update(); }; struct SteamParticle : MiscEntity { + static constexpr auto cEntityType = EntityType::SteamParticle; uint16_t time_to_move; void Update(); @@ -203,7 +212,11 @@ constexpr const uint32_t SPATIAL_INDEX_LOCATION_NULL = SPATIAL_INDEX_SIZE - 1; extern const rct_string_id litterNames[12]; -rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier); +rct_sprite* create_sprite(EntityType type); +template T* CreateEntity() +{ + return reinterpret_cast(create_sprite(T::cEntityType)); +} void reset_sprite_list(); void reset_sprite_spatial_index(); void sprite_clear_all_unused(); @@ -247,7 +260,7 @@ class EntityTweener std::vector PostPos; private: - void PopulateEntities(EntityListId id); + void PopulateEntities(); public: static EntityTweener& Get(); diff --git a/src/openrct2/world/SpriteBase.h b/src/openrct2/world/SpriteBase.h index baaa6d0a92..4e997ca6bc 100644 --- a/src/openrct2/world/SpriteBase.h +++ b/src/openrct2/world/SpriteBase.h @@ -3,9 +3,26 @@ #include "../common.h" struct CoordsXYZ; -enum class EntityListId : uint8_t; enum class SpriteIdentifier : uint8_t; +enum class EntityType : uint8_t +{ + Vehicle, + Guest, + Staff, + Litter, + SteamParticle, + MoneyEffect, + CrashedVehicleParticle, + ExplosionCloud, + CrashSplash, + ExplosionFlare, + JumpingFountain, + Balloon, + Duck, + Count +}; + struct SpriteBase { SpriteIdentifier sprite_identifier;