mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge remote-tracking branch 'upstream/develop' into new-save-format
This commit is contained in:
commit
5199325209
|
@ -2899,7 +2899,7 @@ STR_5626 :Overige parken
|
||||||
STR_5627 :Scenariolijst groeperen op:
|
STR_5627 :Scenariolijst groeperen op:
|
||||||
STR_5628 :Oorsprong
|
STR_5628 :Oorsprong
|
||||||
STR_5629 :Moeilijkheidsgraad
|
STR_5629 :Moeilijkheidsgraad
|
||||||
STR_5630 :Moeilijke scenario’s ontgrendelden met gemakkelijke
|
STR_5630 :Moeilijke scenario’s ontgrendelden met makkelijke
|
||||||
STR_5631 :Originele DLC
|
STR_5631 :Originele DLC
|
||||||
STR_5632 :Bouw je eigen…
|
STR_5632 :Bouw je eigen…
|
||||||
STR_5633 :CMD +
|
STR_5633 :CMD +
|
||||||
|
|
|
@ -387,22 +387,21 @@ void window_editor_bottom_toolbar_paint(rct_window* w, rct_drawpixelinfo* dpi)
|
||||||
|
|
||||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER))
|
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER))
|
||||||
{
|
{
|
||||||
|
auto previousWidget = window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE];
|
||||||
|
auto nextWidget = window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE];
|
||||||
|
|
||||||
if (drawPreviousButton)
|
if (drawPreviousButton)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(
|
auto leftTop = w->windowPos + ScreenCoordsXY{ previousWidget.left, previousWidget.top };
|
||||||
dpi, window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].left + w->windowPos.x,
|
auto rightBottom = w->windowPos + ScreenCoordsXY{ previousWidget.right, previousWidget.bottom };
|
||||||
window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].top + w->windowPos.y,
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||||
window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].right + w->windowPos.x,
|
|
||||||
window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].bottom + w->windowPos.y, FilterPaletteID::Palette51);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((drawPreviousButton || drawNextButton) && gEditorStep != EditorStep::RollercoasterDesigner)
|
if ((drawPreviousButton || drawNextButton) && gEditorStep != EditorStep::RollercoasterDesigner)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(
|
auto leftTop = w->windowPos + ScreenCoordsXY{ nextWidget.left, nextWidget.top };
|
||||||
dpi, window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].left + w->windowPos.x,
|
auto rightBottom = w->windowPos + ScreenCoordsXY{ nextWidget.right, nextWidget.bottom };
|
||||||
window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].top + w->windowPos.y,
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||||
window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].right + w->windowPos.x,
|
|
||||||
window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].bottom + w->windowPos.y, FilterPaletteID::Palette51);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,7 +607,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
||||||
bottom = itemY;
|
bottom = itemY;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_filter_rect(dpi, 0, top, boxWidth, bottom, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, top, boxWidth, bottom }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (researchItem == _editorInventionsListDraggedItem)
|
if (researchItem == _editorInventionsListDraggedItem)
|
||||||
|
|
|
@ -1226,7 +1226,7 @@ static void window_editor_object_selection_scrollpaint(rct_window* w, rct_drawpi
|
||||||
if (highlighted)
|
if (highlighted)
|
||||||
{
|
{
|
||||||
auto bottom = screenCoords.y + (SCROLLABLE_ROW_HEIGHT - 1);
|
auto bottom = screenCoords.y + (SCROLLABLE_ROW_HEIGHT - 1);
|
||||||
gfx_filter_rect(dpi, 0, screenCoords.y, w->width, bottom, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, screenCoords.y, w->width, bottom }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw checkmark
|
// Draw checkmark
|
||||||
|
|
|
@ -1095,7 +1095,7 @@ static void window_editor_objective_options_rides_scrollpaint(rct_window* w, rct
|
||||||
if (i == w->selected_list_item)
|
if (i == w->selected_list_item)
|
||||||
{
|
{
|
||||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
gfx_filter_rect(dpi, 0, y, w->width, y + 11, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, y, w->width, y + 11 }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkbox mark
|
// Checkbox mark
|
||||||
|
|
|
@ -350,26 +350,25 @@ void window_game_bottom_toolbar_invalidate_news_item()
|
||||||
*/
|
*/
|
||||||
static void window_game_bottom_toolbar_paint(rct_window* w, rct_drawpixelinfo* dpi)
|
static void window_game_bottom_toolbar_paint(rct_window* w, rct_drawpixelinfo* dpi)
|
||||||
{
|
{
|
||||||
|
auto leftWidget = window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET];
|
||||||
|
auto rightWidget = window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET];
|
||||||
|
auto middleWidget = window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET];
|
||||||
|
|
||||||
// Draw panel grey backgrounds
|
// Draw panel grey backgrounds
|
||||||
gfx_filter_rect(
|
auto leftTop = w->windowPos + ScreenCoordsXY{ leftWidget.left, leftWidget.top };
|
||||||
dpi, w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET].left,
|
auto rightBottom = w->windowPos + ScreenCoordsXY{ leftWidget.right, leftWidget.bottom };
|
||||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET].top,
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||||
w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET].right,
|
|
||||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET].bottom, FilterPaletteID::Palette51);
|
leftTop = w->windowPos + ScreenCoordsXY{ rightWidget.left, rightWidget.top };
|
||||||
gfx_filter_rect(
|
rightBottom = w->windowPos + ScreenCoordsXY{ rightWidget.right, rightWidget.bottom };
|
||||||
dpi, w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].left,
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].top,
|
|
||||||
w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].right,
|
|
||||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].bottom, FilterPaletteID::Palette51);
|
|
||||||
|
|
||||||
if (ThemeGetFlags() & UITHEME_FLAG_USE_FULL_BOTTOM_TOOLBAR)
|
if (ThemeGetFlags() & UITHEME_FLAG_USE_FULL_BOTTOM_TOOLBAR)
|
||||||
{
|
{
|
||||||
// Draw grey background
|
// Draw grey background
|
||||||
gfx_filter_rect(
|
leftTop = w->windowPos + ScreenCoordsXY{ middleWidget.left, middleWidget.top };
|
||||||
dpi, w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].left,
|
rightBottom = w->windowPos + ScreenCoordsXY{ middleWidget.right, middleWidget.bottom };
|
||||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].top,
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||||
w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].right,
|
|
||||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].bottom, FilterPaletteID::Palette51);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowDrawWidgets(w, dpi);
|
WindowDrawWidgets(w, dpi);
|
||||||
|
|
|
@ -1636,7 +1636,7 @@ void window_guest_rides_scroll_paint(rct_window* w, rct_drawpixelinfo* dpi, int3
|
||||||
rct_string_id stringId = STR_BLACK_STRING;
|
rct_string_id stringId = STR_BLACK_STRING;
|
||||||
if (list_index == w->selected_list_item)
|
if (list_index == w->selected_list_item)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(dpi, 0, y, 800, y + 9, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, y, 800, y + 9 }, FilterPaletteID::PaletteDarken1);
|
||||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -675,7 +675,7 @@ private:
|
||||||
rct_string_id format = STR_BLACK_STRING;
|
rct_string_id format = STR_BLACK_STRING;
|
||||||
if (index == _highlightedIndex)
|
if (index == _highlightedIndex)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(&dpi, 0, y, 800, y + SCROLLABLE_ROW_HEIGHT - 1, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(&dpi, { 0, y, 800, y + SCROLLABLE_ROW_HEIGHT - 1 }, FilterPaletteID::PaletteDarken1);
|
||||||
format = STR_WINDOW_COLOUR_2_STRINGID;
|
format = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,7 +745,7 @@ private:
|
||||||
rct_string_id format = STR_BLACK_STRING;
|
rct_string_id format = STR_BLACK_STRING;
|
||||||
if (index == _highlightedIndex)
|
if (index == _highlightedIndex)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(&dpi, 0, y, 800, y + SUMMARISED_GUEST_ROW_HEIGHT, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(&dpi, { 0, y, 800, y + SUMMARISED_GUEST_ROW_HEIGHT }, FilterPaletteID::PaletteDarken1);
|
||||||
format = STR_WINDOW_COLOUR_2_STRINGID;
|
format = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -759,7 +759,7 @@ static void window_loadsave_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, i
|
||||||
if (i == w->selected_list_item)
|
if (i == w->selected_list_item)
|
||||||
{
|
{
|
||||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
gfx_filter_rect(dpi, 0, y, listWidth, y + SCROLLABLE_ROW_HEIGHT, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, y, listWidth, y + SCROLLABLE_ROW_HEIGHT }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
// display a marker next to the currently loaded game file
|
// display a marker next to the currently loaded game file
|
||||||
if (_listItems[i].loaded)
|
if (_listItems[i].loaded)
|
||||||
|
|
|
@ -603,7 +603,8 @@ static void window_multiplayer_players_scrollpaint(rct_window* w, rct_drawpixeli
|
||||||
if (i == w->selected_list_item)
|
if (i == w->selected_list_item)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(
|
gfx_filter_rect(
|
||||||
dpi, 0, screenCoords.y, 800, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, FilterPaletteID::PaletteDarken1);
|
dpi, { 0, screenCoords.y, 800, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1 },
|
||||||
|
FilterPaletteID::PaletteDarken1);
|
||||||
buffer += network_get_player_name(i);
|
buffer += network_get_player_name(i);
|
||||||
colour = w->colours[2];
|
colour = w->colours[2];
|
||||||
}
|
}
|
||||||
|
@ -905,7 +906,7 @@ static void window_multiplayer_groups_scrollpaint(rct_window* w, rct_drawpixelin
|
||||||
if (i == w->selected_list_item)
|
if (i == w->selected_list_item)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(
|
gfx_filter_rect(
|
||||||
dpi, 0, screenCoords.y, 800, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, FilterPaletteID::PaletteDarken1);
|
dpi, { 0, screenCoords.y, 800, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1 }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
if (screenCoords.y > dpi->y + dpi->height)
|
if (screenCoords.y > dpi->y + dpi->height)
|
||||||
{
|
{
|
||||||
|
|
|
@ -578,7 +578,7 @@ static void window_ride_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi,
|
||||||
if (i == static_cast<size_t>(w->selected_list_item))
|
if (i == static_cast<size_t>(w->selected_list_item))
|
||||||
{
|
{
|
||||||
// Background highlight
|
// Background highlight
|
||||||
gfx_filter_rect(dpi, 0, y, 800, y + SCROLLABLE_ROW_HEIGHT - 1, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, y, 800, y + SCROLLABLE_ROW_HEIGHT - 1 }, FilterPaletteID::PaletteDarken1);
|
||||||
format = (_quickDemolishMode ? STR_LIGHTPINK_STRINGID : STR_WINDOW_COLOUR_2_STRINGID);
|
format = (_quickDemolishMode ? STR_LIGHTPINK_STRINGID : STR_WINDOW_COLOUR_2_STRINGID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -596,7 +596,7 @@ static void window_scenarioselect_scrollpaint(rct_window* w, rct_drawpixelinfo*
|
||||||
bool isHighlighted = w->highlighted_scenario == scenario;
|
bool isHighlighted = w->highlighted_scenario == scenario;
|
||||||
if (isHighlighted)
|
if (isHighlighted)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(dpi, 0, y, w->width, y + scenarioItemHeight - 1, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, y, w->width, y + scenarioItemHeight - 1 }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCompleted = scenario->highscore != nullptr;
|
bool isCompleted = scenario->highscore != nullptr;
|
||||||
|
|
|
@ -40,8 +40,8 @@ static std::future<std::tuple<std::vector<ServerListEntry>, rct_string_id>> _fet
|
||||||
static uint32_t _numPlayersOnline = 0;
|
static uint32_t _numPlayersOnline = 0;
|
||||||
static rct_string_id _statusText = STR_SERVER_LIST_CONNECTING;
|
static rct_string_id _statusText = STR_SERVER_LIST_CONNECTING;
|
||||||
|
|
||||||
// clang-format off
|
enum
|
||||||
enum {
|
{
|
||||||
WIDX_BACKGROUND,
|
WIDX_BACKGROUND,
|
||||||
WIDX_TITLE,
|
WIDX_TITLE,
|
||||||
WIDX_CLOSE,
|
WIDX_CLOSE,
|
||||||
|
@ -52,11 +52,13 @@ enum {
|
||||||
WIDX_START_SERVER
|
WIDX_START_SERVER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
WIDX_LIST_REMOVE,
|
WIDX_LIST_REMOVE,
|
||||||
WIDX_LIST_SPECTATE
|
WIDX_LIST_SPECTATE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
static rct_widget window_server_list_widgets[] = {
|
static rct_widget window_server_list_widgets[] = {
|
||||||
MakeWidget({ 0, 0}, {341, 91}, WindowWidgetType::Frame, WindowColour::Primary ), // panel / background
|
MakeWidget({ 0, 0}, {341, 91}, WindowWidgetType::Frame, WindowColour::Primary ), // panel / background
|
||||||
MakeWidget({ 1, 1}, {338, 14}, WindowWidgetType::Caption, WindowColour::Primary, STR_SERVER_LIST, STR_WINDOW_TITLE_TIP), // title bar
|
MakeWidget({ 1, 1}, {338, 14}, WindowWidgetType::Caption, WindowColour::Primary, STR_SERVER_LIST, STR_WINDOW_TITLE_TIP), // title bar
|
||||||
|
@ -68,6 +70,7 @@ static rct_widget window_server_list_widgets[] = {
|
||||||
MakeWidget({218, 53}, {101, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_START_SERVER ), // start server button
|
MakeWidget({218, 53}, {101, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_START_SERVER ), // start server button
|
||||||
WIDGETS_END,
|
WIDGETS_END,
|
||||||
};
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
static void window_server_list_close(rct_window* w);
|
static void window_server_list_close(rct_window* w);
|
||||||
static void window_server_list_mouseup(rct_window* w, rct_widgetindex widgetIndex);
|
static void window_server_list_mouseup(rct_window* w, rct_widgetindex widgetIndex);
|
||||||
|
@ -78,13 +81,13 @@ static void window_server_list_scroll_getsize(rct_window *w, int32_t scrollIndex
|
||||||
static void window_server_list_scroll_mousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
|
static void window_server_list_scroll_mousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
|
||||||
static void window_server_list_scroll_mouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
|
static void window_server_list_scroll_mouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
|
||||||
static void window_server_list_textinput(rct_window* w, rct_widgetindex widgetIndex, char* text);
|
static void window_server_list_textinput(rct_window* w, rct_widgetindex widgetIndex, char* text);
|
||||||
static OpenRCT2String window_server_list_tooltip(rct_window* const w, const rct_widgetindex widgetIndex, rct_string_id fallback);
|
static OpenRCT2String window_server_list_tooltip(
|
||||||
|
rct_window* const w, const rct_widgetindex widgetIndex, rct_string_id fallback);
|
||||||
static void window_server_list_invalidate(rct_window* w);
|
static void window_server_list_invalidate(rct_window* w);
|
||||||
static void window_server_list_paint(rct_window* w, rct_drawpixelinfo* dpi);
|
static void window_server_list_paint(rct_window* w, rct_drawpixelinfo* dpi);
|
||||||
static void window_server_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex);
|
static void window_server_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex);
|
||||||
|
|
||||||
static rct_window_event_list window_server_list_events([](auto& events)
|
static rct_window_event_list window_server_list_events([](auto& events) {
|
||||||
{
|
|
||||||
events.close = &window_server_list_close;
|
events.close = &window_server_list_close;
|
||||||
events.mouse_up = &window_server_list_mouseup;
|
events.mouse_up = &window_server_list_mouseup;
|
||||||
events.resize = &window_server_list_resize;
|
events.resize = &window_server_list_resize;
|
||||||
|
@ -99,7 +102,6 @@ static rct_window_event_list window_server_list_events([](auto& events)
|
||||||
events.paint = &window_server_list_paint;
|
events.paint = &window_server_list_paint;
|
||||||
events.scroll_paint = &window_server_list_scrollpaint;
|
events.scroll_paint = &window_server_list_scrollpaint;
|
||||||
});
|
});
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -439,7 +441,7 @@ static void window_server_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi
|
||||||
// Draw hover highlight
|
// Draw hover highlight
|
||||||
if (highlighted)
|
if (highlighted)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(dpi, 0, screenCoords.y, width, screenCoords.y + ITEM_HEIGHT, FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(dpi, { 0, screenCoords.y, width, screenCoords.y + ITEM_HEIGHT }, FilterPaletteID::PaletteDarken1);
|
||||||
_version = serverDetails.Version;
|
_version = serverDetails.Version;
|
||||||
listWidget.tooltip = STR_NETWORK_VERSION_TIP;
|
listWidget.tooltip = STR_NETWORK_VERSION_TIP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -509,7 +509,7 @@ private:
|
||||||
if (isHighlighted)
|
if (isHighlighted)
|
||||||
{
|
{
|
||||||
format = STR_WINDOW_COLOUR_2_STRINGID;
|
format = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
gfx_filter_rect(&dpi, 0, y - 1, scrollWidth, y + (SCROLLABLE_ROW_HEIGHT - 2), FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(&dpi, { 0, y - 1, scrollWidth, y + (SCROLLABLE_ROW_HEIGHT - 2) }, FilterPaletteID::PaletteDarken1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bindingOffset = (scrollWidth * 2) / 3;
|
auto bindingOffset = (scrollWidth * 2) / 3;
|
||||||
|
|
|
@ -401,7 +401,7 @@ public:
|
||||||
|
|
||||||
if (i == _highlightedIndex)
|
if (i == _highlightedIndex)
|
||||||
{
|
{
|
||||||
gfx_filter_rect(&dpi, 0, y, 800, y + (SCROLLABLE_ROW_HEIGHT - 1), FilterPaletteID::PaletteDarken1);
|
gfx_filter_rect(&dpi, { 0, y, 800, y + (SCROLLABLE_ROW_HEIGHT - 1) }, FilterPaletteID::PaletteDarken1);
|
||||||
format = (_quickFireMode ? STR_LIGHTPINK_STRINGID : STR_WINDOW_COLOUR_2_STRINGID);
|
format = (_quickFireMode ? STR_LIGHTPINK_STRINGID : STR_WINDOW_COLOUR_2_STRINGID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -867,31 +867,26 @@ void window_themes_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t sc
|
||||||
if (i + 1 < get_colour_scheme_tab_count())
|
if (i + 1 < get_colour_scheme_tab_count())
|
||||||
{
|
{
|
||||||
int32_t colour = w->colours[1];
|
int32_t colour = w->colours[1];
|
||||||
|
|
||||||
|
auto leftTop = ScreenCoordsXY{ 0, screenCoords.y + _row_height - 2 };
|
||||||
|
auto rightBottom = ScreenCoordsXY{ window_themes_widgets[WIDX_THEMES_LIST].right,
|
||||||
|
screenCoords.y + _row_height - 2 };
|
||||||
|
auto yPixelOffset = ScreenCoordsXY{ 0, 1 };
|
||||||
|
|
||||||
if (colour & COLOUR_FLAG_TRANSLUCENT)
|
if (colour & COLOUR_FLAG_TRANSLUCENT)
|
||||||
{
|
{
|
||||||
translucent_window_palette windowPalette = TranslucentWindowPalettes[BASE_COLOUR(colour)];
|
translucent_window_palette windowPalette = TranslucentWindowPalettes[BASE_COLOUR(colour)];
|
||||||
|
|
||||||
gfx_filter_rect(
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, windowPalette.highlight);
|
||||||
dpi, 0, screenCoords.y + _row_height - 2, window_themes_widgets[WIDX_THEMES_LIST].right,
|
gfx_filter_rect(dpi, { leftTop + yPixelOffset, rightBottom + yPixelOffset }, windowPalette.shadow);
|
||||||
screenCoords.y + _row_height - 2, windowPalette.highlight);
|
|
||||||
gfx_filter_rect(
|
|
||||||
dpi, 0, screenCoords.y + _row_height - 1, window_themes_widgets[WIDX_THEMES_LIST].right,
|
|
||||||
screenCoords.y + _row_height - 1, windowPalette.shadow);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
colour = ColourMapA[w->colours[1]].mid_dark;
|
colour = ColourMapA[w->colours[1]].mid_dark;
|
||||||
gfx_fill_rect(
|
gfx_fill_rect(dpi, { leftTop, rightBottom }, colour);
|
||||||
dpi,
|
|
||||||
{ { 0, screenCoords.y + _row_height - 2 },
|
|
||||||
{ window_themes_widgets[WIDX_THEMES_LIST].right, screenCoords.y + _row_height - 2 } },
|
|
||||||
colour);
|
|
||||||
colour = ColourMapA[w->colours[1]].lightest;
|
colour = ColourMapA[w->colours[1]].lightest;
|
||||||
gfx_fill_rect(
|
gfx_fill_rect(dpi, { leftTop + yPixelOffset, rightBottom + yPixelOffset }, colour);
|
||||||
dpi,
|
|
||||||
{ { 0, screenCoords.y + _row_height - 1 },
|
|
||||||
{ window_themes_widgets[WIDX_THEMES_LIST].right, screenCoords.y + _row_height - 1 } },
|
|
||||||
colour);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -690,7 +690,7 @@ public:
|
||||||
{
|
{
|
||||||
// Highlight
|
// Highlight
|
||||||
gfx_filter_rect(
|
gfx_filter_rect(
|
||||||
&dpi, screenCoords.x, screenCoords.y, width, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1,
|
&dpi, { screenCoords, { width, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1 } },
|
||||||
FilterPaletteID::PaletteDarken1);
|
FilterPaletteID::PaletteDarken1);
|
||||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
}
|
}
|
||||||
|
@ -715,7 +715,7 @@ public:
|
||||||
{
|
{
|
||||||
// Highlight
|
// Highlight
|
||||||
gfx_filter_rect(
|
gfx_filter_rect(
|
||||||
&dpi, screenCoords.x, screenCoords.y, width, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1,
|
&dpi, { screenCoords, { width, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1 } },
|
||||||
FilterPaletteID::PaletteDarken1);
|
FilterPaletteID::PaletteDarken1);
|
||||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../interface/Window.h"
|
#include "../interface/Window.h"
|
||||||
#include "../localisation/StringIds.h"
|
#include "../localisation/StringIds.h"
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
#include "../world/Location.hpp"
|
#include "../world/Location.hpp"
|
||||||
#include "../world/Park.h"
|
#include "../world/Park.h"
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../interface/Window.h"
|
#include "../interface/Window.h"
|
||||||
#include "../localisation/StringIds.h"
|
#include "../localisation/StringIds.h"
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
#include "../world/Location.hpp"
|
#include "../world/Location.hpp"
|
||||||
#include "../world/Park.h"
|
#include "../world/Park.h"
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
#include "../ride/RideData.h"
|
#include "../ride/RideData.h"
|
||||||
#include "../windows/Intent.h"
|
#include "../windows/Intent.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/Park.h"
|
#include "../world/Park.h"
|
||||||
#include "../world/Scenery.h"
|
#include "../world/Scenery.h"
|
||||||
#include "../world/SmallScenery.h"
|
#include "../world/SmallScenery.h"
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../object/ObjectLimits.h"
|
#include "../object/ObjectLimits.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
#include "../world/Banner.h"
|
#include "../world/Banner.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/MapAnimation.h"
|
#include "../world/MapAnimation.h"
|
||||||
#include "../world/Surface.h"
|
#include "../world/Surface.h"
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
#include "../ride/RideData.h"
|
#include "../ride/RideData.h"
|
||||||
#include "../ride/TrackData.h"
|
#include "../ride/TrackData.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
|
|
||||||
using namespace OpenRCT2::TrackMetaData;
|
using namespace OpenRCT2::TrackMetaData;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "../ride/RideData.h"
|
#include "../ride/RideData.h"
|
||||||
#include "../ride/Track.h"
|
#include "../ride/Track.h"
|
||||||
#include "../ride/TrackData.h"
|
#include "../ride/TrackData.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
#include "../world/Park.h"
|
#include "../world/Park.h"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../core/MemoryStream.h"
|
#include "../core/MemoryStream.h"
|
||||||
#include "../localisation/StringIds.h"
|
#include "../localisation/StringIds.h"
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/Entrance.h"
|
#include "../world/Entrance.h"
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
#include "../world/MapAnimation.h"
|
#include "../world/MapAnimation.h"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
#include "../ride/Station.h"
|
#include "../ride/Station.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/MapAnimation.h"
|
#include "../world/MapAnimation.h"
|
||||||
|
|
||||||
RideEntranceExitPlaceAction::RideEntranceExitPlaceAction(
|
RideEntranceExitPlaceAction::RideEntranceExitPlaceAction(
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
#include "../ride/TrackDesign.h"
|
#include "../ride/TrackDesign.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/MapAnimation.h"
|
#include "../world/MapAnimation.h"
|
||||||
#include "../world/Park.h"
|
#include "../world/Park.h"
|
||||||
#include "../world/SmallScenery.h"
|
#include "../world/SmallScenery.h"
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "../ride/TrackData.h"
|
#include "../ride/TrackData.h"
|
||||||
#include "../ride/TrackDesign.h"
|
#include "../ride/TrackDesign.h"
|
||||||
#include "../util/Math.hpp"
|
#include "../util/Math.hpp"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/MapAnimation.h"
|
#include "../world/MapAnimation.h"
|
||||||
#include "../world/Surface.h"
|
#include "../world/Surface.h"
|
||||||
#include "RideSetSettingAction.h"
|
#include "RideSetSettingAction.h"
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../ride/Track.h"
|
#include "../ride/Track.h"
|
||||||
#include "../ride/TrackDesign.h"
|
#include "../ride/TrackDesign.h"
|
||||||
#include "../world/Banner.h"
|
#include "../world/Banner.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/LargeScenery.h"
|
#include "../world/LargeScenery.h"
|
||||||
#include "../world/MapAnimation.h"
|
#include "../world/MapAnimation.h"
|
||||||
#include "../world/SmallScenery.h"
|
#include "../world/SmallScenery.h"
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "../OpenRCT2.h"
|
#include "../OpenRCT2.h"
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/Park.h"
|
#include "../world/Park.h"
|
||||||
#include "../world/Surface.h"
|
#include "../world/Surface.h"
|
||||||
|
|
||||||
|
|
|
@ -692,7 +692,6 @@ void gfx_draw_dashed_line(
|
||||||
// rect
|
// rect
|
||||||
void gfx_fill_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colour);
|
void gfx_fill_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colour);
|
||||||
void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colour, uint8_t flags);
|
void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colour, uint8_t flags);
|
||||||
void gfx_filter_rect(rct_drawpixelinfo* dpi, int32_t left, int32_t top, int32_t right, int32_t bottom, FilterPaletteID palette);
|
|
||||||
void gfx_filter_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, FilterPaletteID palette);
|
void gfx_filter_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, FilterPaletteID palette);
|
||||||
|
|
||||||
// sprite
|
// sprite
|
||||||
|
|
|
@ -180,11 +180,6 @@ void gfx_fill_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_filter_rect(rct_drawpixelinfo* dpi, int32_t left, int32_t top, int32_t right, int32_t bottom, FilterPaletteID palette)
|
|
||||||
{
|
|
||||||
gfx_filter_rect(dpi, { left, top, right, bottom }, palette);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gfx_filter_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, FilterPaletteID palette)
|
void gfx_filter_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, FilterPaletteID palette)
|
||||||
{
|
{
|
||||||
auto drawingEngine = dpi->DrawingEngine;
|
auto drawingEngine = dpi->DrawingEngine;
|
||||||
|
|
|
@ -466,6 +466,7 @@
|
||||||
<ClInclude Include="world\Balloon.h" />
|
<ClInclude Include="world\Balloon.h" />
|
||||||
<ClInclude Include="world\Banner.h" />
|
<ClInclude Include="world\Banner.h" />
|
||||||
<ClInclude Include="world\Climate.h" />
|
<ClInclude Include="world\Climate.h" />
|
||||||
|
<ClInclude Include="world\ConstructionClearance.h" />
|
||||||
<ClInclude Include="world\Duck.h" />
|
<ClInclude Include="world\Duck.h" />
|
||||||
<ClInclude Include="world\Entity.h" />
|
<ClInclude Include="world\Entity.h" />
|
||||||
<ClInclude Include="world\EntityList.h" />
|
<ClInclude Include="world\EntityList.h" />
|
||||||
|
@ -911,6 +912,7 @@
|
||||||
<ClCompile Include="world\Balloon.cpp" />
|
<ClCompile Include="world\Balloon.cpp" />
|
||||||
<ClCompile Include="world\Banner.cpp" />
|
<ClCompile Include="world\Banner.cpp" />
|
||||||
<ClCompile Include="world\Climate.cpp" />
|
<ClCompile Include="world\Climate.cpp" />
|
||||||
|
<ClCompile Include="world\ConstructionClearance.cpp" />
|
||||||
<ClCompile Include="world\Duck.cpp" />
|
<ClCompile Include="world\Duck.cpp" />
|
||||||
<ClCompile Include="world\Entity.cpp" />
|
<ClCompile Include="world\Entity.cpp" />
|
||||||
<ClCompile Include="world\EntityTweener.cpp" />
|
<ClCompile Include="world\EntityTweener.cpp" />
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "../../world/Banner.h"
|
#include "../../world/Banner.h"
|
||||||
#include "../../world/Entrance.h"
|
#include "../../world/Entrance.h"
|
||||||
#include "../../world/Footpath.h"
|
#include "../../world/Footpath.h"
|
||||||
|
#include "../../world/Map.h"
|
||||||
#include "../../world/Scenery.h"
|
#include "../../world/Scenery.h"
|
||||||
#include "../../world/Surface.h"
|
#include "../../world/Surface.h"
|
||||||
#include "../Paint.h"
|
#include "../Paint.h"
|
||||||
|
@ -146,27 +147,24 @@ static void sub_68B3FB(paint_session* session, int32_t x, int32_t y)
|
||||||
}
|
}
|
||||||
#endif // __TESTPAINT__
|
#endif // __TESTPAINT__
|
||||||
|
|
||||||
int32_t dx = 0;
|
|
||||||
switch (rotation)
|
switch (rotation)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
dx = x + y;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
x += 32;
|
x += 32;
|
||||||
dx = y - x;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
x += 32;
|
x += 32;
|
||||||
y += 32;
|
y += 32;
|
||||||
dx = -(x + y);
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
y += 32;
|
y += 32;
|
||||||
dx = x - y;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dx >>= 1;
|
|
||||||
|
int32_t screenMinY = translate_3d_to_2d_with_z(rotation, { x, y, 0 }).y;
|
||||||
|
|
||||||
// Display little yellow arrow when building footpaths?
|
// Display little yellow arrow when building footpaths?
|
||||||
if ((gMapSelectFlags & MAP_SELECT_FLAG_ENABLE_ARROW) && session->MapPosition.x == gMapSelectArrowPosition.x
|
if ((gMapSelectFlags & MAP_SELECT_FLAG_ENABLE_ARROW) && session->MapPosition.x == gMapSelectArrowPosition.x
|
||||||
&& session->MapPosition.y == gMapSelectArrowPosition.y)
|
&& session->MapPosition.y == gMapSelectArrowPosition.y)
|
||||||
|
@ -182,9 +180,8 @@ static void sub_68B3FB(paint_session* session, int32_t x, int32_t y)
|
||||||
|
|
||||||
PaintAddImageAsParent(session, imageId, { 0, 0, arrowZ }, { 32, 32, -1 }, { 0, 0, arrowZ + 18 });
|
PaintAddImageAsParent(session, imageId, { 0, 0, arrowZ }, { 32, 32, -1 }, { 0, 0, arrowZ + 18 });
|
||||||
}
|
}
|
||||||
int32_t bx = dx + 52;
|
|
||||||
|
|
||||||
if (bx <= dpi->y)
|
if (screenMinY + 52 <= dpi->y)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const TileElement* element = tile_element; // push tile_element
|
const TileElement* element = tile_element; // push tile_element
|
||||||
|
@ -210,9 +207,7 @@ static void sub_68B3FB(paint_session* session, int32_t x, int32_t y)
|
||||||
}
|
}
|
||||||
#endif // __TESTPAINT__
|
#endif // __TESTPAINT__
|
||||||
|
|
||||||
dx -= max_height + 32;
|
if (screenMinY - (max_height + 32) >= dpi->y + dpi->height)
|
||||||
dx -= dpi->height;
|
|
||||||
if (dx >= dpi->y)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
session->SpritePosition.x = x;
|
session->SpritePosition.x = x;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "../windows/Intent.h"
|
#include "../windows/Intent.h"
|
||||||
#include "../world/Balloon.h"
|
#include "../world/Balloon.h"
|
||||||
#include "../world/Climate.h"
|
#include "../world/Climate.h"
|
||||||
|
#include "../world/ConstructionClearance.h"
|
||||||
#include "../world/EntityTweener.h"
|
#include "../world/EntityTweener.h"
|
||||||
#include "../world/Entrance.h"
|
#include "../world/Entrance.h"
|
||||||
#include "../world/Footpath.h"
|
#include "../world/Footpath.h"
|
||||||
|
|
|
@ -0,0 +1,358 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2021 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ConstructionClearance.h"
|
||||||
|
|
||||||
|
#include "../Game.h"
|
||||||
|
#include "../openrct2/Cheats.h"
|
||||||
|
#include "../ride/Ride.h"
|
||||||
|
#include "../ride/RideData.h"
|
||||||
|
#include "Park.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "SmallScenery.h"
|
||||||
|
#include "Surface.h"
|
||||||
|
|
||||||
|
static int32_t map_place_clear_func(
|
||||||
|
TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price, bool is_scenery)
|
||||||
|
{
|
||||||
|
if ((*tile_element)->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (is_scenery && !(flags & GAME_COMMAND_FLAG_PATH_SCENERY))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
auto* scenery = (*tile_element)->AsSmallScenery()->GetEntry();
|
||||||
|
|
||||||
|
if (gParkFlags & PARK_FLAGS_FORBID_TREE_REMOVAL)
|
||||||
|
{
|
||||||
|
if (scenery != nullptr && scenery->HasFlag(SMALL_SCENERY_FLAG_IS_TREE))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(gParkFlags & PARK_FLAGS_NO_MONEY) && scenery != nullptr)
|
||||||
|
*price += scenery->removal_price * 10;
|
||||||
|
|
||||||
|
if (flags & GAME_COMMAND_FLAG_GHOST)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
map_invalidate_tile({ coords, (*tile_element)->GetBaseZ(), (*tile_element)->GetClearanceZ() });
|
||||||
|
|
||||||
|
tile_element_remove(*tile_element);
|
||||||
|
|
||||||
|
(*tile_element)--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006E0D6E, 0x006B8D88
|
||||||
|
*/
|
||||||
|
int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price)
|
||||||
|
{
|
||||||
|
return map_place_clear_func(tile_element, coords, flags, price, /*is_scenery=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006C5A4F, 0x006CDE57, 0x006A6733, 0x0066637E
|
||||||
|
*/
|
||||||
|
int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price)
|
||||||
|
{
|
||||||
|
return map_place_clear_func(tile_element, coords, flags, price, /*is_scenery=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool MapLoc68BABCShouldContinue(
|
||||||
|
TileElement* tileElement, const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, uint8_t flags, money32& price,
|
||||||
|
uint8_t crossingMode, bool canBuildCrossing)
|
||||||
|
{
|
||||||
|
if (clearFunc != nullptr)
|
||||||
|
{
|
||||||
|
if (!clearFunc(&tileElement, pos, flags, &price))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crossing mode 1: building track over path
|
||||||
|
if (crossingMode == 1 && canBuildCrossing && tileElement->GetType() == TILE_ELEMENT_TYPE_PATH
|
||||||
|
&& tileElement->GetBaseZ() == pos.baseZ && !tileElement->AsPath()->IsQueue() && !tileElement->AsPath()->IsSloped())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Crossing mode 2: building path over track
|
||||||
|
else if (
|
||||||
|
crossingMode == 2 && canBuildCrossing && tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK
|
||||||
|
&& tileElement->GetBaseZ() == pos.baseZ && tileElement->AsTrack()->GetTrackType() == TrackElemType::Flat)
|
||||||
|
{
|
||||||
|
auto ride = get_ride(tileElement->AsTrack()->GetRideIndex());
|
||||||
|
if (ride != nullptr && ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x0068B932
|
||||||
|
* ax = x
|
||||||
|
* cx = y
|
||||||
|
* dl = zLow
|
||||||
|
* dh = zHigh
|
||||||
|
* ebp = clearFunc
|
||||||
|
* bl = bl
|
||||||
|
*/
|
||||||
|
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt(
|
||||||
|
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode, bool isTree)
|
||||||
|
{
|
||||||
|
int32_t northZ, eastZ, baseHeight, southZ, westZ, water_height;
|
||||||
|
northZ = eastZ = baseHeight = southZ = westZ = water_height = 0;
|
||||||
|
auto res = std::make_unique<GameActions::ConstructClearResult>();
|
||||||
|
uint8_t slope = 0;
|
||||||
|
|
||||||
|
res->GroundFlags = ELEMENT_IS_ABOVE_GROUND;
|
||||||
|
bool canBuildCrossing = false;
|
||||||
|
if (map_is_edge(pos))
|
||||||
|
{
|
||||||
|
res->Error = GameActions::Status::InvalidParameters;
|
||||||
|
res->ErrorMessage = STR_OFF_EDGE_OF_MAP;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gCheatsDisableClearanceChecks)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileElement* tileElement = map_get_first_element_at(pos);
|
||||||
|
if (tileElement == nullptr)
|
||||||
|
{
|
||||||
|
res->Error = GameActions::Status::Unknown;
|
||||||
|
res->ErrorMessage = STR_NONE;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SURFACE)
|
||||||
|
{
|
||||||
|
if (pos.baseZ < tileElement->GetClearanceZ() && pos.clearanceZ > tileElement->GetBaseZ()
|
||||||
|
&& !(tileElement->IsGhost()))
|
||||||
|
{
|
||||||
|
if (tileElement->GetOccupiedQuadrants() & (quarterTile.GetBaseQuarterOccupied()))
|
||||||
|
{
|
||||||
|
if (MapLoc68BABCShouldContinue(
|
||||||
|
tileElement, pos, clearFunc, flags, res->Cost, crossingMode, canBuildCrossing))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileElement != nullptr)
|
||||||
|
{
|
||||||
|
map_obstruction_set_error_text(tileElement, *res);
|
||||||
|
res->Error = GameActions::Status::NoClearance;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
water_height = tileElement->AsSurface()->GetWaterHeight();
|
||||||
|
if (water_height && water_height > pos.baseZ && tileElement->GetBaseZ() < pos.clearanceZ)
|
||||||
|
{
|
||||||
|
res->GroundFlags |= ELEMENT_IS_UNDERWATER;
|
||||||
|
if (water_height < pos.clearanceZ)
|
||||||
|
{
|
||||||
|
bool returnError = true;
|
||||||
|
if (clearFunc != nullptr)
|
||||||
|
{
|
||||||
|
if (!clearFunc(&tileElement, pos, flags, &res->Cost))
|
||||||
|
{
|
||||||
|
returnError = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (returnError)
|
||||||
|
{
|
||||||
|
if (tileElement != nullptr)
|
||||||
|
{
|
||||||
|
res->Error = GameActions::Status::NoClearance;
|
||||||
|
res->ErrorMessage = STR_CANNOT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_WATER;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gParkFlags & PARK_FLAGS_FORBID_HIGH_CONSTRUCTION && !isTree)
|
||||||
|
{
|
||||||
|
auto heightFromGround = pos.clearanceZ - tileElement->GetBaseZ();
|
||||||
|
|
||||||
|
if (heightFromGround > (18 * COORDS_Z_STEP))
|
||||||
|
{
|
||||||
|
res->Error = GameActions::Status::Disallowed;
|
||||||
|
res->ErrorMessage = STR_LOCAL_AUTHORITY_WONT_ALLOW_CONSTRUCTION_ABOVE_TREE_HEIGHT;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only allow building crossings directly on a flat surface tile.
|
||||||
|
if (tileElement->GetType() == TILE_ELEMENT_TYPE_SURFACE
|
||||||
|
&& (tileElement->AsSurface()->GetSlope()) == TILE_ELEMENT_SLOPE_FLAT && tileElement->GetBaseZ() == pos.baseZ)
|
||||||
|
{
|
||||||
|
canBuildCrossing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quarterTile.GetZQuarterOccupied() != 0b1111)
|
||||||
|
{
|
||||||
|
if (tileElement->GetBaseZ() >= pos.clearanceZ)
|
||||||
|
{
|
||||||
|
// loc_68BA81
|
||||||
|
res->GroundFlags |= ELEMENT_IS_UNDERGROUND;
|
||||||
|
res->GroundFlags &= ~ELEMENT_IS_ABOVE_GROUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
northZ = tileElement->GetBaseZ();
|
||||||
|
eastZ = northZ;
|
||||||
|
southZ = northZ;
|
||||||
|
westZ = northZ;
|
||||||
|
slope = tileElement->AsSurface()->GetSlope();
|
||||||
|
if (slope & TILE_ELEMENT_SLOPE_N_CORNER_UP)
|
||||||
|
{
|
||||||
|
northZ += LAND_HEIGHT_STEP;
|
||||||
|
if (slope == (TILE_ELEMENT_SLOPE_S_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
||||||
|
northZ += LAND_HEIGHT_STEP;
|
||||||
|
}
|
||||||
|
if (slope & TILE_ELEMENT_SLOPE_E_CORNER_UP)
|
||||||
|
{
|
||||||
|
eastZ += LAND_HEIGHT_STEP;
|
||||||
|
if (slope == (TILE_ELEMENT_SLOPE_W_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
||||||
|
eastZ += LAND_HEIGHT_STEP;
|
||||||
|
}
|
||||||
|
if (slope & TILE_ELEMENT_SLOPE_S_CORNER_UP)
|
||||||
|
{
|
||||||
|
southZ += LAND_HEIGHT_STEP;
|
||||||
|
if (slope == (TILE_ELEMENT_SLOPE_N_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
||||||
|
southZ += LAND_HEIGHT_STEP;
|
||||||
|
}
|
||||||
|
if (slope & TILE_ELEMENT_SLOPE_W_CORNER_UP)
|
||||||
|
{
|
||||||
|
westZ += LAND_HEIGHT_STEP;
|
||||||
|
if (slope == (TILE_ELEMENT_SLOPE_E_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
||||||
|
westZ += LAND_HEIGHT_STEP;
|
||||||
|
}
|
||||||
|
baseHeight = pos.baseZ + (4 * COORDS_Z_STEP);
|
||||||
|
{
|
||||||
|
auto baseQuarter = quarterTile.GetBaseQuarterOccupied();
|
||||||
|
auto zQuarter = quarterTile.GetZQuarterOccupied();
|
||||||
|
if ((!(baseQuarter & 0b0001) || ((zQuarter & 0b0001 || pos.baseZ >= northZ) && baseHeight >= northZ))
|
||||||
|
&& (!(baseQuarter & 0b0010) || ((zQuarter & 0b0010 || pos.baseZ >= eastZ) && baseHeight >= eastZ))
|
||||||
|
&& (!(baseQuarter & 0b0100) || ((zQuarter & 0b0100 || pos.baseZ >= southZ) && baseHeight >= southZ))
|
||||||
|
&& (!(baseQuarter & 0b1000) || ((zQuarter & 0b1000 || pos.baseZ >= westZ) && baseHeight >= westZ)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MapLoc68BABCShouldContinue(tileElement, pos, clearFunc, flags, res->Cost, crossingMode, canBuildCrossing))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileElement != nullptr)
|
||||||
|
{
|
||||||
|
map_obstruction_set_error_text(tileElement, *res);
|
||||||
|
res->Error = GameActions::Status::NoClearance;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!(tileElement++)->IsLastForTile());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl)
|
||||||
|
{
|
||||||
|
return MapCanConstructWithClearAt(pos, nullptr, bl, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x0068BB18
|
||||||
|
*/
|
||||||
|
void map_obstruction_set_error_text(TileElement* tileElement, GameActions::Result& res)
|
||||||
|
{
|
||||||
|
Ride* ride;
|
||||||
|
|
||||||
|
res.ErrorMessage = STR_OBJECT_IN_THE_WAY;
|
||||||
|
switch (tileElement->GetType())
|
||||||
|
{
|
||||||
|
case TILE_ELEMENT_TYPE_SURFACE:
|
||||||
|
res.ErrorMessage = STR_RAISE_OR_LOWER_LAND_FIRST;
|
||||||
|
break;
|
||||||
|
case TILE_ELEMENT_TYPE_PATH:
|
||||||
|
res.ErrorMessage = STR_FOOTPATH_IN_THE_WAY;
|
||||||
|
break;
|
||||||
|
case TILE_ELEMENT_TYPE_TRACK:
|
||||||
|
ride = get_ride(tileElement->AsTrack()->GetRideIndex());
|
||||||
|
if (ride != nullptr)
|
||||||
|
{
|
||||||
|
res.ErrorMessage = STR_X_IN_THE_WAY;
|
||||||
|
|
||||||
|
Formatter ft(res.ErrorMessageArgs.data());
|
||||||
|
ride->FormatNameTo(ft);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||||
|
{
|
||||||
|
auto* sceneryEntry = tileElement->AsSmallScenery()->GetEntry();
|
||||||
|
res.ErrorMessage = STR_X_IN_THE_WAY;
|
||||||
|
auto ft = Formatter(res.ErrorMessageArgs.data());
|
||||||
|
rct_string_id stringId = sceneryEntry != nullptr ? sceneryEntry->name : static_cast<rct_string_id>(STR_EMPTY);
|
||||||
|
ft.Add<rct_string_id>(stringId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||||
|
switch (tileElement->AsEntrance()->GetEntranceType())
|
||||||
|
{
|
||||||
|
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
||||||
|
res.ErrorMessage = STR_RIDE_ENTRANCE_IN_THE_WAY;
|
||||||
|
break;
|
||||||
|
case ENTRANCE_TYPE_RIDE_EXIT:
|
||||||
|
res.ErrorMessage = STR_RIDE_EXIT_IN_THE_WAY;
|
||||||
|
break;
|
||||||
|
case ENTRANCE_TYPE_PARK_ENTRANCE:
|
||||||
|
res.ErrorMessage = STR_PARK_ENTRANCE_IN_THE_WAY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TILE_ELEMENT_TYPE_WALL:
|
||||||
|
{
|
||||||
|
auto* wallEntry = tileElement->AsWall()->GetEntry();
|
||||||
|
res.ErrorMessage = STR_X_IN_THE_WAY;
|
||||||
|
auto ft = Formatter(res.ErrorMessageArgs.data());
|
||||||
|
rct_string_id stringId = wallEntry != nullptr ? wallEntry->name : static_cast<rct_string_id>(STR_EMPTY);
|
||||||
|
ft.Add<rct_string_id>(stringId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||||
|
{
|
||||||
|
auto* sceneryEntry = tileElement->AsLargeScenery()->GetEntry();
|
||||||
|
res.ErrorMessage = STR_X_IN_THE_WAY;
|
||||||
|
auto ft = Formatter(res.ErrorMessageArgs.data());
|
||||||
|
rct_string_id stringId = sceneryEntry != nullptr ? sceneryEntry->name : static_cast<rct_string_id>(STR_EMPTY);
|
||||||
|
ft.Add<rct_string_id>(stringId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2021 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../actions/GameActionResult.h"
|
||||||
|
#include "../common.h"
|
||||||
|
#include "Map.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
struct TileElement;
|
||||||
|
struct CoordsXY;
|
||||||
|
struct CoordsXYRangedZ;
|
||||||
|
class QuarterTile;
|
||||||
|
|
||||||
|
using CLEAR_FUNC = int32_t (*)(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
|
||||||
|
|
||||||
|
int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
|
||||||
|
int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
|
||||||
|
|
||||||
|
[[nodiscard]] std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt(
|
||||||
|
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags,
|
||||||
|
uint8_t crossingMode = CREATE_CROSSING_MODE_NONE, bool isTree = false);
|
||||||
|
|
||||||
|
[[nodiscard]] std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl);
|
||||||
|
|
||||||
|
void map_obstruction_set_error_text(TileElement* tileElement, GameActions::Result& res);
|
|
@ -1308,292 +1308,6 @@ TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants
|
||||||
return insertedElement;
|
return insertedElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x0068BB18
|
|
||||||
*/
|
|
||||||
void map_obstruction_set_error_text(TileElement* tileElement, GameActions::Result& res)
|
|
||||||
{
|
|
||||||
Ride* ride;
|
|
||||||
|
|
||||||
res.ErrorMessage = STR_OBJECT_IN_THE_WAY;
|
|
||||||
switch (tileElement->GetType())
|
|
||||||
{
|
|
||||||
case TILE_ELEMENT_TYPE_SURFACE:
|
|
||||||
res.ErrorMessage = STR_RAISE_OR_LOWER_LAND_FIRST;
|
|
||||||
break;
|
|
||||||
case TILE_ELEMENT_TYPE_PATH:
|
|
||||||
res.ErrorMessage = STR_FOOTPATH_IN_THE_WAY;
|
|
||||||
break;
|
|
||||||
case TILE_ELEMENT_TYPE_TRACK:
|
|
||||||
ride = get_ride(tileElement->AsTrack()->GetRideIndex());
|
|
||||||
if (ride != nullptr)
|
|
||||||
{
|
|
||||||
res.ErrorMessage = STR_X_IN_THE_WAY;
|
|
||||||
|
|
||||||
Formatter ft(res.ErrorMessageArgs.data());
|
|
||||||
ride->FormatNameTo(ft);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
|
||||||
{
|
|
||||||
auto* sceneryEntry = tileElement->AsSmallScenery()->GetEntry();
|
|
||||||
res.ErrorMessage = STR_X_IN_THE_WAY;
|
|
||||||
auto ft = Formatter(res.ErrorMessageArgs.data());
|
|
||||||
rct_string_id stringId = sceneryEntry != nullptr ? sceneryEntry->name : static_cast<rct_string_id>(STR_EMPTY);
|
|
||||||
ft.Add<rct_string_id>(stringId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
|
||||||
switch (tileElement->AsEntrance()->GetEntranceType())
|
|
||||||
{
|
|
||||||
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
|
||||||
res.ErrorMessage = STR_RIDE_ENTRANCE_IN_THE_WAY;
|
|
||||||
break;
|
|
||||||
case ENTRANCE_TYPE_RIDE_EXIT:
|
|
||||||
res.ErrorMessage = STR_RIDE_EXIT_IN_THE_WAY;
|
|
||||||
break;
|
|
||||||
case ENTRANCE_TYPE_PARK_ENTRANCE:
|
|
||||||
res.ErrorMessage = STR_PARK_ENTRANCE_IN_THE_WAY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TILE_ELEMENT_TYPE_WALL:
|
|
||||||
{
|
|
||||||
auto* wallEntry = tileElement->AsWall()->GetEntry();
|
|
||||||
res.ErrorMessage = STR_X_IN_THE_WAY;
|
|
||||||
auto ft = Formatter(res.ErrorMessageArgs.data());
|
|
||||||
rct_string_id stringId = wallEntry != nullptr ? wallEntry->name : static_cast<rct_string_id>(STR_EMPTY);
|
|
||||||
ft.Add<rct_string_id>(stringId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
|
||||||
{
|
|
||||||
auto* sceneryEntry = tileElement->AsLargeScenery()->GetEntry();
|
|
||||||
res.ErrorMessage = STR_X_IN_THE_WAY;
|
|
||||||
auto ft = Formatter(res.ErrorMessageArgs.data());
|
|
||||||
rct_string_id stringId = sceneryEntry != nullptr ? sceneryEntry->name : static_cast<rct_string_id>(STR_EMPTY);
|
|
||||||
ft.Add<rct_string_id>(stringId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool MapLoc68BABCShouldContinue(
|
|
||||||
TileElement* tileElement, const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, uint8_t flags, money32& price,
|
|
||||||
uint8_t crossingMode, bool canBuildCrossing)
|
|
||||||
{
|
|
||||||
if (clearFunc != nullptr)
|
|
||||||
{
|
|
||||||
if (!clearFunc(&tileElement, pos, flags, &price))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crossing mode 1: building track over path
|
|
||||||
if (crossingMode == 1 && canBuildCrossing && tileElement->GetType() == TILE_ELEMENT_TYPE_PATH
|
|
||||||
&& tileElement->GetBaseZ() == pos.baseZ && !tileElement->AsPath()->IsQueue() && !tileElement->AsPath()->IsSloped())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Crossing mode 2: building path over track
|
|
||||||
else if (
|
|
||||||
crossingMode == 2 && canBuildCrossing && tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK
|
|
||||||
&& tileElement->GetBaseZ() == pos.baseZ && tileElement->AsTrack()->GetTrackType() == TrackElemType::Flat)
|
|
||||||
{
|
|
||||||
auto ride = get_ride(tileElement->AsTrack()->GetRideIndex());
|
|
||||||
if (ride != nullptr && ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x0068B932
|
|
||||||
* ax = x
|
|
||||||
* cx = y
|
|
||||||
* dl = zLow
|
|
||||||
* dh = zHigh
|
|
||||||
* ebp = clearFunc
|
|
||||||
* bl = bl
|
|
||||||
*/
|
|
||||||
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt(
|
|
||||||
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode, bool isTree)
|
|
||||||
{
|
|
||||||
int32_t northZ, eastZ, baseHeight, southZ, westZ, water_height;
|
|
||||||
northZ = eastZ = baseHeight = southZ = westZ = water_height = 0;
|
|
||||||
auto res = std::make_unique<GameActions::ConstructClearResult>();
|
|
||||||
uint8_t slope = 0;
|
|
||||||
|
|
||||||
res->GroundFlags = ELEMENT_IS_ABOVE_GROUND;
|
|
||||||
bool canBuildCrossing = false;
|
|
||||||
if (map_is_edge(pos))
|
|
||||||
{
|
|
||||||
res->Error = GameActions::Status::InvalidParameters;
|
|
||||||
res->ErrorMessage = STR_OFF_EDGE_OF_MAP;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gCheatsDisableClearanceChecks)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
TileElement* tileElement = map_get_first_element_at(pos);
|
|
||||||
if (tileElement == nullptr)
|
|
||||||
{
|
|
||||||
res->Error = GameActions::Status::Unknown;
|
|
||||||
res->ErrorMessage = STR_NONE;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SURFACE)
|
|
||||||
{
|
|
||||||
if (pos.baseZ < tileElement->GetClearanceZ() && pos.clearanceZ > tileElement->GetBaseZ()
|
|
||||||
&& !(tileElement->IsGhost()))
|
|
||||||
{
|
|
||||||
if (tileElement->GetOccupiedQuadrants() & (quarterTile.GetBaseQuarterOccupied()))
|
|
||||||
{
|
|
||||||
if (MapLoc68BABCShouldContinue(
|
|
||||||
tileElement, pos, clearFunc, flags, res->Cost, crossingMode, canBuildCrossing))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tileElement != nullptr)
|
|
||||||
{
|
|
||||||
map_obstruction_set_error_text(tileElement, *res);
|
|
||||||
res->Error = GameActions::Status::NoClearance;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
water_height = tileElement->AsSurface()->GetWaterHeight();
|
|
||||||
if (water_height && water_height > pos.baseZ && tileElement->GetBaseZ() < pos.clearanceZ)
|
|
||||||
{
|
|
||||||
res->GroundFlags |= ELEMENT_IS_UNDERWATER;
|
|
||||||
if (water_height < pos.clearanceZ)
|
|
||||||
{
|
|
||||||
bool returnError = true;
|
|
||||||
if (clearFunc != nullptr)
|
|
||||||
{
|
|
||||||
if (!clearFunc(&tileElement, pos, flags, &res->Cost))
|
|
||||||
{
|
|
||||||
returnError = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (returnError)
|
|
||||||
{
|
|
||||||
if (tileElement != nullptr)
|
|
||||||
{
|
|
||||||
res->Error = GameActions::Status::NoClearance;
|
|
||||||
res->ErrorMessage = STR_CANNOT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_WATER;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gParkFlags & PARK_FLAGS_FORBID_HIGH_CONSTRUCTION && !isTree)
|
|
||||||
{
|
|
||||||
auto heightFromGround = pos.clearanceZ - tileElement->GetBaseZ();
|
|
||||||
|
|
||||||
if (heightFromGround > (18 * COORDS_Z_STEP))
|
|
||||||
{
|
|
||||||
res->Error = GameActions::Status::Disallowed;
|
|
||||||
res->ErrorMessage = STR_LOCAL_AUTHORITY_WONT_ALLOW_CONSTRUCTION_ABOVE_TREE_HEIGHT;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only allow building crossings directly on a flat surface tile.
|
|
||||||
if (tileElement->GetType() == TILE_ELEMENT_TYPE_SURFACE
|
|
||||||
&& (tileElement->AsSurface()->GetSlope()) == TILE_ELEMENT_SLOPE_FLAT && tileElement->GetBaseZ() == pos.baseZ)
|
|
||||||
{
|
|
||||||
canBuildCrossing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quarterTile.GetZQuarterOccupied() != 0b1111)
|
|
||||||
{
|
|
||||||
if (tileElement->GetBaseZ() >= pos.clearanceZ)
|
|
||||||
{
|
|
||||||
// loc_68BA81
|
|
||||||
res->GroundFlags |= ELEMENT_IS_UNDERGROUND;
|
|
||||||
res->GroundFlags &= ~ELEMENT_IS_ABOVE_GROUND;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
northZ = tileElement->GetBaseZ();
|
|
||||||
eastZ = northZ;
|
|
||||||
southZ = northZ;
|
|
||||||
westZ = northZ;
|
|
||||||
slope = tileElement->AsSurface()->GetSlope();
|
|
||||||
if (slope & TILE_ELEMENT_SLOPE_N_CORNER_UP)
|
|
||||||
{
|
|
||||||
northZ += LAND_HEIGHT_STEP;
|
|
||||||
if (slope == (TILE_ELEMENT_SLOPE_S_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
|
||||||
northZ += LAND_HEIGHT_STEP;
|
|
||||||
}
|
|
||||||
if (slope & TILE_ELEMENT_SLOPE_E_CORNER_UP)
|
|
||||||
{
|
|
||||||
eastZ += LAND_HEIGHT_STEP;
|
|
||||||
if (slope == (TILE_ELEMENT_SLOPE_W_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
|
||||||
eastZ += LAND_HEIGHT_STEP;
|
|
||||||
}
|
|
||||||
if (slope & TILE_ELEMENT_SLOPE_S_CORNER_UP)
|
|
||||||
{
|
|
||||||
southZ += LAND_HEIGHT_STEP;
|
|
||||||
if (slope == (TILE_ELEMENT_SLOPE_N_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
|
||||||
southZ += LAND_HEIGHT_STEP;
|
|
||||||
}
|
|
||||||
if (slope & TILE_ELEMENT_SLOPE_W_CORNER_UP)
|
|
||||||
{
|
|
||||||
westZ += LAND_HEIGHT_STEP;
|
|
||||||
if (slope == (TILE_ELEMENT_SLOPE_E_CORNER_DN | TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT))
|
|
||||||
westZ += LAND_HEIGHT_STEP;
|
|
||||||
}
|
|
||||||
baseHeight = pos.baseZ + (4 * COORDS_Z_STEP);
|
|
||||||
{
|
|
||||||
auto baseQuarter = quarterTile.GetBaseQuarterOccupied();
|
|
||||||
auto zQuarter = quarterTile.GetZQuarterOccupied();
|
|
||||||
if ((!(baseQuarter & 0b0001) || ((zQuarter & 0b0001 || pos.baseZ >= northZ) && baseHeight >= northZ))
|
|
||||||
&& (!(baseQuarter & 0b0010) || ((zQuarter & 0b0010 || pos.baseZ >= eastZ) && baseHeight >= eastZ))
|
|
||||||
&& (!(baseQuarter & 0b0100) || ((zQuarter & 0b0100 || pos.baseZ >= southZ) && baseHeight >= southZ))
|
|
||||||
&& (!(baseQuarter & 0b1000) || ((zQuarter & 0b1000 || pos.baseZ >= westZ) && baseHeight >= westZ)))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MapLoc68BABCShouldContinue(tileElement, pos, clearFunc, flags, res->Cost, crossingMode, canBuildCrossing))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tileElement != nullptr)
|
|
||||||
{
|
|
||||||
map_obstruction_set_error_text(tileElement, *res);
|
|
||||||
res->Error = GameActions::Status::NoClearance;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!(tileElement++)->IsLastForTile());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl)
|
|
||||||
{
|
|
||||||
return MapCanConstructWithClearAt(pos, nullptr, bl, 0);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Updates grass length, scenery age and jumping fountains.
|
* Updates grass length, scenery age and jumping fountains.
|
||||||
*
|
*
|
||||||
|
|
|
@ -234,21 +234,6 @@ template<typename T> T* TileElementInsert(const CoordsXYZ& loc, int32_t occupied
|
||||||
return (element != nullptr) ? element->template as<T>() : nullptr;
|
return (element != nullptr) ? element->template as<T>() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace GameActions
|
|
||||||
{
|
|
||||||
class Result;
|
|
||||||
class ConstructClearResult;
|
|
||||||
} // namespace GameActions
|
|
||||||
|
|
||||||
using CLEAR_FUNC = int32_t (*)(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
|
|
||||||
|
|
||||||
int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
|
|
||||||
int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
|
|
||||||
[[nodiscard]] std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt(
|
|
||||||
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags,
|
|
||||||
uint8_t crossingMode = CREATE_CROSSING_MODE_NONE, bool isTree = false);
|
|
||||||
[[nodiscard]] std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl);
|
|
||||||
|
|
||||||
struct tile_element_iterator
|
struct tile_element_iterator
|
||||||
{
|
{
|
||||||
int32_t x;
|
int32_t x;
|
||||||
|
@ -306,7 +291,6 @@ TileElement* map_get_track_element_at_from_ride(const CoordsXYZ& trackPos, ride_
|
||||||
TileElement* map_get_track_element_at_with_direction_from_ride(const CoordsXYZD& trackPos, ride_id_t rideIndex);
|
TileElement* map_get_track_element_at_with_direction_from_ride(const CoordsXYZD& trackPos, ride_id_t rideIndex);
|
||||||
|
|
||||||
bool map_is_location_at_edge(const CoordsXY& loc);
|
bool map_is_location_at_edge(const CoordsXY& loc);
|
||||||
void map_obstruction_set_error_text(TileElement* tileElement, GameActions::Result& res);
|
|
||||||
|
|
||||||
uint16_t check_max_allowable_land_rights_for_tile(const CoordsXYZ& tileMapPos);
|
uint16_t check_max_allowable_land_rights_for_tile(const CoordsXYZ& tileMapPos);
|
||||||
|
|
||||||
|
|
|
@ -24,58 +24,6 @@
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "Surface.h"
|
#include "Surface.h"
|
||||||
|
|
||||||
static int32_t map_place_clear_func(
|
|
||||||
TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price, bool is_scenery)
|
|
||||||
{
|
|
||||||
if ((*tile_element)->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (is_scenery && !(flags & GAME_COMMAND_FLAG_PATH_SCENERY))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
auto* scenery = (*tile_element)->AsSmallScenery()->GetEntry();
|
|
||||||
|
|
||||||
if (gParkFlags & PARK_FLAGS_FORBID_TREE_REMOVAL)
|
|
||||||
{
|
|
||||||
if (scenery != nullptr && scenery->HasFlag(SMALL_SCENERY_FLAG_IS_TREE))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(gParkFlags & PARK_FLAGS_NO_MONEY) && scenery != nullptr)
|
|
||||||
*price += scenery->removal_price * 10;
|
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_GHOST)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
map_invalidate_tile({ coords, (*tile_element)->GetBaseZ(), (*tile_element)->GetClearanceZ() });
|
|
||||||
|
|
||||||
tile_element_remove(*tile_element);
|
|
||||||
|
|
||||||
(*tile_element)--;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006E0D6E, 0x006B8D88
|
|
||||||
*/
|
|
||||||
int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price)
|
|
||||||
{
|
|
||||||
return map_place_clear_func(tile_element, coords, flags, price, /*is_scenery=*/true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006C5A4F, 0x006CDE57, 0x006A6733, 0x0066637E
|
|
||||||
*/
|
|
||||||
int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price)
|
|
||||||
{
|
|
||||||
return map_place_clear_func(tile_element, coords, flags, price, /*is_scenery=*/false);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SmallSceneryElement::GetSceneryQuadrant() const
|
uint8_t SmallSceneryElement::GetSceneryQuadrant() const
|
||||||
{
|
{
|
||||||
return (this->type & TILE_ELEMENT_QUADRANT_MASK) >> 6;
|
return (this->type & TILE_ELEMENT_QUADRANT_MASK) >> 6;
|
||||||
|
|
|
@ -894,3 +894,10 @@ namespace OpenRCT2
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} // namespace OpenRCT2
|
} // namespace OpenRCT2
|
||||||
|
|
||||||
|
ScreenCoordsXY translate_3d_to_2d_with_z(int32_t rotation, const CoordsXYZ& pos)
|
||||||
|
{
|
||||||
|
auto rotated = pos.Rotate(rotation);
|
||||||
|
// Use right shift to avoid issues like #9301
|
||||||
|
return ScreenCoordsXY{ rotated.y - rotated.x, ((rotated.x + rotated.y) >> 1) - pos.z };
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue