mirror of https://github.com/OpenRCT2/OpenRCT2.git
Fix #5261 Deleting the sign after copy/pasting it will crash the game
Prior to the previous commit, signs could be duplicated by pasting them using the tile inspector, which results in some funky behaviour. A duplicated sign refers to the same banner index (which in turn refers to the same user string ID), making the player unable to modify it. Deleting it would previously even crash the game. This commit looks for such signs when loading a scenario, and attempts to fix them, by creating a new banner entry (and user string if one is used).
This commit is contained in:
parent
d2479e0de0
commit
087519ca62
|
@ -54,6 +54,7 @@
|
|||
- Fix: [#5190] Cannot build Wild Mouse - Flying Dutchman Gold Mine.
|
||||
- Fix: [#5224] Multiplayer window is not closed when server shuts down.
|
||||
- Fix: [#5228] Top toolbar disappears when opening SC4 file.
|
||||
- Fix: [#5261] Deleting the sign after copy/pasting it will crash the game.
|
||||
- Fix: [#5398] Attempting to place Mini Maze.TD4 results in weird behaviour and crashes.
|
||||
- Fix: [#5417] Hacked Crooked House tracked rides do not dispatch vehicles.
|
||||
- Fix: [#5445] Patrol area not imported from RCT1 saves and scenarios.
|
||||
|
|
|
@ -1297,6 +1297,9 @@ void game_fix_save_vars()
|
|||
// Fix banner list pointing to NULL map elements
|
||||
banner_reset_broken_index();
|
||||
|
||||
// Fix banners which share their index
|
||||
fix_duplicated_banners();
|
||||
|
||||
// Fix invalid vehicle sprite sizes, thus preventing visual corruption of sprites
|
||||
fix_invalid_vehicle_sprite_sizes();
|
||||
|
||||
|
|
|
@ -547,6 +547,70 @@ void banner_reset_broken_index()
|
|||
}
|
||||
}
|
||||
|
||||
void fix_duplicated_banners()
|
||||
{
|
||||
// For each banner in the map, check if the banner index is in use already, and if so, create a new entry for it
|
||||
bool activeBanners[Util::CountOf(gBanners)]{};
|
||||
rct_tile_element * tileElement;
|
||||
for (int y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
|
||||
{
|
||||
for (int x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
|
||||
{
|
||||
tileElement = map_get_first_element_at(x, y);
|
||||
do
|
||||
{
|
||||
// TODO: Handle walls and large-scenery that use banner indices too. Large scenery can be tricky, as they occupy
|
||||
// multiple tiles that should both refer to the same banner index.
|
||||
if (tile_element_get_type(tileElement) == TILE_ELEMENT_TYPE_BANNER)
|
||||
{
|
||||
uint8 bannerIndex = tileElement->properties.banner.index;
|
||||
if (activeBanners[bannerIndex])
|
||||
{
|
||||
log_info(
|
||||
"Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y,
|
||||
tileElement->base_height);
|
||||
|
||||
// Banner index is already in use by another banner, so duplicate it
|
||||
uint8 newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY);
|
||||
if (newBannerIndex == BANNER_NULL)
|
||||
{
|
||||
log_error("Failed to create new banner.");
|
||||
continue;
|
||||
}
|
||||
Guard::Assert(activeBanners[newBannerIndex] == false);
|
||||
|
||||
// Copy over the original banner, but update the location
|
||||
rct_banner & newBanner = gBanners[newBannerIndex];
|
||||
newBanner = gBanners[bannerIndex];
|
||||
newBanner.x = x;
|
||||
newBanner.y = y;
|
||||
|
||||
// Duplicate user string too
|
||||
rct_string_id stringIdx = newBanner.string_idx;
|
||||
if (is_user_string_id(stringIdx))
|
||||
{
|
||||
utf8 buffer[USER_STRING_MAX_LENGTH];
|
||||
format_string(buffer, USER_STRING_MAX_LENGTH, stringIdx, nullptr);
|
||||
rct_string_id newStringIdx = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
|
||||
if (newStringIdx == 0)
|
||||
{
|
||||
log_error("Failed to allocate user string for banner");
|
||||
continue;
|
||||
}
|
||||
newBanner.string_idx = newStringIdx;
|
||||
}
|
||||
|
||||
tileElement->properties.banner.index = newBannerIndex;
|
||||
}
|
||||
|
||||
// Mark banner index as in-use
|
||||
activeBanners[bannerIndex] = true;
|
||||
}
|
||||
} while (!tile_element_is_last_for_tile(tileElement++));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BA058
|
||||
|
|
|
@ -50,6 +50,7 @@ sint32 create_new_banner(uint8 flags);
|
|||
rct_tile_element *banner_get_tile_element(sint32 bannerIndex);
|
||||
sint32 banner_get_closest_ride_index(sint32 x, sint32 y, sint32 z);
|
||||
void banner_reset_broken_index();
|
||||
void fix_duplicated_banners();
|
||||
void game_command_callback_place_banner(sint32 eax, sint32 ebx, sint32 ecx, sint32 edx, sint32 esi, sint32 edi, sint32 ebp);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue