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