2016-05-04 19:24:41 +02:00
|
|
|
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
2014-09-28 00:48:42 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
|
|
*
|
2016-05-04 19:24:41 +02:00
|
|
|
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
|
|
|
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
2014-09-28 00:48:42 +02:00
|
|
|
*
|
|
|
|
* OpenRCT2 is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2016-05-04 19:24:41 +02:00
|
|
|
*
|
|
|
|
* A full copy of the GNU General Public License can be found in licence.txt
|
2014-09-28 00:48:42 +02:00
|
|
|
*****************************************************************************/
|
2016-05-04 19:24:41 +02:00
|
|
|
#pragma endregion
|
2014-09-28 00:48:42 +02:00
|
|
|
|
2014-10-06 18:36:58 +02:00
|
|
|
#include "../audio/audio.h"
|
2016-05-01 20:41:48 +02:00
|
|
|
#include "../cheats.h"
|
2014-10-06 18:36:58 +02:00
|
|
|
#include "../game.h"
|
2014-10-15 23:59:26 +02:00
|
|
|
#include "../input.h"
|
2016-05-01 20:41:48 +02:00
|
|
|
#include "../interface/themes.h"
|
2014-10-06 18:36:58 +02:00
|
|
|
#include "../interface/viewport.h"
|
|
|
|
#include "../interface/widget.h"
|
|
|
|
#include "../interface/window.h"
|
2014-10-15 23:59:26 +02:00
|
|
|
#include "../localisation/localisation.h"
|
|
|
|
#include "../ride/track.h"
|
2015-02-07 19:38:48 +01:00
|
|
|
#include "../ride/track_data.h"
|
2016-04-28 22:46:39 +02:00
|
|
|
#include "../ride/track_design.h"
|
2016-10-22 18:06:27 +02:00
|
|
|
#include "../ride/TrackDesignRepository.h"
|
2016-05-01 20:41:48 +02:00
|
|
|
#include "../sprites.h"
|
|
|
|
#include "../util/util.h"
|
2014-09-28 00:48:42 +02:00
|
|
|
|
2014-10-01 03:03:36 +02:00
|
|
|
#define TRACK_MINI_PREVIEW_WIDTH 168
|
|
|
|
#define TRACK_MINI_PREVIEW_HEIGHT 78
|
|
|
|
#define TRACK_MINI_PREVIEW_SIZE (TRACK_MINI_PREVIEW_WIDTH * TRACK_MINI_PREVIEW_HEIGHT)
|
|
|
|
|
2016-11-15 19:37:21 +01:00
|
|
|
#define PALETTE_INDEX_TRANSPARENT (0)
|
|
|
|
#define PALETTE_INDEX_PRIMARY_MID_DARK (248)
|
|
|
|
#define PALETTE_INDEX_PRIMARY_LIGHTEST (252)
|
|
|
|
|
2014-09-30 19:56:30 +02:00
|
|
|
enum {
|
|
|
|
WIDX_BACKGROUND,
|
|
|
|
WIDX_TITLE,
|
|
|
|
WIDX_CLOSE,
|
|
|
|
WIDX_ROTATE,
|
|
|
|
WIDX_MIRROR,
|
|
|
|
WIDX_SELECT_DIFFERENT_DESIGN,
|
|
|
|
WIDX_PRICE
|
|
|
|
};
|
|
|
|
|
|
|
|
static rct_widget window_track_place_widgets[] = {
|
|
|
|
{ WWT_FRAME, 0, 0, 199, 0, 123, 0xFFFFFFFF, STR_NONE },
|
2016-09-26 04:24:29 +02:00
|
|
|
{ WWT_CAPTION, 0, 1, 198, 1, 14, STR_STRING, STR_WINDOW_TITLE_TIP },
|
2014-09-30 19:56:30 +02:00
|
|
|
{ WWT_CLOSEBOX, 0, 187, 197, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
|
|
|
{ WWT_FLATBTN, 0, 173, 196, 83, 106, SPR_ROTATE_ARROW, STR_ROTATE_90_TIP },
|
2016-07-14 14:07:49 +02:00
|
|
|
{ WWT_FLATBTN, 0, 173, 196, 59, 82, SPR_MIRROR_ARROW, STR_MIRROR_IMAGE_TIP },
|
2014-09-30 19:56:30 +02:00
|
|
|
{ WWT_DROPDOWN_BUTTON, 0, 4, 195, 109, 120, STR_SELECT_A_DIFFERENT_DESIGN, STR_GO_BACK_TO_DESIGN_SELECTION_WINDOW_TIP },
|
|
|
|
{ WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, STR_NONE },
|
|
|
|
{ WIDGETS_END },
|
|
|
|
};
|
|
|
|
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_close(rct_window *w);
|
|
|
|
static void window_track_place_mouseup(rct_window *w, int widgetIndex);
|
2014-09-30 19:56:30 +02:00
|
|
|
static void window_track_place_update(rct_window *w);
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x, int y);
|
|
|
|
static void window_track_place_tooldown(rct_window* w, int widgetIndex, int x, int y);
|
|
|
|
static void window_track_place_toolabort(rct_window *w, int widgetIndex);
|
|
|
|
static void window_track_place_unknown14(rct_window *w);
|
|
|
|
static void window_track_place_invalidate(rct_window *w);
|
|
|
|
static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi);
|
|
|
|
|
|
|
|
static rct_window_event_list window_track_place_events = {
|
2014-09-30 19:56:30 +02:00
|
|
|
window_track_place_close,
|
|
|
|
window_track_place_mouseup,
|
2015-07-10 02:39:16 +02:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2014-09-30 19:56:30 +02:00
|
|
|
window_track_place_update,
|
2015-07-10 02:39:16 +02:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2014-09-30 19:56:30 +02:00
|
|
|
window_track_place_toolupdate,
|
|
|
|
window_track_place_tooldown,
|
2015-07-10 02:39:16 +02:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2014-09-30 19:56:30 +02:00
|
|
|
window_track_place_toolabort,
|
2015-07-10 02:39:16 +02:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2014-09-30 19:56:30 +02:00
|
|
|
window_track_place_unknown14,
|
2015-07-10 02:39:16 +02:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2015-05-29 18:04:53 +02:00
|
|
|
window_track_place_invalidate,
|
2014-09-30 19:56:30 +02:00
|
|
|
window_track_place_paint,
|
2015-07-10 02:39:16 +02:00
|
|
|
NULL
|
2014-09-30 19:56:30 +02:00
|
|
|
};
|
|
|
|
|
2014-10-01 03:03:36 +02:00
|
|
|
static uint8 *_window_track_place_mini_preview;
|
|
|
|
static sint16 _window_track_place_last_x;
|
|
|
|
static sint16 _window_track_place_last_y;
|
|
|
|
|
2016-05-05 21:27:56 +02:00
|
|
|
static uint8 _window_track_place_ride_index;
|
|
|
|
static bool _window_track_place_last_was_valid;
|
2014-10-01 03:03:36 +02:00
|
|
|
static sint16 _window_track_place_last_valid_x;
|
|
|
|
static sint16 _window_track_place_last_valid_y;
|
|
|
|
static sint16 _window_track_place_last_valid_z;
|
|
|
|
static money32 _window_track_place_last_cost;
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
static rct_track_td6 *_trackDesign;
|
|
|
|
|
2016-04-30 14:27:12 +02:00
|
|
|
static void window_track_place_clear_provisional();
|
|
|
|
static int window_track_place_get_base_z(int x, int y);
|
2016-04-30 20:55:13 +02:00
|
|
|
static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex);
|
2016-04-30 14:27:12 +02:00
|
|
|
|
|
|
|
static void window_track_place_clear_mini_preview();
|
2016-04-30 20:55:13 +02:00
|
|
|
static void window_track_place_draw_mini_preview(rct_track_td6 *td6);
|
|
|
|
static void window_track_place_draw_mini_preview_track(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max);
|
|
|
|
static void window_track_place_draw_mini_preview_maze(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max);
|
|
|
|
static rct_xy16 draw_mini_preview_get_pixel_position(sint16 x, sint16 y);
|
|
|
|
static bool draw_mini_preview_is_pixel_in_bounds(rct_xy16 pixel);
|
|
|
|
static uint8 *draw_mini_preview_get_pixel_ptr(rct_xy16 pixel);
|
2016-04-30 14:27:12 +02:00
|
|
|
|
2014-10-01 03:03:36 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006D182E
|
|
|
|
*/
|
|
|
|
static void window_track_place_clear_mini_preview()
|
|
|
|
{
|
2016-11-15 19:37:21 +01:00
|
|
|
memset(_window_track_place_mini_preview, PALETTE_INDEX_TRANSPARENT, TRACK_MINI_PREVIEW_SIZE);
|
2014-10-01 03:03:36 +02:00
|
|
|
}
|
|
|
|
|
2014-10-04 01:28:43 +02:00
|
|
|
#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y;
|
|
|
|
|
2014-09-28 00:48:42 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFCA0
|
|
|
|
*/
|
2016-05-01 23:46:08 +02:00
|
|
|
void window_track_place_open(const track_design_file_ref *tdFileRef)
|
2014-09-28 00:48:42 +02:00
|
|
|
{
|
2016-05-01 23:46:08 +02:00
|
|
|
rct_track_td6 *td6 = track_design_open(tdFileRef->path);
|
|
|
|
if (td6 == NULL) {
|
2016-04-30 14:27:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-01 23:46:08 +02:00
|
|
|
window_close_construction_windows();
|
|
|
|
|
2014-10-01 03:03:36 +02:00
|
|
|
_window_track_place_mini_preview = malloc(TRACK_MINI_PREVIEW_SIZE);
|
2014-09-28 00:48:42 +02:00
|
|
|
|
2016-05-01 23:46:08 +02:00
|
|
|
rct_window *w = window_create(
|
2015-06-13 23:16:14 +02:00
|
|
|
0,
|
|
|
|
29,
|
|
|
|
200,
|
|
|
|
124,
|
2015-07-10 02:39:16 +02:00
|
|
|
&window_track_place_events,
|
2015-06-13 23:16:14 +02:00
|
|
|
WC_TRACK_DESIGN_PLACE,
|
|
|
|
0
|
|
|
|
);
|
2014-09-30 19:56:30 +02:00
|
|
|
w->widgets = window_track_place_widgets;
|
2016-11-15 19:37:21 +01:00
|
|
|
w->enabled_widgets = 1 << WIDX_CLOSE
|
|
|
|
| 1 << WIDX_ROTATE
|
|
|
|
| 1 << WIDX_MIRROR
|
|
|
|
| 1 << WIDX_SELECT_DIFFERENT_DESIGN;
|
2014-09-28 00:48:42 +02:00
|
|
|
window_init_scroll_widgets(w);
|
|
|
|
tool_set(w, 6, 12);
|
2016-01-04 23:53:03 +01:00
|
|
|
gInputFlags |= INPUT_FLAG_6;
|
2014-09-28 00:48:42 +02:00
|
|
|
window_push_others_right(w);
|
|
|
|
show_gridlines();
|
2014-10-01 03:03:36 +02:00
|
|
|
_window_track_place_last_cost = MONEY32_UNDEFINED;
|
|
|
|
_window_track_place_last_x = 0xFFFF;
|
2016-04-15 21:56:48 +02:00
|
|
|
_currentTrackPieceDirection = (2 - get_current_rotation()) & 3;
|
2016-11-07 12:35:14 +01:00
|
|
|
|
|
|
|
window_track_place_clear_mini_preview();
|
2016-05-01 23:46:08 +02:00
|
|
|
window_track_place_draw_mini_preview(td6);
|
2016-11-13 20:17:49 +01:00
|
|
|
|
2016-05-01 23:46:08 +02:00
|
|
|
_trackDesign = td6;
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006D0119
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_close(rct_window *w)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
2014-10-01 03:03:36 +02:00
|
|
|
window_track_place_clear_provisional();
|
2014-09-30 19:56:30 +02:00
|
|
|
viewport_set_visibility(0);
|
2014-12-17 21:45:27 +01:00
|
|
|
map_invalidate_map_selection_tiles();
|
2016-05-14 01:54:13 +02:00
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
|
2014-09-30 19:56:30 +02:00
|
|
|
hide_gridlines();
|
2016-04-30 14:27:12 +02:00
|
|
|
SafeFree(_window_track_place_mini_preview);
|
2016-05-01 20:41:48 +02:00
|
|
|
track_design_dispose(_trackDesign);
|
|
|
|
_trackDesign = NULL;
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFEAC
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_mouseup(rct_window *w, int widgetIndex)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
|
|
|
switch (widgetIndex) {
|
|
|
|
case WIDX_CLOSE:
|
|
|
|
window_close(w);
|
|
|
|
break;
|
|
|
|
case WIDX_ROTATE:
|
2014-10-01 03:03:36 +02:00
|
|
|
window_track_place_clear_provisional();
|
2016-04-23 00:59:16 +02:00
|
|
|
_currentTrackPieceDirection = (_currentTrackPieceDirection + 1) & 3;
|
2014-09-30 19:56:30 +02:00
|
|
|
window_invalidate(w);
|
2014-10-01 03:03:36 +02:00
|
|
|
_window_track_place_last_x = 0xFFFF;
|
2016-04-30 20:55:13 +02:00
|
|
|
window_track_place_draw_mini_preview(_trackDesign);
|
2014-09-30 19:56:30 +02:00
|
|
|
break;
|
|
|
|
case WIDX_MIRROR:
|
2016-05-01 20:41:48 +02:00
|
|
|
track_design_mirror(_trackDesign);
|
2016-04-23 00:59:16 +02:00
|
|
|
_currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3;
|
2014-09-30 19:56:30 +02:00
|
|
|
window_invalidate(w);
|
2014-10-01 03:03:36 +02:00
|
|
|
_window_track_place_last_x = 0xFFFF;
|
2016-04-30 20:55:13 +02:00
|
|
|
window_track_place_draw_mini_preview(_trackDesign);
|
2014-09-30 19:56:30 +02:00
|
|
|
break;
|
|
|
|
case WIDX_SELECT_DIFFERENT_DESIGN:
|
|
|
|
window_close(w);
|
|
|
|
window_track_list_open(_window_track_list_item);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFCA0
|
|
|
|
*/
|
|
|
|
static void window_track_place_update(rct_window *w)
|
|
|
|
{
|
2016-01-04 23:53:03 +01:00
|
|
|
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
|
2016-04-15 19:26:47 +02:00
|
|
|
if (gCurrentToolWidget.window_classification != WC_TRACK_DESIGN_PLACE)
|
2014-09-30 19:56:30 +02:00
|
|
|
window_close(w);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFF2D
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x, int y)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
2015-07-10 02:39:16 +02:00
|
|
|
short mapX, mapY, mapZ;
|
2014-09-30 19:56:30 +02:00
|
|
|
|
2014-12-17 21:45:27 +01:00
|
|
|
map_invalidate_map_selection_tiles();
|
2016-05-14 01:54:13 +02:00
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
|
2014-10-01 03:03:36 +02:00
|
|
|
|
|
|
|
// Get the tool map position
|
2015-07-10 02:39:16 +02:00
|
|
|
sub_68A15E(x, y, &mapX, &mapY, NULL, NULL);
|
|
|
|
if (mapX == (short)0x8000) {
|
2014-10-01 03:03:36 +02:00
|
|
|
window_track_place_clear_provisional();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if tool map position has changed since last update
|
2015-07-10 02:39:16 +02:00
|
|
|
if (mapX == _window_track_place_last_x && mapY == _window_track_place_last_y) {
|
2016-04-30 20:55:13 +02:00
|
|
|
sub_6D01B3(_trackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, 0);
|
2014-10-01 03:03:36 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-30 23:32:47 +01:00
|
|
|
money32 cost = MONEY32_UNDEFINED;
|
2014-10-01 03:03:36 +02:00
|
|
|
|
|
|
|
// Get base Z position
|
2015-07-10 02:39:16 +02:00
|
|
|
mapZ = window_track_place_get_base_z(mapX, mapY);
|
2016-04-23 14:34:55 +02:00
|
|
|
if (game_is_not_paused() || gCheatsBuildInPauseMode) {
|
2014-10-01 03:03:36 +02:00
|
|
|
window_track_place_clear_provisional();
|
2015-10-20 20:16:30 +02:00
|
|
|
|
2014-10-01 03:03:36 +02:00
|
|
|
// Try increasing Z until a feasible placement is found
|
2016-11-30 23:32:47 +01:00
|
|
|
for (int i = 0; i < 7; i++) {
|
|
|
|
uint8 rideIndex;
|
2016-04-30 20:55:13 +02:00
|
|
|
window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 105, &cost, &rideIndex);
|
2014-10-01 03:03:36 +02:00
|
|
|
if (cost != MONEY32_UNDEFINED) {
|
2016-05-05 21:27:56 +02:00
|
|
|
_window_track_place_ride_index = rideIndex;
|
2015-07-10 02:39:16 +02:00
|
|
|
_window_track_place_last_valid_x = mapX;
|
|
|
|
_window_track_place_last_valid_y = mapY;
|
|
|
|
_window_track_place_last_valid_z = mapZ;
|
2016-05-05 21:27:56 +02:00
|
|
|
_window_track_place_last_was_valid = true;
|
2014-10-01 03:03:36 +02:00
|
|
|
break;
|
|
|
|
}
|
2015-07-10 02:39:16 +02:00
|
|
|
mapZ += 8;
|
2014-10-01 03:03:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 02:39:16 +02:00
|
|
|
_window_track_place_last_x = mapX;
|
|
|
|
_window_track_place_last_y = mapY;
|
2014-10-01 03:03:36 +02:00
|
|
|
if (cost != _window_track_place_last_cost) {
|
|
|
|
_window_track_place_last_cost = cost;
|
2014-10-16 03:02:43 +02:00
|
|
|
widget_invalidate(w, WIDX_PRICE);
|
2014-10-01 03:03:36 +02:00
|
|
|
}
|
2015-10-20 20:16:30 +02:00
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
sub_6D01B3(_trackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, mapZ);
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFF34
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_tooldown(rct_window* w, int widgetIndex, int x, int y)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
2014-10-03 18:50:09 +02:00
|
|
|
int i;
|
2015-07-10 02:39:16 +02:00
|
|
|
short mapX, mapY, mapZ;
|
2014-10-03 18:50:09 +02:00
|
|
|
money32 cost;
|
2014-10-03 19:15:20 +02:00
|
|
|
uint8 rideIndex;
|
2014-09-30 19:56:30 +02:00
|
|
|
|
2014-10-03 18:50:09 +02:00
|
|
|
window_track_place_clear_provisional();
|
2014-12-17 21:45:27 +01:00
|
|
|
map_invalidate_map_selection_tiles();
|
2016-05-14 01:54:13 +02:00
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
|
|
|
|
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
|
2014-10-03 18:50:09 +02:00
|
|
|
|
2015-07-10 02:39:16 +02:00
|
|
|
sub_68A15E(x, y, &mapX, &mapY, NULL, NULL);
|
|
|
|
if (mapX == (short)0x8000)
|
2014-10-03 18:50:09 +02:00
|
|
|
return;
|
2015-10-20 20:16:30 +02:00
|
|
|
|
2014-10-03 18:50:09 +02:00
|
|
|
// Try increasing Z until a feasible placement is found
|
2015-07-10 02:39:16 +02:00
|
|
|
mapZ = window_track_place_get_base_z(mapX, mapY);
|
2014-10-03 18:50:09 +02:00
|
|
|
for (i = 0; i < 7; i++) {
|
2016-09-03 15:22:03 +02:00
|
|
|
gDisableErrorWindowSound = true;
|
2016-04-30 20:55:13 +02:00
|
|
|
window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 1, &cost, &rideIndex);
|
2016-09-03 15:22:03 +02:00
|
|
|
gDisableErrorWindowSound = false;
|
2014-10-03 18:50:09 +02:00
|
|
|
|
|
|
|
if (cost != MONEY32_UNDEFINED) {
|
2014-10-16 03:02:43 +02:00
|
|
|
window_close_by_class(WC_ERROR);
|
2015-11-18 01:03:15 +01:00
|
|
|
audio_play_sound_at_location(SOUND_PLACE_ITEM, mapX, mapY, mapZ);
|
2014-10-03 18:50:09 +02:00
|
|
|
|
2016-04-15 21:29:07 +02:00
|
|
|
_currentRideIndex = rideIndex;
|
2016-05-02 03:40:56 +02:00
|
|
|
if (byte_F4414E & 1) {
|
2014-10-03 18:50:09 +02:00
|
|
|
window_ride_main_open(rideIndex);
|
|
|
|
window_close(w);
|
|
|
|
} else {
|
2014-11-04 22:39:03 +01:00
|
|
|
sub_6CC3FB(rideIndex);
|
2014-10-16 03:02:43 +02:00
|
|
|
w = window_find_by_class(WC_RIDE_CONSTRUCTION);
|
2014-11-11 21:51:25 +01:00
|
|
|
window_event_mouse_up_call(w, 29);
|
2014-10-03 18:50:09 +02:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if player did not have enough funds
|
2016-07-14 14:07:49 +02:00
|
|
|
if (gGameCommandErrorText == STR_NOT_ENOUGH_CASH_REQUIRES)
|
2014-10-03 18:50:09 +02:00
|
|
|
break;
|
|
|
|
|
2015-07-10 02:39:16 +02:00
|
|
|
mapZ += 8;
|
2014-10-03 18:50:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Unable to build track
|
2015-11-18 01:03:15 +01:00
|
|
|
audio_play_sound_at_location(SOUND_ERROR, mapX, mapY, mapZ);
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006D015C
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_toolabort(rct_window *w, int widgetIndex)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
2014-10-01 03:03:36 +02:00
|
|
|
window_track_place_clear_provisional();
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFF01
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_unknown14(rct_window *w)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
2016-04-30 20:55:13 +02:00
|
|
|
window_track_place_draw_mini_preview(_trackDesign);
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_invalidate(rct_window *w)
|
2015-05-29 18:04:53 +02:00
|
|
|
{
|
|
|
|
colour_scheme_update(w);
|
2016-11-07 12:35:14 +01:00
|
|
|
window_track_place_draw_mini_preview(_trackDesign);
|
2015-05-29 18:04:53 +02:00
|
|
|
}
|
|
|
|
|
2016-04-30 14:27:12 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006D017F
|
|
|
|
*/
|
|
|
|
static void window_track_place_clear_provisional()
|
|
|
|
{
|
|
|
|
if (_window_track_place_last_was_valid) {
|
|
|
|
sub_6D01B3(
|
2016-04-30 20:55:13 +02:00
|
|
|
_trackDesign,
|
2016-04-30 14:27:12 +02:00
|
|
|
PTD_OPERATION_CLEAR_OUTLINES,
|
2016-05-05 21:27:56 +02:00
|
|
|
_window_track_place_ride_index,
|
2016-04-30 14:27:12 +02:00
|
|
|
_window_track_place_last_valid_x,
|
|
|
|
_window_track_place_last_valid_y,
|
|
|
|
_window_track_place_last_valid_z
|
|
|
|
);
|
2016-05-05 21:27:56 +02:00
|
|
|
_window_track_place_last_was_valid = false;
|
2016-04-30 14:27:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006D17C6
|
|
|
|
*/
|
|
|
|
static int window_track_place_get_base_z(int x, int y)
|
|
|
|
{
|
|
|
|
rct_map_element *mapElement;
|
|
|
|
int z;
|
|
|
|
|
|
|
|
mapElement = map_get_surface_element_at(x >> 5, y >> 5);
|
|
|
|
z = mapElement->base_height * 8;
|
|
|
|
|
|
|
|
// Increase Z above slope
|
|
|
|
if (mapElement->properties.surface.slope & 0x0F) {
|
|
|
|
z += 16;
|
|
|
|
|
|
|
|
// Increase Z above double slope
|
|
|
|
if (mapElement->properties.surface.slope & 0x10)
|
|
|
|
z += 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increase Z above water
|
|
|
|
if (mapElement->properties.surface.terrain & 0x1F)
|
|
|
|
z = max(z, (mapElement->properties.surface.terrain & 0x1F) << 4);
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
return z + sub_6D01B3(_trackDesign, PTD_OPERATION_GET_PLACE_Z, 0, x, y, z);
|
2016-04-30 14:27:12 +02:00
|
|
|
}
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex)
|
2016-04-30 14:27:12 +02:00
|
|
|
{
|
|
|
|
int eax, ebx, ecx, edx, esi, edi, ebp;
|
|
|
|
money32 result;
|
|
|
|
|
|
|
|
edx = esi = ebp = 0;
|
|
|
|
eax = x;
|
|
|
|
ebx = bl;
|
|
|
|
ecx = y;
|
|
|
|
edi = z;
|
2016-11-13 20:17:49 +01:00
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
gActiveTrackDesign = _trackDesign;
|
2016-04-30 14:27:12 +02:00
|
|
|
result = game_do_command_p(GAME_COMMAND_PLACE_TRACK_DESIGN, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
2016-04-30 20:55:13 +02:00
|
|
|
gActiveTrackDesign = NULL;
|
2016-04-30 14:27:12 +02:00
|
|
|
|
|
|
|
if (cost != NULL) *cost = result;
|
|
|
|
if (rideIndex != NULL) *rideIndex = edi & 0xFF;
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:56:30 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006CFD9D
|
|
|
|
*/
|
2015-07-10 02:39:16 +02:00
|
|
|
static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
2014-09-30 19:56:30 +02:00
|
|
|
{
|
2016-09-26 04:24:29 +02:00
|
|
|
set_format_arg(0, char *, _trackDesign->name);
|
2014-09-30 19:56:30 +02:00
|
|
|
window_draw_widgets(w, dpi);
|
|
|
|
|
|
|
|
// Draw mini tile preview
|
2016-04-30 14:27:12 +02:00
|
|
|
rct_drawpixelinfo clippedDpi;
|
2016-01-15 21:20:29 +01:00
|
|
|
if (clip_drawpixelinfo(&clippedDpi, dpi, w->x + 4, w->y + 18, 168, 78)) {
|
2016-04-30 14:27:12 +02:00
|
|
|
rct_g1_element *substituteElement = &g1Elements[0];
|
|
|
|
rct_g1_element tmpElement = *substituteElement;
|
2015-12-22 16:31:51 +01:00
|
|
|
substituteElement->offset = _window_track_place_mini_preview;
|
|
|
|
substituteElement->width = TRACK_MINI_PREVIEW_WIDTH;
|
|
|
|
substituteElement->height = TRACK_MINI_PREVIEW_HEIGHT;
|
|
|
|
substituteElement->x_offset = 0;
|
|
|
|
substituteElement->y_offset = 0;
|
|
|
|
substituteElement->flags = 0;
|
2016-11-15 19:37:21 +01:00
|
|
|
gfx_draw_sprite(&clippedDpi, 0 | IMAGE_TYPE_REMAP | NOT_TRANSLUCENT(w->colours[0]) << 19, 0, 0, 0);
|
2015-12-22 16:31:51 +01:00
|
|
|
*substituteElement = tmpElement;
|
2014-09-30 19:56:30 +02:00
|
|
|
}
|
|
|
|
|
2014-10-01 03:03:36 +02:00
|
|
|
// Price
|
2016-04-30 14:27:12 +02:00
|
|
|
if (_window_track_place_last_cost != MONEY32_UNDEFINED && !(gParkFlags & PARK_FLAGS_NO_MONEY)) {
|
2016-11-13 18:20:30 +01:00
|
|
|
gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, COLOUR_BLACK, &_window_track_place_last_cost);
|
2016-04-30 14:27:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006D1845
|
|
|
|
*/
|
2016-04-30 20:55:13 +02:00
|
|
|
static void window_track_place_draw_mini_preview(rct_track_td6 *td6)
|
2016-04-30 14:27:12 +02:00
|
|
|
{
|
|
|
|
window_track_place_clear_mini_preview();
|
|
|
|
|
|
|
|
// First pass is used to determine the width and height of the image so it can centre it
|
|
|
|
rct_xy16 min = { 0, 0 };
|
|
|
|
rct_xy16 max = { 0, 0 };
|
|
|
|
for (int pass = 0; pass < 2; pass++) {
|
|
|
|
rct_xy16 origin = { 0, 0 };
|
|
|
|
if (pass == 1) {
|
|
|
|
origin.x -= ((max.x + min.x) >> 6) << 5;
|
|
|
|
origin.y -= ((max.y + min.y) >> 6) << 5;
|
|
|
|
}
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
if (td6->type == RIDE_TYPE_MAZE) {
|
|
|
|
window_track_place_draw_mini_preview_maze(td6, pass, origin, &min, &max);
|
2016-04-30 14:27:12 +02:00
|
|
|
} else {
|
2016-04-30 20:55:13 +02:00
|
|
|
window_track_place_draw_mini_preview_track(td6, pass, origin, &min, &max);
|
2016-04-30 14:27:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
static void window_track_place_draw_mini_preview_track(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max)
|
2016-04-30 14:27:12 +02:00
|
|
|
{
|
2016-04-30 20:55:13 +02:00
|
|
|
uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
|
|
|
|
rct_td6_track_element *trackElement = td6->track_elements;
|
2016-04-30 14:27:12 +02:00
|
|
|
while (trackElement->type != 255) {
|
|
|
|
int trackType = trackElement->type;
|
|
|
|
if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) {
|
|
|
|
trackType = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Follow a single track piece shape
|
|
|
|
const rct_preview_track *trackBlock = TrackBlocks[trackType];
|
|
|
|
while (trackBlock->index != 255) {
|
|
|
|
sint16 x = origin.x;
|
|
|
|
sint16 y = origin.y;
|
|
|
|
map_offset_with_rotation(&x, &y, trackBlock->x, trackBlock->y, rotation);
|
|
|
|
|
|
|
|
if (pass == 0) {
|
|
|
|
min->x = min(min->x, x);
|
|
|
|
max->x = max(max->x, x);
|
|
|
|
min->y = min(min->y, y);
|
|
|
|
max->y = max(max->y, y);
|
|
|
|
} else {
|
2016-04-30 20:55:13 +02:00
|
|
|
rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y);
|
|
|
|
if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) {
|
|
|
|
uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition);
|
2016-04-30 14:27:12 +02:00
|
|
|
|
|
|
|
uint8 bits = trackBlock->var_08 << (rotation & 3);
|
|
|
|
bits = (bits & 0x0F) | ((bits & 0xF0) >> 4);
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
// Station track is a lighter colour
|
2016-11-30 23:32:47 +01:00
|
|
|
uint8 colour = (TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN) ? PALETTE_INDEX_PRIMARY_LIGHTEST : PALETTE_INDEX_PRIMARY_MID_DARK;
|
2016-04-30 20:55:13 +02:00
|
|
|
|
2016-04-30 14:27:12 +02:00
|
|
|
for (int i = 0; i < 4; i++) {
|
2016-11-15 19:37:21 +01:00
|
|
|
if (bits & 1) pixel[338 + i] = colour; // x + 2, y + 2
|
|
|
|
if (bits & 2) pixel[168 + i] = colour; // y + 1
|
|
|
|
if (bits & 4) pixel[ 2 + i] = colour; // x + 2
|
|
|
|
if (bits & 8) pixel[172 + i] = colour; // x + 4, y + 1
|
2016-04-30 14:27:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trackBlock++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change rotation and next position based on track curvature
|
|
|
|
rotation &= 3;
|
|
|
|
const rct_track_coordinates* track_coordinate = &TrackCoordinates[trackType];
|
|
|
|
|
|
|
|
trackType *= 10;
|
|
|
|
map_offset_with_rotation(&origin.x, &origin.y, track_coordinate->x, track_coordinate->y, rotation);
|
|
|
|
rotation += track_coordinate->rotation_end - track_coordinate->rotation_begin;
|
|
|
|
rotation &= 3;
|
2016-04-30 20:55:13 +02:00
|
|
|
if (track_coordinate->rotation_end & 4) {
|
2016-04-30 14:27:12 +02:00
|
|
|
rotation |= 4;
|
2016-04-30 20:55:13 +02:00
|
|
|
}
|
2016-04-30 14:27:12 +02:00
|
|
|
if (!(rotation & 4)) {
|
|
|
|
origin.x += TileDirectionDelta[rotation].x;
|
|
|
|
origin.y += TileDirectionDelta[rotation].y;
|
|
|
|
}
|
|
|
|
trackElement++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-30 20:55:13 +02:00
|
|
|
static void window_track_place_draw_mini_preview_maze(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max)
|
2016-04-30 14:27:12 +02:00
|
|
|
{
|
2016-04-30 20:55:13 +02:00
|
|
|
uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
|
|
|
|
rct_td6_maze_element *mazeElement = td6->maze_elements;
|
2016-04-30 14:27:12 +02:00
|
|
|
while (mazeElement->all != 0) {
|
|
|
|
sint16 x = mazeElement->x * 32;
|
|
|
|
sint16 y = mazeElement->y * 32;
|
|
|
|
rotate_map_coordinates(&x, &y, rotation);
|
|
|
|
|
|
|
|
x += origin.x;
|
|
|
|
y += origin.y;
|
|
|
|
|
|
|
|
if (pass == 0) {
|
|
|
|
min->x = min(min->x, x);
|
|
|
|
max->x = max(max->x, x);
|
|
|
|
min->y = min(min->y, y);
|
|
|
|
max->y = max(max->y, y);
|
|
|
|
} else {
|
2016-04-30 20:55:13 +02:00
|
|
|
rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y);
|
|
|
|
if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) {
|
|
|
|
uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition);
|
|
|
|
|
|
|
|
// Entrance or exit is a lighter colour
|
2016-11-15 19:37:21 +01:00
|
|
|
uint8 colour = mazeElement->type == 8 || mazeElement->type == 128 ? PALETTE_INDEX_PRIMARY_LIGHTEST : PALETTE_INDEX_PRIMARY_MID_DARK;
|
2016-04-30 20:55:13 +02:00
|
|
|
|
2016-04-30 14:27:12 +02:00
|
|
|
for (int i = 0; i < 4; i++) {
|
2016-11-15 19:37:21 +01:00
|
|
|
pixel[338 + i] = colour; // x + 2, y + 2
|
|
|
|
pixel[168 + i] = colour; // y + 1
|
|
|
|
pixel[ 2 + i] = colour; // x + 2
|
|
|
|
pixel[172 + i] = colour; // x + 4, y + 1
|
2016-04-30 14:27:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mazeElement++;
|
|
|
|
}
|
2015-06-10 18:12:21 +02:00
|
|
|
}
|
2016-04-30 20:55:13 +02:00
|
|
|
|
|
|
|
static rct_xy16 draw_mini_preview_get_pixel_position(sint16 x, sint16 y)
|
|
|
|
{
|
|
|
|
return (rct_xy16) {
|
|
|
|
80 + ((y / 32) - (x / 32)) * 4,
|
|
|
|
38 + ((y / 32) + (x / 32)) * 2
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool draw_mini_preview_is_pixel_in_bounds(rct_xy16 pixel)
|
|
|
|
{
|
|
|
|
return pixel.x >= 0 && pixel.y >= 0 && pixel.x <= 160 && pixel.y <= 75;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8 *draw_mini_preview_get_pixel_ptr(rct_xy16 pixel)
|
|
|
|
{
|
|
|
|
return &_window_track_place_mini_preview[pixel.y * TRACK_MINI_PREVIEW_WIDTH + pixel.x];
|
|
|
|
}
|