OpenRCT2/src/openrct2/ride/TrackDesignSave.cpp

586 lines
19 KiB
C++
Raw Normal View History

2016-05-04 19:54:33 +02:00
/*****************************************************************************
2020-07-21 15:04:34 +02:00
* Copyright (c) 2014-2020 OpenRCT2 developers
2016-05-04 19:54:33 +02:00
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
2016-05-04 19:54:33 +02:00
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
2016-05-04 19:54:33 +02:00
*****************************************************************************/
2017-11-20 11:13:55 +01:00
#include "../Context.h"
2017-11-30 18:17:06 +01:00
#include "../Game.h"
2018-06-22 23:14:18 +02:00
#include "../audio/audio.h"
#include "../config/Config.h"
#include "../interface/Viewport.h"
2018-01-06 18:32:25 +01:00
#include "../localisation/Localisation.h"
#include "../localisation/StringIds.h"
2018-02-13 15:20:55 +01:00
#include "../object/ObjectList.h"
2017-12-13 13:02:24 +01:00
#include "../util/SawyerCoding.h"
#include "../util/Util.h"
#include "../windows/Intent.h"
2018-01-11 10:59:26 +01:00
#include "../world/Footpath.h"
2017-11-20 11:13:55 +01:00
#include "../world/LargeScenery.h"
2018-01-11 10:59:26 +01:00
#include "../world/Scenery.h"
2017-11-20 11:13:55 +01:00
#include "../world/SmallScenery.h"
#include "../world/Wall.h"
2018-01-10 00:00:09 +01:00
#include "RideData.h"
2018-06-22 23:14:18 +02:00
#include "Station.h"
2017-10-17 13:51:47 +02:00
#include "Track.h"
2017-10-16 12:02:23 +02:00
#include "TrackData.h"
#include "TrackDesign.h"
2016-10-22 18:06:27 +02:00
#include "TrackDesignRepository.h"
2018-06-22 23:14:18 +02:00
#include <algorithm>
2018-02-13 15:20:55 +01:00
2019-10-24 03:37:34 +02:00
constexpr size_t TRACK_MAX_SAVED_TILE_ELEMENTS = 1500;
constexpr int32_t TRACK_NEARBY_SCENERY_DISTANCE = 1;
2016-09-10 19:03:25 +02:00
bool gTrackDesignSaveMode = false;
2019-01-12 11:11:55 +01:00
ride_id_t gTrackDesignSaveRideIndex = RIDE_ID_NULL;
2016-09-10 19:03:25 +02:00
2019-04-16 20:36:00 +02:00
std::vector<const TileElement*> _trackSavedTileElements;
std::vector<TrackDesignSceneryElement> _trackSavedTileElementsDesc;
2019-04-08 20:34:24 +02:00
2019-04-16 20:36:00 +02:00
static bool track_design_save_should_select_scenery_around(ride_id_t rideIndex, TileElement* tileElement);
static void track_design_save_select_nearby_scenery_for_tile(ride_id_t rideIndex, int32_t cx, int32_t cy);
static bool track_design_save_add_tile_element(
ViewportInteractionItem interactionType, const CoordsXY& loc, TileElement* tileElement);
static void track_design_save_remove_tile_element(
ViewportInteractionItem interactionType, const CoordsXY& loc, TileElement* tileElement);
2019-04-16 20:36:00 +02:00
void track_design_save_init()
{
_trackSavedTileElements.clear();
_trackSavedTileElementsDesc.clear();
}
/**
*
* rct2: 0x006D2B07
*/
void track_design_save_select_tile_element(
ViewportInteractionItem interactionType, const CoordsXY& loc, TileElement* tileElement, bool collect)
2019-04-16 20:36:00 +02:00
{
if (track_design_save_contains_tile_element(tileElement))
{
if (!collect)
{
track_design_save_remove_tile_element(interactionType, loc, tileElement);
2019-04-16 20:36:00 +02:00
}
}
else
{
if (collect)
{
if (!track_design_save_add_tile_element(interactionType, loc, tileElement))
2019-04-16 20:36:00 +02:00
{
context_show_error(
STR_SAVE_TRACK_SCENERY_UNABLE_TO_SELECT_ADDITIONAL_ITEM_OF_SCENERY,
STR_SAVE_TRACK_SCENERY_TOO_MANY_ITEMS_SELECTED, {});
2019-04-16 20:36:00 +02:00
}
}
}
}
/**
*
* rct2: 0x006D303D
*/
void track_design_save_select_nearby_scenery(ride_id_t rideIndex)
{
tile_element_iterator it;
tile_element_iterator_begin(&it);
do
2019-04-16 20:36:00 +02:00
{
if (track_design_save_should_select_scenery_around(rideIndex, it.element))
2019-04-16 20:36:00 +02:00
{
track_design_save_select_nearby_scenery_for_tile(rideIndex, it.x, it.y);
2019-04-16 20:36:00 +02:00
}
} while (tile_element_iterator_next(&it));
2019-04-16 20:36:00 +02:00
gfx_invalidate_screen();
}
/**
*
* rct2: 0x006D3026
*/
void track_design_save_reset_scenery()
{
track_design_save_init();
gfx_invalidate_screen();
}
bool track_design_save_contains_tile_element(const TileElement* tileElement)
{
for (auto& tile : _trackSavedTileElements)
{
if (tile == tileElement)
{
return true;
}
}
return false;
}
static int32_t tile_element_get_total_element_count(TileElement* tileElement)
{
int32_t elementCount;
rct_large_scenery_tile* tile;
switch (tileElement->GetType())
{
case TILE_ELEMENT_TYPE_PATH:
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
case TILE_ELEMENT_TYPE_WALL:
return 1;
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
{
auto* sceneryEntry = tileElement->AsLargeScenery()->GetEntry();
tile = sceneryEntry->tiles;
2019-04-16 20:36:00 +02:00
elementCount = 0;
do
{
tile++;
elementCount++;
} while (tile->x_offset != static_cast<int16_t>(static_cast<uint16_t>(0xFFFF)));
2019-04-16 20:36:00 +02:00
return elementCount;
}
2019-04-16 20:36:00 +02:00
default:
return 0;
}
}
/**
*
* rct2: 0x006D2ED2
*/
static bool track_design_save_can_add_tile_element(TileElement* tileElement)
{
size_t newElementCount = tile_element_get_total_element_count(tileElement);
if (newElementCount == 0)
{
return false;
}
// Get number of spare elements left
size_t spareSavedElements = TRACK_MAX_SAVED_TILE_ELEMENTS - _trackSavedTileElements.size();
if (newElementCount > spareSavedElements)
{
// No more spare saved elements left
return false;
}
return true;
}
/**
*
* rct2: 0x006D2F4C
*/
static void track_design_save_push_tile_element(const CoordsXY& loc, TileElement* tileElement)
2019-04-16 20:36:00 +02:00
{
if (_trackSavedTileElements.size() < TRACK_MAX_SAVED_TILE_ELEMENTS)
{
_trackSavedTileElements.push_back(tileElement);
map_invalidate_tile_full(loc);
2019-04-16 20:36:00 +02:00
}
}
/**
*
* rct2: 0x006D2FA7
*/
static void track_design_save_push_tile_element_desc(
const rct_object_entry* entry, const CoordsXYZ& loc, uint8_t flags, uint8_t primaryColour, uint8_t secondaryColour)
2019-04-16 20:36:00 +02:00
{
2020-03-13 12:03:43 +01:00
auto tileLoc = TileCoordsXYZ(loc);
TrackDesignSceneryElement item{};
2019-04-16 20:36:00 +02:00
item.scenery_object = *entry;
2020-03-13 12:03:43 +01:00
item.x = tileLoc.x;
item.y = tileLoc.y;
item.z = tileLoc.z;
2019-04-16 20:36:00 +02:00
item.flags = flags;
item.primary_colour = primaryColour;
item.secondary_colour = secondaryColour;
_trackSavedTileElementsDesc.push_back(std::move(item));
2019-04-16 20:36:00 +02:00
}
static void track_design_save_add_scenery(const CoordsXY& loc, SmallSceneryElement* sceneryElement)
2019-04-16 20:36:00 +02:00
{
int32_t entryType = sceneryElement->GetEntryIndex();
auto entry = object_entry_get_object(ObjectType::SmallScenery, entryType);
2019-04-16 20:36:00 +02:00
uint8_t flags = 0;
flags |= sceneryElement->GetDirection();
flags |= sceneryElement->GetSceneryQuadrant() << 2;
2019-04-16 20:36:00 +02:00
uint8_t primaryColour = sceneryElement->GetPrimaryColour();
uint8_t secondaryColour = sceneryElement->GetSecondaryColour();
track_design_save_push_tile_element(loc, reinterpret_cast<TileElement*>(sceneryElement));
track_design_save_push_tile_element_desc(
entry->GetObjectEntry(), { loc.x, loc.y, sceneryElement->GetBaseZ() }, flags, primaryColour, secondaryColour);
2019-04-16 20:36:00 +02:00
}
static void track_design_save_add_large_scenery(const CoordsXY& loc, LargeSceneryElement* tileElement)
2019-04-16 20:36:00 +02:00
{
rct_large_scenery_tile *sceneryTiles, *tile;
int32_t direction, sequence;
2020-04-19 22:35:24 +02:00
if (tileElement == nullptr)
{
log_warning("Null tile element");
return;
}
2019-04-16 20:36:00 +02:00
int32_t entryType = tileElement->GetEntryIndex();
auto entry = object_entry_get_object(ObjectType::LargeScenery, entryType);
sceneryTiles = get_large_scenery_entry(entryType)->tiles;
2019-04-16 20:36:00 +02:00
int32_t z = tileElement->base_height;
2019-04-16 20:36:00 +02:00
direction = tileElement->GetDirection();
sequence = tileElement->GetSequenceIndex();
2019-12-23 15:13:31 +01:00
auto sceneryOrigin = map_large_scenery_get_origin(
{ loc.x, loc.y, z << 3, static_cast<Direction>(direction) }, sequence, nullptr);
if (!sceneryOrigin)
2019-04-16 20:36:00 +02:00
{
return;
}
// Iterate through each tile of the large scenery element
sequence = 0;
for (tile = sceneryTiles; tile->x_offset != -1; tile++, sequence++)
{
CoordsXY offsetPos{ tile->x_offset, tile->y_offset };
auto rotatedOffsetPos = offsetPos.Rotate(direction);
2019-04-16 20:36:00 +02:00
CoordsXYZ tileLoc = { sceneryOrigin->x + rotatedOffsetPos.x, sceneryOrigin->y + rotatedOffsetPos.y,
sceneryOrigin->z + tile->z_offset };
auto largeElement = map_get_large_scenery_segment({ tileLoc, static_cast<Direction>(direction) }, sequence);
2019-04-16 20:36:00 +02:00
if (largeElement != nullptr)
{
if (sequence == 0)
{
uint8_t flags = largeElement->GetDirection();
uint8_t primaryColour = largeElement->GetPrimaryColour();
uint8_t secondaryColour = largeElement->GetSecondaryColour();
track_design_save_push_tile_element_desc(
entry->GetObjectEntry(), tileLoc, flags, primaryColour, secondaryColour);
2019-04-16 20:36:00 +02:00
}
track_design_save_push_tile_element({ tileLoc.x, tileLoc.y }, reinterpret_cast<TileElement*>(largeElement));
2019-04-16 20:36:00 +02:00
}
}
}
static void track_design_save_add_wall(const CoordsXY& loc, WallElement* wallElement)
2019-04-16 20:36:00 +02:00
{
int32_t entryType = wallElement->GetEntryIndex();
auto entry = object_entry_get_object(ObjectType::Walls, entryType);
2019-04-16 20:36:00 +02:00
uint8_t flags = 0;
flags |= wallElement->GetDirection();
flags |= wallElement->GetTertiaryColour() << 2;
2019-04-16 20:36:00 +02:00
uint8_t secondaryColour = wallElement->GetSecondaryColour();
uint8_t primaryColour = wallElement->GetPrimaryColour();
2019-04-16 20:36:00 +02:00
track_design_save_push_tile_element(loc, reinterpret_cast<TileElement*>(wallElement));
track_design_save_push_tile_element_desc(
entry->GetObjectEntry(), { loc.x, loc.y, wallElement->GetBaseZ() }, flags, primaryColour, secondaryColour);
2019-04-16 20:36:00 +02:00
}
static void track_design_save_add_footpath(const CoordsXY& loc, PathElement* pathElement)
2019-04-16 20:36:00 +02:00
{
2020-03-04 18:43:09 +01:00
int32_t entryType = pathElement->GetSurfaceEntryIndex();
auto entry = object_entry_get_object(ObjectType::Paths, entryType);
2019-04-16 20:36:00 +02:00
uint8_t flags = 0;
flags |= pathElement->GetEdges();
flags |= (pathElement->GetSlopeDirection()) << 5;
if (pathElement->IsSloped())
2019-04-16 20:36:00 +02:00
flags |= 0b00010000;
if (pathElement->IsQueue())
2019-04-16 20:36:00 +02:00
flags |= 1 << 7;
track_design_save_push_tile_element(loc, reinterpret_cast<TileElement*>(pathElement));
track_design_save_push_tile_element_desc(entry->GetObjectEntry(), { loc.x, loc.y, pathElement->GetBaseZ() }, flags, 0, 0);
2019-04-16 20:36:00 +02:00
}
/**
*
* rct2: 0x006D2B3C
*/
static bool track_design_save_add_tile_element(
ViewportInteractionItem interactionType, const CoordsXY& loc, TileElement* tileElement)
2019-04-16 20:36:00 +02:00
{
if (!track_design_save_can_add_tile_element(tileElement))
{
return false;
}
switch (interactionType)
{
case ViewportInteractionItem::Scenery:
track_design_save_add_scenery(loc, tileElement->AsSmallScenery());
2019-04-16 20:36:00 +02:00
return true;
case ViewportInteractionItem::LargeScenery:
track_design_save_add_large_scenery(loc, tileElement->AsLargeScenery());
2019-04-16 20:36:00 +02:00
return true;
case ViewportInteractionItem::Wall:
track_design_save_add_wall(loc, tileElement->AsWall());
2019-04-16 20:36:00 +02:00
return true;
case ViewportInteractionItem::Footpath:
track_design_save_add_footpath(loc, tileElement->AsPath());
2019-04-16 20:36:00 +02:00
return true;
default:
return false;
}
}
/**
*
* rct2: 0x006D2F78
*/
static void track_design_save_pop_tile_element(const CoordsXY& loc, TileElement* tileElement)
2019-04-16 20:36:00 +02:00
{
map_invalidate_tile_full(loc);
2019-04-16 20:36:00 +02:00
// Find index of map element to remove
size_t removeIndex = SIZE_MAX;
for (size_t i = 0; i < _trackSavedTileElements.size(); i++)
{
if (_trackSavedTileElements[i] == tileElement)
{
removeIndex = i;
}
}
if (removeIndex != SIZE_MAX)
{
_trackSavedTileElements.erase(_trackSavedTileElements.begin() + removeIndex);
}
}
/**
*
* rct2: 0x006D2FDD
*/
static void track_design_save_pop_tile_element_desc(const rct_object_entry* entry, const CoordsXYZ& loc, uint8_t flags)
2019-04-16 20:36:00 +02:00
{
size_t removeIndex = SIZE_MAX;
2020-03-13 12:03:43 +01:00
auto tileLoc = TileCoordsXYZ(loc);
2019-04-16 20:36:00 +02:00
for (size_t i = 0; i < _trackSavedTileElementsDesc.size(); i++)
{
TrackDesignSceneryElement* item = &_trackSavedTileElementsDesc[i];
2020-03-13 12:03:43 +01:00
if (item->x != tileLoc.x)
2019-04-16 20:36:00 +02:00
continue;
2020-03-13 12:03:43 +01:00
if (item->y != tileLoc.y)
2019-04-16 20:36:00 +02:00
continue;
2020-03-13 12:03:43 +01:00
if (item->z != tileLoc.z)
2019-04-16 20:36:00 +02:00
continue;
if (item->flags != flags)
continue;
if (!object_entry_compare(&item->scenery_object, entry))
continue;
removeIndex = i;
}
if (removeIndex != SIZE_MAX)
{
_trackSavedTileElementsDesc.erase(_trackSavedTileElementsDesc.begin() + removeIndex);
}
}
static void track_design_save_remove_scenery(const CoordsXY& loc, SmallSceneryElement* sceneryElement)
2019-04-16 20:36:00 +02:00
{
int32_t entryType = sceneryElement->GetEntryIndex();
auto entry = object_entry_get_object(ObjectType::SmallScenery, entryType);
2019-04-16 20:36:00 +02:00
uint8_t flags = 0;
flags |= sceneryElement->GetDirection();
flags |= sceneryElement->GetSceneryQuadrant() << 2;
2019-04-16 20:36:00 +02:00
track_design_save_pop_tile_element(loc, reinterpret_cast<TileElement*>(sceneryElement));
track_design_save_pop_tile_element_desc(entry->GetObjectEntry(), { loc.x, loc.y, sceneryElement->GetBaseZ() }, flags);
2019-04-16 20:36:00 +02:00
}
static void track_design_save_remove_large_scenery(const CoordsXY& loc, LargeSceneryElement* tileElement)
2019-04-16 20:36:00 +02:00
{
rct_large_scenery_tile *sceneryTiles, *tile;
int32_t direction, sequence;
2020-04-19 22:35:24 +02:00
if (tileElement == nullptr)
{
log_warning("Null tile element");
return;
}
2019-04-16 20:36:00 +02:00
int32_t entryType = tileElement->GetEntryIndex();
auto entry = object_entry_get_object(ObjectType::LargeScenery, entryType);
sceneryTiles = get_large_scenery_entry(entryType)->tiles;
2019-04-16 20:36:00 +02:00
int32_t z = tileElement->base_height;
2019-04-16 20:36:00 +02:00
direction = tileElement->GetDirection();
sequence = tileElement->GetSequenceIndex();
2019-12-23 15:13:31 +01:00
auto sceneryOrigin = map_large_scenery_get_origin(
{ loc.x, loc.y, z << 3, static_cast<Direction>(direction) }, sequence, nullptr);
if (!sceneryOrigin)
2019-04-16 20:36:00 +02:00
{
return;
}
// Iterate through each tile of the large scenery element
sequence = 0;
for (tile = sceneryTiles; tile->x_offset != -1; tile++, sequence++)
{
CoordsXY offsetPos{ tile->x_offset, tile->y_offset };
auto rotatedOffsetPos = offsetPos.Rotate(direction);
2019-04-16 20:36:00 +02:00
CoordsXYZ tileLoc = { sceneryOrigin->x + rotatedOffsetPos.x, sceneryOrigin->y + rotatedOffsetPos.y,
sceneryOrigin->z + tile->z_offset };
auto largeElement = map_get_large_scenery_segment({ tileLoc, static_cast<Direction>(direction) }, sequence);
2019-04-16 20:36:00 +02:00
if (largeElement != nullptr)
{
if (sequence == 0)
{
uint8_t flags = largeElement->GetDirection();
track_design_save_pop_tile_element_desc(entry->GetObjectEntry(), tileLoc, flags);
2019-04-16 20:36:00 +02:00
}
track_design_save_pop_tile_element({ tileLoc.x, tileLoc.y }, reinterpret_cast<TileElement*>(largeElement));
2019-04-16 20:36:00 +02:00
}
}
}
static void track_design_save_remove_wall(const CoordsXY& loc, WallElement* wallElement)
2019-04-16 20:36:00 +02:00
{
int32_t entryType = wallElement->GetEntryIndex();
auto entry = object_entry_get_object(ObjectType::Walls, entryType);
2019-04-16 20:36:00 +02:00
uint8_t flags = 0;
flags |= wallElement->GetDirection();
flags |= wallElement->GetTertiaryColour() << 2;
2019-04-16 20:36:00 +02:00
track_design_save_pop_tile_element(loc, reinterpret_cast<TileElement*>(wallElement));
track_design_save_pop_tile_element_desc(entry->GetObjectEntry(), { loc.x, loc.y, wallElement->GetBaseZ() }, flags);
2019-04-16 20:36:00 +02:00
}
static void track_design_save_remove_footpath(const CoordsXY& loc, PathElement* pathElement)
2019-04-16 20:36:00 +02:00
{
2020-03-04 18:43:09 +01:00
int32_t entryType = pathElement->GetSurfaceEntryIndex();
auto entry = object_entry_get_object(ObjectType::Paths, entryType);
2019-04-16 20:36:00 +02:00
uint8_t flags = 0;
flags |= pathElement->GetEdges();
if (pathElement->IsSloped())
2019-04-16 20:36:00 +02:00
flags |= (1 << 4);
flags |= (pathElement->GetSlopeDirection()) << 5;
if (pathElement->IsQueue())
2019-04-16 20:36:00 +02:00
flags |= (1 << 7);
track_design_save_pop_tile_element(loc, reinterpret_cast<TileElement*>(pathElement));
track_design_save_pop_tile_element_desc(entry->GetObjectEntry(), { loc.x, loc.y, pathElement->GetBaseZ() }, flags);
2019-04-16 20:36:00 +02:00
}
/**
*
* rct2: 0x006D2B3C
*/
static void track_design_save_remove_tile_element(
ViewportInteractionItem interactionType, const CoordsXY& loc, TileElement* tileElement)
2019-04-16 20:36:00 +02:00
{
switch (interactionType)
{
case ViewportInteractionItem::Scenery:
track_design_save_remove_scenery(loc, tileElement->AsSmallScenery());
2019-04-16 20:36:00 +02:00
break;
case ViewportInteractionItem::LargeScenery:
track_design_save_remove_large_scenery(loc, tileElement->AsLargeScenery());
2019-04-16 20:36:00 +02:00
break;
case ViewportInteractionItem::Wall:
track_design_save_remove_wall(loc, tileElement->AsWall());
2019-04-16 20:36:00 +02:00
break;
case ViewportInteractionItem::Footpath:
track_design_save_remove_footpath(loc, tileElement->AsPath());
2019-04-16 20:36:00 +02:00
break;
default:
break;
2019-04-16 20:36:00 +02:00
}
}
static bool track_design_save_should_select_scenery_around(ride_id_t rideIndex, TileElement* tileElement)
{
switch (tileElement->GetType())
{
case TILE_ELEMENT_TYPE_PATH:
if (tileElement->AsPath()->IsQueue() && tileElement->AsPath()->GetRideIndex() == rideIndex)
return true;
break;
case TILE_ELEMENT_TYPE_TRACK:
if (tileElement->AsTrack()->GetRideIndex() == rideIndex)
return true;
break;
case TILE_ELEMENT_TYPE_ENTRANCE:
// FIXME: This will always break and return false!
if (tileElement->AsEntrance()->GetEntranceType() != ENTRANCE_TYPE_RIDE_ENTRANCE)
break;
if (tileElement->AsEntrance()->GetEntranceType() != ENTRANCE_TYPE_RIDE_EXIT)
break;
if (tileElement->AsEntrance()->GetRideIndex() == rideIndex)
return true;
break;
}
return false;
}
static void track_design_save_select_nearby_scenery_for_tile(ride_id_t rideIndex, int32_t cx, int32_t cy)
{
TileElement* tileElement;
for (int32_t y = cy - TRACK_NEARBY_SCENERY_DISTANCE; y <= cy + TRACK_NEARBY_SCENERY_DISTANCE; y++)
{
for (int32_t x = cx - TRACK_NEARBY_SCENERY_DISTANCE; x <= cx + TRACK_NEARBY_SCENERY_DISTANCE; x++)
{
tileElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY());
Avoid dereferencing map_get_first_element_at nullptr on libopenrct2 (#10013) * Avoid dereferencing map_get_first_element_at nullptr on Map.cpp * Avoid dereferencing map_get_first_element_at nullptr on MapAnimation.cpp Returning true or internal control variable, based on what was seen on `map_animation_invalidate_track_onridephoto` * Avoid dereferencing map_get_first_element_at nullptr on Park.cpp * Avoid dereferencing map_get_first_element_at nullptr on Scenery.cpp * Avoid dereferencing map_get_first_element_at nullptr on Sprite.cpp * Avoid dereferencing map_get_first_element_at nullptr on TileInspector.cpp * Avoid dereferencing map_get_first_element_at nullptr on Wall.cpp * Avoid dereferencing map_get_first_element_at nullptr on Fountain.cpp * Avoid dereferencing map_get_first_element_at nullptr on Footpath.cpp * Avoid dereferencing map_get_first_element_at nullptr on Entrance.cpp * Avoid dereferencing map_get_first_element_at nullptr on Banner.cpp * Avoid dereferencing map_get_first_element_at nullptr on Vehicle.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesignSave.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesign.cpp * Avoid dereferencing map_get_first_element_at nullptr on Track.cpp * Avoid dereferencing map_get_first_element_at nullptr on Station.cpp * Avoid dereferencing map_get_first_element_at nullptr on RideRatings.cpp * Avoid dereferencing map_get_first_element_at nullptr on Ride.cpp * Avoid dereferencing map_get_first_element_at nullptr on S4Importer.cpp * Avoid dereferencing map_get_first_element_at nullptr on Staff.cpp * Avoid dereferencing map_get_first_element_at nullptr on Peep.cpp * Avoid dereferencing map_get_first_element_at nullptr on GuestPathfinding.cpp * Avoid dereferencing map_get_first_element_at nullptr on Guest.cpp * Avoid dereferencing map_get_first_element_at nullptr on VirtualFloor.cpp * Avoid dereferencing map_get_first_element_at nullptr on Paint.TileElement.cpp * Fix issues raised on review * Fix remaining review issues. * Early exit on loops if tileElement is nullptr * Fix clang-format issues
2019-10-09 16:02:21 +02:00
if (tileElement == nullptr)
continue;
2019-04-16 20:36:00 +02:00
do
{
ViewportInteractionItem interactionType = ViewportInteractionItem::None;
2019-04-16 20:36:00 +02:00
switch (tileElement->GetType())
{
case TILE_ELEMENT_TYPE_PATH:
if (!tileElement->AsPath()->IsQueue())
interactionType = ViewportInteractionItem::Footpath;
2019-04-16 20:36:00 +02:00
else if (tileElement->AsPath()->GetRideIndex() == rideIndex)
interactionType = ViewportInteractionItem::Footpath;
2019-04-16 20:36:00 +02:00
break;
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
interactionType = ViewportInteractionItem::Scenery;
2019-04-16 20:36:00 +02:00
break;
case TILE_ELEMENT_TYPE_WALL:
interactionType = ViewportInteractionItem::Wall;
2019-04-16 20:36:00 +02:00
break;
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
interactionType = ViewportInteractionItem::LargeScenery;
2019-04-16 20:36:00 +02:00
break;
}
if (interactionType != ViewportInteractionItem::None)
2019-04-16 20:36:00 +02:00
{
if (!track_design_save_contains_tile_element(tileElement))
{
2020-03-13 12:03:43 +01:00
track_design_save_add_tile_element(interactionType, TileCoordsXY(x, y).ToCoordsXY(), tileElement);
2019-04-16 20:36:00 +02:00
}
}
} while (!(tileElement++)->IsLastForTile());
}
}
}