Merge pull request #9644 from IntelOrca/refactor/banners

Refactor banners
This commit is contained in:
Michael Steenbeek 2019-07-27 10:59:57 +02:00 committed by GitHub
commit 382935c50f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 497 additions and 303 deletions

View File

@ -204,7 +204,6 @@ int32_t viewport_interaction_get_item_right(int32_t x, int32_t y, viewport_inter
{
TileElement* tileElement;
rct_scenery_entry* sceneryEntry;
rct_banner* banner;
Ride* ride;
int32_t i, stationIndex;
@ -325,7 +324,7 @@ int32_t viewport_interaction_get_item_right(int32_t x, int32_t y, viewport_inter
sceneryEntry = tileElement->AsWall()->GetEntry();
if (sceneryEntry->wall.scrolling_mode != SCROLLING_MODE_NONE)
{
banner = &gBanners[tileElement->AsWall()->GetBannerIndex()];
auto banner = tileElement->AsWall()->GetBanner();
set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_BANNER_STRINGID_STRINGID);
set_map_tooltip_format_arg(2, rct_string_id, banner->string_idx);
set_map_tooltip_format_arg(4, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY);
@ -338,7 +337,7 @@ int32_t viewport_interaction_get_item_right(int32_t x, int32_t y, viewport_inter
sceneryEntry = tileElement->AsLargeScenery()->GetEntry();
if (sceneryEntry->large_scenery.scrolling_mode != SCROLLING_MODE_NONE)
{
banner = &gBanners[tileElement->AsLargeScenery()->GetBannerIndex()];
auto banner = tileElement->AsLargeScenery()->GetBanner();
set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_BANNER_STRINGID_STRINGID);
set_map_tooltip_format_arg(2, rct_string_id, banner->string_idx);
set_map_tooltip_format_arg(4, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY);
@ -348,7 +347,8 @@ int32_t viewport_interaction_get_item_right(int32_t x, int32_t y, viewport_inter
break;
case VIEWPORT_INTERACTION_ITEM_BANNER:
banner = &gBanners[tileElement->AsBanner()->GetIndex()];
{
auto banner = tileElement->AsBanner()->GetBanner();
sceneryEntry = get_banner_entry(banner->type);
set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_BANNER_STRINGID_STRINGID);
@ -361,6 +361,7 @@ int32_t viewport_interaction_get_item_right(int32_t x, int32_t y, viewport_inter
set_map_tooltip_format_arg(4, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY);
set_map_tooltip_format_arg(6, rct_string_id, sceneryEntry->name);
return info->type;
}
}
if (!(input_test_flag(INPUT_FLAG_6)) || !(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))

View File

@ -132,8 +132,9 @@ rct_window* window_banner_open(rct_windownumber number)
w->number = number;
window_init_scroll_widgets(w);
int32_t view_x = gBanners[w->number].x << 5;
int32_t view_y = gBanners[w->number].y << 5;
auto banner = GetBanner(w->number);
int32_t view_x = banner->position.x << 5;
int32_t view_y = banner->position.y << 5;
TileElement* tile_element = map_get_first_element_at(view_x / 32, view_y / 32);
while (1)
@ -170,9 +171,9 @@ rct_window* window_banner_open(rct_windownumber number)
*/
static void window_banner_mouseup(rct_window* w, rct_widgetindex widgetIndex)
{
rct_banner* banner = &gBanners[w->number];
int32_t x = banner->x << 5;
int32_t y = banner->y << 5;
auto banner = GetBanner(w->number);
int32_t x = banner->position.x << 5;
int32_t y = banner->position.y << 5;
TileElement* tile_element = map_get_first_element_at(x / 32, y / 32);
@ -196,8 +197,7 @@ static void window_banner_mouseup(rct_window* w, rct_widgetindex widgetIndex)
break;
}
case WIDX_BANNER_TEXT:
window_text_input_open(
w, WIDX_BANNER_TEXT, STR_BANNER_TEXT, STR_ENTER_BANNER_TEXT, gBanners[w->number].string_idx, 0, 32);
window_text_input_open(w, WIDX_BANNER_TEXT, STR_BANNER_TEXT, STR_ENTER_BANNER_TEXT, banner->string_idx, 0, 32);
break;
case WIDX_BANNER_NO_ENTRY:
{
@ -216,7 +216,7 @@ static void window_banner_mouseup(rct_window* w, rct_widgetindex widgetIndex)
*/
static void window_banner_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
{
rct_banner* banner = &gBanners[w->number];
auto banner = GetBanner(w->number);
switch (widgetIndex)
{
@ -290,7 +290,7 @@ static void window_banner_textinput(rct_window* w, rct_widgetindex widgetIndex,
*/
static void window_banner_invalidate(rct_window* w)
{
rct_banner* banner = &gBanners[w->number];
auto banner = GetBanner(w->number);
rct_widget* colour_btn = &window_banner_widgets[WIDX_MAIN_COLOUR];
colour_btn->type = WWT_EMPTY;
@ -341,10 +341,10 @@ static void window_banner_viewport_rotate(rct_window* w)
view->width = 0;
rct_banner* banner = &gBanners[w->number];
auto banner = GetBanner(w->number);
int32_t view_x = (banner->x << 5) + 16;
int32_t view_y = (banner->y << 5) + 16;
int32_t view_x = (banner->position.x << 5) + 16;
int32_t view_y = (banner->position.y << 5) + 16;
int32_t view_z = w->frame_no;
// Create viewport

View File

@ -153,8 +153,9 @@ rct_window* window_sign_open(rct_windownumber number)
w->number = number;
window_init_scroll_widgets(w);
int32_t view_x = gBanners[w->number].x << 5;
int32_t view_y = gBanners[w->number].y << 5;
auto banner = GetBanner(w->number);
int32_t view_x = banner->position.x << 5;
int32_t view_y = banner->position.y << 5;
TileElement* tile_element = map_get_first_element_at(view_x / 32, view_y / 32);
@ -202,13 +203,10 @@ rct_window* window_sign_open(rct_windownumber number)
*/
static void window_sign_mouseup(rct_window* w, rct_widgetindex widgetIndex)
{
rct_banner* banner = &gBanners[w->number];
int32_t x = banner->x << 5;
int32_t y = banner->y << 5;
rct_string_id string_id;
TileElement* tile_element = map_get_first_element_at(x / 32, y / 32);
auto banner = GetBanner(w->number);
int32_t x = banner->position.x << 5;
int32_t y = banner->position.y << 5;
auto tile_element = map_get_first_element_at(x / 32, y / 32);
switch (widgetIndex)
{
@ -240,18 +238,17 @@ static void window_sign_mouseup(rct_window* w, rct_widgetindex widgetIndex)
break;
}
case WIDX_SIGN_TEXT:
{
auto stringId = banner->string_idx;
if (banner->flags & BANNER_FLAG_LINKED_TO_RIDE)
{
Ride* ride = get_ride(banner->ride_index);
set_format_arg(16, uint32_t, ride->name_arguments);
string_id = ride->name;
stringId = ride->name;
}
else
{
string_id = gBanners[w->number].string_idx;
}
window_text_input_open(w, WIDX_SIGN_TEXT, STR_SIGN_TEXT_TITLE, STR_SIGN_TEXT_PROMPT, string_id, 0, 32);
window_text_input_open(w, WIDX_SIGN_TEXT, STR_SIGN_TEXT_TITLE, STR_SIGN_TEXT_PROMPT, stringId, 0, 32);
break;
}
}
}
@ -371,10 +368,10 @@ static void window_sign_viewport_rotate(rct_window* w)
view->width = 0;
rct_banner* banner = &gBanners[w->number];
auto banner = GetBanner(w->number);
int32_t view_x = (banner->x << 5) + 16;
int32_t view_y = (banner->y << 5) + 16;
int32_t view_x = (banner->position.x << 5) + 16;
int32_t view_y = (banner->position.y << 5) + 16;
int32_t view_z = w->frame_no;
// Create viewport
@ -412,8 +409,9 @@ rct_window* window_sign_small_open(rct_windownumber number)
w->colours[1] = COLOUR_DARK_BROWN;
w->colours[2] = COLOUR_DARK_BROWN;
int32_t view_x = gBanners[w->number].x << 5;
int32_t view_y = gBanners[w->number].y << 5;
auto banner = GetBanner(w->number);
int32_t view_x = banner->position.x << 5;
int32_t view_y = banner->position.y << 5;
TileElement* tile_element = map_get_first_element_at(view_x / 32, view_y / 32);
@ -460,13 +458,10 @@ rct_window* window_sign_small_open(rct_windownumber number)
*/
static void window_sign_small_mouseup(rct_window* w, rct_widgetindex widgetIndex)
{
rct_banner* banner = &gBanners[w->number];
int32_t x = banner->x << 5;
int32_t y = banner->y << 5;
rct_string_id string_id;
TileElement* tile_element = map_get_first_element_at(x / 32, y / 32);
auto banner = GetBanner(w->number);
int32_t x = banner->position.x << 5;
int32_t y = banner->position.y << 5;
auto tile_element = map_get_first_element_at(x / 32, y / 32);
switch (widgetIndex)
{
@ -491,21 +486,20 @@ static void window_sign_small_mouseup(rct_window* w, rct_widgetindex widgetIndex
TileCoordsXYZD wallLocation = { x >> 5, y >> 5, tile_element->base_height, tile_element->GetDirection() };
auto wallRemoveAction = WallRemoveAction(wallLocation);
GameActions::Execute(&wallRemoveAction);
break;
}
break;
case WIDX_SIGN_TEXT:
{
auto stringId = banner->string_idx;
if (banner->flags & BANNER_FLAG_LINKED_TO_RIDE)
{
Ride* ride = get_ride(banner->ride_index);
set_format_arg(16, uint32_t, ride->name_arguments);
string_id = ride->name;
stringId = ride->name;
}
else
{
string_id = gBanners[w->number].string_idx;
}
window_text_input_open(w, WIDX_SIGN_TEXT, STR_SIGN_TEXT_TITLE, STR_SIGN_TEXT_PROMPT, string_id, 0, 32);
window_text_input_open(w, WIDX_SIGN_TEXT, STR_SIGN_TEXT_TITLE, STR_SIGN_TEXT_PROMPT, stringId, 0, 32);
break;
}
}
}

View File

@ -2032,9 +2032,12 @@ static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi)
rct_wall_scenery_entry wallEntry = get_wall_entry(wallType)->wall;
if (wallEntry.flags & WALL_SCENERY_IS_BANNER)
{
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT,
&gBanners[tileElement->AsWall()->GetBannerIndex()].string_idx, COLOUR_DARK_GREEN, x, y + 11);
auto banner = tileElement->AsWall()->GetBanner();
if (banner != nullptr)
{
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &banner->string_idx, COLOUR_DARK_GREEN, x, y + 11);
}
}
else
{
@ -2074,9 +2077,13 @@ static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi)
rct_scenery_entry* largeSceneryEntry = get_large_scenery_entry(largeSceneryType);
if (largeSceneryEntry->large_scenery.scrolling_mode != SCROLLING_MODE_NONE)
{
const BannerIndex bannerIndex = sceneryElement->GetBannerIndex();
rct_string_id* string = &gBanners[bannerIndex].string_idx;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, string, COLOUR_DARK_GREEN, x, y + 22);
auto banner = sceneryElement->GetBanner();
if (banner != nullptr)
{
auto stringId = banner->string_idx;
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &stringId, COLOUR_DARK_GREEN, x, y + 22);
}
}
else
{
@ -2099,16 +2106,20 @@ static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
// Details
// Banner info
const uint8_t bannerIndex = tileElement->AsBanner()->GetIndex();
if (gBanners[bannerIndex].flags & BANNER_FLAG_NO_ENTRY)
auto banner = tileElement->AsBanner()->GetBanner();
if (banner != nullptr)
{
rct_string_id noEntryStringIdx = STR_NO_ENTRY;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &noEntryStringIdx, COLOUR_DARK_GREEN, x, y);
}
else
{
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &gBanners[bannerIndex].string_idx, COLOUR_DARK_GREEN, x, y);
if (banner->flags & BANNER_FLAG_NO_ENTRY)
{
rct_string_id noEntryStringIdx = STR_NO_ENTRY;
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &noEntryStringIdx, COLOUR_DARK_GREEN, x, y);
}
else
{
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &banner->string_idx, COLOUR_DARK_GREEN, x, y);
}
}
// Properties

