1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-25 07:44:38 +01:00

Make tile elements dynamic and resizeable

This commit is contained in:
Ted John
2021-04-09 02:09:08 +01:00
committed by duncanspumpkin
parent 051a09d2b7
commit 81d7c3f02b
10 changed files with 235 additions and 245 deletions

View File

@@ -1247,8 +1247,8 @@ static int32_t cc_remove_park_fences(InteractiveConsole& console, [[maybe_unused
static int32_t cc_show_limits(InteractiveConsole& console, [[maybe_unused]] const arguments_t& argv)
{
map_reorganise_elements();
int32_t tileElementCount = gNextFreeTileElement - gTileElements - 1;
const auto& tileElements = GetTileElements();
int32_t tileElementCount = tileElements.size();
int32_t rideCount = ride_get_count();
int32_t spriteCount = 0;

View File

@@ -2770,7 +2770,6 @@ bool NetworkBase::LoadMap(IStream* stream)
bool NetworkBase::SaveMap(IStream* stream, const std::vector<const ObjectRepositoryItem*>& objects) const
{
bool result = false;
map_reorganise_elements();
viewport_set_saved_view();
try
{

View File

@@ -1483,38 +1483,44 @@ private:
// Build tile pointer cache (needed to get the first element at a certain location)
auto tilePointerIndex = TilePointerIndex<RCT12TileElement>(RCT1_MAX_MAP_SIZE, _s4.tile_elements);
TileElement* dstElement = gTileElements;
std::vector<TileElement> tileElements;
for (TileCoordsXY coords = { 0, 0 }; coords.y < MAXIMUM_MAP_SIZE_TECHNICAL; coords.y++)
{
for (coords.x = 0; coords.x < MAXIMUM_MAP_SIZE_TECHNICAL; coords.x++)
{
if (coords.x >= RCT1_MAX_MAP_SIZE || coords.y >= RCT1_MAX_MAP_SIZE)
{
dstElement->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
dstElement->SetLastForTile(true);
dstElement++;
continue;
auto& dstElement = tileElements.emplace_back();
dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE);
dstElement.SetLastForTile(true);
}
// This is the equivalent of map_get_first_element_at(x, y), but on S4 data.
RCT12TileElement* srcElement = tilePointerIndex.GetFirstElementAt(coords);
do
else
{
if (srcElement->base_height == RCT12_MAX_ELEMENT_HEIGHT)
continue;
// This is the equivalent of map_get_first_element_at(x, y), but on S4 data.
RCT12TileElement* srcElement = tilePointerIndex.GetFirstElementAt(coords);
do
{
if (srcElement->base_height == RCT12_MAX_ELEMENT_HEIGHT)
continue;
auto numAddedElements = ImportTileElement(dstElement, srcElement);
dstElement += numAddedElements;
} while (!(srcElement++)->IsLastForTile());
// Reserve 8 elements for import
auto originalSize = tileElements.size();
tileElements.resize(originalSize + 16);
auto dstElement = tileElements.data() + originalSize;
auto numAddedElements = ImportTileElement(dstElement, srcElement);
tileElements.resize(originalSize + numAddedElements);
} while (!(srcElement++)->IsLastForTile());
// Set last element flag in case the original last element was never added
(dstElement - 1)->SetLastForTile(true);
// Set last element flag in case the original last element was never added
if (tileElements.size() > 0)
{
tileElements.back().SetLastForTile(true);
}
}
}
}
map_update_tile_pointers();
SetTileElements(std::move(tileElements));
FixEntrancePositions();
}

View File

@@ -465,7 +465,6 @@ public:
// Fix and set dynamic variables
map_strip_ghost_flag_from_elements();
map_update_tile_pointers();
game_convert_strings_to_utf8();
map_count_remaining_land_rights();
determine_ride_entrance_and_exit_locations();
@@ -1040,16 +1039,16 @@ public:
// Build tile pointer cache (needed to get the first element at a certain location)
auto tilePointerIndex = TilePointerIndex<RCT12TileElement>(RCT2_MAXIMUM_MAP_SIZE_TECHNICAL, _s6.tile_elements);
TileElement* dstElement = gTileElements;
std::vector<TileElement> tileElements;
for (TileCoordsXY coords = { 0, 0 }; coords.y < MAXIMUM_MAP_SIZE_TECHNICAL; coords.y++)
{
for (coords.x = 0; coords.x < MAXIMUM_MAP_SIZE_TECHNICAL; coords.x++)
{
if (coords.x >= RCT2_MAXIMUM_MAP_SIZE_TECHNICAL || coords.y >= RCT2_MAXIMUM_MAP_SIZE_TECHNICAL)
{
dstElement->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
dstElement->SetLastForTile(true);
dstElement++;
auto& dstElement = tileElements.emplace_back();
dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE);
dstElement.SetLastForTile(true);
continue;
}
@@ -1057,17 +1056,18 @@ public:
// This might happen with damaged parks. Make sure there is *something* to avoid crashes.
if (srcElement == nullptr)
{
dstElement->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
dstElement->SetLastForTile(true);
dstElement++;
auto& dstElement = tileElements.emplace_back();
dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE);
dstElement.SetLastForTile(true);
continue;
}
do
{
auto& dstElement = tileElements.emplace_back();
if (srcElement->base_height == RCT12_MAX_ELEMENT_HEIGHT)
{
std::memcpy(dstElement, srcElement, sizeof(*srcElement));
std::memcpy(&dstElement, srcElement, sizeof(*srcElement));
}
else
{
@@ -1076,19 +1076,20 @@ public:
if (tileElementType == RCT12TileElementType::Corrupt
|| tileElementType == RCT12TileElementType::EightCarsCorrupt14
|| tileElementType == RCT12TileElementType::EightCarsCorrupt15)
std::memcpy(dstElement, srcElement, sizeof(*srcElement));
std::memcpy(&dstElement, srcElement, sizeof(*srcElement));
else
ImportTileElement(dstElement, srcElement);
ImportTileElement(&dstElement, srcElement);
}
dstElement++;
} while (!(srcElement++)->IsLastForTile());
// Set last element flag in case the original last element was never added
if (tileElements.size() > 0)
{
tileElements.back().SetLastForTile(true);
}
}
}
gNextFreeTileElementPointerIndex = _s6.next_free_tile_element_pointer_index;
map_update_tile_pointers();
SetTileElements(std::move(tileElements));
}
void ImportTileElement(TileElement* dst, const RCT12TileElement* src)

