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_5628 :Oorsprong
|
||||
STR_5629 :Moeilijkheidsgraad
|
||||
STR_5630 :Moeilijke scenario’s ontgrendelden met gemakkelijke
|
||||
STR_5630 :Moeilijke scenario’s ontgrendelden met makkelijke
|
||||
STR_5631 :Originele DLC
|
||||
STR_5632 :Bouw je eigen…
|
||||
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))
|
||||
{
|
||||
auto previousWidget = window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE];
|
||||
auto nextWidget = window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE];
|
||||
|
||||
if (drawPreviousButton)
|
||||
{
|
||||
gfx_filter_rect(
|
||||
dpi, window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].left + w->windowPos.x,
|
||||
window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].top + w->windowPos.y,
|
||||
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);
|
||||
auto leftTop = w->windowPos + ScreenCoordsXY{ previousWidget.left, previousWidget.top };
|
||||
auto rightBottom = w->windowPos + ScreenCoordsXY{ previousWidget.right, previousWidget.bottom };
|
||||
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||
}
|
||||
|
||||
if ((drawPreviousButton || drawNextButton) && gEditorStep != EditorStep::RollercoasterDesigner)
|
||||
{
|
||||
gfx_filter_rect(
|
||||
dpi, window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].left + w->windowPos.x,
|
||||
window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].top + w->windowPos.y,
|
||||
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);
|
||||
auto leftTop = w->windowPos + ScreenCoordsXY{ nextWidget.left, nextWidget.top };
|
||||
auto rightBottom = w->windowPos + ScreenCoordsXY{ nextWidget.right, nextWidget.bottom };
|
||||
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -607,7 +607,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
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)
|
||||
|
|
|
@ -1226,7 +1226,7 @@ static void window_editor_object_selection_scrollpaint(rct_window* w, rct_drawpi
|
|||
if (highlighted)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -1095,7 +1095,7 @@ static void window_editor_objective_options_rides_scrollpaint(rct_window* w, rct
|
|||
if (i == w->selected_list_item)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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
|
||||
gfx_filter_rect(
|
||||
dpi, w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET].left,
|
||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_LEFT_OUTSET].top,
|
||||
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);
|
||||
gfx_filter_rect(
|
||||
dpi, w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].left,
|
||||
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);
|
||||
auto leftTop = w->windowPos + ScreenCoordsXY{ leftWidget.left, leftWidget.top };
|
||||
auto rightBottom = w->windowPos + ScreenCoordsXY{ leftWidget.right, leftWidget.bottom };
|
||||
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||
|
||||
leftTop = w->windowPos + ScreenCoordsXY{ rightWidget.left, rightWidget.top };
|
||||
rightBottom = w->windowPos + ScreenCoordsXY{ rightWidget.right, rightWidget.bottom };
|
||||
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||
|
||||
if (ThemeGetFlags() & UITHEME_FLAG_USE_FULL_BOTTOM_TOOLBAR)
|
||||
{
|
||||
// Draw grey background
|
||||
gfx_filter_rect(
|
||||
dpi, w->windowPos.x + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].left,
|
||||
w->windowPos.y + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].top,
|
||||
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);
|
||||
leftTop = w->windowPos + ScreenCoordsXY{ middleWidget.left, middleWidget.top };
|
||||
rightBottom = w->windowPos + ScreenCoordsXY{ middleWidget.right, middleWidget.bottom };
|
||||
gfx_filter_rect(dpi, { leftTop, rightBottom }, FilterPaletteID::Palette51);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -675,7 +675,7 @@ private:
|
|||
rct_string_id format = STR_BLACK_STRING;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -745,7 +745,7 @@ private:
|
|||
rct_string_id format = STR_BLACK_STRING;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -759,7 +759,7 @@ static void window_loadsave_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, i
|
|||
if (i == w->selected_list_item)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -596,7 +596,7 @@ static void window_scenarioselect_scrollpaint(rct_window* w, rct_drawpixelinfo*
|
|||
bool isHighlighted = w->highlighted_scenario == scenario;
|
||||
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;
|
||||
|
|
|
@ -40,8 +40,8 @@ static std::future<std::tuple<std::vector<ServerListEntry>, rct_string_id>> _fet
|
|||
static uint32_t _numPlayersOnline = 0;
|
||||
static rct_string_id _statusText = STR_SERVER_LIST_CONNECTING;
|
||||
|
||||
// clang-format off
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
WIDX_BACKGROUND,
|
||||
WIDX_TITLE,
|
||||
WIDX_CLOSE,
|
||||
|
@ -52,39 +52,42 @@ enum {
|
|||
WIDX_START_SERVER
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
WIDX_LIST_REMOVE,
|
||||
WIDX_LIST_SPECTATE
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static rct_widget window_server_list_widgets[] = {
|
||||
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({327, 2}, { 11, 12}, WindowWidgetType::CloseBox, WindowColour::Primary , STR_CLOSE_X, STR_CLOSE_WINDOW_TIP), // close x button
|
||||
MakeWidget({100, 20}, {245, 12}, WindowWidgetType::TextBox, WindowColour::Secondary ), // player name text box
|
||||
MakeWidget({ 1, 1}, {338, 14}, WindowWidgetType::Caption, WindowColour::Primary, STR_SERVER_LIST, STR_WINDOW_TITLE_TIP), // title bar
|
||||
MakeWidget({327, 2}, { 11, 12}, WindowWidgetType::CloseBox, WindowColour::Primary, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP), // close x button
|
||||
MakeWidget({100, 20}, {245, 12}, WindowWidgetType::TextBox, WindowColour::Secondary ), // player name text box
|
||||
MakeWidget({ 6, 37}, {332, 14}, WindowWidgetType::Scroll, WindowColour::Secondary ), // server list
|
||||
MakeWidget({ 6, 53}, {101, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_FETCH_SERVERS ), // fetch servers button
|
||||
MakeWidget({112, 53}, {101, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_ADD_SERVER ), // add server button
|
||||
MakeWidget({218, 53}, {101, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_START_SERVER ), // start server button
|
||||
WIDGETS_END,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
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_resize(rct_window *w);
|
||||
static void window_server_list_dropdown(rct_window *w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
|
||||
static void window_server_list_update(rct_window *w);
|
||||
static void window_server_list_scroll_getsize(rct_window *w, int32_t scrollIndex, int32_t *width, int32_t *height);
|
||||
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_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 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_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int32_t scrollIndex);
|
||||
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_resize(rct_window* w);
|
||||
static void window_server_list_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
|
||||
static void window_server_list_update(rct_window* w);
|
||||
static void window_server_list_scroll_getsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height);
|
||||
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_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 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_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.mouse_up = &window_server_list_mouseup;
|
||||
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.scroll_paint = &window_server_list_scrollpaint;
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -439,7 +441,7 @@ static void window_server_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi
|
|||
// Draw hover highlight
|
||||
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;
|
||||
listWidget.tooltip = STR_NETWORK_VERSION_TIP;
|
||||
}
|
||||
|
|
|
@ -509,7 +509,7 @@ private:
|
|||
if (isHighlighted)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -401,7 +401,7 @@ public:
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
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)
|
||||
{
|
||||
translucent_window_palette windowPalette = TranslucentWindowPalettes[BASE_COLOUR(colour)];
|
||||
|
||||
gfx_filter_rect(
|
||||
dpi, 0, screenCoords.y + _row_height - 2, window_themes_widgets[WIDX_THEMES_LIST].right,
|
||||
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);
|
||||
gfx_filter_rect(dpi, { leftTop, rightBottom }, windowPalette.highlight);
|
||||
gfx_filter_rect(dpi, { leftTop + yPixelOffset, rightBottom + yPixelOffset }, windowPalette.shadow);
|
||||
}
|
||||
else
|
||||
{
|
||||
colour = ColourMapA[w->colours[1]].mid_dark;
|
||||
gfx_fill_rect(
|
||||
dpi,
|
||||
{ { 0, screenCoords.y + _row_height - 2 },
|
||||
{ window_themes_widgets[WIDX_THEMES_LIST].right, screenCoords.y + _row_height - 2 } },
|
||||
colour);
|
||||
gfx_fill_rect(dpi, { leftTop, rightBottom }, colour);
|
||||
|
||||
colour = ColourMapA[w->colours[1]].lightest;
|
||||
gfx_fill_rect(
|
||||
dpi,
|
||||
{ { 0, screenCoords.y + _row_height - 1 },
|
||||
{ window_themes_widgets[WIDX_THEMES_LIST].right, screenCoords.y + _row_height - 1 } },
|
||||
colour);
|
||||
gfx_fill_rect(dpi, { leftTop + yPixelOffset, rightBottom + yPixelOffset }, colour);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -690,7 +690,7 @@ public:
|
|||
{
|
||||
// Highlight
|
||||
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);
|
||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||
}
|
||||
|
@ -715,7 +715,7 @@ public:
|
|||
{
|
||||
// Highlight
|
||||
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);
|
||||
stringId = STR_WINDOW_COLOUR_2_STRINGID;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "../interface/Window.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/Footpath.h"
|
||||
#include "../world/Location.hpp"
|
||||
#include "../world/Park.h"
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "../interface/Window.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/Footpath.h"
|
||||
#include "../world/Location.hpp"
|
||||
#include "../world/Park.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../management/Finance.h"
|
||||
#include "../ride/RideData.h"
|
||||
#include "../windows/Intent.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/Park.h"
|
||||
#include "../world/Scenery.h"
|
||||
#include "../world/SmallScenery.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../object/ObjectLimits.h"
|
||||
#include "../ride/Ride.h"
|
||||
#include "../world/Banner.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/MapAnimation.h"
|
||||
#include "../world/Surface.h"
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../management/Finance.h"
|
||||
#include "../ride/RideData.h"
|
||||
#include "../ride/TrackData.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
|
||||
using namespace OpenRCT2::TrackMetaData;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "../ride/RideData.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../ride/TrackData.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/Footpath.h"
|
||||
#include "../world/Park.h"
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../core/MemoryStream.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/Entrance.h"
|
||||
#include "../world/Footpath.h"
|
||||
#include "../world/MapAnimation.h"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "../management/Finance.h"
|
||||
#include "../ride/Ride.h"
|
||||
#include "../ride/Station.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/MapAnimation.h"
|
||||
|
||||
RideEntranceExitPlaceAction::RideEntranceExitPlaceAction(
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "../management/Finance.h"
|
||||
#include "../ride/Ride.h"
|
||||
#include "../ride/TrackDesign.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/MapAnimation.h"
|
||||
#include "../world/Park.h"
|
||||
#include "../world/SmallScenery.h"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "../ride/TrackData.h"
|
||||
#include "../ride/TrackDesign.h"
|
||||
#include "../util/Math.hpp"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/MapAnimation.h"
|
||||
#include "../world/Surface.h"
|
||||
#include "RideSetSettingAction.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../ride/Track.h"
|
||||
#include "../ride/TrackDesign.h"
|
||||
#include "../world/Banner.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/LargeScenery.h"
|
||||
#include "../world/MapAnimation.h"
|
||||
#include "../world/SmallScenery.h"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/Park.h"
|
||||
#include "../world/Surface.h"
|
||||
|
||||
|
|
|
@ -692,7 +692,6 @@ void gfx_draw_dashed_line(
|
|||
// rect
|
||||
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_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);
|
||||
|
||||
// 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)
|
||||
{
|
||||
auto drawingEngine = dpi->DrawingEngine;
|
||||
|
|
|
@ -466,6 +466,7 @@
|
|||
<ClInclude Include="world\Balloon.h" />
|
||||
<ClInclude Include="world\Banner.h" />
|
||||
<ClInclude Include="world\Climate.h" />
|
||||
<ClInclude Include="world\ConstructionClearance.h" />
|
||||
<ClInclude Include="world\Duck.h" />
|
||||
<ClInclude Include="world\Entity.h" />
|
||||
<ClInclude Include="world\EntityList.h" />
|
||||
|
@ -911,6 +912,7 @@
|
|||
<ClCompile Include="world\Balloon.cpp" />
|
||||
<ClCompile Include="world\Banner.cpp" />
|
||||
<ClCompile Include="world\Climate.cpp" />
|
||||
<ClCompile Include="world\ConstructionClearance.cpp" />
|
||||
<ClCompile Include="world\Duck.cpp" />
|
||||
<ClCompile Include="world\Entity.cpp" />
|
||||
<ClCompile Include="world\EntityTweener.cpp" />
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "../../world/Banner.h"
|
||||
#include "../../world/Entrance.h"
|
||||
#include "../../world/Footpath.h"
|
||||
#include "../../world/Map.h"
|
||||
#include "../../world/Scenery.h"
|
||||
#include "../../world/Surface.h"
|
||||
#include "../Paint.h"
|
||||
|
@ -146,27 +147,24 @@ static void sub_68B3FB(paint_session* session, int32_t x, int32_t y)
|
|||
}
|
||||
#endif // __TESTPAINT__
|
||||
|
||||
int32_t dx = 0;
|
||||
switch (rotation)
|
||||
{
|
||||
case 0:
|
||||
dx = x + y;
|
||||
break;
|
||||
case 1:
|
||||
x += 32;
|
||||
dx = y - x;
|
||||
break;
|
||||
case 2:
|
||||
x += 32;
|
||||
y += 32;
|
||||
dx = -(x + y);
|
||||
break;
|
||||
case 3:
|
||||
y += 32;
|
||||
dx = x - y;
|
||||
break;
|
||||
}
|
||||
dx >>= 1;
|
||||
|
||||
int32_t screenMinY = translate_3d_to_2d_with_z(rotation, { x, y, 0 }).y;
|
||||
|
||||
// Display little yellow arrow when building footpaths?
|
||||
if ((gMapSelectFlags & MAP_SELECT_FLAG_ENABLE_ARROW) && session->MapPosition.x == gMapSelectArrowPosition.x
|
||||
&& 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 });
|
||||
}
|
||||
int32_t bx = dx + 52;
|
||||
|
||||
if (bx <= dpi->y)
|
||||
if (screenMinY + 52 <= dpi->y)
|
||||
return;
|
||||
|
||||
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__
|
||||
|
||||
dx -= max_height + 32;
|
||||
dx -= dpi->height;
|
||||
if (dx >= dpi->y)
|
||||
if (screenMinY - (max_height + 32) >= dpi->y + dpi->height)
|
||||
return;
|
||||
|
||||
session->SpritePosition.x = x;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "../windows/Intent.h"
|
||||
#include "../world/Balloon.h"
|
||||
#include "../world/Climate.h"
|
||||
#include "../world/ConstructionClearance.h"
|
||||
#include "../world/EntityTweener.h"
|
||||
#include "../world/Entrance.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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -234,21 +234,6 @@ template<typename T> T* TileElementInsert(const CoordsXYZ& loc, int32_t occupied
|
|||
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
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -24,58 +24,6 @@
|
|||
#include "Scenery.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
|
||||
{
|
||||
return (this->type & TILE_ELEMENT_QUADRANT_MASK) >> 6;
|
||||
|
|
|
@ -894,3 +894,10 @@ namespace OpenRCT2
|
|||
return nullptr;
|
||||
}
|
||||
} // 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