diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 3008795c63..1dc1267087 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -1148,66 +1148,9 @@ static void scenery_eyedropper_tool_down(const ScreenCoordsXY& windowPos, rct_wi } } -/** - * - * rct2: 0x006E1F34 - * Outputs - * eax : gridX - * ebx : parameter_1 - * ecx : gridY - * edx : parameter_2 - * edi : parameter_3 - */ -static void sub_6E1F34( - const ScreenCoordsXY& sourceScreenPos, ScenerySelection selection, CoordsXY& gridPos, uint32_t* parameter_1, - uint32_t* parameter_2, uint32_t* parameter_3) +static void sub_6E1F34_update_screen_coords_and_buttons_pressed(bool canRaiseItem, ScreenCoordsXY& screenPos) { - rct_window* w = window_find_by_class(WC_SCENERY); - - if (w == nullptr) - { - gridPos.setNull(); - return; - } - - auto screenPos = sourceScreenPos; - uint16_t maxPossibleHeight = (std::numeric_limits::max() - 32) * ZoomLevel::max(); - bool can_raise_item = false; - - if (selection.SceneryType == SCENERY_TYPE_SMALL) - { - rct_scenery_entry* scenery_entry = get_small_scenery_entry(selection.EntryIndex); - maxPossibleHeight -= scenery_entry->small_scenery.height; - if (scenery_small_entry_has_flag(scenery_entry, SMALL_SCENERY_FLAG_STACKABLE)) - { - can_raise_item = true; - } - } - else if (selection.SceneryType == SCENERY_TYPE_WALL) - { - rct_scenery_entry* scenery_entry = get_wall_entry(selection.EntryIndex); - if (scenery_entry) - { - maxPossibleHeight -= scenery_entry->wall.height; - } - can_raise_item = true; - } - else if (selection.SceneryType == SCENERY_TYPE_LARGE) - { - rct_scenery_entry* scenery_entry = get_large_scenery_entry(selection.EntryIndex); - if (scenery_entry) - { - int16_t maxClearZ = 0; - for (int32_t i = 0; scenery_entry->large_scenery.tiles[i].x_offset != -1; ++i) - { - maxClearZ = std::max(maxClearZ, scenery_entry->large_scenery.tiles[i].z_clearance); - } - maxPossibleHeight = std::max(0, maxPossibleHeight - maxClearZ); - } - can_raise_item = true; - } - - if (!can_raise_item && !gCheatsDisableSupportLimits) + if (!canRaiseItem && !gCheatsDisableSupportLimits) { gSceneryCtrlPressed = false; gSceneryShiftPressed = false; @@ -1275,378 +1218,471 @@ static void sub_6E1F34( } } } +} - switch (selection.SceneryType) +static void sub_6E1F34_small_scenery( + const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, uint8_t* outQuadrant, + colour_t* outPrimaryColour, colour_t* outSecondaryColour, Direction* outRotation) +{ + rct_window* w = window_find_by_class(WC_SCENERY); + + if (w == nullptr) { - case SCENERY_TYPE_SMALL: + gridPos.setNull(); + return; + } + + auto screenPos = sourceScreenPos; + uint16_t maxPossibleHeight = (std::numeric_limits::max() - 32) * ZoomLevel::max(); + bool can_raise_item = false; + + rct_scenery_entry* scenery = get_small_scenery_entry(sceneryIndex); + maxPossibleHeight -= scenery->small_scenery.height; + if (scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_STACKABLE)) + { + can_raise_item = true; + } + + sub_6E1F34_update_screen_coords_and_buttons_pressed(can_raise_item, screenPos); + + // Small scenery + if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_FULL_TILE)) + { + uint8_t quadrant = 0; + + // If CTRL not pressed + if (!gSceneryCtrlPressed) { - // Small scenery - rct_scenery_entry* scenery = get_small_scenery_entry(selection.EntryIndex); - if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_FULL_TILE)) + auto gridCoords = screen_get_map_xy_quadrant(screenPos, &quadrant); + if (!gridCoords) { - uint8_t quadrant = 0; - - // If CTRL not pressed - if (!gSceneryCtrlPressed) - { - auto gridCoords = screen_get_map_xy_quadrant(screenPos, &quadrant); - if (!gridCoords) - { - gridPos.setNull(); - return; - } - gridPos = *gridCoords; - - gSceneryPlaceZ = 0; - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - auto* surfaceElement = map_get_surface_element_at(gridPos); - - if (surfaceElement == nullptr) - { - gridPos.setNull(); - return; - } - - int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; - z += gSceneryShiftPressZOffset; - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - } - else - { - int16_t z = gSceneryCtrlPressZ; - - auto mapCoords = screen_get_map_xy_quadrant_with_z(screenPos, z, &quadrant); - if (!mapCoords) - { - gridPos.setNull(); - return; - } - gridPos = *mapCoords; - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - z += gSceneryShiftPressZOffset; - } - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - - if (gridPos.isNull()) - return; - - uint8_t rotation = gWindowSceneryRotation; - - if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_ROTATABLE)) - { - rotation = util_rand() & 0xFF; - } - - rotation -= get_current_rotation(); - rotation &= 0x3; - - // Also places it in lower but think thats for clobbering - *parameter_1 = selection.EntryIndex << 8; - *parameter_2 = (quadrant ^ (1 << 1)) | (gWindowSceneryPrimaryColour << 8); - *parameter_3 = rotation | (gWindowScenerySecondaryColour << 16); - - if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off) - { - virtual_floor_set_height(gSceneryPlaceZ); - } - + gridPos.setNull(); return; } + gridPos = *gridCoords; - // If CTRL not pressed - if (!gSceneryCtrlPressed) + gSceneryPlaceZ = 0; + + // If SHIFT pressed + if (gSceneryShiftPressed) { - auto flags = VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER; + auto* surfaceElement = map_get_surface_element_at(gridPos); - auto info = get_map_coordinates_from_pos(screenPos, flags); - gridPos = info.Loc; - - if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE) + if (surfaceElement == nullptr) { gridPos.setNull(); return; } - // If CTRL and SHIFT not pressed - gSceneryPlaceZ = 0; - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - auto surfaceElement = map_get_surface_element_at(gridPos); - - if (surfaceElement == nullptr) - { - gridPos.setNull(); - return; - } - - int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; - z += gSceneryShiftPressZOffset; - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - } - else - { - int16_t z = gSceneryCtrlPressZ; - auto coords = screen_get_map_xy_with_z(screenPos, z); - if (coords) - { - gridPos = *coords; - } - else - { - gridPos.setNull(); - } - // If SHIFT pressed - if (gSceneryShiftPressed) - { - z += gSceneryShiftPressZOffset; - } + int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; + z += gSceneryShiftPressZOffset; z = std::clamp(z, 16, maxPossibleHeight); gSceneryPlaceZ = z; } + } + else + { + int16_t z = gSceneryCtrlPressZ; - if (gridPos.isNull()) - return; - - gridPos = gridPos.ToTileStart(); - uint8_t rotation = gWindowSceneryRotation; - - if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_ROTATABLE)) + auto mapCoords = screen_get_map_xy_quadrant_with_z(screenPos, z, &quadrant); + if (!mapCoords) { - rotation = util_rand() & 0xFF; + gridPos.setNull(); + return; + } + gridPos = *mapCoords; + + // If SHIFT pressed + if (gSceneryShiftPressed) + { + z += gSceneryShiftPressZOffset; } - rotation -= get_current_rotation(); - rotation &= 0x3; + z = std::clamp(z, 16, maxPossibleHeight); - // Also places it in lower but think thats for clobbering - *parameter_1 = selection.EntryIndex << 8; - *parameter_2 = 0 | (gWindowSceneryPrimaryColour << 8); - *parameter_3 = rotation | (gWindowScenerySecondaryColour << 16); - break; + gSceneryPlaceZ = z; } - case SCENERY_TYPE_PATH_ITEM: + + if (gridPos.isNull()) + return; + + uint8_t rotation = gWindowSceneryRotation; + + if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_ROTATABLE)) { - // Path bits - auto flags = VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_FOOTPATH_ITEM; + rotation = util_rand() & 0xFF; + } - auto info = get_map_coordinates_from_pos(screenPos, flags); - gridPos = info.Loc; + rotation -= get_current_rotation(); + rotation &= 0x3; - if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE) + if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off) + { + virtual_floor_set_height(gSceneryPlaceZ); + } + + *outQuadrant = quadrant ^ 2; + *outPrimaryColour = gWindowSceneryPrimaryColour; + *outSecondaryColour = gWindowScenerySecondaryColour; + *outRotation = rotation; + + return; + } + + // If CTRL not pressed + if (!gSceneryCtrlPressed) + { + auto flags = VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER; + + auto info = get_map_coordinates_from_pos(screenPos, flags); + gridPos = info.Loc; + + if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE) + { + gridPos.setNull(); + return; + } + + // If CTRL and SHIFT not pressed + gSceneryPlaceZ = 0; + + // If SHIFT pressed + if (gSceneryShiftPressed) + { + auto surfaceElement = map_get_surface_element_at(gridPos); + + if (surfaceElement == nullptr) { gridPos.setNull(); return; } - *parameter_1 = info.Element->AsPath()->GetSlopeDirection() << 8; - if (info.Element->AsPath()->IsSloped()) - *parameter_1 |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED << 8; - *parameter_2 = info.Element->base_height; - *parameter_2 |= (info.Element->AsPath()->GetSurfaceEntryIndex() << 8); - if (info.Element->AsPath()->IsQueue()) - { - *parameter_2 |= LOCATION_NULL; - } - *parameter_3 = selection.EntryIndex + 1; - break; + int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; + z += gSceneryShiftPressZOffset; + + z = std::clamp(z, 16, maxPossibleHeight); + + gSceneryPlaceZ = z; } - case SCENERY_TYPE_WALL: + } + else + { + int16_t z = gSceneryCtrlPressZ; + auto coords = screen_get_map_xy_with_z(screenPos, z); + if (coords) { - // Walls - uint8_t cl; - // If CTRL not pressed - if (!gSceneryCtrlPressed) - { - auto gridCoords = screen_get_map_xy_side(screenPos, &cl); - if (!gridCoords) - { - gridPos.setNull(); - return; - } - gridPos = *gridCoords; - - gSceneryPlaceZ = 0; - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - auto* surfaceElement = map_get_surface_element_at(gridPos); - - if (surfaceElement == nullptr) - { - gridPos.setNull(); - return; - } - - int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; - z += gSceneryShiftPressZOffset; - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - } - else - { - int16_t z = gSceneryCtrlPressZ; - auto mapCoords = screen_get_map_xy_side_with_z(screenPos, z, &cl); - if (!mapCoords) - { - gridPos.setNull(); - return; - } - gridPos = *mapCoords; - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - z += gSceneryShiftPressZOffset; - } - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - - if (gridPos.isNull()) - return; - - _secondaryColour = gWindowScenerySecondaryColour; - _tertiaryColour = gWindowSceneryTertiaryColour; - // Also places it in lower but think thats for clobbering - *parameter_1 = selection.EntryIndex << 8; - *parameter_2 = cl | (gWindowSceneryPrimaryColour << 8); - *parameter_3 = 0; - break; + gridPos = *coords; } - case SCENERY_TYPE_LARGE: + else { - // Large scenery - // If CTRL not pressed - if (!gSceneryCtrlPressed) - { - const CoordsXY mapCoords = ViewportInteractionGetTileStartAtCursor(screenPos); - gridPos = mapCoords; - - if (gridPos.isNull()) - return; - - gSceneryPlaceZ = 0; - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - auto* surfaceElement = map_get_surface_element_at(gridPos); - - if (surfaceElement == nullptr) - { - gridPos.setNull(); - return; - } - - int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; - z += gSceneryShiftPressZOffset; - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - } - else - { - int16_t z = gSceneryCtrlPressZ; - auto coords = screen_get_map_xy_with_z(screenPos, z); - if (coords) - { - gridPos = *coords; - } - else - { - gridPos.setNull(); - } - - // If SHIFT pressed - if (gSceneryShiftPressed) - { - z += gSceneryShiftPressZOffset; - } - - z = std::clamp(z, 16, maxPossibleHeight); - - gSceneryPlaceZ = z; - } - - if (gridPos.isNull()) - return; - - gridPos = gridPos.ToTileStart(); - - uint8_t rotation = gWindowSceneryRotation; - rotation -= get_current_rotation(); - rotation &= 0x3; - - *parameter_1 = (rotation << 8); - *parameter_2 = gWindowSceneryPrimaryColour | (gWindowScenerySecondaryColour << 8); - *parameter_3 = selection.EntryIndex; - break; + gridPos.setNull(); } - case SCENERY_TYPE_BANNER: + // If SHIFT pressed + if (gSceneryShiftPressed) { - // Banner - auto flags = VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_FOOTPATH_ITEM; + z += gSceneryShiftPressZOffset; + } - auto info = get_map_coordinates_from_pos(screenPos, flags); - gridPos = info.Loc; + z = std::clamp(z, 16, maxPossibleHeight); - if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE) + gSceneryPlaceZ = z; + } + + if (gridPos.isNull()) + return; + + gridPos = gridPos.ToTileStart(); + uint8_t rotation = gWindowSceneryRotation; + + if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_ROTATABLE)) + { + rotation = util_rand() & 0xFF; + } + + rotation -= get_current_rotation(); + rotation &= 0x3; + + if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off) + { + virtual_floor_set_height(gSceneryPlaceZ); + } + + *outQuadrant = 0; + *outPrimaryColour = gWindowSceneryPrimaryColour; + *outSecondaryColour = gWindowScenerySecondaryColour; + *outRotation = rotation; +} + +static void sub_6E1F34_path_item( + const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, int32_t* outZ) +{ + rct_window* w = window_find_by_class(WC_SCENERY); + + if (w == nullptr) + { + gridPos.setNull(); + return; + } + + auto screenPos = sourceScreenPos; + sub_6E1F34_update_screen_coords_and_buttons_pressed(false, screenPos); + + // Path bits + auto flags = VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_FOOTPATH_ITEM; + + auto info = get_map_coordinates_from_pos(screenPos, flags); + gridPos = info.Loc; + + if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE) + { + gridPos.setNull(); + return; + } + + if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off) + { + virtual_floor_set_height(gSceneryPlaceZ); + } + + *outZ = info.Element->GetBaseZ(); +} + +static void sub_6E1F34_wall( + const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, colour_t* outPrimaryColour, + uint8_t* outEdges) +{ + rct_window* w = window_find_by_class(WC_SCENERY); + + if (w == nullptr) + { + gridPos.setNull(); + return; + } + + auto screenPos = sourceScreenPos; + uint16_t maxPossibleHeight = (std::numeric_limits::max() - 32) * ZoomLevel::max(); + + rct_scenery_entry* scenery_entry = get_wall_entry(sceneryIndex); + if (scenery_entry) + { + maxPossibleHeight -= scenery_entry->wall.height; + } + + sub_6E1F34_update_screen_coords_and_buttons_pressed(true, screenPos); + + // Walls + uint8_t edge; + // If CTRL not pressed + if (!gSceneryCtrlPressed) + { + auto gridCoords = screen_get_map_xy_side(screenPos, &edge); + if (!gridCoords) + { + gridPos.setNull(); + return; + } + gridPos = *gridCoords; + + gSceneryPlaceZ = 0; + + // If SHIFT pressed + if (gSceneryShiftPressed) + { + auto* surfaceElement = map_get_surface_element_at(gridPos); + + if (surfaceElement == nullptr) { gridPos.setNull(); return; } - uint8_t rotation = gWindowSceneryRotation; - rotation -= get_current_rotation(); - rotation &= 0x3; + int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; + z += gSceneryShiftPressZOffset; - int16_t z = info.Element->base_height; + z = std::clamp(z, 16, maxPossibleHeight); - if (info.Element->AsPath()->IsSloped()) + gSceneryPlaceZ = z; + } + } + else + { + int16_t z = gSceneryCtrlPressZ; + auto mapCoords = screen_get_map_xy_side_with_z(screenPos, z, &edge); + if (!mapCoords) + { + gridPos.setNull(); + return; + } + gridPos = *mapCoords; + + // If SHIFT pressed + if (gSceneryShiftPressed) + { + z += gSceneryShiftPressZOffset; + } + + z = std::clamp(z, 16, maxPossibleHeight); + + gSceneryPlaceZ = z; + } + + if (gridPos.isNull()) + return; + + _secondaryColour = gWindowScenerySecondaryColour; + _tertiaryColour = gWindowSceneryTertiaryColour; + + if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off) + { + virtual_floor_set_height(gSceneryPlaceZ); + } + + *outPrimaryColour = gWindowSceneryPrimaryColour; + *outEdges = edge; +} + +static void sub_6E1F34_large_scenery( + const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, colour_t* outPrimaryColour, + colour_t* outSecondaryColour, Direction* outDirection) +{ + rct_window* w = window_find_by_class(WC_SCENERY); + + if (w == nullptr) + { + gridPos.setNull(); + return; + } + + auto screenPos = sourceScreenPos; + uint16_t maxPossibleHeight = (std::numeric_limits::max() - 32) * ZoomLevel::max(); + + rct_scenery_entry* scenery_entry = get_large_scenery_entry(sceneryIndex); + if (scenery_entry) + { + int16_t maxClearZ = 0; + for (int32_t i = 0; scenery_entry->large_scenery.tiles[i].x_offset != -1; ++i) + { + maxClearZ = std::max(maxClearZ, scenery_entry->large_scenery.tiles[i].z_clearance); + } + maxPossibleHeight = std::max(0, maxPossibleHeight - maxClearZ); + } + + sub_6E1F34_update_screen_coords_and_buttons_pressed(true, screenPos); + + // Large scenery + // If CTRL not pressed + if (!gSceneryCtrlPressed) + { + const CoordsXY mapCoords = ViewportInteractionGetTileStartAtCursor(screenPos); + gridPos = mapCoords; + + if (gridPos.isNull()) + return; + + gSceneryPlaceZ = 0; + + // If SHIFT pressed + if (gSceneryShiftPressed) + { + auto* surfaceElement = map_get_surface_element_at(gridPos); + + if (surfaceElement == nullptr) { - if (rotation != direction_reverse(info.Element->AsPath()->GetSlopeDirection())) - { - z += 2; - } + gridPos.setNull(); + return; } - z /= 2; + int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0; + z += gSceneryShiftPressZOffset; - // Also places it in lower but think thats for clobbering - *parameter_1 = selection.EntryIndex << 8; - *parameter_2 = z | (rotation << 8); - *parameter_3 = gWindowSceneryPrimaryColour; - break; + z = std::clamp(z, 16, maxPossibleHeight); + + gSceneryPlaceZ = z; + } + } + else + { + int16_t z = gSceneryCtrlPressZ; + auto coords = screen_get_map_xy_with_z(screenPos, z); + if (coords) + { + gridPos = *coords; + } + else + { + gridPos.setNull(); + } + + // If SHIFT pressed + if (gSceneryShiftPressed) + { + z += gSceneryShiftPressZOffset; + } + + z = std::clamp(z, 16, maxPossibleHeight); + + gSceneryPlaceZ = z; + } + + if (gridPos.isNull()) + return; + + gridPos = gridPos.ToTileStart(); + + Direction rotation = gWindowSceneryRotation; + rotation -= get_current_rotation(); + rotation &= 0x3; + + if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off) + { + virtual_floor_set_height(gSceneryPlaceZ); + } + + *outPrimaryColour = gWindowSceneryPrimaryColour; + *outSecondaryColour = gWindowScenerySecondaryColour; + *outDirection = rotation; +} + +static void sub_6E1F34_banner( + const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, int32_t* outZ, + Direction* outDirection) +{ + rct_window* w = window_find_by_class(WC_SCENERY); + + if (w == nullptr) + { + gridPos.setNull(); + return; + } + + auto screenPos = sourceScreenPos; + sub_6E1F34_update_screen_coords_and_buttons_pressed(false, screenPos); + + // Banner + auto flags = VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_FOOTPATH_ITEM; + + auto info = get_map_coordinates_from_pos(screenPos, flags); + gridPos = info.Loc; + + if (info.SpriteType == VIEWPORT_INTERACTION_ITEM_NONE) + { + gridPos.setNull(); + return; + } + + uint8_t rotation = gWindowSceneryRotation; + rotation -= get_current_rotation(); + rotation &= 0x3; + + auto z = info.Element->GetBaseZ(); + + if (info.Element->AsPath()->IsSloped()) + { + if (rotation != direction_reverse(info.Element->AsPath()->GetSlopeDirection())) + { + z += (2 * COORDS_Z_STEP); } } @@ -1654,58 +1690,9 @@ static void sub_6E1F34( { virtual_floor_set_height(gSceneryPlaceZ); } -} -static void sub_6E1F34_small_scenery( - const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, uint8_t* outQuadrant, - colour_t* outPrimaryColour, colour_t* outSecondaryColour) -{ - uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0; - sub_6E1F34(screenCoords, { SCENERY_TYPE_SMALL, sceneryIndex }, gridPos, ¶meter1, ¶meter2, ¶meter3); - - *outQuadrant = parameter2 & 0xFF; - *outPrimaryColour = (parameter2 >> 8) & 0xFF; - *outSecondaryColour = (parameter3 >> 16) & 0xFF; -} - -static void sub_6E1F34_path_item(const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, int32_t* outZ) -{ - uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0; - sub_6E1F34(screenCoords, { SCENERY_TYPE_PATH_ITEM, sceneryIndex }, gridPos, ¶meter1, ¶meter2, ¶meter3); - - *outZ = (parameter2 & 0xFF) * COORDS_Z_STEP; -} - -static void sub_6E1F34_wall( - const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, colour_t* outPrimaryColour, uint8_t* outEdges) -{ - uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0; - sub_6E1F34(screenCoords, { SCENERY_TYPE_WALL, sceneryIndex }, gridPos, ¶meter1, ¶meter2, ¶meter3); - - *outPrimaryColour = (parameter2 >> 8) & 0xFF; - *outEdges = parameter2 & 0xFF; -} - -static void sub_6E1F34_large_scenery( - const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, colour_t* outPrimaryColour, - colour_t* outSecondaryColour, Direction* outDirection) -{ - uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0; - sub_6E1F34(screenCoords, { SCENERY_TYPE_LARGE, sceneryIndex }, gridPos, ¶meter1, ¶meter2, ¶meter3); - - *outPrimaryColour = parameter2 & 0xFF; - *outSecondaryColour = (parameter2 >> 8) & 0xFF; - *outDirection = (parameter1 & 0xFF00) >> 8; -} - -static void sub_6E1F34_banner( - const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, int32_t* outZ, Direction* outDirection) -{ - uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0; - sub_6E1F34(screenCoords, { SCENERY_TYPE_BANNER, sceneryIndex }, gridPos, ¶meter1, ¶meter2, ¶meter3); - - *outDirection = (parameter2 >> 8) & 0xFF; - *outZ = (parameter2 & 0xFF) * COORDS_Z_PER_TINY_Z; + *outDirection = rotation; + *outZ = z; } /** @@ -1742,7 +1729,9 @@ static void window_top_toolbar_scenery_tool_down(const ScreenCoordsXY& windowPos uint8_t quadrant; colour_t primaryColour; colour_t secondaryColour; - sub_6E1F34_small_scenery(windowPos, selectedScenery, gridPos, &quadrant, &primaryColour, &secondaryColour); + Direction rotation; + sub_6E1F34_small_scenery( + windowPos, selectedScenery, gridPos, &quadrant, &primaryColour, &secondaryColour, &rotation); if (gridPos.isNull()) return; @@ -2472,172 +2461,143 @@ static void top_toolbar_tool_update_water(const ScreenCoordsXY& screenPos) * On failure returns MONEY32_UNDEFINED * On success places ghost scenery and returns cost to place proper */ -static money32 try_place_ghost_scenery( - CoordsXY map_tile, uint32_t parameter_1, uint32_t parameter_2, uint32_t parameter_3, uint8_t scenery_type, - ObjectEntryIndex entryIndex) +static money32 try_place_ghost_small_scenery( + CoordsXYZD loc, uint8_t quadrant, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour) { scenery_remove_ghost_tool_placement(); - money32 cost = 0; - TileElement* tileElement; + // 6e252b + auto smallSceneryPlaceAction = SmallSceneryPlaceAction(loc, quadrant, entryIndex, primaryColour, secondaryColour); + smallSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); + auto res = GameActions::Execute(&smallSceneryPlaceAction); + auto sspar = dynamic_cast(res.get()); + if (sspar == nullptr || res->Error != GameActions::Status::Ok) + return MONEY32_UNDEFINED; - switch (scenery_type) + gSceneryPlaceRotation = loc.direction; + gSceneryPlaceObject.SceneryType = SCENERY_TYPE_SMALL; + gSceneryPlaceObject.EntryIndex = entryIndex; + + TileElement* tileElement = sspar->tileElement; + gSceneryGhostPosition = { loc, tileElement->GetBaseZ() }; + gSceneryQuadrant = tileElement->AsSmallScenery()->GetSceneryQuadrant(); + if (sspar->GroundFlags & ELEMENT_IS_UNDERGROUND) { - case SCENERY_TYPE_SMALL: - { - // Small Scenery - // 6e252b - uint8_t quadrant = parameter_2 & 0xFF; - uint8_t primaryColour = (parameter_2 >> 8) & 0xFF; - uint8_t secondaryColour = (parameter_3 >> 16) & 0xFF; - uint8_t rotation = parameter_3 & 0xFF; - auto smallSceneryPlaceAction = SmallSceneryPlaceAction( - { map_tile.x, map_tile.y, gSceneryPlaceZ, rotation }, quadrant, entryIndex, primaryColour, secondaryColour); - smallSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); - auto res = GameActions::Execute(&smallSceneryPlaceAction); - auto sspar = dynamic_cast(res.get()); - if (sspar == nullptr || res->Error != GameActions::Status::Ok) - return MONEY32_UNDEFINED; - - gSceneryPlaceRotation = static_cast(parameter_3 & 0xFF); - gSceneryPlaceObject.SceneryType = SCENERY_TYPE_SMALL; - gSceneryPlaceObject.EntryIndex = entryIndex; - - tileElement = sspar->tileElement; - gSceneryGhostPosition = { map_tile, tileElement->GetBaseZ() }; - gSceneryQuadrant = tileElement->AsSmallScenery()->GetSceneryQuadrant(); - if (sspar->GroundFlags & ELEMENT_IS_UNDERGROUND) - { - // Set underground on - viewport_set_visibility(4); - } - else - { - // Set underground off - viewport_set_visibility(5); - } - - gSceneryGhostType |= SCENERY_GHOST_FLAG_0; - cost = res->Cost; - break; - } - case SCENERY_TYPE_PATH_ITEM: - { - // Path Bits - // 6e265b - int32_t z = (parameter_2 & 0xFF) * COORDS_Z_STEP; - auto footpathAdditionPlaceAction = FootpathAdditionPlaceAction({ map_tile.x, map_tile.y, z }, entryIndex + 1); - footpathAdditionPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); - footpathAdditionPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) { - if (result->Error != GameActions::Status::Ok) - { - return; - } - gSceneryGhostPosition = { map_tile, static_cast((parameter_2 & 0xFF) * COORDS_Z_STEP) }; - gSceneryGhostType |= SCENERY_GHOST_FLAG_1; - }); - auto res = GameActions::Execute(&footpathAdditionPlaceAction); - if (res->Error != GameActions::Status::Ok) - return MONEY32_UNDEFINED; - - cost = res->Cost; - break; - } - case SCENERY_TYPE_WALL: - { - // Walls - // 6e26b0 - auto primaryColour = (parameter_2 >> 8) & 0xFF; - auto edges = parameter_2 & 0xFF; - auto wallPlaceAction = WallPlaceAction( - entryIndex, { map_tile.x, map_tile.y, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour, - _tertiaryColour); - wallPlaceAction.SetFlags( - GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); - wallPlaceAction.SetCallback([=](const GameAction* ga, const WallPlaceActionResult* result) { - if (result->Error != GameActions::Status::Ok) - return; - - gSceneryGhostPosition = { map_tile, result->tileElement->GetBaseZ() }; - gSceneryGhostWallRotation = edges; - - gSceneryGhostType |= SCENERY_GHOST_FLAG_2; - }); - - auto res = GameActions::Execute(&wallPlaceAction); - if (res->Error != GameActions::Status::Ok) - return MONEY32_UNDEFINED; - cost = res->Cost; - break; - } - case SCENERY_TYPE_LARGE: - { - // Large Scenery - // 6e25a7 - auto primaryColour = parameter_2 & 0xFF; - auto secondaryColour = (parameter_2 >> 8) & 0xFF; - uint8_t direction = (parameter_1 & 0xFF00) >> 8; - CoordsXYZD loc = { map_tile.x, map_tile.y, gSceneryPlaceZ, direction }; - - auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, entryIndex, primaryColour, secondaryColour); - sceneryPlaceAction.SetFlags( - GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); - auto res = GameActions::Execute(&sceneryPlaceAction); - auto lspar = dynamic_cast(res.get()); - if (lspar == nullptr || res->Error != GameActions::Status::Ok) - return MONEY32_UNDEFINED; - - gSceneryPlaceRotation = loc.direction; - - tileElement = lspar->tileElement; - gSceneryGhostPosition = { map_tile, tileElement->GetBaseZ() }; - - if (lspar->GroundFlags & ELEMENT_IS_UNDERGROUND) - { - // Set underground on - viewport_set_visibility(4); - } - else - { - // Set underground off - viewport_set_visibility(5); - } - - gSceneryGhostType |= SCENERY_GHOST_FLAG_3; - cost = res->Cost; - break; - } - case SCENERY_TYPE_BANNER: - { - // Banners - // 6e2612 - uint8_t direction = (parameter_2 >> 8) & 0xFF; - int32_t z = (parameter_2 & 0xFF) * COORDS_Z_PER_TINY_Z; - CoordsXYZD loc{ map_tile.x, map_tile.y, z, direction }; - auto primaryColour = gWindowSceneryPrimaryColour; - auto bannerIndex = create_new_banner(0); - if (bannerIndex == BANNER_INDEX_NULL) - { - // Silently fail as this is just for the ghost - break; - } - auto bannerPlaceAction = BannerPlaceAction(loc, entryIndex, bannerIndex, primaryColour); - bannerPlaceAction.SetFlags( - GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); - auto res = GameActions::Execute(&bannerPlaceAction); - if (res->Error != GameActions::Status::Ok) - return MONEY32_UNDEFINED; - - gSceneryGhostPosition = loc; - gSceneryGhostPosition.z += PATH_HEIGHT_STEP; - gSceneryPlaceRotation = direction; - gSceneryGhostType |= SCENERY_GHOST_FLAG_4; - cost = res->Cost; - break; - } + // Set underground on + viewport_set_visibility(4); + } + else + { + // Set underground off + viewport_set_visibility(5); } - return cost; + gSceneryGhostType |= SCENERY_GHOST_FLAG_0; + return res->Cost; +} + +static money32 try_place_ghost_path_addition(CoordsXYZ loc, ObjectEntryIndex entryIndex) +{ + scenery_remove_ghost_tool_placement(); + + // 6e265b + auto footpathAdditionPlaceAction = FootpathAdditionPlaceAction(loc, entryIndex + 1); + footpathAdditionPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); + footpathAdditionPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) { + if (result->Error != GameActions::Status::Ok) + { + return; + } + gSceneryGhostPosition = loc; + gSceneryGhostType |= SCENERY_GHOST_FLAG_1; + }); + auto res = GameActions::Execute(&footpathAdditionPlaceAction); + if (res->Error != GameActions::Status::Ok) + return MONEY32_UNDEFINED; + + return res->Cost; +} + +static money32 try_place_ghost_wall(CoordsXYZ loc, uint8_t edge, ObjectEntryIndex entryIndex, colour_t primaryColour) +{ + scenery_remove_ghost_tool_placement(); + + // 6e26b0 + auto wallPlaceAction = WallPlaceAction(entryIndex, loc, edge, primaryColour, _secondaryColour, _tertiaryColour); + wallPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); + wallPlaceAction.SetCallback([=](const GameAction* ga, const WallPlaceActionResult* result) { + if (result->Error != GameActions::Status::Ok) + return; + + gSceneryGhostPosition = { loc, result->tileElement->GetBaseZ() }; + gSceneryGhostWallRotation = edge; + + gSceneryGhostType |= SCENERY_GHOST_FLAG_2; + }); + + auto res = GameActions::Execute(&wallPlaceAction); + if (res->Error != GameActions::Status::Ok) + return MONEY32_UNDEFINED; + + return res->Cost; +} + +static money32 try_place_ghost_large_scenery( + CoordsXYZD loc, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour) +{ + scenery_remove_ghost_tool_placement(); + + // 6e25a7 + auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, entryIndex, primaryColour, secondaryColour); + sceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); + auto res = GameActions::Execute(&sceneryPlaceAction); + auto lspar = dynamic_cast(res.get()); + if (lspar == nullptr || res->Error != GameActions::Status::Ok) + return MONEY32_UNDEFINED; + + gSceneryPlaceRotation = loc.direction; + + TileElement* tileElement = lspar->tileElement; + gSceneryGhostPosition = { loc, tileElement->GetBaseZ() }; + + if (lspar->GroundFlags & ELEMENT_IS_UNDERGROUND) + { + // Set underground on + viewport_set_visibility(4); + } + else + { + // Set underground off + viewport_set_visibility(5); + } + + gSceneryGhostType |= SCENERY_GHOST_FLAG_3; + return res->Cost; +} + +static money32 try_place_ghost_banner(CoordsXYZD loc, ObjectEntryIndex entryIndex) +{ + scenery_remove_ghost_tool_placement(); + + // 6e2612 + auto primaryColour = gWindowSceneryPrimaryColour; + auto bannerIndex = create_new_banner(0); + if (bannerIndex == BANNER_INDEX_NULL) + { + // Silently fail as this is just for the ghost + return 0; + } + auto bannerPlaceAction = BannerPlaceAction(loc, entryIndex, bannerIndex, primaryColour); + bannerPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND); + auto res = GameActions::Execute(&bannerPlaceAction); + if (res->Error != GameActions::Status::Ok) + return MONEY32_UNDEFINED; + + gSceneryGhostPosition = loc; + gSceneryGhostPosition.z += PATH_HEIGHT_STEP; + gSceneryPlaceRotation = loc.direction; + gSceneryGhostType |= SCENERY_GHOST_FLAG_4; + return res->Cost; } /** @@ -2670,26 +2630,26 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) return; } - uint8_t sceneryType = selection.SceneryType; - uint16_t selectedScenery = selection.EntryIndex; - CoordsXY mapTile = {}; - uint32_t parameter1, parameter2, parameter3; - - sub_6E1F34(screenPos, selection, mapTile, ¶meter1, ¶meter2, ¶meter3); - - if (mapTile.isNull()) - { - scenery_remove_ghost_tool_placement(); - return; - } - - rct_scenery_entry* scenery; - uint8_t bl; money32 cost = 0; - switch (sceneryType) + switch (selection.SceneryType) { case SCENERY_TYPE_SMALL: + { + CoordsXY mapTile = {}; + uint8_t quadrant; + colour_t primaryColour, secondaryColour; + Direction rotation; + + sub_6E1F34_small_scenery( + screenPos, selection.EntryIndex, mapTile, &quadrant, &primaryColour, &secondaryColour, &rotation); + + if (mapTile.isNull()) + { + scenery_remove_ghost_tool_placement(); + return; + } + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; if (gWindowSceneryScatterEnabled) { @@ -2712,38 +2672,39 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) gMapSelectPositionB.y = mapTile.y; } - scenery = get_small_scenery_entry(selectedScenery); + rct_scenery_entry* scenery = get_small_scenery_entry(selection.EntryIndex); gMapSelectType = MAP_SELECT_TYPE_FULL; if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_FULL_TILE) && !gWindowSceneryScatterEnabled) { - gMapSelectType = MAP_SELECT_TYPE_QUARTER_0 + ((parameter2 & 0xFF) ^ 2); + gMapSelectType = MAP_SELECT_TYPE_QUARTER_0 + (quadrant ^ 2); } map_invalidate_selection_rect(); // If no change in ghost placement - if ((gSceneryGhostType & SCENERY_GHOST_FLAG_0) && mapTile == gSceneryGhostPosition - && (parameter2 & 0xFF) == _unkF64F0E && gSceneryPlaceZ == _unkF64F0A - && gSceneryPlaceObject.SceneryType == SCENERY_TYPE_SMALL && gSceneryPlaceObject.EntryIndex == selectedScenery) + if ((gSceneryGhostType & SCENERY_GHOST_FLAG_0) && mapTile == gSceneryGhostPosition && quadrant == _unkF64F0E + && gSceneryPlaceZ == _unkF64F0A && gSceneryPlaceObject.SceneryType == SCENERY_TYPE_SMALL + && gSceneryPlaceObject.EntryIndex == selection.EntryIndex) { return; } scenery_remove_ghost_tool_placement(); - _unkF64F0E = (parameter2 & 0xFF); + _unkF64F0E = quadrant; _unkF64F0A = gSceneryPlaceZ; - bl = 1; + uint8_t attemptsLeft = 1; if (gSceneryPlaceZ != 0 && gSceneryShiftPressed) { - bl = 20; + attemptsLeft = 20; } - for (; bl != 0; bl--) + for (; attemptsLeft != 0; attemptsLeft--) { - cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery); + cost = try_place_ghost_small_scenery( + { mapTile, gSceneryPlaceZ, rotation }, quadrant, selection.EntryIndex, primaryColour, secondaryColour); if (cost != MONEY32_UNDEFINED) break; @@ -2752,7 +2713,20 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) gSceneryPlaceCost = cost; break; + } case SCENERY_TYPE_PATH_ITEM: + { + CoordsXY mapTile = {}; + int32_t z; + + sub_6E1F34_path_item(screenPos, selection.EntryIndex, mapTile, &z); + + if (mapTile.isNull()) + { + scenery_remove_ghost_tool_placement(); + return; + } + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; gMapSelectPositionA.x = mapTile.x; gMapSelectPositionA.y = mapTile.y; @@ -2763,50 +2737,63 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) map_invalidate_selection_rect(); // If no change in ghost placement - if ((gSceneryGhostType & SCENERY_GHOST_FLAG_1) && mapTile == gSceneryGhostPosition - && static_cast(parameter2 & 0xFF) * COORDS_Z_STEP == gSceneryGhostPosition.z) + if ((gSceneryGhostType & SCENERY_GHOST_FLAG_1) && mapTile == gSceneryGhostPosition && z == gSceneryGhostPosition.z) { return; } scenery_remove_ghost_tool_placement(); - cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery); + cost = try_place_ghost_path_addition({ mapTile, z }, selection.EntryIndex); gSceneryPlaceCost = cost; break; + } case SCENERY_TYPE_WALL: + { + CoordsXY mapTile = {}; + colour_t primaryColour; + uint8_t edge; + + sub_6E1F34_wall(screenPos, selection.EntryIndex, mapTile, &primaryColour, &edge); + + if (mapTile.isNull()) + { + scenery_remove_ghost_tool_placement(); + return; + } + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; gMapSelectPositionA.x = mapTile.x; gMapSelectPositionA.y = mapTile.y; gMapSelectPositionB.x = mapTile.x; gMapSelectPositionB.y = mapTile.y; - gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + (parameter2 & 0xFF); + gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + edge; map_invalidate_selection_rect(); // If no change in ghost placement if ((gSceneryGhostType & SCENERY_GHOST_FLAG_2) && mapTile == gSceneryGhostPosition - && (parameter2 & 0xFF) == gSceneryGhostWallRotation && gSceneryPlaceZ == _unkF64F0A) + && edge == gSceneryGhostWallRotation && gSceneryPlaceZ == _unkF64F0A) { return; } scenery_remove_ghost_tool_placement(); - gSceneryGhostWallRotation = (parameter2 & 0xFF); + gSceneryGhostWallRotation = edge; _unkF64F0A = gSceneryPlaceZ; - bl = 1; + uint8_t attemptsLeft = 1; if (gSceneryPlaceZ != 0 && gSceneryShiftPressed) { - bl = 20; + attemptsLeft = 20; } cost = 0; - for (; bl != 0; bl--) + for (; attemptsLeft != 0; attemptsLeft--) { - cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery); + cost = try_place_ghost_wall({ mapTile, gSceneryPlaceZ }, edge, selection.EntryIndex, primaryColour); if (cost != MONEY32_UNDEFINED) break; @@ -2815,16 +2802,29 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) gSceneryPlaceCost = cost; break; + } case SCENERY_TYPE_LARGE: { - scenery = get_large_scenery_entry(selectedScenery); + CoordsXY mapTile = {}; + colour_t primaryColour, secondaryColour; + Direction direction; + + sub_6E1F34_large_scenery(screenPos, selection.EntryIndex, mapTile, &primaryColour, &secondaryColour, &direction); + + if (mapTile.isNull()) + { + scenery_remove_ghost_tool_placement(); + return; + } + + rct_scenery_entry* scenery = get_large_scenery_entry(selection.EntryIndex); gMapSelectionTiles.clear(); for (rct_large_scenery_tile* tile = scenery->large_scenery.tiles; tile->x_offset != static_cast(static_cast(0xFFFF)); tile++) { CoordsXY tileLocation = { tile->x_offset, tile->y_offset }; - auto rotatedTileCoords = tileLocation.Rotate((parameter1 >> 8) & 0xFF); + auto rotatedTileCoords = tileLocation.Rotate(direction); rotatedTileCoords.x += mapTile.x; rotatedTileCoords.y += mapTile.y; @@ -2837,7 +2837,8 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) // If no change in ghost placement if ((gSceneryGhostType & SCENERY_GHOST_FLAG_3) && mapTile == gSceneryGhostPosition && gSceneryPlaceZ == _unkF64F0A - && gSceneryPlaceObject.SceneryType == SCENERY_TYPE_LARGE && gSceneryPlaceObject.EntryIndex == selectedScenery) + && gSceneryPlaceObject.SceneryType == SCENERY_TYPE_LARGE + && gSceneryPlaceObject.EntryIndex == selection.EntryIndex) { return; } @@ -2845,29 +2846,43 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) scenery_remove_ghost_tool_placement(); gSceneryPlaceObject.SceneryType = SCENERY_TYPE_LARGE; - gSceneryPlaceObject.EntryIndex = selectedScenery; + gSceneryPlaceObject.EntryIndex = selection.EntryIndex; _unkF64F0A = gSceneryPlaceZ; - bl = 1; + uint8_t attemptsLeft = 1; if (gSceneryPlaceZ != 0 && gSceneryShiftPressed) { - bl = 20; + attemptsLeft = 20; } cost = 0; - for (; bl != 0; bl--) + for (; attemptsLeft != 0; attemptsLeft--) { - cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery); + cost = try_place_ghost_large_scenery( + { mapTile, gSceneryPlaceZ, direction }, selection.EntryIndex, primaryColour, secondaryColour); if (cost != MONEY32_UNDEFINED) break; - gSceneryPlaceZ += 8; + gSceneryPlaceZ += COORDS_Z_STEP; } gSceneryPlaceCost = cost; break; } case SCENERY_TYPE_BANNER: + { + CoordsXY mapTile = {}; + Direction direction; + int32_t z; + + sub_6E1F34_banner(screenPos, selection.EntryIndex, mapTile, &z, &direction); + + if (mapTile.isNull()) + { + scenery_remove_ghost_tool_placement(); + return; + } + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; gMapSelectPositionA.x = mapTile.x; gMapSelectPositionA.y = mapTile.y; @@ -2878,19 +2893,19 @@ static void top_toolbar_tool_update_scenery(const ScreenCoordsXY& screenPos) map_invalidate_selection_rect(); // If no change in ghost placement - if ((gSceneryGhostType & SCENERY_GHOST_FLAG_4) && mapTile == gSceneryGhostPosition - && static_cast(parameter2 & 0xFF) * COORDS_Z_STEP == gSceneryGhostPosition.z - && ((parameter2 >> 8) & 0xFF) == gSceneryPlaceRotation) + if ((gSceneryGhostType & SCENERY_GHOST_FLAG_4) && mapTile == gSceneryGhostPosition && z == gSceneryGhostPosition.z + && direction == gSceneryPlaceRotation) { return; } scenery_remove_ghost_tool_placement(); - cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery); + cost = try_place_ghost_banner({ mapTile, z, direction }, selection.EntryIndex); gSceneryPlaceCost = cost; break; + } } }