View File

@@ -96,10 +96,6 @@ static bool _trackDesignPlaceStateHasScenery = false;
static bool _trackDesignPlaceStatePlaceScenery = true;
static bool _trackDesignPlaceIsReplay = false;
static std::unique_ptr<map_backup> track_design_preview_backup_map();
static void track_design_preview_restore_map(map_backup* backup);
static void track_design_preview_clear_map();
rct_string_id TrackDesign::CreateTrackDesign(const Ride& ride)
@@ -1985,12 +1981,7 @@ static bool track_design_place_preview(TrackDesign* td6, money32* cost, Ride** o
*/
void track_design_draw_preview(TrackDesign* td6, uint8_t* pixels)
{
// Make a copy of the map
auto mapBackup = track_design_preview_backup_map();
if (mapBackup == nullptr)
{
return;
}
StashMap();
track_design_preview_clear_map();
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)
@@ -2004,7 +1995,7 @@ void track_design_draw_preview(TrackDesign* td6, uint8_t* pixels)
if (!track_design_place_preview(td6, &cost, &ride, &flags))
{
std::fill_n(pixels, TRACK_PREVIEW_IMAGE_SIZE * 4, 0x00);
track_design_preview_restore_map(mapBackup.get());
UnstashMap();
return;
}
td6->cost = cost;
@@ -2087,43 +2078,7 @@ void track_design_draw_preview(TrackDesign* td6, uint8_t* pixels)
}
ride->Delete();
track_design_preview_restore_map(mapBackup.get());
}
/**
* Create a backup of the map as it will be cleared for drawing the track
* design preview.
* rct2: 0x006D1C68
*/
static std::unique_ptr<map_backup> track_design_preview_backup_map()
{
auto backup = std::make_unique<map_backup>();
if (backup != nullptr)
{
std::memcpy(backup->tile_elements, gTileElements, sizeof(backup->tile_elements));
std::memcpy(backup->tile_pointers, gTileElementTilePointers, sizeof(backup->tile_pointers));
backup->next_free_tile_element = gNextFreeTileElement;
backup->map_size_units = gMapSizeUnits;
backup->map_size_units_minus_2 = gMapSizeMinus2;
backup->map_size = gMapSize;
backup->current_rotation = get_current_rotation();
}
return backup;
}
/**
* Restores the map from a backup.
* rct2: 0x006D2378
*/
static void track_design_preview_restore_map(map_backup* backup)
{
std::memcpy(gTileElements, backup->tile_elements, sizeof(backup->tile_elements));
std::memcpy(gTileElementTilePointers, backup->tile_pointers, sizeof(backup->tile_pointers));
gNextFreeTileElement = backup->next_free_tile_element;
gMapSizeUnits = backup->map_size_units;
gMapSizeMinus2 = backup->map_size_units_minus_2;
gMapSize = backup->map_size;
gCurrentRotation = backup->current_rotation;
UnstashMap();
}
/**
@@ -2132,26 +2087,30 @@ static void track_design_preview_restore_map(map_backup* backup)
*/
static void track_design_preview_clear_map()
{
// These values were previously allocated in backup map but
// it seems more fitting to place in this function
auto numTiles = MAXIMUM_MAP_SIZE_TECHNICAL * MAXIMUM_MAP_SIZE_TECHNICAL;
gMapSizeUnits = 255 * COORDS_XY_STEP;
gMapSizeMinus2 = (264 * 32) - 2;
gMapSize = 256;
for (int32_t i = 0; i < MAX_TILE_TILE_ELEMENT_POINTERS; i++)
// Reserve ~8 elements per tile
std::vector<TileElement> tileElements;
tileElements.reserve(numTiles * 8);
for (int32_t i = 0; i < numTiles; i++)
{
TileElement* tile_element = &gTileElements[i];
tile_element->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
tile_element->SetLastForTile(true);
tile_element->AsSurface()->SetSlope(TILE_ELEMENT_SLOPE_FLAT);
tile_element->AsSurface()->SetWaterHeight(0);
tile_element->AsSurface()->SetSurfaceStyle(0);
tile_element->AsSurface()->SetEdgeStyle(0);
tile_element->AsSurface()->SetGrassLength(GRASS_LENGTH_CLEAR_0);
tile_element->AsSurface()->SetOwnership(OWNERSHIP_OWNED);
tile_element->AsSurface()->SetParkFences(0);
auto* element = &tileElements.emplace_back();
element->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
element->SetLastForTile(true);
element->AsSurface()->SetSlope(TILE_ELEMENT_SLOPE_FLAT);
element->AsSurface()->SetWaterHeight(0);
element->AsSurface()->SetSurfaceStyle(0);
element->AsSurface()->SetEdgeStyle(0);
element->AsSurface()->SetGrassLength(GRASS_LENGTH_CLEAR_0);
element->AsSurface()->SetOwnership(OWNERSHIP_OWNED);
element->AsSurface()->SetParkFences(0);
}
map_update_tile_pointers();
SetTileElements(std::move(tileElements));
}
bool track_design_are_entrance_and_exit_placed()