View File

@ -1080,15 +1080,18 @@ static void repaint_scenery_tool_down(int16_t x, int16_t y, rct_widgetindex widg
}
case VIEWPORT_INTERACTION_ITEM_BANNER:
{
rct_banner* banner = &gBanners[tile_element->AsBanner()->GetIndex()];
rct_scenery_entry* scenery_entry = get_banner_entry(banner->type);
if (scenery_entry->banner.flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR)
auto banner = tile_element->AsBanner()->GetBanner();
if (banner != nullptr)
{
auto repaintScenery = BannerSetColourAction(
{ grid_x, grid_y, tile_element->base_height * 8, tile_element->AsBanner()->GetPosition() },
gWindowSceneryPrimaryColour);
auto scenery_entry = get_banner_entry(banner->type);
if (scenery_entry->banner.flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR)
{
auto repaintScenery = BannerSetColourAction(
{ grid_x, grid_y, tile_element->base_height * 8, tile_element->AsBanner()->GetPosition() },
gWindowSceneryPrimaryColour);
GameActions::Execute(&repaintScenery);
GameActions::Execute(&repaintScenery);
}
}
break;
}
@ -1164,15 +1167,17 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
}
case VIEWPORT_INTERACTION_ITEM_BANNER:
{
int32_t bannerIndex = tileElement->AsBanner()->GetIndex();
rct_banner* banner = &gBanners[bannerIndex];
rct_scenery_entry* sceneryEntry = get_banner_entry(banner->type);
if (sceneryEntry != nullptr)
auto banner = tileElement->AsBanner()->GetBanner();
if (banner != nullptr)
{
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_BANNERS, banner->type);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
auto sceneryEntry = get_banner_entry(banner->type);
if (sceneryEntry != nullptr)
{
gWindowSceneryEyedropperEnabled = false;
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_BANNERS, banner->type);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
{
gWindowSceneryEyedropperEnabled = false;
}
}
}
break;

View File

@ -294,11 +294,12 @@ namespace Editor
map_remove_all_rides();
//
for (auto& banner : gBanners)
for (BannerIndex i = 0; i < MAX_BANNERS; i++)
{
if (banner.type == 255)
auto banner = GetBanner(i);
if (banner->type == BANNER_NULL)
{
banner.flags &= ~BANNER_FLAG_LINKED_TO_RIDE;
banner->flags &= ~BANNER_FLAG_LINKED_TO_RIDE;
}
}

View File

@ -125,7 +125,6 @@ void setup_in_use_selection_flags()
do
{
uint16_t type;
rct_banner* banner;
switch (iter.element->GetType())
{
@ -173,11 +172,16 @@ void setup_in_use_selection_flags()
Editor::SetSelectedObject(OBJECT_TYPE_LARGE_SCENERY, type, OBJECT_SELECTION_FLAG_SELECTED);
break;
case TILE_ELEMENT_TYPE_BANNER:
banner = &gBanners[iter.element->AsBanner()->GetIndex()];
type = banner->type;
assert(type < object_entry_group_counts[OBJECT_TYPE_BANNERS]);
Editor::SetSelectedObject(OBJECT_TYPE_BANNERS, type, OBJECT_SELECTION_FLAG_SELECTED);
{
auto banner = iter.element->AsBanner()->GetBanner();
if (banner != nullptr)
{
type = banner->type;
assert(type < object_entry_group_counts[OBJECT_TYPE_BANNERS]);
Editor::SetSelectedObject(OBJECT_TYPE_BANNERS, type, OBJECT_SELECTION_FLAG_SELECTED);
}
break;
}
}
} while (tile_element_iterator_next(&iter));

View File

@ -90,7 +90,8 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE);
}
if (gBanners[_bannerIndex].type != BANNER_NULL)
auto banner = GetBanner(_bannerIndex);
if (banner->type != BANNER_NULL)
{
log_error("Banner index in use, bannerIndex = %u", _bannerIndex);
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE);
@ -129,7 +130,8 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE);
}
if (gBanners[_bannerIndex].type != BANNER_NULL)
auto banner = GetBanner(_bannerIndex);
if (banner->type != BANNER_NULL)
{
log_error("Banner index in use, bannerIndex = %u", _bannerIndex);
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE);
@ -137,15 +139,14 @@ public:
TileElement* newTileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, baseHeight, 0);
assert(newTileElement != nullptr);
rct_banner* banner = &gBanners[_bannerIndex];
banner->flags = 0;
banner->string_idx = STR_DEFAULT_SIGN;
banner->text_colour = 2;
banner->type = _bannerType;
banner->colour = _primaryColour;
banner->x = _loc.x / 32;
banner->y = _loc.y / 32;
banner->position.x = _loc.x / 32;
banner->position.y = _loc.y / 32;
newTileElement->SetType(TILE_ELEMENT_TYPE_BANNER);
BannerElement* bannerElement = newTileElement->AsBanner();
bannerElement->clearance_height = newTileElement->base_height + 2;

View File

@ -67,8 +67,7 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS);
}
rct_banner* banner = &gBanners[bannerElement->GetIndex()];
auto banner = bannerElement->GetBanner();
if (banner == nullptr)
{
log_error("Invalid banner index. index = ", bannerElement->GetIndex());
@ -107,8 +106,7 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_REMOVE_THIS);
}
rct_banner* banner = &gBanners[bannerElement->GetIndex()];
auto banner = bannerElement->GetBanner();
if (banner == nullptr)
{
log_error("Invalid banner index. index = ", bannerElement->GetIndex());

View File

@ -101,7 +101,8 @@ private:
intent.putExtra(INTENT_EXTRA_BANNER_INDEX, index);
context_broadcast_intent(&intent);
gBanners[index].colour = _primaryColour;
auto banner = GetBanner(index);
banner->colour = _primaryColour;
map_invalidate_tile_zoom1(_loc.x, _loc.y, _loc.z, _loc.z + 32);
}

View File

@ -71,7 +71,7 @@ public:
GameActionResult::Ptr Execute() const override
{
rct_banner* banner = &gBanners[_bannerIndex];
auto banner = GetBanner(_bannerIndex);
utf8* buffer = gCommonStringFormatBuffer;
utf8* dst = buffer;

View File

@ -63,12 +63,12 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_SELECTION_OF_OBJECTS);
}
rct_banner* banner = &gBanners[_bannerIndex];
auto banner = GetBanner(_bannerIndex);
res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
res->Position.x = banner->x * 32 + 16;
res->Position.y = banner->y * 32 + 16;
res->Position.z = tile_element_height(banner->x, banner->y);
res->Position.x = banner->position.x * 32 + 16;
res->Position.y = banner->position.y * 32 + 16;
res->Position.z = tile_element_height(banner->position.x, banner->position.y);
TileElement* tileElement = banner_get_tile_element(_bannerIndex);
@ -113,12 +113,12 @@ public:
{
auto res = MakeResult();
rct_banner* banner = &gBanners[_bannerIndex];
auto banner = GetBanner(_bannerIndex);
res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
res->Position.x = banner->x * 32 + 16;
res->Position.y = banner->y * 32 + 16;
res->Position.z = tile_element_height(banner->x, banner->y);
res->Position.x = banner->position.x * 32 + 16;
res->Position.y = banner->position.y * 32 + 16;
res->Position.z = tile_element_height(banner->position.x, banner->position.y);
TileElement* tileElement = banner_get_tile_element(_bannerIndex);

View File

@ -136,7 +136,8 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_TOO_MANY_BANNERS_IN_GAME);
}
if (gBanners[_bannerId].type != BANNER_NULL)
auto banner = GetBanner(_bannerId);
if (banner->type != BANNER_NULL)
{
log_error("No free banners available");
return std::make_unique<LargeSceneryPlaceActionResult>(GA_ERROR::NO_FREE_ELEMENTS);
@ -252,20 +253,20 @@ public:
return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_TOO_MANY_BANNERS_IN_GAME);
}
if (gBanners[_bannerId].type != BANNER_NULL)
auto banner = GetBanner(_bannerId);
if (banner->type != BANNER_NULL)
{
log_error("No free banners available");
return std::make_unique<LargeSceneryPlaceActionResult>(GA_ERROR::NO_FREE_ELEMENTS);
}
rct_banner* banner = &gBanners[_bannerId];
banner->string_idx = STR_DEFAULT_SIGN;
banner->colour = 2;
banner->text_colour = 2;
banner->flags = BANNER_FLAG_IS_LARGE_SCENERY;
banner->type = 0;
banner->x = _loc.x / 32;
banner->y = _loc.y / 32;
banner->position.x = _loc.x / 32;
banner->position.y = _loc.y / 32;
ride_id_t rideIndex = banner_get_closest_ride_index(_loc.x, _loc.y, maxHeight);
if (rideIndex != RIDE_ID_NULL)

