From 904e6c6987fb3a17496534fd636600d114699a70 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 6 Jun 2020 11:32:37 +0100 Subject: [PATCH] Implement GetSprite and use it in a number of places This will eventually replace all of the get_sprite and try_get_sprite calls Further use of GetSprite Use GetSprite in all remaining easy to use functions Correct formatting Rename GetSprite to GetEntity Make suggested changes Remove const to allow for building Fix crashes due to next sprite --- src/openrct2-ui/windows/Guest.cpp | 2 +- src/openrct2-ui/windows/Ride.cpp | 23 +- src/openrct2-ui/windows/Staff.cpp | 5 +- src/openrct2-ui/windows/StaffFirePrompt.cpp | 2 +- .../windows/TitleCommandEditor.cpp | 2 +- src/openrct2/Editor.cpp | 2 +- src/openrct2/Game.cpp | 6 +- src/openrct2/GameStateSnapshots.cpp | 1 + src/openrct2/actions/SetCheatAction.hpp | 9 +- src/openrct2/interface/InteractiveConsole.cpp | 6 +- src/openrct2/interface/Viewport.cpp | 12 +- src/openrct2/interface/Window_internal.cpp | 8 +- src/openrct2/paint/sprite/Paint.Sprite.cpp | 47 ++-- src/openrct2/peep/Guest.cpp | 50 ++-- src/openrct2/peep/Peep.cpp | 13 +- src/openrct2/peep/Peep.h | 2 +- src/openrct2/peep/Staff.cpp | 26 +- src/openrct2/rct1/S4Importer.cpp | 5 +- src/openrct2/rct2/S6Exporter.cpp | 2 +- src/openrct2/rct2/S6Importer.cpp | 4 +- src/openrct2/ride/Ride.cpp | 13 +- src/openrct2/ride/Station.cpp | 2 +- src/openrct2/ride/Vehicle.cpp | 44 ++- src/openrct2/ride/gentle/CrookedHouse.cpp | 2 +- src/openrct2/ride/gentle/MiniGolf.cpp | 4 +- src/openrct2/scripting/ScEntity.hpp | 4 +- src/openrct2/scripting/ScMap.hpp | 64 ++--- src/openrct2/world/Duck.cpp | 8 +- src/openrct2/world/Footpath.cpp | 29 +- src/openrct2/world/MapAnimation.cpp | 18 +- src/openrct2/world/Park.cpp | 7 +- src/openrct2/world/Sprite.cpp | 253 +++++++++--------- src/openrct2/world/Sprite.h | 9 + 33 files changed, 323 insertions(+), 361 deletions(-) diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index 20f139a465..ff7e72bb16 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -604,7 +604,7 @@ static void window_guest_common_invalidate(rct_window* w) */ void window_guest_disable_widgets(rct_window* w) { - Peep* peep = &get_sprite(w->number)->peep; + Peep* peep = GetEntity(w->number); uint64_t disabled_widgets = 0; if (peep_can_be_picked_up(peep)) diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 18ab98b74d..9a49f337fb 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -1739,7 +1739,7 @@ rct_window* window_ride_open_vehicle(Vehicle* vehicle) rct_window* w2 = window_find_by_number(WC_PEEP, peepSpriteIndex); if (w2 == nullptr) { - Peep* peep = &(get_sprite(peepSpriteIndex)->peep); + Peep* peep = GetEntity(peepSpriteIndex); auto intent = Intent(WC_PEEP); intent.putExtra(INTENT_EXTRA_PEEP, peep); context_open_intent(&intent); @@ -2551,7 +2551,7 @@ static void window_ride_main_update(rct_window* w) if (vehicleSpriteIndex == SPRITE_INDEX_NULL) return; - Vehicle* vehicle = &(get_sprite(vehicleSpriteIndex)->vehicle); + Vehicle* vehicle = GetEntity(vehicleSpriteIndex); if (vehicle->status != VEHICLE_STATUS_TRAVELLING && vehicle->status != VEHICLE_STATUS_TRAVELLING_CABLE_LIFT && vehicle->status != VEHICLE_STATUS_TRAVELLING_DODGEMS && vehicle->status != VEHICLE_STATUS_TRAVELLING_BOAT) @@ -2757,21 +2757,16 @@ static rct_string_id window_ride_get_status_overall_view(rct_window* w, void* ar */ static rct_string_id window_ride_get_status_vehicle(rct_window* w, void* arguments) { - Vehicle* vehicle; - int32_t vehicleIndex; - uint16_t vehicleSpriteIndex; - rct_string_id stringId; - auto ride = get_ride(w->number); if (ride == nullptr) return 0; - vehicleIndex = w->ride.view - 1; - vehicleSpriteIndex = ride->vehicles[vehicleIndex]; + auto vehicleIndex = w->ride.view - 1; + auto vehicleSpriteIndex = ride->vehicles[vehicleIndex]; if (vehicleSpriteIndex == SPRITE_INDEX_NULL) return 0; - vehicle = &(get_sprite(vehicleSpriteIndex)->vehicle); + auto vehicle = GetEntity(vehicleSpriteIndex); if (vehicle->status != VEHICLE_STATUS_CRASHING && vehicle->status != VEHICLE_STATUS_CRASHED) { int32_t trackType = vehicle->GetTrackType(); @@ -2787,7 +2782,7 @@ static rct_string_id window_ride_get_status_vehicle(rct_window* w, void* argumen } } - stringId = VehicleStatusNames[vehicle->status]; + auto stringId = VehicleStatusNames[vehicle->status]; // Get speed in mph *(reinterpret_cast(reinterpret_cast(arguments) + 2)) = (abs(vehicle->velocity) * 9) >> 18; @@ -4156,11 +4151,11 @@ static void window_ride_maintenance_dropdown(rct_window* w, rct_widgetindex widg case BREAKDOWN_RESTRAINTS_STUCK_OPEN: case BREAKDOWN_DOORS_STUCK_CLOSED: case BREAKDOWN_DOORS_STUCK_OPEN: - vehicle = &(get_sprite(ride->vehicles[ride->broken_vehicle])->vehicle); + vehicle = GetEntity(ride->vehicles[ride->broken_vehicle]); vehicle->ClearUpdateFlag(VEHICLE_UPDATE_FLAG_BROKEN_CAR); break; case BREAKDOWN_VEHICLE_MALFUNCTION: - vehicle = &(get_sprite(ride->vehicles[ride->broken_vehicle])->vehicle); + vehicle = GetEntity(ride->vehicles[ride->broken_vehicle]); vehicle->ClearUpdateFlag(VEHICLE_UPDATE_FLAG_BROKEN_TRAIN); break; } @@ -4380,7 +4375,7 @@ static void window_ride_maintenance_paint(rct_window* w, rct_drawpixelinfo* dpi) } else { - auto peep = (&(get_sprite(ride->mechanic)->peep))->AsStaff(); + auto peep = GetEntity(ride->mechanic)->AsStaff(); if (peep != nullptr && peep->IsMechanic()) { peep->FormatNameTo(gCommonFormatArgs); diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index 6995aa4d13..1b69fc1424 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -336,7 +336,8 @@ rct_window* window_staff_open(Peep* peep) window_staff_disable_widgets(w); window_init_scroll_widgets(w); window_staff_viewport_init(w); - if (get_sprite(w->number)->peep.State == PEEP_STATE_PICKED) + + if (GetEntity(w->number)->State == PEEP_STATE_PICKED) window_event_mouse_up_call(w, WIDX_CHECKBOX_3); return w; @@ -348,7 +349,7 @@ rct_window* window_staff_open(Peep* peep) */ void window_staff_disable_widgets(rct_window* w) { - Peep* peep = &get_sprite(w->number)->peep; + Peep* peep = GetEntity(w->number); uint64_t disabled_widgets = (1 << WIDX_TAB_4); if (peep->StaffType == STAFF_TYPE_SECURITY) diff --git a/src/openrct2-ui/windows/StaffFirePrompt.cpp b/src/openrct2-ui/windows/StaffFirePrompt.cpp index 5a5306f1c9..3d523ac690 100644 --- a/src/openrct2-ui/windows/StaffFirePrompt.cpp +++ b/src/openrct2-ui/windows/StaffFirePrompt.cpp @@ -124,7 +124,7 @@ static void window_staff_fire_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); - Peep* peep = &get_sprite(w->number)->peep; + Peep* peep = GetEntity(w->number); peep->FormatNameTo(gCommonFormatArgs); diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index 72c6c75342..b1bfdaff3f 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -648,7 +648,7 @@ static void window_title_command_editor_tool_down( } else if (spriteIdentifier == SPRITE_IDENTIFIER_LITTER) { - Litter* litter = &(get_sprite(spriteIndex)->litter); + Litter* litter = GetEntity(spriteIndex); if (litter->type < std::size(litterNames)) { validSprite = true; diff --git a/src/openrct2/Editor.cpp b/src/openrct2/Editor.cpp index 2e7e6a2c82..c7575aabad 100644 --- a/src/openrct2/Editor.cpp +++ b/src/openrct2/Editor.cpp @@ -309,7 +309,7 @@ namespace Editor // for (int32_t i = 0; i < MAX_SPRITES; i++) { - auto peep = get_sprite(i)->generic.As(); + auto peep = GetEntity(i); if (peep != nullptr) { peep->SetName({}); diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 8c482e8942..68c8b5e558 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -614,10 +614,10 @@ void reset_all_sprite_quadrant_placements() { for (size_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* spr = get_sprite(i); - if (spr->generic.sprite_identifier != SPRITE_IDENTIFIER_NULL) + auto* spr = GetEntity(i); + if (spr->sprite_identifier != SPRITE_IDENTIFIER_NULL) { - spr->generic.MoveTo({ spr->generic.x, spr->generic.y, spr->generic.z }); + spr->MoveTo({ spr->x, spr->y, spr->z }); } } } diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp index ad32ad9fad..a46b0a48a8 100644 --- a/src/openrct2/GameStateSnapshots.cpp +++ b/src/openrct2/GameStateSnapshots.cpp @@ -132,6 +132,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots virtual void Capture(GameStateSnapshot_t& snapshot) override final { + // TODO refactor to not use this as a proxy for getting a pointer to the sprite array snapshot.SerialiseSprites(get_sprite(0), MAX_SPRITES, true); // log_info("Snapshot size: %u bytes", static_cast(snapshot.storedSprites.GetLength())); diff --git a/src/openrct2/actions/SetCheatAction.hpp b/src/openrct2/actions/SetCheatAction.hpp index f20a22cb31..c2ba7fe6c6 100644 --- a/src/openrct2/actions/SetCheatAction.hpp +++ b/src/openrct2/actions/SetCheatAction.hpp @@ -427,13 +427,10 @@ private: void RemoveLitter() const { - Litter* litter; - uint16_t spriteIndex, nextSpriteIndex; - - for (spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) + for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL;) { - litter = &(get_sprite(spriteIndex)->litter); - nextSpriteIndex = litter->next; + auto litter = GetEntity(spriteIndex); + spriteIndex = litter->next; sprite_remove(litter); } diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index a9b6a9c1f3..953d985e5a 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1573,11 +1573,11 @@ static int32_t cc_mp_desync(InteractiveConsole& console, const arguments_t& argv for (int i = 0; i < MAX_SPRITES; i++) { - rct_sprite* sprite = get_sprite(i); - if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_NULL) + auto* sprite = GetEntity(i); + if (sprite->sprite_identifier == SPRITE_IDENTIFIER_NULL) continue; - auto peep = sprite->generic.As(); + auto peep = sprite->As(); if (peep != nullptr) peeps.push_back(peep); } diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index b9a20fd62f..0cc3a7d6bc 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -175,8 +175,8 @@ void viewport_create( if (flags & VIEWPORT_FOCUS_TYPE_SPRITE) { w->viewport_target_sprite = sprite; - rct_sprite* centre_sprite = get_sprite(sprite); - centrePos = { centre_sprite->generic.x, centre_sprite->generic.y, centre_sprite->generic.z }; + auto* centre_sprite = GetEntity(sprite); + centrePos = { centre_sprite->x, centre_sprite->y, centre_sprite->z }; } else { @@ -619,14 +619,14 @@ void viewport_update_sprite_follow(rct_window* window) { if (window->viewport_target_sprite != SPRITE_INDEX_NULL && window->viewport) { - rct_sprite* sprite = get_sprite(window->viewport_target_sprite); + auto* sprite = GetEntity(window->viewport_target_sprite); - int32_t height = (tile_element_height({ sprite->generic.x, sprite->generic.y })) - 16; - int32_t underground = sprite->generic.z < height; + int32_t height = (tile_element_height({ sprite->x, sprite->y })) - 16; + int32_t underground = sprite->z < height; viewport_set_underground_flag(underground, window, window->viewport); - auto centreLoc = centre_2d_coordinates({ sprite->generic.x, sprite->generic.y, sprite->generic.z }, window->viewport); + auto centreLoc = centre_2d_coordinates({ sprite->x, sprite->y, sprite->z }, window->viewport); if (centreLoc) { window->savedViewPos = *centreLoc; diff --git a/src/openrct2/interface/Window_internal.cpp b/src/openrct2/interface/Window_internal.cpp index 1ef2425ea3..387cc552c4 100644 --- a/src/openrct2/interface/Window_internal.cpp +++ b/src/openrct2/interface/Window_internal.cpp @@ -19,10 +19,10 @@ void rct_window::ScrollToViewport() if (viewport_focus_sprite.type & VIEWPORT_FOCUS_TYPE_SPRITE) { - rct_sprite* sprite = get_sprite(viewport_focus_sprite.sprite_id); - newX = sprite->generic.x; - newY = sprite->generic.y; - newZ = sprite->generic.z; + auto* sprite = GetEntity(viewport_focus_sprite.sprite_id); + newX = sprite->x; + newY = sprite->y; + newZ = sprite->z; } else { diff --git a/src/openrct2/paint/sprite/Paint.Sprite.cpp b/src/openrct2/paint/sprite/Paint.Sprite.cpp index 54e146164f..d11e5b6763 100644 --- a/src/openrct2/paint/sprite/Paint.Sprite.cpp +++ b/src/openrct2/paint/sprite/Paint.Sprite.cpp @@ -35,12 +35,6 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t return; } - uint16_t sprite_idx = sprite_get_first_in_quadrant(x, y); - if (sprite_idx == SPRITE_INDEX_NULL) - { - return; - } - rct_drawpixelinfo* dpi = &session->DPI; if (dpi->zoom_level > 2) { @@ -49,22 +43,22 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t const bool highlightPathIssues = (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES); - for (const rct_sprite* spr = get_sprite(sprite_idx); sprite_idx != SPRITE_INDEX_NULL; - sprite_idx = spr->generic.next_in_quadrant) + for (uint16_t sprite_idx = sprite_get_first_in_quadrant(x, y); sprite_idx != SPRITE_INDEX_NULL;) { - spr = get_sprite(sprite_idx); + auto spr = GetEntity(sprite_idx); + sprite_idx = spr->next_in_quadrant; if (highlightPathIssues) { - if (spr->generic.Is()) + const auto peep = spr->As(); + if (peep != nullptr) { - const Peep* peep = reinterpret_cast(spr); if (!(peep->AssignedPeepType == PEEP_TYPE_STAFF && peep->StaffType == STAFF_TYPE_HANDYMAN)) { continue; } } - else if (spr->generic.sprite_identifier != SPRITE_IDENTIFIER_LITTER) + else if (spr->sprite_identifier != SPRITE_IDENTIFIER_LITTER) { continue; } @@ -76,15 +70,15 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t // height of the slope element, and consequently clipped. if ((session->ViewFlags & VIEWPORT_FLAG_CLIP_VIEW)) { - if (spr->generic.z > (gClipHeight * COORDS_Z_STEP)) + if (spr->z > (gClipHeight * COORDS_Z_STEP)) { continue; } - if (spr->generic.x < gClipSelectionA.x || spr->generic.x > gClipSelectionB.x) + if (spr->x < gClipSelectionA.x || spr->x > gClipSelectionB.x) { continue; } - if (spr->generic.y < gClipSelectionA.y || spr->generic.y > gClipSelectionB.y) + if (spr->y < gClipSelectionA.y || spr->y > gClipSelectionB.y) { continue; } @@ -92,41 +86,42 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t dpi = &session->DPI; - if (dpi->y + dpi->height <= spr->generic.sprite_top || spr->generic.sprite_bottom <= dpi->y - || dpi->x + dpi->width <= spr->generic.sprite_left || spr->generic.sprite_right <= dpi->x) + if (dpi->y + dpi->height <= spr->sprite_top || spr->sprite_bottom <= dpi->y || dpi->x + dpi->width <= spr->sprite_left + || spr->sprite_right <= dpi->x) { continue; } int32_t image_direction = session->CurrentRotation; image_direction <<= 3; - image_direction += spr->generic.sprite_direction; + image_direction += spr->sprite_direction; image_direction &= 0x1F; session->CurrentlyDrawnItem = spr; - session->SpritePosition.x = spr->generic.x; - session->SpritePosition.y = spr->generic.y; + session->SpritePosition.x = spr->x; + session->SpritePosition.y = spr->y; session->InteractionType = VIEWPORT_INTERACTION_ITEM_SPRITE; - switch (spr->generic.sprite_identifier) + switch (spr->sprite_identifier) { case SPRITE_IDENTIFIER_VEHICLE: - vehicle_paint(session, reinterpret_cast(spr), image_direction); + vehicle_paint(session, spr->As(), image_direction); #ifdef __ENABLE_LIGHTFX__ if (lightfx_for_vehicles_is_available()) { - lightfx_add_lights_magic_vehicle(reinterpret_cast(const_cast(spr))); + lightfx_add_lights_magic_vehicle(spr->As()); } #endif break; case SPRITE_IDENTIFIER_PEEP: - peep_paint(session, reinterpret_cast(spr), image_direction); + peep_paint(session, spr->As(), image_direction); break; case SPRITE_IDENTIFIER_MISC: - misc_paint(session, spr, image_direction); + // TODO: Update misc_paint to take a specific sprite type + misc_paint(session, reinterpret_cast(spr), image_direction); break; case SPRITE_IDENTIFIER_LITTER: - litter_paint(session, reinterpret_cast(spr), image_direction); + litter_paint(session, spr->As(), image_direction); break; default: assert(false); diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp index d60bd0a3e2..dafff3c097 100644 --- a/src/openrct2/peep/Guest.cpp +++ b/src/openrct2/peep/Guest.cpp @@ -3012,10 +3012,10 @@ static PeepThoughtType peep_assess_surroundings(int16_t centre_x, int16_t centre } } - Litter* litter; - for (uint16_t sprite_idx = gSpriteListHead[SPRITE_LIST_LITTER]; sprite_idx != SPRITE_INDEX_NULL; sprite_idx = litter->next) + for (uint16_t sprite_idx = gSpriteListHead[SPRITE_LIST_LITTER]; sprite_idx != SPRITE_INDEX_NULL;) { - litter = &(get_sprite(sprite_idx)->litter); + auto litter = GetEntity(sprite_idx); + sprite_idx = litter->next; int16_t dist_x = abs(litter->x - centre_x); int16_t dist_y = abs(litter->y - centre_y); @@ -5477,24 +5477,25 @@ void Guest::UpdateWalking() return; // Check if there is a peep watching (and if there is place for us) - uint16_t sprite_id = sprite_get_first_in_quadrant(x, y); - for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->generic.next_in_quadrant) + for (uint16_t sprite_id = sprite_get_first_in_quadrant(x, y); sprite_id != SPRITE_INDEX_NULL;) { - sprite = get_sprite(sprite_id); + auto sprite = GetEntity(sprite_id); + sprite_id = sprite->next_in_quadrant; + auto peep = sprite->As(); - if (!sprite->generic.Is()) + if (peep == nullptr) continue; - if (sprite->peep.State != PEEP_STATE_WATCHING) + if (peep->State != PEEP_STATE_WATCHING) continue; - if (z != sprite->peep.z) + if (z != peep->z) continue; - if ((sprite->peep.Var37 & 0x3) != chosen_edge) + if ((peep->Var37 & 0x3) != chosen_edge) continue; - positions_free &= ~(1 << ((sprite->peep.Var37 & 0x1C) >> 2)); + positions_free &= ~(1 << ((peep->Var37 & 0x1C) >> 2)); } if (!positions_free) @@ -6060,27 +6061,28 @@ bool Guest::UpdateWalkingFindBench() for (; !(edges & (1 << chosen_edge));) chosen_edge = (chosen_edge + 1) & 0x3; - uint16_t sprite_id = sprite_get_first_in_quadrant(x, y); uint8_t free_edge = 3; // Check if there is no peep sitting in chosen_edge - for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->generic.next_in_quadrant) + for (uint16_t sprite_id = sprite_get_first_in_quadrant(x, y); sprite_id != SPRITE_INDEX_NULL;) { - sprite = get_sprite(sprite_id); + auto sprite = GetEntity(sprite_id); + sprite_id = sprite->next_in_quadrant; + auto peep = sprite->As(); - if (!sprite->generic.Is()) + if (peep == nullptr) continue; - if (sprite->peep.State != PEEP_STATE_SITTING) + if (peep->State != PEEP_STATE_SITTING) continue; - if (z != sprite->peep.z) + if (z != peep->z) continue; - if ((sprite->peep.Var37 & 0x3) != chosen_edge) + if ((peep->Var37 & 0x3) != chosen_edge) continue; - free_edge &= ~(1 << ((sprite->peep.Var37 & 0x4) >> 2)); + free_edge &= ~(1 << ((peep->Var37 & 0x4) >> 2)); } if (!free_edge) @@ -6255,14 +6257,14 @@ static void peep_update_walking_break_scenery(Peep* peep) if (edges == 0xF) return; - uint16_t sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); - // Check if a peep is already sitting on the bench. If so, do not vandalise it. - for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->generic.next_in_quadrant) + for (uint16_t sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); sprite_id != SPRITE_INDEX_NULL;) { - sprite = get_sprite(sprite_id); + auto sprite = GetEntity(sprite_id); + sprite_id = sprite->next_in_quadrant; + auto peep2 = sprite->As(); - if (!sprite->generic.Is() || (sprite->peep.State != PEEP_STATE_SITTING) || (peep->z != sprite->peep.z)) + if (peep2 == nullptr || (peep2->State != PEEP_STATE_SITTING) || (peep->z != peep2->z)) { continue; } diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index f7a494f216..247f824bf7 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -2678,13 +2678,13 @@ static void peep_footpath_move_forward(Peep* peep, int16_t x, int16_t y, TileEle uint16_t crowded = 0; uint8_t litter_count = 0; uint8_t sick_count = 0; - uint16_t sprite_id = sprite_get_first_in_quadrant(x, y); - for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->generic.next_in_quadrant) + for (uint16_t sprite_id = sprite_get_first_in_quadrant(x, y); sprite_id != SPRITE_INDEX_NULL;) { - sprite = get_sprite(sprite_id); - if (sprite->generic.Is()) + auto sprite = GetEntity(sprite_id); + sprite_id = sprite->next_in_quadrant; + + if (auto other_peep = sprite->As(); other_peep != nullptr) { - Peep* other_peep = reinterpret_cast(sprite); if (other_peep->State != PEEP_STATE_WALKING) continue; @@ -2693,9 +2693,8 @@ static void peep_footpath_move_forward(Peep* peep, int16_t x, int16_t y, TileEle crowded++; continue; } - else if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_LITTER) + else if (auto litter = sprite->As(); litter != nullptr) { - Litter* litter = reinterpret_cast(sprite); if (abs(litter->z - peep->NextLoc.z) > 16) continue; diff --git a/src/openrct2/peep/Peep.h b/src/openrct2/peep/Peep.h index 67b832c2a5..bb225dc959 100644 --- a/src/openrct2/peep/Peep.h +++ b/src/openrct2/peep/Peep.h @@ -994,7 +994,7 @@ enum */ #define FOR_ALL_PEEPS(sprite_index, peep) \ for ((sprite_index) = gSpriteListHead[SPRITE_LIST_PEEP]; (sprite_index) != SPRITE_INDEX_NULL; (sprite_index) = peep->next) \ - if (((peep) = GET_PEEP(sprite_index)) != nullptr || 1) + if (((peep) = GetEntity(sprite_index)) != nullptr || 1) #define FOR_ALL_GUESTS(sprite_index, peep) \ FOR_ALL_PEEPS (sprite_index, peep) \ diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index 56896abe37..519d99cbcd 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -126,7 +126,7 @@ bool staff_hire_new_member(STAFF_TYPE staffType, ENTERTAINER_COSTUME entertainer return; // Open window for new staff. - Peep* peep = &get_sprite(res->peepSriteIndex)->peep; + auto peep = GetEntity(res->peepSriteIndex); auto intent = Intent(WC_PEEP); intent.putExtra(INTENT_EXTRA_PEEP, peep); context_open_intent(&intent); @@ -443,11 +443,10 @@ static uint8_t staff_handyman_direction_to_nearest_litter(Peep* peep) { uint16_t nearestLitterDist = 0xFFFF; Litter* nearestLitter = nullptr; - Litter* litter = nullptr; - - for (uint16_t litterIndex = gSpriteListHead[SPRITE_LIST_LITTER]; litterIndex != 0xFFFF; litterIndex = litter->next) + for (uint16_t litterIndex = gSpriteListHead[SPRITE_LIST_LITTER]; litterIndex != SPRITE_INDEX_NULL;) { - litter = &get_sprite(litterIndex)->litter; + auto litter = GetEntity(litterIndex); + litterIndex = litter->next; uint16_t distance = abs(litter->x - peep->x) + abs(litter->y - peep->y) + abs(litter->z - peep->z) * 4; @@ -1817,24 +1816,25 @@ static int32_t peep_update_patrolling_find_sweeping(Peep* peep) if (!(peep->StaffOrders & STAFF_ORDERS_SWEEPING)) return 0; - uint16_t sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); - - for (rct_sprite* sprite = nullptr; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->generic.next_in_quadrant) + for (uint16_t sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); sprite_id != SPRITE_INDEX_NULL;) { - sprite = get_sprite(sprite_id); + auto sprite = GetEntity(sprite_id); + sprite_id = sprite->next_in_quadrant; + auto litter = sprite->As(); - if (sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_LITTER) + if (litter == nullptr) continue; - uint16_t z_diff = abs(peep->z - sprite->litter.z); + uint16_t z_diff = abs(peep->z - litter->z); if (z_diff >= 16) continue; peep->SetState(PEEP_STATE_SWEEPING); + peep->Var37 = 0; - peep->DestinationX = sprite->litter.x; - peep->DestinationY = sprite->litter.y; + peep->DestinationX = litter->x; + peep->DestinationY = litter->y; peep->DestinationTolerance = 5; return 1; } diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 1961158c29..bcc8fb077f 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1341,10 +1341,9 @@ private: } for (size_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* sprite = get_sprite(i); - if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE) + auto vehicle = GetEntity(i); + if (vehicle != nullptr) { - Vehicle* vehicle = reinterpret_cast(sprite); FixVehiclePeepLinks(vehicle, spriteIndexMap); } } diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index ea0bd00f95..c150730224 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -945,7 +945,7 @@ void S6Exporter::ExportSprites() sprite_clear_all_unused(); for (int32_t i = 0; i < RCT2_MAX_SPRITES; i++) { - ExportSprite(&_s6.sprites[i], get_sprite(i)); + ExportSprite(&_s6.sprites[i], reinterpret_cast(GetEntity(i))); } for (int32_t i = 0; i < SPRITE_LIST_COUNT; i++) diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 23fd05548b..873a504044 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1282,8 +1282,8 @@ public: for (int32_t i = 0; i < RCT2_MAX_SPRITES; i++) { auto src = &_s6.sprites[i]; - auto dst = get_sprite(i); - ImportSprite(dst, src); + auto dst = GetEntity(i); + ImportSprite(reinterpret_cast(dst), src); } for (int32_t i = 0; i < SPRITE_LIST_COUNT; i++) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index a0d3cacd0c..422eae379a 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -831,10 +831,9 @@ size_t Ride::FormatStatusTo(void* argsV) const mode == RIDE_MODE_RACE && !(lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) && race_winner != SPRITE_INDEX_NULL) { - auto sprite = get_sprite(race_winner); - if (sprite != nullptr && sprite->generic.Is()) + auto peep = GetEntity(race_winner); + if (peep != nullptr) { - auto peep = sprite->generic.As(); ft.Add(STR_RACE_WON_BY); peep->FormatNameTo(ft); } @@ -2739,10 +2738,12 @@ Staff* ride_get_mechanic(Ride* ride) { if (ride->mechanic != SPRITE_INDEX_NULL) { - auto peep = (&(get_sprite(ride->mechanic)->peep))->AsStaff(); - if (peep != nullptr && peep->IsMechanic()) + auto peep = GetEntity(ride->mechanic); + if (peep != nullptr) { - return peep; + auto staff = peep->AsStaff(); + if (staff != nullptr && staff->IsMechanic()) + return staff; } } return nullptr; diff --git a/src/openrct2/ride/Station.cpp b/src/openrct2/ride/Station.cpp index d6e482f266..53049dc01a 100644 --- a/src/openrct2/ride/Station.cpp +++ b/src/openrct2/ride/Station.cpp @@ -281,7 +281,7 @@ static void ride_race_init_vehicle_speeds(Ride* ride) if (vehicle->num_peeps != 0) { - Peep* peep = &get_sprite(vehicle->peep[0])->peep; + auto peep = GetEntity(vehicle->peep[0]); // Easter egg names should only work on guests Guest* guest = peep->AsGuest(); diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 92cba22248..b125adaaa8 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -1321,9 +1321,11 @@ void vehicle_sounds_update() vehicle_sounds_update_window_setup(); - for (uint16_t i = gSpriteListHead[SPRITE_LIST_TRAIN_HEAD]; i != SPRITE_INDEX_NULL; i = get_sprite(i)->vehicle.next) + for (uint16_t i = gSpriteListHead[SPRITE_LIST_TRAIN_HEAD]; i != SPRITE_INDEX_NULL;) { - get_sprite(i)->vehicle.UpdateSoundParams(vehicleSoundParamsList); + auto vehicle = GetEntity(i); + i = vehicle->next; + vehicle->UpdateSoundParams(vehicleSoundParamsList); } // Stop all playing sounds that no longer have priority to play after vehicle_update_sound_params @@ -5632,12 +5634,7 @@ void Vehicle::UpdateSound() */ SoundId Vehicle::UpdateScreamSound() { - uint32_t r; - uint16_t spriteIndex; - rct_ride_entry* rideEntry; - Vehicle* vehicle2; - - rideEntry = get_ride_entry(ride_subtype); + rct_ride_entry* rideEntry = get_ride_entry(ride_subtype); rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle_type]; @@ -5650,10 +5647,11 @@ SoundId Vehicle::UpdateScreamSound() if (velocity > -0x2C000) return SoundId::Null; - spriteIndex = sprite_index; - do + for (uint16_t spriteIndex = sprite_index; spriteIndex != SPRITE_INDEX_NULL;) { - vehicle2 = &(get_sprite(spriteIndex)->vehicle); + auto vehicle2 = GetEntity(spriteIndex); + spriteIndex = vehicle2->next_vehicle_on_train; + if (vehicle2->vehicle_sprite_type < 1) continue; if (vehicle2->vehicle_sprite_type <= 4) @@ -5662,17 +5660,18 @@ SoundId Vehicle::UpdateScreamSound() continue; if (vehicle2->vehicle_sprite_type <= 15) goto produceScream; - } while ((spriteIndex = vehicle2->next_vehicle_on_train) != SPRITE_INDEX_NULL); + } return SoundId::Null; } if (velocity < 0x2C000) return SoundId::Null; - spriteIndex = sprite_index; - do + for (uint16_t spriteIndex = sprite_index; spriteIndex != SPRITE_INDEX_NULL;) { - vehicle2 = &(get_sprite(spriteIndex)->vehicle); + auto vehicle2 = GetEntity(spriteIndex); + spriteIndex = vehicle2->next_vehicle_on_train; + if (vehicle2->vehicle_sprite_type < 5) continue; if (vehicle2->vehicle_sprite_type <= 8) @@ -5681,13 +5680,13 @@ SoundId Vehicle::UpdateScreamSound() continue; if (vehicle2->vehicle_sprite_type <= 23) goto produceScream; - } while ((spriteIndex = vehicle2->next_vehicle_on_train) != SPRITE_INDEX_NULL); + } return SoundId::Null; produceScream: if (scream_sound_id == SoundId::Null) { - r = scenario_rand(); + auto r = scenario_rand(); if (totalNumPeeps >= static_cast(r % 16)) { switch (vehicleEntry->sound_range) @@ -9713,17 +9712,12 @@ rct_ride_entry_vehicle* Vehicle::Entry() const int32_t Vehicle::NumPeepsUntilTrainTail() const { - const Vehicle* vehicle = this; - uint16_t spriteIndex; int32_t numPeeps = 0; - for (;;) + for (uint16_t spriteIndex = sprite_index; spriteIndex != SPRITE_INDEX_NULL;) { - numPeeps += vehicle->num_peeps; + const Vehicle* vehicle = GetEntity(spriteIndex); spriteIndex = vehicle->next_vehicle_on_train; - if (spriteIndex == SPRITE_INDEX_NULL) - break; - - vehicle = &(get_sprite(spriteIndex)->vehicle); + numPeeps += vehicle->num_peeps; } return numPeeps; diff --git a/src/openrct2/ride/gentle/CrookedHouse.cpp b/src/openrct2/ride/gentle/CrookedHouse.cpp index 5b0c9f42d6..0c74453f8e 100644 --- a/src/openrct2/ride/gentle/CrookedHouse.cpp +++ b/src/openrct2/ride/gentle/CrookedHouse.cpp @@ -48,7 +48,7 @@ static void paint_crooked_house_structure( { if (ride->vehicles[0] != SPRITE_INDEX_NULL) { - rct_sprite* sprite = get_sprite(ride->vehicles[0]); + auto sprite = GetEntity(ride->vehicles[0]); session->InteractionType = VIEWPORT_INTERACTION_ITEM_SPRITE; session->CurrentlyDrawnItem = sprite; } diff --git a/src/openrct2/ride/gentle/MiniGolf.cpp b/src/openrct2/ride/gentle/MiniGolf.cpp index 0bf3a48199..bb57347100 100644 --- a/src/openrct2/ride/gentle/MiniGolf.cpp +++ b/src/openrct2/ride/gentle/MiniGolf.cpp @@ -1216,13 +1216,13 @@ void vehicle_visual_mini_golf_player( if (rideEntry == nullptr) return; - rct_sprite* sprite = get_sprite(vehicle->peep[0]); + auto* peep = GetEntity(vehicle->peep[0]); uint8_t frame = mini_golf_peep_animation_frames[vehicle->mini_golf_current_animation][vehicle->animation_frame]; uint32_t ebx = (frame << 2) + (imageDirection >> 3); uint32_t image_id = rideEntry->vehicles[0].base_image_id + 1 + ebx; - uint32_t peep_palette = sprite->peep.TshirtColour << 19 | sprite->peep.TrousersColour << 24 | 0x0A0000000; + uint32_t peep_palette = peep->TshirtColour << 19 | peep->TrousersColour << 24 | 0x0A0000000; sub_98197C(session, image_id | peep_palette, 0, 0, 1, 1, 11, z, 0, 0, z + 5); } diff --git a/src/openrct2/scripting/ScEntity.hpp b/src/openrct2/scripting/ScEntity.hpp index daecef03c7..ee4836ecdc 100644 --- a/src/openrct2/scripting/ScEntity.hpp +++ b/src/openrct2/scripting/ScEntity.hpp @@ -162,7 +162,7 @@ namespace OpenRCT2::Scripting SpriteBase* GetEntity() const { - return &get_sprite(_id)->generic; + return ::GetEntity(_id); } public: @@ -746,7 +746,7 @@ namespace OpenRCT2::Scripting protected: Peep* GetPeep() const { - return get_sprite(_id)->generic.As(); + return ::GetEntity(_id); } }; diff --git a/src/openrct2/scripting/ScMap.hpp b/src/openrct2/scripting/ScMap.hpp index ee1a0f8704..7628f60de9 100644 --- a/src/openrct2/scripting/ScMap.hpp +++ b/src/openrct2/scripting/ScMap.hpp @@ -89,10 +89,10 @@ namespace OpenRCT2::Scripting if (id >= 0 && id < MAX_SPRITES) { auto spriteId = static_cast(id); - auto sprite = get_sprite(spriteId); - if (sprite != nullptr && sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_NULL) + auto sprite = GetEntity(spriteId); + if (sprite != nullptr && sprite->sprite_identifier != SPRITE_IDENTIFIER_NULL) { - return GetEntityAsDukValue(sprite); + return GetEntityAsDukValue(reinterpret_cast(sprite)); } } duk_push_null(_context); @@ -131,49 +131,35 @@ namespace OpenRCT2::Scripting } std::vector result; - auto spriteId = gSpriteListHead[targetList]; - while (spriteId != SPRITE_INDEX_NULL) + + for (auto spriteId = gSpriteListHead[targetList]; spriteId != SPRITE_INDEX_NULL;) { - auto sprite = get_sprite(spriteId); - if (sprite == nullptr) + auto sprite = GetEntity(spriteId); + spriteId = sprite->next; + + // Only the misc list checks the type property + if (targetList != SPRITE_LIST_MISC || sprite->type == targetType) { - break; - } - else - { - // Only the misc list checks the type property - if (targetList != SPRITE_LIST_MISC || sprite->generic.type == targetType) + if (targetList == SPRITE_LIST_PEEP) { - if (targetList == SPRITE_LIST_PEEP) - { - if (sprite->peep.AssignedPeepType == PEEP_TYPE_STAFF) - result.push_back(GetObjectAsDukValue(_context, std::make_shared(spriteId))); - else - result.push_back(GetObjectAsDukValue(_context, std::make_shared(spriteId))); - } - else if (targetList == SPRITE_LIST_TRAIN_HEAD) - { - auto carId = spriteId; - while (carId != SPRITE_INDEX_NULL) - { - auto car = get_sprite(carId); - if (car == nullptr) - { - break; - } - else - { - result.push_back(GetObjectAsDukValue(_context, std::make_shared(carId))); - carId = car->vehicle.next_vehicle_on_train; - } - } - } + if (sprite->As()->AssignedPeepType == PEEP_TYPE_STAFF) + 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 == SPRITE_LIST_TRAIN_HEAD) + { + for (auto carId = sprite->sprite_index; carId != SPRITE_INDEX_NULL;) { - result.push_back(GetObjectAsDukValue(_context, std::make_shared(spriteId))); + auto car = GetEntity(carId); + carId = car->next_vehicle_on_train; + result.push_back(GetObjectAsDukValue(_context, std::make_shared(carId))); } } - spriteId = sprite->generic.next; + else + { + result.push_back(GetObjectAsDukValue(_context, std::make_shared(sprite->sprite_index))); + } } } return result; diff --git a/src/openrct2/world/Duck.cpp b/src/openrct2/world/Duck.cpp index 2be9f11739..ca83e93358 100644 --- a/src/openrct2/world/Duck.cpp +++ b/src/openrct2/world/Duck.cpp @@ -363,12 +363,10 @@ void duck_press(Duck* duck) void duck_remove_all() { - uint16_t nextSpriteIndex; - for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL; - spriteIndex = nextSpriteIndex) + for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL;) { - SpriteGeneric* sprite = &(get_sprite(spriteIndex)->generic); - nextSpriteIndex = sprite->next; + auto sprite = GetEntity(spriteIndex); + spriteIndex = sprite->next; if (sprite->type == SPRITE_MISC_DUCK) { sprite->Invalidate1(); diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 8cd13e63e5..7b994fafdb 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -390,21 +390,20 @@ CoordsXY footpath_bridge_get_info_from_pos(const ScreenCoordsXY& screenCoords, i */ void footpath_remove_litter(const CoordsXYZ& footpathPos) { - uint16_t spriteIndex = sprite_get_first_in_quadrant(footpathPos.x, footpathPos.y); - while (spriteIndex != SPRITE_INDEX_NULL) + for (uint16_t spriteIndex = sprite_get_first_in_quadrant(footpathPos.x, footpathPos.y); spriteIndex != SPRITE_INDEX_NULL;) { - Litter* sprite = &get_sprite(spriteIndex)->litter; - uint16_t nextSpriteIndex = sprite->next_in_quadrant; - if (sprite->sprite_identifier == SPRITE_IDENTIFIER_LITTER) + auto sprite = GetEntity(spriteIndex); + spriteIndex = sprite->next_in_quadrant; + Litter* litter = sprite->As(); + if (litter != nullptr) { - int32_t distanceZ = abs(sprite->z - footpathPos.z); + int32_t distanceZ = abs(litter->z - footpathPos.z); if (distanceZ <= 32) { - sprite->Invalidate0(); - sprite_remove(sprite); + litter->Invalidate0(); + sprite_remove(litter); } } - spriteIndex = nextSpriteIndex; } } @@ -414,14 +413,13 @@ void footpath_remove_litter(const CoordsXYZ& footpathPos) */ void footpath_interrupt_peeps(const CoordsXYZ& footpathPos) { - uint16_t spriteIndex = sprite_get_first_in_quadrant(footpathPos.x, footpathPos.y); - while (spriteIndex != SPRITE_INDEX_NULL) + for (auto spriteIndex = sprite_get_first_in_quadrant(footpathPos.x, footpathPos.y); spriteIndex != SPRITE_INDEX_NULL;) { - auto* entity = get_sprite(spriteIndex); - uint16_t nextSpriteIndex = entity->generic.next_in_quadrant; - if (entity->generic.Is()) + auto entity = GetEntity(spriteIndex); + spriteIndex = entity->next_in_quadrant; + auto peep = entity->As(); + if (peep != nullptr) { - Peep* peep = &entity->peep; if (peep->State == PEEP_STATE_SITTING || peep->State == PEEP_STATE_WATCHING) { if (peep->z == footpathPos.z) @@ -434,7 +432,6 @@ void footpath_interrupt_peeps(const CoordsXYZ& footpathPos) } } } - spriteIndex = nextSpriteIndex; } } diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index 3f00f93747..ad7bf164b8 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -159,12 +159,8 @@ static bool map_animation_invalidate_queue_banner(const CoordsXYZ& loc) static bool map_animation_invalidate_small_scenery(const CoordsXYZ& loc) { TileCoordsXYZ tileLoc{ loc }; - TileElement* tileElement; - rct_scenery_entry* sceneryEntry; - rct_sprite* sprite; - Peep* peep; - tileElement = map_get_first_element_at(loc); + auto tileElement = map_get_first_element_at(loc); if (tileElement == nullptr) return true; do @@ -176,7 +172,7 @@ static bool map_animation_invalidate_small_scenery(const CoordsXYZ& loc) if (tileElement->IsGhost()) continue; - sceneryEntry = tileElement->AsSmallScenery()->GetEntry(); + auto sceneryEntry = tileElement->AsSmallScenery()->GetEntry(); if (sceneryEntry == nullptr) continue; @@ -198,14 +194,14 @@ static bool map_animation_invalidate_small_scenery(const CoordsXYZ& loc) int32_t x2 = loc.x - CoordsDirectionDelta[direction].x; int32_t y2 = loc.y - CoordsDirectionDelta[direction].y; - uint16_t spriteIdx = sprite_get_first_in_quadrant(x2, y2); - for (; spriteIdx != SPRITE_INDEX_NULL; spriteIdx = sprite->generic.next_in_quadrant) + for (uint16_t spriteIdx = sprite_get_first_in_quadrant(x2, y2); spriteIdx != SPRITE_INDEX_NULL;) { - sprite = get_sprite(spriteIdx); - if (!sprite->generic.Is()) + auto sprite = GetEntity(spriteIdx); + spriteIdx = sprite->next_in_quadrant; + auto peep = sprite->As(); + if (peep == nullptr) continue; - peep = &sprite->peep; if (peep->State != PEEP_STATE_WALKING) continue; if (peep->z != loc.z) diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 4d90830b96..208707c1b5 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -469,12 +469,11 @@ int32_t Park::CalculateParkRating() const // Litter { - Litter* litter; int32_t litterCount = 0; - for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL; - spriteIndex = litter->next) + for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL;) { - litter = &(get_sprite(spriteIndex)->litter); + auto litter = GetEntity(spriteIndex); + spriteIndex = litter->next; // Ignore recently dropped litter if (litter->creationTick - gScenarioTicks >= 7680) diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index cc7bef4857..2675bbd698 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -52,6 +52,12 @@ static CoordsXYZ _spritelocations2[MAX_SPRITES]; static size_t GetSpatialIndexOffset(int32_t x, int32_t y); static void move_sprite_to_list(SpriteBase* sprite, SPRITE_LIST newListIndex); +// Required for GetEntity to return a default +template<> bool SpriteBase::Is() const +{ + return true; +} + template<> bool SpriteBase::Is() const { return sprite_identifier == SPRITE_IDENTIFIER_LITTER; @@ -111,6 +117,11 @@ rct_sprite* get_sprite(size_t sprite_idx) return &_spriteList[sprite_idx]; } +SpriteBase* GetEntity(size_t sprite_idx) +{ + return GetEntity(sprite_idx); +} + uint16_t sprite_get_first_in_quadrant(int32_t x, int32_t y) { return gSpriteSpatialIndex[GetSpatialIndexOffset(x, y)]; @@ -174,24 +185,24 @@ void reset_sprite_list() _spriteFlashingList[i] = false; } - rct_sprite* previous_spr = nullptr; + SpriteBase* previous_spr = nullptr; for (int32_t i = 0; i < MAX_SPRITES; ++i) { - rct_sprite* spr = get_sprite(i); - spr->generic.sprite_identifier = SPRITE_IDENTIFIER_NULL; - spr->generic.sprite_index = i; - spr->generic.next = SPRITE_INDEX_NULL; - spr->generic.linked_list_index = SPRITE_LIST_FREE; + auto* spr = GetEntity(i); + spr->sprite_identifier = SPRITE_IDENTIFIER_NULL; + spr->sprite_index = i; + spr->next = SPRITE_INDEX_NULL; + spr->linked_list_index = SPRITE_LIST_FREE; if (previous_spr != nullptr) { - spr->generic.previous = previous_spr->generic.sprite_index; - previous_spr->generic.next = i; + spr->previous = previous_spr->sprite_index; + previous_spr->next = i; } else { - spr->generic.previous = SPRITE_INDEX_NULL; + spr->previous = SPRITE_INDEX_NULL; gSpriteListHead[SPRITE_LIST_FREE] = i; } _spriteFlashingList[i] = false; @@ -214,13 +225,13 @@ void reset_sprite_spatial_index() std::fill_n(gSpriteSpatialIndex, std::size(gSpriteSpatialIndex), SPRITE_INDEX_NULL); for (size_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* spr = get_sprite(i); - if (spr->generic.sprite_identifier != SPRITE_IDENTIFIER_NULL) + auto* spr = GetEntity(i); + if (spr->sprite_identifier != SPRITE_IDENTIFIER_NULL) { - size_t index = GetSpatialIndexOffset(spr->generic.x, spr->generic.y); + size_t index = GetSpatialIndexOffset(spr->x, spr->y); uint32_t nextSpriteId = gSpriteSpatialIndex[index]; - gSpriteSpatialIndex[index] = spr->generic.sprite_index; - spr->generic.next_in_quadrant = nextSpriteId; + gSpriteSpatialIndex[index] = spr->sprite_index; + spr->next_in_quadrant = nextSpriteId; } } } @@ -267,6 +278,7 @@ rct_sprite_checksum sprite_checksum() _spriteHashAlg->Clear(); for (size_t i = 0; i < MAX_SPRITES; i++) { + // TODO create a way to copy only the specific type auto sprite = get_sprite(i); if (sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_NULL && sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_MISC) @@ -278,10 +290,10 @@ rct_sprite_checksum sprite_checksum() copy.generic.sprite_width = copy.generic.sprite_height_negative = copy.generic.sprite_height_positive = 0; // Next in quadrant might be a misc sprite, set first non-misc sprite in quadrant. - while (auto* nextSprite = get_sprite(copy.generic.next_in_quadrant)) + while (auto* nextSprite = GetEntity(copy.generic.next_in_quadrant)) { - if (nextSprite->generic.sprite_identifier == SPRITE_IDENTIFIER_MISC) - copy.generic.next_in_quadrant = nextSprite->generic.next_in_quadrant; + if (nextSprite->sprite_identifier == SPRITE_IDENTIFIER_MISC) + copy.generic.next_in_quadrant = nextSprite->next_in_quadrant; else break; } @@ -346,21 +358,14 @@ static void sprite_reset(SpriteBase* sprite) */ void sprite_clear_all_unused() { - SpriteGeneric* sprite; - uint16_t spriteIndex, nextSpriteIndex; - - spriteIndex = gSpriteListHead[SPRITE_LIST_FREE]; - while (spriteIndex != SPRITE_INDEX_NULL) + for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_FREE]; spriteIndex != SPRITE_INDEX_NULL;) { - sprite = &get_sprite(spriteIndex)->generic; - nextSpriteIndex = sprite->next; + auto sprite = GetEntity(spriteIndex); + spriteIndex = sprite->next; + sprite_reset(sprite); sprite->linked_list_index = SPRITE_LIST_FREE; - // This shouldn't be necessary, as sprite_reset() preserves the index - // but it has been left in as a safety net in case the index isn't set correctly - sprite->sprite_index = spriteIndex; - // sprite->next_in_quadrant will only end up as zero owing to corruption // most likely due to previous builds not preserving it when resetting sprites // We reset it to SPRITE_INDEX_NULL to prevent cycles in the sprite lists @@ -368,8 +373,7 @@ void sprite_clear_all_unused() { sprite->next_in_quadrant = SPRITE_INDEX_NULL; } - _spriteFlashingList[spriteIndex] = false; - spriteIndex = nextSpriteIndex; + _spriteFlashingList[sprite->sprite_index] = false; } } @@ -397,7 +401,7 @@ rct_sprite* create_sprite(SPRITE_IDENTIFIER spriteIdentifier, SPRITE_LIST linked } } - SpriteGeneric* sprite = &(get_sprite(gSpriteListHead[SPRITE_LIST_FREE]))->generic; + auto* sprite = GetEntity(gSpriteListHead[SPRITE_LIST_FREE]); move_sprite_to_list(sprite, linkedListIndex); @@ -467,13 +471,13 @@ static void move_sprite_to_list(SpriteBase* sprite, SPRITE_LIST newListIndex) else { // Hook up sprite->previous->next to sprite->next, removing the sprite from its old list - get_sprite(sprite->previous)->generic.next = sprite->next; + GetEntity(sprite->previous)->next = sprite->next; } // Similarly, hook up sprite->next->previous to sprite->previous if (sprite->next != SPRITE_INDEX_NULL) { - get_sprite(sprite->next)->generic.previous = sprite->previous; + GetEntity(sprite->next)->previous = sprite->previous; } sprite->previous = SPRITE_INDEX_NULL; // We become the new head of the target list, so there's no previous sprite @@ -485,7 +489,7 @@ static void move_sprite_to_list(SpriteBase* sprite, SPRITE_LIST newListIndex) if (sprite->next != SPRITE_INDEX_NULL) { // Fix the chain by settings sprite->next->previous to sprite_index - get_sprite(sprite->next)->generic.previous = sprite->sprite_index; + GetEntity(sprite->next)->previous = sprite->sprite_index; } // These globals are probably counters for each sprite list? @@ -627,15 +631,11 @@ static void sprite_misc_update(rct_sprite* sprite) */ void sprite_misc_update_all() { - rct_sprite* sprite; - uint16_t spriteIndex; - - spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; - while (spriteIndex != SPRITE_INDEX_NULL) + for (auto spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL;) { - sprite = get_sprite(spriteIndex); - spriteIndex = sprite->generic.next; - sprite_misc_update(sprite); + auto sprite = GetEntity(spriteIndex); + spriteIndex = sprite->next; + sprite_misc_update(reinterpret_cast(sprite)); } } @@ -647,7 +647,7 @@ static void SpriteSpatialInsert(SpriteBase* sprite, const CoordsXY& newLoc) auto* next = &gSpriteSpatialIndex[newIndex]; while (sprite->sprite_index < *next && *next != SPRITE_INDEX_NULL) { - auto sprite2 = &get_sprite(*next)->generic; + auto sprite2 = GetEntity(*next); next = &sprite2->next_in_quadrant; } @@ -667,7 +667,7 @@ static void SpriteSpatialRemove(SpriteBase* sprite) reset_sprite_spatial_index(); } - auto* sprite2 = &get_sprite(*index)->generic; + auto* sprite2 = GetEntity(*index); while (sprite != sprite2) { index = &sprite2->next_in_quadrant; @@ -675,7 +675,7 @@ static void SpriteSpatialRemove(SpriteBase* sprite) { break; } - sprite2 = &get_sprite(*index)->generic; + sprite2 = GetEntity(*index); } *index = sprite->next_in_quadrant; } @@ -756,7 +756,7 @@ void sprite_remove(SpriteBase* sprite) size_t quadrantIndex = GetSpatialIndexOffset(sprite->x, sprite->y); uint16_t* spriteIndex = &gSpriteSpatialIndex[quadrantIndex]; SpriteBase* quadrantSprite; - while (*spriteIndex != SPRITE_INDEX_NULL && (quadrantSprite = &get_sprite(*spriteIndex)->generic) != sprite) + while (*spriteIndex != SPRITE_INDEX_NULL && (quadrantSprite = GetEntity(*spriteIndex)) != sprite) { spriteIndex = &quadrantSprite->next_in_quadrant; } @@ -806,11 +806,10 @@ void litter_create(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t t { Litter* newestLitter = nullptr; uint32_t newestLitterCreationTick = 0; - for (uint16_t nextSpriteIndex, spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL; - spriteIndex = nextSpriteIndex) + for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL;) { - Litter* litter = &get_sprite(spriteIndex)->litter; - nextSpriteIndex = litter->next; + Litter* litter = GetEntity(spriteIndex); + spriteIndex = litter->next; if (newestLitterCreationTick <= litter->creationTick) { newestLitterCreationTick = litter->creationTick; @@ -846,15 +845,13 @@ void litter_create(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t t */ void litter_remove_at(int32_t x, int32_t y, int32_t z) { - uint16_t spriteIndex = sprite_get_first_in_quadrant(x, y); - while (spriteIndex != SPRITE_INDEX_NULL) + for (uint16_t spriteIndex = sprite_get_first_in_quadrant(x, y); spriteIndex != SPRITE_INDEX_NULL;) { - rct_sprite* sprite = get_sprite(spriteIndex); - uint16_t nextSpriteIndex = sprite->generic.next_in_quadrant; - if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_LITTER) + auto* sprite = GetEntity(spriteIndex); + spriteIndex = sprite->next_in_quadrant; + auto* litter = sprite->As(); + if (litter != nullptr) { - Litter* litter = &sprite->litter; - if (abs(litter->z - z) <= 16) { if (abs(litter->x - x) <= 8 && abs(litter->y - y) <= 8) @@ -864,7 +861,6 @@ void litter_remove_at(int32_t x, int32_t y, int32_t z) } } } - spriteIndex = nextSpriteIndex; } } @@ -877,26 +873,24 @@ uint16_t remove_floating_sprites() uint16_t removed = 0; for (uint16_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* rctSprite = get_sprite(i); - if (rctSprite->generic.Is()) + auto* entity = GetEntity(i); + if (entity->Is()) { - sprite_remove(&rctSprite->generic); - sprite_misc_update(rctSprite); + sprite_remove(entity); removed++; } - else if (rctSprite->generic.Is()) + else if (entity->Is()) { - if (rctSprite->generic.As()->IsFlying()) + auto* duck = entity->As(); + if (duck->IsFlying()) { - rctSprite->duck.Remove(); - sprite_misc_update(rctSprite); + duck->Remove(); removed++; } } - else if (rctSprite->generic.Is()) + else if (entity->Is()) { - sprite_remove(&rctSprite->generic); - sprite_misc_update(rctSprite); + sprite_remove(entity); removed++; } } @@ -906,9 +900,9 @@ uint16_t remove_floating_sprites() /** * Determines whether it's worth tweening a sprite or not when frame smoothing is on. */ -static bool sprite_should_tween(rct_sprite* sprite) +static bool sprite_should_tween(SpriteBase* sprite) { - switch (sprite->generic.sprite_identifier) + switch (sprite->sprite_identifier) { case SPRITE_IDENTIFIER_PEEP: case SPRITE_IDENTIFIER_VEHICLE: @@ -946,7 +940,7 @@ void sprite_position_tween_all(float alpha) for (uint16_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* sprite = get_sprite(i); + auto* sprite = GetEntity(i); if (sprite_should_tween(sprite)) { auto posA = _spritelocations1[i]; @@ -957,8 +951,8 @@ void sprite_position_tween_all(float alpha) } sprite_set_coordinates( std::round(posB.x * alpha + posA.x * inv), std::round(posB.y * alpha + posA.y * inv), - std::round(posB.z * alpha + posA.z * inv), &sprite->generic); - sprite->generic.Invalidate2(); + std::round(posB.z * alpha + posA.z * inv), sprite); + sprite->Invalidate2(); } } } @@ -970,13 +964,13 @@ void sprite_position_tween_restore() { for (uint16_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* sprite = get_sprite(i); + auto* sprite = GetEntity(i); if (sprite_should_tween(sprite)) { - sprite->generic.Invalidate2(); + sprite->Invalidate2(); auto pos = _spritelocations2[i]; - sprite_set_coordinates(pos.x, pos.y, pos.z, &sprite->generic); + sprite_set_coordinates(pos.x, pos.y, pos.z, sprite); } } } @@ -985,10 +979,10 @@ void sprite_position_tween_reset() { for (uint16_t i = 0; i < MAX_SPRITES; i++) { - rct_sprite* sprite = get_sprite(i); - _spritelocations1[i].x = _spritelocations2[i].x = sprite->generic.x; - _spritelocations1[i].y = _spritelocations2[i].y = sprite->generic.y; - _spritelocations1[i].z = _spritelocations2[i].z = sprite->generic.z; + auto* sprite = GetEntity(i); + _spritelocations1[i].x = _spritelocations2[i].x = sprite->x; + _spritelocations1[i].y = _spritelocations2[i].y = sprite->y; + _spritelocations1[i].z = _spritelocations2[i].z = sprite->z; } } @@ -1004,72 +998,72 @@ bool sprite_get_flashing(SpriteBase* sprite) return _spriteFlashingList[sprite->sprite_index]; } -static rct_sprite* find_sprite_list_cycle(uint16_t sprite_idx) +static SpriteBase* find_sprite_list_cycle(uint16_t sprite_idx) { if (sprite_idx == SPRITE_INDEX_NULL) { return nullptr; } - const rct_sprite* fast = get_sprite(sprite_idx); - const rct_sprite* slow = fast; + const SpriteBase* fast = GetEntity(sprite_idx); + const SpriteBase* slow = fast; bool increment_slow = false; - rct_sprite* cycle_start = nullptr; - while (fast->generic.sprite_index != SPRITE_INDEX_NULL) + SpriteBase* cycle_start = nullptr; + while (fast->sprite_index != SPRITE_INDEX_NULL) { // increment fast every time, unless reached the end - if (fast->generic.next == SPRITE_INDEX_NULL) + if (fast->next == SPRITE_INDEX_NULL) { break; } else { - fast = get_sprite(fast->generic.next); + fast = GetEntity(fast->next); } // increment slow only every second iteration if (increment_slow) { - slow = get_sprite(slow->generic.next); + slow = GetEntity(slow->next); } increment_slow = !increment_slow; if (fast == slow) { - cycle_start = get_sprite(slow->generic.sprite_index); + cycle_start = GetEntity(slow->sprite_index); break; } } return cycle_start; } -static rct_sprite* find_sprite_quadrant_cycle(uint16_t sprite_idx) +static SpriteBase* find_sprite_quadrant_cycle(uint16_t sprite_idx) { if (sprite_idx == SPRITE_INDEX_NULL) { return nullptr; } - const rct_sprite* fast = get_sprite(sprite_idx); - const rct_sprite* slow = fast; + const SpriteBase* fast = GetEntity(sprite_idx); + const SpriteBase* slow = fast; bool increment_slow = false; - rct_sprite* cycle_start = nullptr; - while (fast->generic.sprite_index != SPRITE_INDEX_NULL) + SpriteBase* cycle_start = nullptr; + while (fast->sprite_index != SPRITE_INDEX_NULL) { // increment fast every time, unless reached the end - if (fast->generic.next_in_quadrant == SPRITE_INDEX_NULL) + if (fast->next_in_quadrant == SPRITE_INDEX_NULL) { break; } else { - fast = get_sprite(fast->generic.next_in_quadrant); + fast = GetEntity(fast->next_in_quadrant); } // increment slow only every second iteration if (increment_slow) { - slow = get_sprite(slow->generic.next_in_quadrant); + slow = GetEntity(slow->next_in_quadrant); } increment_slow = !increment_slow; if (fast == slow) { - cycle_start = get_sprite(slow->generic.sprite_index); + cycle_start = GetEntity(slow->sprite_index); break; } } @@ -1078,14 +1072,13 @@ static rct_sprite* find_sprite_quadrant_cycle(uint16_t sprite_idx) static bool index_is_in_list(uint16_t index, enum SPRITE_LIST sl) { - uint16_t sprite_index = gSpriteListHead[sl]; - while (sprite_index != SPRITE_INDEX_NULL) + for (uint16_t sprite_index = gSpriteListHead[sl]; sprite_index != SPRITE_INDEX_NULL; + sprite_index = GetEntity(sprite_index)->next) { if (sprite_index == index) { return true; } - sprite_index = get_sprite(sprite_index)->generic.next; } return false; } @@ -1094,31 +1087,31 @@ int32_t check_for_sprite_list_cycles(bool fix) { for (int32_t i = 0; i < SPRITE_LIST_COUNT; i++) { - rct_sprite* cycle_start = find_sprite_list_cycle(gSpriteListHead[i]); + auto* cycle_start = find_sprite_list_cycle(gSpriteListHead[i]); if (cycle_start != nullptr) { if (fix) { // Fix head list, but only in reverse order // This is likely not needed, but just in case - get_sprite(gSpriteListHead[i])->generic.previous = SPRITE_INDEX_NULL; + GetEntity(gSpriteListHead[i])->previous = SPRITE_INDEX_NULL; // Store the leftover part of cycle to be fixed - uint16_t cycle_next = cycle_start->generic.next; + uint16_t cycle_next = cycle_start->next; // Break the cycle - cycle_start->generic.next = SPRITE_INDEX_NULL; + cycle_start->next = SPRITE_INDEX_NULL; // Now re-add remainder of the cycle back to list, safely. // Add each sprite to the list until we encounter one that is already part of the list. while (!index_is_in_list(cycle_next, static_cast(i))) { - rct_sprite* spr = get_sprite(cycle_next); + auto* spr = GetEntity(cycle_next); - cycle_start->generic.next = cycle_next; - spr->generic.previous = cycle_start->generic.sprite_index; - cycle_next = spr->generic.next; - spr->generic.next = SPRITE_INDEX_NULL; + cycle_start->next = cycle_next; + spr->previous = cycle_start->sprite_index; + cycle_next = spr->next; + spr->next = SPRITE_INDEX_NULL; cycle_start = spr; } } @@ -1137,32 +1130,32 @@ int32_t fix_disjoint_sprites() { // Find reachable sprites bool reachable[MAX_SPRITES] = { false }; - uint16_t sprite_idx = gSpriteListHead[SPRITE_LIST_FREE]; - rct_sprite* null_list_tail = nullptr; - while (sprite_idx != SPRITE_INDEX_NULL) + + SpriteBase* null_list_tail = nullptr; + for (uint16_t sprite_idx = gSpriteListHead[SPRITE_LIST_FREE]; sprite_idx != SPRITE_INDEX_NULL;) { reachable[sprite_idx] = true; // cache the tail, so we don't have to walk the list twice - null_list_tail = get_sprite(sprite_idx); - sprite_idx = null_list_tail->generic.next; + null_list_tail = GetEntity(sprite_idx); + sprite_idx = null_list_tail->next; } int32_t count = 0; // Find all null sprites - for (sprite_idx = 0; sprite_idx < MAX_SPRITES; sprite_idx++) + for (uint16_t sprite_idx = 0; sprite_idx < MAX_SPRITES; sprite_idx++) { - rct_sprite* spr = get_sprite(sprite_idx); - if (spr->generic.sprite_identifier == SPRITE_IDENTIFIER_NULL) + auto* spr = GetEntity(sprite_idx); + if (spr->sprite_identifier == SPRITE_IDENTIFIER_NULL) { openrct2_assert(null_list_tail != nullptr, "Null list is empty, yet found null sprites"); - spr->generic.sprite_index = sprite_idx; + spr->sprite_index = sprite_idx; if (!reachable[sprite_idx]) { // Add the sprite directly to the list - null_list_tail->generic.next = sprite_idx; - spr->generic.next = SPRITE_INDEX_NULL; - spr->generic.previous = null_list_tail->generic.sprite_index; + null_list_tail->next = sprite_idx; + spr->next = SPRITE_INDEX_NULL; + spr->previous = null_list_tail->sprite_index; null_list_tail = spr; count++; reachable[sprite_idx] = true; @@ -1176,26 +1169,26 @@ int32_t check_for_spatial_index_cycles(bool fix) { for (uint32_t i = 0; i < SPATIAL_INDEX_LOCATION_NULL; i++) { - rct_sprite* cycle_start = find_sprite_quadrant_cycle(gSpriteSpatialIndex[i]); + auto* cycle_start = find_sprite_quadrant_cycle(gSpriteSpatialIndex[i]); if (cycle_start != nullptr) { if (fix) { // Store the leftover part of cycle to be fixed - uint16_t cycle_next = cycle_start->generic.next_in_quadrant; + uint16_t cycle_next = cycle_start->next_in_quadrant; // Break the cycle - cycle_start->generic.next_in_quadrant = SPRITE_INDEX_NULL; + cycle_start->next_in_quadrant = SPRITE_INDEX_NULL; // Now re-add remainder of the cycle back to list, safely. // Add each sprite to the list until we encounter one that is already part of the list. while (!index_is_in_list(cycle_next, static_cast(i))) { - rct_sprite* spr = get_sprite(cycle_next); + auto* spr = GetEntity(cycle_next); - cycle_start->generic.next_in_quadrant = cycle_next; - cycle_next = spr->generic.next_in_quadrant; - spr->generic.next_in_quadrant = SPRITE_INDEX_NULL; + cycle_start->next_in_quadrant = cycle_next; + cycle_next = spr->next_in_quadrant; + spr->next_in_quadrant = SPRITE_INDEX_NULL; cycle_start = spr; } } diff --git a/src/openrct2/world/Sprite.h b/src/openrct2/world/Sprite.h index 337bf92ae9..98c2d430e2 100644 --- a/src/openrct2/world/Sprite.h +++ b/src/openrct2/world/Sprite.h @@ -193,6 +193,15 @@ enum rct_sprite* try_get_sprite(size_t spriteIndex); rct_sprite* get_sprite(size_t sprite_idx); +template T* GetEntity(size_t sprite_idx) +{ + auto spr = reinterpret_cast(get_sprite(sprite_idx)); + if (spr == nullptr) + return nullptr; + return spr->As(); +} + +SpriteBase* GetEntity(size_t sprite_idx); extern uint16_t gSpriteListHead[SPRITE_LIST_COUNT]; extern uint16_t gSpriteListCount[SPRITE_LIST_COUNT];