View File

@@ -81,6 +81,8 @@ const std::array<CoordsXY, 8> CoordsDirectionDelta = {
const TileCoordsXY TileDirectionDelta[] = { { -1, 0 }, { 0, +1 }, { +1, 0 }, { 0, -1 },
{ -1, +1 }, { +1, +1 }, { +1, -1 }, { -1, -1 } };
constexpr size_t MIN_TILE_ELEMENTS = 1024;
uint16_t gMapSelectFlags;
uint16_t gMapSelectType;
CoordsXY gMapSelectPositionA;
@@ -99,14 +101,9 @@ int16_t gMapSize;
int16_t gMapSizeMaxXY;
int16_t gMapBaseZ;
TileElement gTileElements[MAX_TILE_ELEMENTS_WITH_SPARE_ROOM];
TileElement* gTileElementTilePointers[MAX_TILE_TILE_ELEMENT_POINTERS];
std::vector<CoordsXY> gMapSelectionTiles;
std::vector<PeepSpawn> gPeepSpawns;
TileElement* gNextFreeTileElement;
uint32_t gNextFreeTileElementPointerIndex;
bool gLandMountainMode;
bool gLandPaintMode;
bool gClearSmallScenery;
@@ -118,6 +115,114 @@ uint16_t gLandRemainingConstructionSales;
bool gMapLandRightsUpdateSuccess;
static TilePointerIndex<TileElement> _tileIndex;
static std::vector<TileElement> _tileElements;
static TilePointerIndex<TileElement> _tileIndexStash;
static std::vector<TileElement> _tileElementsStash;
static int32_t _mapSizeUnitsStash;
static int32_t _mapSizeMinus2Stash;
static int32_t _mapSizeStash;
static int32_t _currentRotationStash;
void StashMap()
{
_tileIndexStash = std::move(_tileIndex);
_tileElementsStash = std::move(_tileElements);
_mapSizeUnitsStash = gMapSizeUnits;
_mapSizeMinus2Stash = gMapSizeMinus2;
_mapSizeStash = gMapSize;
_currentRotationStash = gCurrentRotation;
}
void UnstashMap()
{
_tileIndex = std::move(_tileIndexStash);
_tileElements = std::move(_tileElementsStash);
gMapSizeUnits = _mapSizeUnitsStash;
gMapSizeMinus2 = _mapSizeMinus2Stash;
gMapSize = _mapSizeStash;
gCurrentRotation = _currentRotationStash;
}
const std::vector<TileElement>& GetTileElements()
{
return _tileElements;
}
void SetTileElements(std::vector<TileElement>&& tileElements)
{
_tileElements = std::move(tileElements);
_tileIndex = TilePointerIndex<TileElement>(MAXIMUM_MAP_SIZE_TECHNICAL, _tileElements.data());
}
static void ReorganiseTileElements(size_t capacity)
{
context_setcurrentcursor(CursorID::ZZZ);
std::vector<TileElement> newElements;
newElements.reserve(std::max(MIN_TILE_ELEMENTS, capacity));
for (int32_t y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
{
for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
{
const auto* element = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY());
if (element == nullptr)
{
auto& newElement = newElements.emplace_back();
newElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE);
newElement.SetLastForTile(true);
newElement.base_height = 14;
newElement.clearance_height = 14;
newElement.AsSurface()->SetWaterHeight(0);
newElement.AsSurface()->SetSlope(TILE_ELEMENT_SLOPE_FLAT);
newElement.AsSurface()->SetGrassLength(GRASS_LENGTH_CLEAR_0);
newElement.AsSurface()->SetOwnership(OWNERSHIP_UNOWNED);
newElement.AsSurface()->SetParkFences(0);
newElement.AsSurface()->SetSurfaceStyle(0);
newElement.AsSurface()->SetEdgeStyle(0);
}
else
{
do
{
newElements.push_back(*element);
} while (!(element++)->IsLastForTile());
}
}
}
SetTileElements(std::move(newElements));
}
void ReorganiseTileElements()
{
ReorganiseTileElements(_tileElements.size());
}
bool map_check_free_elements_and_reorganise(size_t numElements)
{
auto freeElements = _tileElements.capacity() - _tileElements.size();
if (freeElements >= numElements)
{
return true;
}
else
{
auto newCapacity = std::min<size_t>(MAX_TILE_ELEMENTS, _tileElements.capacity() * 2);
if (newCapacity - _tileElements.size() < numElements)
{
// Limit reached
gGameCommandErrorText = STR_ERR_LANDSCAPE_DATA_AREA_FULL;
return false;
}
else
{
ReorganiseTileElements(newCapacity);
return true;
}
}
}
static void clear_elements_at(const CoordsXY& loc);
static ScreenCoordsXY translate_3d_to_2d(int32_t rotation, const CoordsXY& pos);
@@ -173,7 +278,7 @@ TileElement* map_get_first_element_at(const CoordsXY& elementPos)
return nullptr;
}
auto tileElementPos = TileCoordsXY{ elementPos };
return gTileElementTilePointers[tileElementPos.x + tileElementPos.y * MAXIMUM_MAP_SIZE_TECHNICAL];
return _tileIndex.GetFirstElementAt(tileElementPos);
}
TileElement* map_get_nth_element_at(const CoordsXY& coords, int32_t n)
@@ -210,7 +315,7 @@ void map_set_tile_element(const TileCoordsXY& tilePos, TileElement* elements)
log_error("Trying to access element outside of range");
return;
}
gTileElementTilePointers[tilePos.x + tilePos.y * MAXIMUM_MAP_SIZE_TECHNICAL] = elements;
_tileIndex.SetTile(tilePos, elements);
}
SurfaceElement* map_get_surface_element_at(const CoordsXY& coords)
@@ -253,23 +358,26 @@ BannerElement* map_get_banner_element_at(const CoordsXYZ& bannerPos, uint8_t pos
*/
void map_init(int32_t size)
{
gNextFreeTileElementPointerIndex = 0;
auto numTiles = MAXIMUM_MAP_SIZE_TECHNICAL * MAXIMUM_MAP_SIZE_TECHNICAL;
for (int32_t i = 0; i < MAX_TILE_TILE_ELEMENT_POINTERS; i++)
std::vector<TileElement> tileElements;
tileElements.resize(numTiles);
for (int32_t i = 0; i < numTiles; i++)
{
TileElement* tile_element = &gTileElements[i];
tile_element->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
tile_element->SetLastForTile(true);
tile_element->base_height = 14;
tile_element->clearance_height = 14;
tile_element->AsSurface()->SetWaterHeight(0);
tile_element->AsSurface()->SetSlope(TILE_ELEMENT_SLOPE_FLAT);
tile_element->AsSurface()->SetGrassLength(GRASS_LENGTH_CLEAR_0);
tile_element->AsSurface()->SetOwnership(OWNERSHIP_UNOWNED);
tile_element->AsSurface()->SetParkFences(0);
tile_element->AsSurface()->SetSurfaceStyle(0);
tile_element->AsSurface()->SetEdgeStyle(0);
auto* element = &tileElements[i];
element->ClearAs(TILE_ELEMENT_TYPE_SURFACE);
element->SetLastForTile(true);
element->base_height = 14;
element->clearance_height = 14;
element->AsSurface()->SetWaterHeight(0);
element->AsSurface()->SetSlope(TILE_ELEMENT_SLOPE_FLAT);
element->AsSurface()->SetGrassLength(GRASS_LENGTH_CLEAR_0);
element->AsSurface()->SetOwnership(OWNERSHIP_UNOWNED);
element->AsSurface()->SetParkFences(0);
element->AsSurface()->SetSurfaceStyle(0);
element->AsSurface()->SetEdgeStyle(0);
}
SetTileElements(std::move(tileElements));
gGrassSceneryTileLoopPosition = 0;
gWidePathTileLoopPosition = {};
@@ -278,7 +386,6 @@ void map_init(int32_t size)
gMapSize = size;
gMapSizeMaxXY = size * 32 - 33;
gMapBaseZ = 7;
map_update_tile_pointers();
map_remove_out_of_range_elements();
AutoCreateMapAnimations();
@@ -338,40 +445,12 @@ void map_count_remaining_land_rights()
*/
void map_strip_ghost_flag_from_elements()
{
for (auto& element : gTileElements)
for (auto& element : _tileElements)
{
element.SetGhost(false);
}
}
/**
*
* rct2: 0x0068AFFD
*/
void map_update_tile_pointers()
{
int32_t i, x, y;
for (i = 0; i < MAX_TILE_TILE_ELEMENT_POINTERS; i++)
{
gTileElementTilePointers[i] = TILE_UNDEFINED_TILE_ELEMENT;
}
TileElement* tileElement = gTileElements;
TileElement** tile = gTileElementTilePointers;
for (y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
{
for (x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
{
*tile++ = tileElement;
while (!(tileElement++)->IsLastForTile())
;
}
}
gNextFreeTileElement = tileElement;
}
/**
* Return the absolute height of an element, given its (x,y) coordinates
*
@@ -925,9 +1004,9 @@ void tile_element_remove(TileElement* tileElement)
(tileElement - 1)->SetLastForTile(true);
tileElement->base_height = MAX_ELEMENT_HEIGHT;
if ((tileElement + 1) == gNextFreeTileElement)
if ((tileElement + 1) == &_tileElements[_tileElements.size()])
{
gNextFreeTileElement--;
_tileElements.pop_back();
}
}
@@ -1029,77 +1108,28 @@ void map_invalidate_selection_rect()
viewports_invalidate(left, top, right, bottom);
}
/**
*
* rct2: 0x0068B111
*/
void map_reorganise_elements()
static size_t CountElementsOnTile(const CoordsXY& loc)
{
context_setcurrentcursor(CursorID::ZZZ);
auto newTileElements = std::make_unique<TileElement[]>(MAX_TILE_ELEMENTS_WITH_SPARE_ROOM);
TileElement* newElementsPtr = newTileElements.get();
if (newTileElements == nullptr)
size_t count = 0;
auto* element = _tileIndex.GetFirstElementAt(TileCoordsXY(loc));
do
{
log_fatal("Unable to allocate memory for map elements.");
return;
}
for (int32_t y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
{
for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
{
TileElement* startElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY());
if (startElement == nullptr)
continue;
TileElement* endElement = startElement;
while (!(endElement++)->IsLastForTile())
;
const auto numElements = static_cast<uint32_t>(endElement - startElement);
std::memcpy(newElementsPtr, startElement, numElements * sizeof(TileElement));
newElementsPtr += numElements;
}
}
const auto numElements = static_cast<uint32_t>(newElementsPtr - newTileElements.get());
std::memcpy(gTileElements, newTileElements.get(), numElements * sizeof(TileElement));
std::memset(gTileElements + numElements, 0, (MAX_TILE_ELEMENTS_WITH_SPARE_ROOM - numElements) * sizeof(TileElement));
map_update_tile_pointers();
count++;
} while (!(element++)->IsLastForTile());
return count;
}
/**
*
* rct2: 0x0068B044
* Returns true on space available for more elements
* Reorganises the map elements to check for space
*/
bool map_check_free_elements_and_reorganise(int32_t numElements)
static TileElement* AllocateTileElements(size_t count)
{
if (numElements != 0)
if (!map_check_free_elements_and_reorganise(count))
{
auto tileElementEnd = &gTileElements[MAX_TILE_ELEMENTS];
// Check if is there is room for the required number of elements
auto newTileElementEnd = gNextFreeTileElement + numElements;
if (newTileElementEnd > tileElementEnd)
{
// Defragment the map element list
map_reorganise_elements();
// Check if there is any room again
newTileElementEnd = gNextFreeTileElement + numElements;
if (newTileElementEnd > tileElementEnd)
{
// Not enough spare elements left :'(
gGameCommandErrorText = STR_ERR_LANDSCAPE_DATA_AREA_FULL;
return false;
}
}
log_error("Cannot insert new element");
return nullptr;
}
return true;
auto oldSize = _tileElements.size();
_tileElements.resize(_tileElements.size() + count);
return &_tileElements[oldSize];
}
/**
@@ -1109,21 +1139,16 @@ bool map_check_free_elements_and_reorganise(int32_t numElements)
TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type)
{
const auto& tileLoc = TileCoordsXYZ(loc);
TileElement *originalTileElement, *newTileElement, *insertedElement;
bool isLastForTile = false;
if (!map_check_free_elements_and_reorganise(1))
{
log_error("Cannot insert new element");
return nullptr;
}
newTileElement = gNextFreeTileElement;
originalTileElement = gTileElementTilePointers[tileLoc.y * MAXIMUM_MAP_SIZE_TECHNICAL + tileLoc.x];
auto numElementsOnTileOld = CountElementsOnTile(loc);
auto numElementsOnTileNew = numElementsOnTileOld + 1;
auto* newTileElement = AllocateTileElements(numElementsOnTileNew);
auto* originalTileElement = _tileIndex.GetFirstElementAt(tileLoc);
// Set tile index pointer to point to new element block
gTileElementTilePointers[tileLoc.y * MAXIMUM_MAP_SIZE_TECHNICAL + tileLoc.x] = newTileElement;
_tileIndex.SetTile(tileLoc, newTileElement);
bool isLastForTile = false;
if (originalTileElement == nullptr)
{
isLastForTile = true;
@@ -1150,7 +1175,7 @@ TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants
}
// Insert new map element
insertedElement = newTileElement;
auto* insertedElement = newTileElement;
newTileElement->type = 0;
newTileElement->SetType(static_cast<uint8_t>(type));
newTileElement->SetBaseZ(loc.z);
@@ -1176,7 +1201,6 @@ TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants
} while (!((newTileElement - 1)->IsLastForTile()));
}
gNextFreeTileElement = newTileElement;
return insertedElement;
}

View File

@@ -116,15 +116,9 @@ extern uint8_t gMapSelectArrowDirection;
extern uint8_t gMapGroundFlags;
extern TileElement gTileElements[MAX_TILE_ELEMENTS_WITH_SPARE_ROOM];
extern TileElement* gTileElementTilePointers[MAX_TILE_TILE_ELEMENT_POINTERS];
extern std::vector<CoordsXY> gMapSelectionTiles;
extern std::vector<PeepSpawn> gPeepSpawns;
extern TileElement* gNextFreeTileElement;
extern uint32_t gNextFreeTileElementPointerIndex;
// Used in the land tool window to enable mountain tool / land smoothing
extern bool gLandMountainMode;
// Used in the land tool window to allow dragging and changing land styles
@@ -146,9 +140,11 @@ extern const uint8_t tile_element_raise_styles[9][32];
template<typename T> class TilePointerIndex
{
std::vector<T*> TilePointers;
uint16_t MapSize;
uint16_t MapSize{};
public:
TilePointerIndex() = default;
explicit TilePointerIndex(const uint16_t mapSize, T* tileElements)
{
MapSize = mapSize;
@@ -171,13 +167,23 @@ public:
{
return TilePointers[coords.x + (coords.y * MapSize)];
}
void SetTile(TileCoordsXY coords, T* tileElement)
{
TilePointers[coords.x + (coords.y * MapSize)] = tileElement;
}
};
void ReorganiseTileElements();
const std::vector<TileElement>& GetTileElements();
void SetTileElements(std::vector<TileElement>&& tileElements);
void StashMap();
void UnstashMap();
void map_init(int32_t size);
void map_count_remaining_land_rights();
void map_strip_ghost_flag_from_elements();
void map_update_tile_pointers();
TileElement* map_get_first_element_at(const CoordsXY& elementPos);
TileElement* map_get_nth_element_at(const CoordsXY& coords, int32_t n);
void map_set_tile_element(const TileCoordsXY& tilePos, TileElement* elements);
@@ -210,8 +216,7 @@ void tile_element_remove(TileElement* tileElement);
void map_remove_all_rides();
void map_invalidate_map_selection_tiles();
void map_invalidate_selection_rect();
void map_reorganise_elements();
bool map_check_free_elements_and_reorganise(int32_t num_elements);
bool map_check_free_elements_and_reorganise(size_t num_elements);
TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type);
template<typename T> T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants)

View File

@@ -231,8 +231,6 @@ void mapgen_generate(mapgen_settings* settings)
// Place the trees
if (settings->trees != 0)
mapgen_place_trees();
map_reorganise_elements();
}
static void mapgen_place_tree(int32_t type, const CoordsXY& loc)

View File

@@ -54,7 +54,6 @@ static std::unique_ptr<IContext> localStartGame(const std::string& parkPath)
reset_all_sprite_quadrant_placements();
scenery_set_default_placement_configuration();
load_palette();
map_reorganise_elements();
EntityTweener::Get().Reset();
AutoCreateMapAnimations();
fix_invalid_vehicle_sprite_sizes();

View File

@@ -75,7 +75,6 @@ static void GameInit(bool retainSpatialIndices)
reset_all_sprite_quadrant_placements();
scenery_set_default_placement_configuration();
load_palette();
map_reorganise_elements();
EntityTweener::Get().Reset();
AutoCreateMapAnimations();
fix_invalid_vehicle_sprite_sizes();