View File

@ -136,12 +136,13 @@ private:
ride_clear_leftover_entrances(ride);
news_item_disable_news(NEWS_ITEM_RIDE, _rideIndex);
for (auto& banner : gBanners)
for (BannerIndex i = 0; i < MAX_BANNERS; i++)
{
if (banner.type != BANNER_NULL && banner.flags & BANNER_FLAG_LINKED_TO_RIDE && banner.ride_index == _rideIndex)
auto banner = GetBanner(i);
if (banner->type != BANNER_NULL && banner->flags & BANNER_FLAG_LINKED_TO_RIDE && banner->ride_index == _rideIndex)
{
banner.flags &= 0xFB;
banner.string_idx = STR_DEFAULT_SIGN;
banner->flags &= ~BANNER_FLAG_LINKED_TO_RIDE;
banner->string_idx = STR_DEFAULT_SIGN;
}
}

View File

@ -70,10 +70,10 @@ public:
GameActionResult::Ptr Execute() const override
{
rct_banner* banner = &gBanners[_bannerIndex];
auto banner = GetBanner(_bannerIndex);
int32_t x = banner->x << 5;
int32_t y = banner->y << 5;
int32_t x = banner->position.x << 5;
int32_t y = banner->position.y << 5;
if (_name.empty() == false)
{

View File

@ -57,9 +57,9 @@ public:
return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
}
rct_banner* banner = &gBanners[_bannerIndex];
auto banner = GetBanner(_bannerIndex);
CoordsXY coords{ banner->x * 32, banner->y * 32 };
CoordsXY coords{ banner->position.x * 32, banner->position.y * 32 };
if (_isLarge)
{
@ -91,9 +91,9 @@ public:
GameActionResult::Ptr Execute() const override
{
rct_banner* banner = &gBanners[_bannerIndex];
auto banner = GetBanner(_bannerIndex);
CoordsXY coords{ banner->x * 32, banner->y * 32 };
CoordsXY coords{ banner->position.x * 32, banner->position.y * 32 };
if (_isLarge)
{

View File

@ -259,7 +259,8 @@ public:
return std::make_unique<WallPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_TOO_MANY_BANNERS_IN_GAME);
}
if (gBanners[_bannerId].type != BANNER_NULL)
auto banner = GetBanner(_bannerId);
if (banner->type != BANNER_NULL)
{
log_error("No free banners available");
return std::make_unique<WallPlaceActionResult>(GA_ERROR::NO_FREE_ELEMENTS);
@ -348,20 +349,20 @@ public:
return std::make_unique<WallPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_TOO_MANY_BANNERS_IN_GAME);
}
if (gBanners[_bannerId].type != BANNER_NULL)
auto banner = GetBanner(_bannerId);
if (banner->type != BANNER_NULL)
{
log_error("No free banners available");
return std::make_unique<WallPlaceActionResult>(GA_ERROR::NO_FREE_ELEMENTS);
}
rct_banner* banner = &gBanners[_bannerId];
banner->string_idx = STR_DEFAULT_SIGN;
banner->colour = 2;
banner->text_colour = 2;
banner->flags = BANNER_FLAG_IS_WALL;
banner->type = 0;
banner->x = _loc.x / 32;
banner->y = _loc.y / 32;
banner->position.x = _loc.x / 32;
banner->position.y = _loc.y / 32;
ride_id_t rideIndex = banner_get_closest_ride_index(_loc.x, _loc.y, targetHeight);
if (rideIndex != RIDE_ID_NULL)

View File

@ -1262,7 +1262,8 @@ static int32_t cc_show_limits(InteractiveConsole& console, [[maybe_unused]] cons
int32_t bannerCount = 0;
for (BannerIndex i = 0; i < MAX_BANNERS; ++i)
{
if (gBanners[i].type != BANNER_NULL)
auto banner = GetBanner(i);
if (banner->type != BANNER_NULL)
{
bannerCount++;
}

View File

@ -43,8 +43,13 @@ void banner_paint(paint_session* session, uint8_t direction, int32_t height, con
height -= 16;
rct_scenery_entry* banner_scenery = get_banner_entry(gBanners[tile_element->AsBanner()->GetIndex()].type);
auto banner = tile_element->AsBanner()->GetBanner();
if (banner == nullptr)
{
return;
}
auto banner_scenery = get_banner_entry(banner->type);
if (banner_scenery == nullptr)
{
return;
@ -67,7 +72,7 @@ void banner_paint(paint_session* session, uint8_t direction, int32_t height, con
}
else
{
image_id |= (gBanners[tile_element->AsBanner()->GetIndex()].colour << 19) | IMAGE_TYPE_REMAP;
image_id |= (banner->colour << 19) | IMAGE_TYPE_REMAP;
}
sub_98197C(session, image_id, 0, 0, 1, 1, 0x15, height, boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ);
@ -95,13 +100,13 @@ void banner_paint(paint_session* session, uint8_t direction, int32_t height, con
set_format_arg(0, uint32_t, 0);
set_format_arg(4, uint32_t, 0);
if (gBanners[tile_element->AsBanner()->GetIndex()].flags & BANNER_FLAG_NO_ENTRY)
if (banner->flags & BANNER_FLAG_NO_ENTRY)
{
set_format_arg(0, rct_string_id, STR_NO_ENTRY);
}
else
{
set_format_arg(0, rct_string_id, gBanners[tile_element->AsBanner()->GetIndex()].string_idx);
set_format_arg(0, rct_string_id, banner->string_idx);
}
if (gConfigGeneral.upper_case_banners)

View File

@ -309,94 +309,97 @@ void large_scenery_paint(paint_session* session, uint8_t direction, uint16_t hei
textColour = COLOUR_GREY;
}
textColour = (textColour << 19) | IMAGE_TYPE_REMAP;
BannerIndex bannerIndex = tileElement->AsLargeScenery()->GetBannerIndex();
rct_banner* banner = &gBanners[bannerIndex];
rct_string_id stringId = banner->string_idx;
if (banner->flags & BANNER_FLAG_LINKED_TO_RIDE)
auto banner = tileElement->AsLargeScenery()->GetBanner();
if (banner != nullptr)
{
Ride* ride = get_ride(banner->ride_index);
stringId = ride->name;
set_format_arg(0, uint32_t, ride->name_arguments);
}
utf8 signString[256];
format_string(signString, sizeof(signString), stringId, gCommonFormatArgs);
rct_large_scenery_text* text = entry->large_scenery.text;
int32_t y_offset = (text->offset[(direction & 1)].y * 2);
if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
{
// Draw vertical sign:
y_offset += 1;
utf8 fitStr[32];
large_scenery_sign_fit_text(signString, text, true, fitStr, sizeof(fitStr));
safe_strcpy(fitStr, fitStr, sizeof(fitStr));
const utf8* fitStrPtr = fitStr;
int32_t height2 = large_scenery_sign_text_height(fitStr, text);
uint32_t codepoint;
while ((codepoint = utf8_get_next(fitStrPtr, &fitStrPtr)) != 0)
auto stringId = banner->string_idx;
if (banner->flags & BANNER_FLAG_LINKED_TO_RIDE)
{
utf8 str[5] = { 0 };
utf8_write_codepoint(str, codepoint);
large_scenery_sign_paint_line(
session, str, entry->large_scenery.text, entry->large_scenery.text_image, textColour, direction,
y_offset - height2);
y_offset += large_scenery_sign_get_glyph(text, codepoint)->height * 2;
auto ride = get_ride(banner->ride_index);
stringId = ride->name;
set_format_arg(0, uint32_t, ride->name_arguments);
}
}
else
{
y_offset -= (direction & 1);
if (text->flags & LARGE_SCENERY_TEXT_FLAG_TWO_LINE)
utf8 signString[256];
format_string(signString, sizeof(signString), stringId, gCommonFormatArgs);
rct_large_scenery_text* text = entry->large_scenery.text;
int32_t y_offset = (text->offset[(direction & 1)].y * 2);
if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
{
// Draw two-line sign:
int32_t width = large_scenery_sign_text_width(signString, text);
if (width > text->max_width)
{
y_offset -= large_scenery_sign_get_glyph(text, 'A')->height + 1;
utf8* src = signString;
for (int32_t i = 0; i < 2; i++)
{
utf8 str1[64] = { 0 };
utf8* dst = str1;
utf8* srcold = src;
utf8* spacesrc = nullptr;
utf8* spacedst = nullptr;
int32_t w = 0;
uint32_t codepoint = utf8_get_next(src, (const utf8**)&src);
do
{
w += large_scenery_sign_get_glyph(text, codepoint)->width;
if (codepoint == ' ')
{
spacesrc = src;
spacedst = dst;
}
} while (w <= text->max_width && (dst = utf8_write_codepoint(dst, codepoint)) != nullptr
&& (srcold = src) != nullptr && (codepoint = utf8_get_next(src, (const utf8**)&src)) != '\0');
src = srcold;
if (spacesrc && codepoint)
{
*spacedst = 0;
src = spacesrc;
}
large_scenery_sign_paint_line(
session, str1, entry->large_scenery.text, entry->large_scenery.text_image, textColour, direction,
y_offset);
y_offset += (large_scenery_sign_get_glyph(text, 'A')->height + 1) * 2;
}
}
else
// Draw vertical sign:
y_offset += 1;
utf8 fitStr[32];
large_scenery_sign_fit_text(signString, text, true, fitStr, sizeof(fitStr));
safe_strcpy(fitStr, fitStr, sizeof(fitStr));
const utf8* fitStrPtr = fitStr;
int32_t height2 = large_scenery_sign_text_height(fitStr, text);
uint32_t codepoint;
while ((codepoint = utf8_get_next(fitStrPtr, &fitStrPtr)) != 0)
{
utf8 str[5] = { 0 };
utf8_write_codepoint(str, codepoint);
large_scenery_sign_paint_line(
session, signString, entry->large_scenery.text, entry->large_scenery.text_image, textColour, direction,
y_offset);
session, str, entry->large_scenery.text, entry->large_scenery.text_image, textColour, direction,
y_offset - height2);
y_offset += large_scenery_sign_get_glyph(text, codepoint)->height * 2;
}
}
else
{
// Draw one-line sign:
large_scenery_sign_paint_line(
session, signString, entry->large_scenery.text, entry->large_scenery.text_image, textColour, direction,
y_offset);
y_offset -= (direction & 1);
if (text->flags & LARGE_SCENERY_TEXT_FLAG_TWO_LINE)
{
// Draw two-line sign:
int32_t width = large_scenery_sign_text_width(signString, text);
if (width > text->max_width)
{
y_offset -= large_scenery_sign_get_glyph(text, 'A')->height + 1;
utf8* src = signString;
for (int32_t i = 0; i < 2; i++)
{
utf8 str1[64] = { 0 };
utf8* dst = str1;
utf8* srcold = src;
utf8* spacesrc = nullptr;
utf8* spacedst = nullptr;
int32_t w = 0;
uint32_t codepoint = utf8_get_next(src, (const utf8**)&src);
do
{
w += large_scenery_sign_get_glyph(text, codepoint)->width;
if (codepoint == ' ')
{
spacesrc = src;
spacedst = dst;
}
} while (w <= text->max_width && (dst = utf8_write_codepoint(dst, codepoint)) != nullptr
&& (srcold = src) != nullptr
&& (codepoint = utf8_get_next(src, (const utf8**)&src)) != '\0');
src = srcold;
if (spacesrc && codepoint)
{
*spacedst = 0;
src = spacesrc;
}
large_scenery_sign_paint_line(
session, str1, entry->large_scenery.text, entry->large_scenery.text_image, textColour,
direction, y_offset);
y_offset += (large_scenery_sign_get_glyph(text, 'A')->height + 1) * 2;
}
}
else
{
large_scenery_sign_paint_line(
session, signString, entry->large_scenery.text, entry->large_scenery.text_image, textColour,
direction, y_offset);
}
}
else
{
// Draw one-line sign:
large_scenery_sign_paint_line(
session, signString, entry->large_scenery.text, entry->large_scenery.text_image, textColour, direction,
y_offset);
}
}
}
return;
@ -429,7 +432,7 @@ void large_scenery_paint(paint_session* session, uint8_t direction, uint16_t hei
set_format_arg(7, uint8_t, textColour);
BannerIndex bannerIndex = tileElement->AsLargeScenery()->GetBannerIndex();
uint16_t scrollMode = entry->large_scenery.scrolling_mode + ((direction + 1) & 0x3);
rct_banner* banner = &gBanners[bannerIndex];
auto banner = GetBanner(bannerIndex);
set_format_arg(0, rct_string_id, banner->string_idx);
if (banner->flags & BANNER_FLAG_LINKED_TO_RIDE)
{

View File

@ -430,8 +430,7 @@ void fence_paint(paint_session* session, uint8_t direction, int32_t height, cons
uint16_t scrollingMode = sceneryEntry->wall.scrolling_mode + ((direction + 1) & 0x3);
uint8_t bannerIndex = tile_element->AsWall()->GetBannerIndex();
rct_banner* banner = &gBanners[bannerIndex];
auto banner = tile_element->AsWall()->GetBanner();
set_format_arg(0, rct_string_id, banner->string_idx);
if (banner->flags & BANNER_FLAG_LINKED_TO_RIDE)

View File

@ -27,6 +27,7 @@
#define RCT1_MAX_STAFF 116
#define RCT1_RESEARCH_FLAGS_SEPARATOR 0xFF
#define RCT1_MAX_ANIMATED_OBJECTS 1000
#define RCT1_MAX_BANNERS 100
struct ParkLoadResult;
@ -665,7 +666,7 @@ struct rct1_s4
uint16_t unk_199C9A;
rct1_research_item research_items_LL[180];
uint8_t unk_19A020[5468];
rct_banner banners[100];
RCT12Banner banners[RCT1_MAX_BANNERS];
char string_table[RCT12_MAX_USER_STRINGS][RCT12_USER_STRING_MAX_LENGTH];
uint32_t game_time_counter;
rct1_ride rides[RCT12_MAX_RIDES_IN_PARK];

View File

@ -2254,10 +2254,12 @@ private:
dst2->SetPosition(src2->GetPosition());
dst2->SetAllowedEdges(src2->GetAllowedEdges());
rct_banner* srcBanner = &_s4.banners[index];
rct_banner* dstBanner = &gBanners[index];
ImportBanner(dstBanner, srcBanner);
if (index < std::size(_s4.banners))
{
auto srcBanner = &_s4.banners[index];
auto dstBanner = GetBanner(index);
ImportBanner(dstBanner, srcBanner);
}
break;
}
default:
@ -2831,10 +2833,16 @@ private:
}
}
void ImportBanner(rct_banner* dst, rct_banner* src)
void ImportBanner(Banner* dst, const RCT12Banner* src)
{
*dst = *src;
dst->colour = RCT1::GetColour(src->colour);
*dst = {};
dst->type = src->type;
dst->flags = 0;
if (src->flags & BANNER_FLAG_NO_ENTRY)
{
dst->flags |= BANNER_FLAG_NO_ENTRY;
}
dst->string_idx = STR_DEFAULT_SIGN;
if (is_user_string_id(src->string_idx))
@ -2849,6 +2857,11 @@ private:
}
}
}
dst->colour = RCT1::GetColour(src->colour);
dst->text_colour = src->text_colour;
dst->position.x = src->x;
dst->position.y = src->y;
}
void FixEntrancePositions()

View File

@ -521,4 +521,20 @@ struct RCT12RideMeasurement
};
assert_struct_size(RCT12RideMeasurement, 0x4B0C);
struct RCT12Banner
{
uint8_t type;
uint8_t flags; // 0x01
rct_string_id string_idx; // 0x02
union
{
uint8_t colour; // 0x04
uint8_t ride_index; // 0x04
};
uint8_t text_colour; // 0x05
uint8_t x; // 0x06
uint8_t y; // 0x07
};
assert_struct_size(RCT12Banner, 8);
#pragma pack(pop)

View File

@ -343,7 +343,7 @@ void S6Exporter::Export()
}
safe_strcpy(_s6.scenario_filename, gScenarioFileName, sizeof(_s6.scenario_filename));
std::memcpy(_s6.saved_expansion_pack_names, gScenarioExpansionPacks, sizeof(_s6.saved_expansion_pack_names));
std::memcpy(_s6.banners, gBanners, sizeof(_s6.banners));
ExportBanners();
std::memcpy(_s6.custom_strings, gUserStrings, sizeof(_s6.custom_strings));
_s6.game_ticks_1 = gCurrentTicks;
@ -1173,6 +1173,34 @@ void S6Exporter::ExportSpriteLitter(RCT12SpriteLitter* dst, const rct_litter* sr
dst->creationTick = src->creationTick;
}
void S6Exporter::ExportBanners()
{
for (BannerIndex i = 0; i < RCT2_MAX_BANNERS_IN_PARK; i++)
{
auto src = GetBanner(i);
auto dst = &_s6.banners[i];
ExportBanner(*dst, *src);
}
}
void S6Exporter::ExportBanner(RCT12Banner& dst, const Banner& src)
{
dst.type = src.type;
dst.flags = src.flags;
dst.string_idx = src.string_idx;
if (src.flags & BANNER_FLAG_LINKED_TO_RIDE)
{
dst.ride_index = src.ride_index;
}
else
{
dst.colour = src.colour;
}
dst.text_colour = src.text_colour;
dst.x = src.position.x;
dst.y = src.position.y;
}
enum : uint32_t
{
S6_SAVE_FLAG_EXPORT = 1 << 0,

View File

@ -60,4 +60,6 @@ private:
void ExportPeepSpawns();
void ExportRideMeasurements();
void ExportRideMeasurement(RCT12RideMeasurement& dst, const RideMeasurement& src);
void ExportBanners();
void ExportBanner(RCT12Banner& dst, const Banner& src);
};

View File

@ -47,6 +47,7 @@
#include "../world/Entrance.h"
#include "../world/MapAnimation.h"
#include "../world/Park.h"
#include "../world/Scenery.h"
#include "../world/Sprite.h"
#include "../world/Surface.h"
@ -370,7 +371,6 @@ public:
String::Set(gScenarioFileName, sizeof(gScenarioFileName), _s6.scenario_filename);
}
std::memcpy(gScenarioExpansionPacks, _s6.saved_expansion_pack_names, sizeof(_s6.saved_expansion_pack_names));
std::memcpy(gBanners, _s6.banners, sizeof(_s6.banners));
// Clear all of the strings, since we will probably have a higher limit on user strings in the future than RCT2.
user_string_clear_all();
std::memcpy(gUserStrings, _s6.custom_strings, sizeof(_s6.custom_strings));
@ -836,6 +836,27 @@ public:
std::memcpy(gResearchItems, _s6.research_items, sizeof(_s6.research_items));
}
void ImportBanner(Banner* dst, const RCT12Banner* src)
{
*dst = {};
dst->type = src->type;
dst->flags = src->flags;
dst->string_idx = src->string_idx;
if (src->flags & BANNER_FLAG_LINKED_TO_RIDE)
{
dst->ride_index = src->ride_index;
}
else
{
dst->colour = src->colour;
}
dst->text_colour = src->text_colour;
dst->position.x = src->x;
dst->position.y = src->y;
}
void Initialise()
{
OpenRCT2::GetContext()->GetGameState()->InitAll(_s6.map_size);
@ -1040,6 +1061,22 @@ public:
dst2->SetAcrossTrack(src2->IsAcrossTrack());
dst2->SetAnimationIsBackwards(src2->AnimationIsBackwards());
// Import banner information
auto entry = dst2->GetEntry();
if (entry != nullptr && entry->wall.scrolling_mode != SCROLLING_MODE_NONE)
{
auto bannerIndex = dst2->GetBannerIndex();
if (bannerIndex < std::size(_s6.banners))
{
auto srcBanner = &_s6.banners[bannerIndex];
auto dstBanner = GetBanner(bannerIndex);
ImportBanner(dstBanner, srcBanner);
}
else
{
dst2->SetBannerIndex(BANNER_INDEX_NULL);
}
}
break;
}
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
@ -1053,6 +1090,22 @@ public:
dst2->SetSecondaryColour(src2->GetSecondaryColour());
dst2->SetBannerIndex(src2->GetBannerIndex());
// Import banner information
auto entry = dst2->GetEntry();
if (entry != nullptr && entry->large_scenery.scrolling_mode != SCROLLING_MODE_NONE)
{
auto bannerIndex = dst2->GetBannerIndex();
if (bannerIndex < std::size(_s6.banners))
{
auto srcBanner = &_s6.banners[bannerIndex];
auto dstBanner = GetBanner(bannerIndex);
ImportBanner(dstBanner, srcBanner);
}
else
{
dst2->SetBannerIndex(BANNER_INDEX_NULL);
}
}
break;
}
case TILE_ELEMENT_TYPE_BANNER:
@ -1064,6 +1117,17 @@ public:
dst2->SetPosition(src2->GetPosition());
dst2->SetAllowedEdges(src2->GetAllowedEdges());
auto bannerIndex = src2->GetIndex();
if (bannerIndex < std::size(_s6.banners))
{
auto srcBanner = &_s6.banners[bannerIndex];
auto dstBanner = GetBanner(bannerIndex);
ImportBanner(dstBanner, srcBanner);
}
else
{
dst2->SetIndex(BANNER_INDEX_NULL);
}
break;
}
default:

View File

@ -625,7 +625,7 @@ void scenario_fix_ghosts(rct_s6_data* s6)
BannerIndex bannerIndex = tile_element_get_banner_index(reinterpret_cast<TileElement*>(originalElement));
if (bannerIndex != BANNER_INDEX_NULL)
{
rct_banner* banner = &s6->banners[bannerIndex];
auto banner = &s6->banners[bannerIndex];
if (banner->type != BANNER_NULL)
{
banner->type = BANNER_NULL;

View File

@ -251,7 +251,7 @@ struct rct_s6_data
uint8_t park_entrance_direction[RCT12_MAX_PARK_ENTRANCES];
char scenario_filename[256];
uint8_t saved_expansion_pack_names[3256];
rct_banner banners[RCT2_MAX_BANNERS_IN_PARK];
RCT12Banner banners[RCT2_MAX_BANNERS_IN_PARK];
char custom_strings[RCT12_MAX_USER_STRINGS][RCT12_USER_STRING_MAX_LENGTH];
uint32_t game_ticks_1;
rct2_ride rides[RCT12_MAX_RIDES_IN_PARK];

View File

@ -30,7 +30,7 @@
#include <iterator>
#include <limits>
rct_banner gBanners[MAX_BANNERS];
static Banner _banners[MAX_BANNERS];
/**
*
@ -63,7 +63,7 @@ static BannerIndex BannerGetNewIndex()
{
for (BannerIndex bannerIndex = 0; bannerIndex < MAX_BANNERS; bannerIndex++)
{
if (gBanners[bannerIndex].type == BANNER_NULL)
if (_banners[bannerIndex].type == BANNER_NULL)
{
return bannerIndex;
}
@ -77,7 +77,7 @@ static BannerIndex BannerGetNewIndex()
*/
void banner_init()
{
for (auto& banner : gBanners)
for (auto& banner : _banners)
{
banner.type = BANNER_NULL;
}
@ -103,7 +103,7 @@ BannerIndex create_new_banner(uint8_t flags)
if (flags & GAME_COMMAND_FLAG_APPLY)
{
rct_banner* banner = &gBanners[bannerIndex];
auto banner = &_banners[bannerIndex];
banner->flags = 0;
banner->type = 0;
@ -116,23 +116,31 @@ BannerIndex create_new_banner(uint8_t flags)
TileElement* banner_get_tile_element(BannerIndex bannerIndex)
{
rct_banner* banner = &gBanners[bannerIndex];
TileElement* tileElement = map_get_first_element_at(banner->x, banner->y);
do
auto banner = GetBanner(bannerIndex);
if (banner != nullptr)
{
if (tile_element_get_banner_index(tileElement) == bannerIndex)
auto tileElement = map_get_first_element_at(banner->position.x, banner->position.y);
if (tileElement != nullptr)
{
return tileElement;
do
{
if (tile_element_get_banner_index(tileElement) == bannerIndex)
{
return tileElement;
}
} while (!(tileElement++)->IsLastForTile());
}
} while (!(tileElement++)->IsLastForTile());
}
return nullptr;
}
WallElement* banner_get_scrolling_wall_tile_element(BannerIndex bannerIndex)
{
rct_banner* banner = &gBanners[bannerIndex];
TileElement* tileElement = map_get_first_element_at(banner->x, banner->y);
auto banner = GetBanner(bannerIndex);
if (banner == nullptr)
return nullptr;
auto tileElement = map_get_first_element_at(banner->position.x, banner->position.y);
if (tileElement == nullptr)
return nullptr;
@ -204,76 +212,94 @@ void banner_reset_broken_index()
{
for (BannerIndex bannerIndex = 0; bannerIndex < MAX_BANNERS; bannerIndex++)
{
TileElement* tileElement = banner_get_tile_element(bannerIndex);
auto tileElement = banner_get_tile_element(bannerIndex);
if (tileElement == nullptr)
gBanners[bannerIndex].type = BANNER_NULL;
{
_banners[bannerIndex].type = BANNER_NULL;
}
}
}
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[std::size(gBanners)]{};
TileElement* tileElement;
bool activeBanners[std::size(_banners)]{};
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
auto tileElement = map_get_first_element_at(x, y);
if (tileElement != nullptr)
{
// 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 (tileElement->GetType() == TILE_ELEMENT_TYPE_BANNER)
do
{
uint8_t bannerIndex = tileElement->AsBanner()->GetIndex();
if (activeBanners[bannerIndex])
// 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 (tileElement->GetType() == TILE_ELEMENT_TYPE_BANNER)
{
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
BannerIndex newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY);
if (newBannerIndex == BANNER_INDEX_NULL)
uint8_t bannerIndex = tileElement->AsBanner()->GetIndex();
if (activeBanners[bannerIndex])
{
log_error("Failed to create new banner.");
continue;
}
Guard::Assert(!activeBanners[newBannerIndex]);
log_info(
"Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y,
tileElement->base_height);
// 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)
// Banner index is already in use by another banner, so duplicate it
BannerIndex newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY);
if (newBannerIndex == BANNER_INDEX_NULL)
{
log_error("Failed to allocate user string for banner");
log_error("Failed to create new banner.");
continue;
}
newBanner.string_idx = newStringIdx;
Guard::Assert(!activeBanners[newBannerIndex]);
// Copy over the original banner, but update the location
auto& newBanner = *GetBanner(newBannerIndex);
newBanner = *GetBanner(bannerIndex);
newBanner.position = { x, 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->AsBanner()->SetIndex(newBannerIndex);
}
tileElement->AsBanner()->SetIndex(newBannerIndex);
// Mark banner index as in-use
activeBanners[bannerIndex] = true;
}
// Mark banner index as in-use
activeBanners[bannerIndex] = true;
}
} while (!(tileElement++)->IsLastForTile());
} while (!(tileElement++)->IsLastForTile());
}
}
}
}
Banner* BannerElement::GetBanner() const
{
return ::GetBanner(GetIndex());
}
rct_scenery_entry* BannerElement::GetEntry() const
{
auto banner = GetBanner();
if (banner != nullptr)
{
return get_banner_entry(banner->type);
}
return nullptr;
}
BannerIndex BannerElement::GetIndex() const
{
return index;
@ -309,3 +335,12 @@ void BannerElement::ResetAllowedEdges()
{
flags |= 0b00001111;
}
Banner* GetBanner(BannerIndex id)
{
if (id < std::size(_banners))
{
return &_banners[id];
}
return nullptr;
}

View File

@ -18,23 +18,16 @@ constexpr BannerIndex BANNER_INDEX_NULL = (BannerIndex)-1;
constexpr uint8_t SCROLLING_MODE_NONE = 255;
#pragma pack(push, 1)
struct rct_banner
struct Banner
{
uint8_t type;
uint8_t flags; // 0x01
rct_string_id string_idx; // 0x02
union
{
uint8_t colour; // 0x04
uint8_t ride_index; // 0x04
};
uint8_t text_colour; // 0x05
uint8_t x; // 0x06
uint8_t y; // 0x07
uint8_t flags;
rct_string_id string_idx;
uint8_t colour;
uint8_t ride_index;
uint8_t text_colour;
TileCoordsXY position;
};
assert_struct_size(rct_banner, 8);
#pragma pack(pop)
enum BANNER_FLAGS
{
@ -44,8 +37,6 @@ enum BANNER_FLAGS
BANNER_FLAG_IS_WALL = (1 << 3)
};
extern rct_banner gBanners[MAX_BANNERS];
void banner_init();
BannerIndex create_new_banner(uint8_t flags);
TileElement* banner_get_tile_element(BannerIndex bannerIndex);
@ -53,3 +44,4 @@ WallElement* banner_get_scrolling_wall_tile_element(BannerIndex bannerIndex);
uint8_t banner_get_closest_ride_index(int32_t x, int32_t y, int32_t z);
void banner_reset_broken_index();
void fix_duplicated_banners();
Banner* GetBanner(BannerIndex id);

View File

@ -12,6 +12,7 @@
#include "../Context.h"
#include "../common.h"
#include "../object/ObjectManager.h"
#include "../world/Banner.h"
#include "TileElement.h"
colour_t LargeSceneryElement::GetPrimaryColour() const
@ -38,6 +39,11 @@ void LargeSceneryElement::SetSecondaryColour(colour_t newColour)
colour[1] |= newColour;
}
Banner* LargeSceneryElement::GetBanner() const
{
return ::GetBanner(GetBannerIndex());
}
BannerIndex LargeSceneryElement::GetBannerIndex() const
{
return (type & 0xC0) | (((colour[0]) & ~TILE_ELEMENT_COLOUR_MASK) >> 2) | (((colour[1]) & ~TILE_ELEMENT_COLOUR_MASK) >> 5);

View File

@ -127,7 +127,7 @@ void tile_element_remove_banner_entry(TileElement* tileElement)
if (bannerIndex == BANNER_INDEX_NULL)
return;
rct_banner* banner = &gBanners[bannerIndex];
auto banner = GetBanner(bannerIndex);
if (banner->type != BANNER_NULL)
{
rct_windownumber windowNumber = bannerIndex;

View File

@ -14,6 +14,7 @@
#include "Footpath.h"
#include "Location.hpp"
struct Banner;
struct rct_scenery_entry;
struct rct_footpath_entry;
@ -370,6 +371,7 @@ public:
colour_t GetSecondaryColour() const;
void SetSecondaryColour(colour_t colour);
Banner* GetBanner() const;
BannerIndex GetBannerIndex() const;
void SetBannerIndex(BannerIndex newIndex);
@ -408,6 +410,7 @@ public:
uint8_t GetAnimationFrame() const;
void SetAnimationFrame(uint8_t frameNum);
Banner* GetBanner() const;
BannerIndex GetBannerIndex() const;
void SetBannerIndex(BannerIndex newIndex);
@ -459,6 +462,9 @@ private:
uint8_t unused; // 7
#pragma clang diagnostic pop
public:
Banner* GetBanner() const;
rct_scenery_entry* GetEntry() const;
BannerIndex GetIndex() const;
void SetIndex(BannerIndex newIndex);

View File

@ -307,10 +307,9 @@ GameActionResult::Ptr tile_inspector_paste_element_at(CoordsXY loc, TileElement
{
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
}
rct_banner& newBanner = gBanners[newBannerIndex];
newBanner = gBanners[bannerIndex];
newBanner.x = loc.x / 32;
newBanner.y = loc.y / 32;
auto& newBanner = *GetBanner(newBannerIndex);
newBanner = *GetBanner(bannerIndex);
newBanner.position = TileCoordsXY(loc);
// Use the new banner index
tile_element_set_banner_index(&element, newBannerIndex);
@ -326,7 +325,7 @@ GameActionResult::Ptr tile_inspector_paste_element_at(CoordsXY loc, TileElement
{
return std::make_unique<GameActionResult>(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE);
}
gBanners[newBannerIndex].string_idx = newStringIdx;
GetBanner(newBannerIndex)->string_idx = newStringIdx;
}
}

View File

@ -169,6 +169,11 @@ void WallElement::SetEntryIndex(uint8_t newIndex)
entryIndex = newIndex;
}
Banner* WallElement::GetBanner() const
{
return ::GetBanner(GetBannerIndex());
}
BannerIndex WallElement::GetBannerIndex() const
{
return banner_index;