1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 12:33:17 +01:00

Merge branch 'track-list-window'

This commit is contained in:
IntelOrca
2014-09-28 17:58:40 +01:00
15 changed files with 1079 additions and 20 deletions

View File

@@ -143,6 +143,9 @@
<ClCompile Include="..\src\window_title_scenarioselect.c" />
<ClCompile Include="..\src\window_game_top_toolbar.c" />
<ClCompile Include="..\src\window_tooltip.c" />
<ClCompile Include="..\src\window_track_list.c" />
<ClCompile Include="..\src\window_track_manage.c" />
<ClCompile Include="..\src\window_track_place.c" />
<ClCompile Include="..\src\window_water.c" />
<ClCompile Include="..\src\staff.c" />
<ClCompile Include="..\src\window_scenery.c" />

View File

@@ -168,6 +168,12 @@
<ClInclude Include="..\src\window_scenery.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\hook.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\mixer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\game.c">
@@ -401,6 +407,24 @@
<ClCompile Include="..\src\window_publisher_credits.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\libspeex\resample.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\hook.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\mixer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\window_track_list.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\src\window_track_manage.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\src\window_track_place.c">
<Filter>Windows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\openrct2.exe">

View File

@@ -161,7 +161,10 @@ void rct2_init()
// RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap
object_list_load();
scenario_load_list();
track_load_list(253);
ride_list_item item = { 253, 0 };
track_load_list(item);
gfx_load_g1();
//RCT2_CALLPROC_EBPSAFE(0x006C19AC); //Load character widths
gfx_load_character_widths();

View File

@@ -430,10 +430,10 @@ rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *ou
*
* rct2: 0x006B4800
*/
void ride_construct_new(int list_item)
void ride_construct_new(ride_list_item listItem)
{
int eax, ebx, ecx, edx, esi, edi, ebp;
edx = list_item;
edx = *((uint16*)&listItem);
eax = 0;
ecx = 0;
ebx = 1;

View File

@@ -39,6 +39,14 @@ typedef struct {
ride_rating nausea;
} rating_tuple;
/**
* Couples a ride type and subtype together.
*/
typedef struct {
uint8 type;
uint8 entry_index;
} ride_list_item;
/**
* Ride type structure.
* size: unknown
@@ -543,7 +551,7 @@ void ride_update_favourited_stat();
void ride_check_all_reachable();
rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY);
rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *outX, int *outY);
void ride_construct_new(int list_item);
void ride_construct_new(ride_list_item listItem);
int ride_try_construct(rct_map_element *trackMapElement);
void ride_get_status(int rideIndex, int *formatSecondary, int *argument);
rct_peep *ride_get_assigned_mechanic(rct_ride *ride);

View File

@@ -183,7 +183,7 @@ void scenario_load_and_play(const rct_scenario_basic *scenario)
srand0 = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32) ^ timeGetTime();
srand1 = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, uint32) ^ timeGetTime();
RCT2_CALLPROC_EBPSAFE(0x006CBCC3);
window_close_construction_windows();
subsitute_path(
RCT2_ADDRESS(0x0141EF68, char),

View File

@@ -471,6 +471,10 @@ enum {
STR_MEASUREMENTS_AND_TEST_DATA_TIP = 1398,
STR_GRAPHS_TIP = 1399,
STR_ROTATE_90_TIP = 1404,
STR_MIRROR_IMAGE_TIP = 1405,
STR_TOGGLE_SCENERY_TIP = 1406,
STR_BUILD_THIS = 1407,
STR_COST_LABEL = 1408,
@@ -823,6 +827,17 @@ enum {
STR_CHANGE_BASE_LAND_TIP = 2294,
STR_CHANGE_VERTICAL_LAND_TIP = 2295,
STR_SELECT_DESIGN = 2307,
STR_TRACK_DESIGNS = 2308,
STR_BUILD_CUSTOM_DESIGN = 2310,
STR_TRACK_LIST_EXCITEMENT_RATING = 2311,
STR_TRACK_LIST_INTENSITY_RATING = 2312,
STR_TRACK_LIST_NAUSEA_RATING = 2313,
STR_TRACK_LIST_RIDE_LENGTH = 2314,
STR_TRACK_LIST_COST_AROUND = 2315,
STR_TRACK_LIST_SPACE_REQUIRED = 2316,
STR_SOUND_QUALITY = 2317,
STR_SOUND_LOW = 2318,
STR_SOUND_MEDIUM = 2319,
@@ -1160,6 +1175,9 @@ enum {
STR_OPEN_RIDE = 3109,
STR_BLOCK_SECTIONS = 3110,
STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP = 3111,
STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT = 3112,
STR_SAVE_TRACK_DESIGN = 3115,
STR_SAVE_TRACK_DESIGN_NOT_POSSIBLE = 3116,
@@ -1177,6 +1195,9 @@ enum {
STR_DESIGN_CANCEL = 3131,
STR_CLICK_ITEMS_OF_SCENERY_TO_SELECT = 3132,
STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE = 3134,
STR_VEHICLE_DESIGN_UNAVAILABLE = 3135,
STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE = 3136,
STR_SELECT_NEARBY_SCENERY = 3137,
STR_RESET_SELECTION = 3138,
@@ -1226,6 +1247,10 @@ enum {
STR_ROLLER_COASTER_DESIGNER = 3344,
STR_TRACK_DESIGNS_MANAGER = 3345,
STR_NO_TRACK_DESIGNS_OF_THIS_TYPE = 3359,
STR_WARNING = 3360,
STR_TOO_MANY_TRACK_DESIGNS_OF_THIS_TYPE = 3361,
STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING = 3362,
STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING_TIP = 3363,

View File

@@ -18,7 +18,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <string.h>
#include <windows.h>
#include "addresses.h"
#include "ride.h"
#include "osinterface.h"
#include "track.h"
/**
@@ -220,7 +224,207 @@ const rct_trackdefinition gTrackDefinitions[] = {
*
* rct2: 0x006CED50
*/
void track_load_list(int edx)
void track_load_list(ride_list_item item)
{
RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, edx, 0, 0, 0);
RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, *((uint16*)&item), 0, 0, 0);
}
/**
*
* rct2: 0x00676EBA
*/
static uint8 sub_676EBA()
{
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x00676EBA, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return eax & 0xFF;
}
/**
*
* rct2: 0x00676EAF
*/
static void sub_676EAF(uint8 *esi, int ecx)
{
do {
*esi++ = sub_676EBA();
} while (--ecx != 0);
}
/**
*
* rct2: 0x0067726A
* path: 0x0141EF68
*/
int sub_67726A(const char *path)
{
HANDLE *hFile;
const char *ch;
char trackFilename[MAX_PATH], *dst;
int i;
uint8* edi;
RCT2_GLOBAL(0x009AAC54, uint8) = 1;
// Get filename
ch = strrchr(path, '\\');
ch = ch == NULL ? path : ch + 1;
dst = trackFilename;
while (*ch != 0 && *ch != '.') {
*dst++ = *ch++;
}
*dst = 0;
hFile = osinterface_file_open(path);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
RCT2_GLOBAL(0x009E382C, HANDLE) = hFile;
if (!RCT2_CALLPROC_X(0x006770C1, 0, 0, 0, 0, 0, 0, 0)) {
CloseHandle(hFile);
return 0;
}
RCT2_CALLPROC_EBPSAFE(0x00676E7A);
memset((void*)0x009D81D8, 0, 67);
sub_676EAF((void*)0x009D8178, 32);
uint8 al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
if (al >= 2)
sub_676EAF((void*)0x009D8198, 40);
sub_676EAF((void*)0x009D81C0, 24);
al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
if (al != 0)
sub_676EAF((void*)0x009D81D8, al == 1 ? 140 : 67);
sub_676EAF((void*)0x009D821B, 24572);
al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
if (al < 2) {
if (RCT2_GLOBAL(0x009D8178, uint8) == 20) {
edi = (uint8*)0x009D821B;
while (*edi != 0) {
edi += 4;
}
edi += 4;
memset(edi, 255, (uint8*)0x009DE217 - edi);
} else {
edi = (uint8*)0x009D821B;
while (*edi != 255) {
edi += 2;
}
edi++;
memset(edi, 255, (uint8*)0x009DE217 - edi);
}
}
CloseHandle(hFile);
al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
if (al > 2)
return 0;
if (al <= 1) {
edi = (uint8*)0x009D8180;
for (i = 0; i < 67; i++)
*edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi];
edi = (uint8*)0x009D81D8;
for (i = 0; i < 12; i++)
*edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi];
RCT2_GLOBAL(0x009D81D2, uint8) >>= 1;
if (!RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0))
RCT2_GLOBAL(0x009D8178, uint8) = 255;
if (RCT2_GLOBAL(0x009D8178, uint8) == 4)
RCT2_GLOBAL(0x009D8178, uint8) = 255;
if (RCT2_GLOBAL(0x009D8178, uint8) == 0)
RCT2_GLOBAL(0x009D8178, uint8) = 52;
if (RCT2_GLOBAL(0x009D8178, uint8) == 19) {
if (RCT2_GLOBAL(0x009D817E, uint8) == 3)
RCT2_GLOBAL(0x009D817E, uint8) = 35;
if (RCT2_GLOBAL(0x009D8179, uint8) == 79) {
if (RCT2_GLOBAL(0x009D817E, uint8) == 2)
RCT2_GLOBAL(0x009D817E, uint8) = 1;
}
}
int unk1 = RCT2_GLOBAL(0x009D8179, uint8);
if (RCT2_GLOBAL(0x009D8178, uint8) == 20) {
unk1 = 0x0097F66C;
} else {
if (unk1 == 3 && RCT2_GLOBAL(0x009D8178, uint8) == 3)
unk1 = 80;
unk1 = 0x0097F0DC + (unk1 * 16);
}
memcpy((void*)0x009D81E8, (void*)unk1, 16);
for (i = 0; i < 32; i++)
RCT2_ADDRESS(0x009D81FA, uint8)[i] = RCT2_ADDRESS(0x009D8181, uint8)[i * 2];
RCT2_GLOBAL(0x009D81F8, uint8) = 255;
RCT2_GLOBAL(0x009D81F9, uint8) = 255;
RCT2_GLOBAL(0x009D821A, uint8) = 5;
}
RCT2_GLOBAL(0x009D81C8, uint8) = min(
RCT2_GLOBAL(0x009D81C8, uint8),
RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (RCT2_GLOBAL(0x009D8178, uint8) * 8), uint8)
);
return 1;
}
/**
*
* I don't think preview is a necessary output argument. It can be obtained easily using the track design structure.
* rct2: 0x006D1DEC
*/
rct_track_design *track_get_info(int index, uint8** preview)
{
rct_track_design *trackDesign;
uint8 *trackDesignList = (uint8*)0x00F441EC;
int i;
trackDesign = NULL;
// Check if track design has already been loaded
for (i = 0; i < 4; i++) {
if (index == RCT2_ADDRESS(0x00F44109, uint32)[i]) {
trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i];
break;
}
}
if (trackDesign == NULL) {
// Load track design
i = RCT2_GLOBAL(0x00F44119, uint32);
RCT2_GLOBAL(0x00F44119, uint32)++;
if (RCT2_GLOBAL(0x00F44119, uint32) >= 4)
RCT2_GLOBAL(0x00F44119, uint32) = 0;
RCT2_ADDRESS(0x00F44109, uint32)[i] = index;
subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128));
if (!sub_67726A((char*)0x0141EF68)) {
if (preview != NULL) *preview = NULL;
return NULL;
}
trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i];
memcpy(trackDesign, (void*)0x009D8178, 163);
RCT2_CALLPROC_EBPSAFE(0x006D1EF0);
trackDesign->cost = RCT2_GLOBAL(0x00F4411D, money32);
trackDesign->var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7;
}
// Set preview to correct preview image based on rotation
if (preview != NULL)
*preview = trackDesign->preview[RCT2_GLOBAL(0x00F440AE, uint8)];
return trackDesign;
}

View File

@@ -33,6 +33,45 @@ typedef struct {
uint8 pad[2];
} rct_trackdefinition;
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
/**
* Track design structure.
* size: 0x4E72B
*/
typedef struct {
uint8 type; // 0x00
uint8 pad_01;
money32 cost; // 0x02
uint8 var_06;
uint8 var_07;
uint8 pad_08[0x42];
uint8 total_air_time; // 0x4A
uint8 pad_4B[0x06];
uint8 max_speed; // 0x51
uint8 average_speed; // 0x52
uint16 ride_length; // 0x53
uint8 max_positive_vertical_g; // 0x55
uint8 max_negitive_vertical_g; // 0x56
uint8 max_lateral_g; // 0x57
union {
uint8 inversions; // 0x58
uint8 holes; // 0x58
};
uint8 drops; // 0x59
uint8 highest_drop_height; // 0x5A
uint8 excitement; // 0x5B
uint8 intensity; // 0x5C
uint8 nausea; // 0x5D
uint8 pad_5E[0x0E];
uint32 var_6C;
uint8 pad_70[0x10];
uint8 space_required_x; // 0x80
uint8 space_required_y; // 0x81
uint8 pad_82[0x21];
uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3
} rct_track_design;
enum {
TRACK_NONE = 0,
@@ -90,6 +129,8 @@ enum {
TRACK_CORKSCREW_DOWN = 224
};
void track_load_list(int edx);
void track_load_list(ride_list_item item);
int sub_67726A(const char *path);
rct_track_design *track_get_info(int index, uint8** preview);
#endif

View File

@@ -1688,3 +1688,14 @@ void window_align_tabs(rct_window *w, uint8 start_tab_id, uint8 end_tab_id)
}
}
/**
*
* rct2: 0x006CBCC3
*/
void window_close_construction_windows()
{
window_close_by_id(WC_RIDE_CONSTRUCTION, 0);
window_close_by_id(WC_FOOTPATH, 0);
window_close_by_id(WC_TRACK_DESIGN_LIST, 0);
window_close_by_id(WC_TRACK_DESIGN_PLACE, 0);
}

View File

@@ -25,6 +25,7 @@
#include "park.h"
#include "peep.h"
#include "rct2.h"
#include "ride.h"
struct rct_window;
union rct_window_event;
@@ -168,6 +169,12 @@ typedef struct {
sint16 hover_counter;
} scenery_variables;
typedef struct {
uint16 var_480;
uint16 var_482;
uint16 var_484;
} track_list_variables;
/**
* Window structure
* size: 0x4C0
@@ -206,6 +213,7 @@ typedef struct rct_window {
map_variables map;
ride_variables ride;
scenery_variables scenery;
track_list_variables track_list;
};
sint16 page; // 0x48A
sint16 var_48C;
@@ -361,6 +369,7 @@ enum {
WC_RECENT_NEWS = 31,
WC_SCENARIO_SELECT = 32,
WC_TRACK_DESIGN_LIST = 33,
WC_TRACK_DESIGN_PLACE = 34,
WC_NEW_CAMPAIGN = 35,
WC_KEYBOARD_SHORTCUT_LIST = 36,
WC_CHANGE_KEYBOARD_SHORTCUT = 37,
@@ -371,6 +380,8 @@ enum {
WC_EDITOR_INVENTION_LIST = 43,
WC_EDITOR_SCENARIO_OPTIONS = 45,
WC_EDTIOR_OBJECTIVE_OPTIONS = 46,
WC_47,
WC_48,
WC_CLEAR_SCENERY = 50,
WC_MANAGE_TRACK_DESIGN = 89,
WC_CHEATS = 110,
@@ -433,6 +444,8 @@ void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth,
int tool_set(rct_window *w, int widgetIndex, int tool);
void tool_cancel();
void window_close_construction_windows();
// Open window functions
void window_main_open();
void window_resize_gui(int width, int height);
@@ -447,6 +460,7 @@ void window_title_exit_open();
void window_title_logo_open();
void window_news_open();
void window_scenarioselect_open();
void window_track_list_open(ride_list_item item);
void window_clear_scenery_open();
void window_land_open();
void window_water_open();
@@ -466,6 +480,7 @@ void window_finances_research_open();
void window_new_campaign_open(sint16 campaignType);
void window_ride_main_open(int rideIndex);
void window_ride_list_open();
void window_track_place_open();
void window_new_ride_open();
void window_banner_open();
void window_cheats_open();
@@ -473,6 +488,7 @@ void window_research_open();
void window_scenery_open();
void window_music_credits_open();
void window_publisher_credits_open();
void window_track_manage_open();
void window_guest_list_init_vars_a();
void window_guest_list_init_vars_b();

View File

@@ -32,11 +32,6 @@
#define _window_new_ride_current_tab RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_SELECTED_TAB, uint8)
typedef struct {
uint8 type;
uint8 entry_index;
} ride_list_item;
#pragma region Ride type view order
/**
@@ -874,7 +869,7 @@ static ride_list_item window_new_ride_scroll_get_ride_list_item_at(rct_window *w
static int get_num_track_designs(ride_list_item item)
{
track_load_list(*((uint16*)&item));
track_load_list(item);
uint8 *trackDesignList = (uint8*)0x00F441EC;
int count = 0;
@@ -964,17 +959,14 @@ static void window_new_ride_select(rct_window *w)
uint32 rideTypeFlags = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (item.type * 8), uint32);
if (rideTypeFlags & 0x10000000) {
track_load_list(*((sint16*)&item));
track_load_list(item);
uint8 *trackDesignList = (uint8*)0x00F441EC;
if (*trackDesignList != 0) {
// Show track design list
RCT2_CALLPROC_X(0x006CF1A2, *((sint16*)&item), 0, 0, 0, 0, 0, 0);
window_track_list_open(item);
return;
}
}
// Show ride construction window
//RCT2_CALLPROC_X(0x006B4800, *((sint16*)&item), 0, 0, 0, 0, 0, 0);
ride_construct_new(*((sint16*)&item));
ride_construct_new(item);
}

649
src/window_track_list.c Normal file
View File

@@ -0,0 +1,649 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <memory.h>
#include "addresses.h"
#include "audio.h"
#include "editor.h"
#include "ride.h"
#include "sprites.h"
#include "string_ids.h"
#include "track.h"
#include "widget.h"
#include "window.h"
#include "window_error.h"
enum {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_TRACK_LIST,
WIDX_TRACK_PREVIEW,
WIDX_ROTATE,
WIDX_TOGGLE_SCENERY
};
static rct_widget window_track_list_widgets[] = {
{ WWT_FRAME, 0, 0, 599, 0, 399, 0xFFFFFFFF, STR_NONE },
{ WWT_CAPTION, 0, 1, 598, 1, 14, STR_SELECT_DESIGN, STR_WINDOW_TITLE_TIP },
{ WWT_CLOSEBOX, 0, 587, 597, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
{ WWT_SCROLL, 0, 4, 221, 18, 395, 2, STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP },
{ WWT_FLATBTN, 0, 224, 595, 18, 236, 0xFFFFFFFF, STR_NONE },
{ WWT_FLATBTN, 0, 574, 597, 374, 397, 5169, STR_ROTATE_90_TIP },
{ WWT_FLATBTN, 0, 574, 597, 350, 373, 5171, STR_TOGGLE_SCENERY_TIP },
{ WIDGETS_END },
};
static void window_track_list_emptysub() { }
static void window_track_list_close();
static void window_track_list_mouseup();
static void window_track_list_scrollgetsize();
static void window_track_list_scrollmousedown();
static void window_track_list_scrollmouseover();
static void window_track_list_tooltip();
static void window_track_list_invalidate();
static void window_track_list_paint();
static void window_track_list_scrollpaint();
static void* window_track_list_events[] = {
(uint32*)window_track_list_close,
(uint32*)window_track_list_mouseup,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_scrollgetsize,
(uint32*)window_track_list_scrollmousedown,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_scrollmouseover,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_tooltip,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_emptysub,
(uint32*)window_track_list_invalidate,
(uint32*)window_track_list_paint,
(uint32*)window_track_list_scrollpaint
};
static ride_list_item _window_track_list_item;
void window_track_list_format_name(char *dst, const char *src, char colour)
{
if (colour != 0)
*dst++ = colour;
*dst++ = FORMAT_OPENQUOTES;
while (*src != '.' && *src != 0) {
*dst++ = *src++;
}
*dst++ = FORMAT_ENDQUOTES;
*dst = 0;
}
/**
*
* rct2: 0x006CF1A2
*/
void window_track_list_open(ride_list_item item)
{
rct_window *w;
int x, y;
void *mem;
window_close_construction_windows();
_window_track_list_item = item;
if (RCT2_GLOBAL(0x00F635ED, uint8) & 1)
window_error_open(STR_WARNING, STR_TOO_MANY_TRACK_DESIGNS_OF_THIS_TYPE);
mem = malloc(1285292);
if (mem == NULL)
return;
RCT2_GLOBAL(0x00F44105, void*) = mem;
RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2 - 300;
y = max(28, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) / 2 - 200);
} else {
x = 0;
y = 29;
}
w = window_create(0, 29, 600, 400, (uint32*)window_track_list_events, WC_TRACK_DESIGN_LIST, 0);
w->widgets = window_track_list_widgets;
w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY);
window_init_scroll_widgets(w);
w->colours[0] = 26;
w->colours[1] = 26;
w->colours[2] = 26;
w->track_list.var_480 = 0xFFFF;
w->track_list.var_482 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 1 : 0;
w->track_list.var_484 = 0;
RCT2_GLOBAL(0x00F44152, uint8) = 0;
window_push_others_right(w);
RCT2_GLOBAL(0x00F440AE, uint8) = 2;
}
/**
*
* rct2: 0x006CFB82
*/
static void window_track_list_select(rct_window *w, int index)
{
uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
rct_track_design *trackDesign;
w->track_list.var_480 = index;
sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8) && index == 0) {
window_close(w);
ride_construct_new(_window_track_list_item);
return;
}
if (RCT2_GLOBAL(0x00F44153, uint8) != 0)
RCT2_GLOBAL(0x00F44152, uint8) = 1;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8))
index--;
trackDesignItem = trackDesignList + (index * 128);;
RCT2_GLOBAL(0x00F4403C, uint8*) = trackDesignItem;
window_track_list_format_name(
(char*)0x009BC313,
trackDesignItem,
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8 ?
0 :
FORMAT_WHITE
);
subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8) {
window_track_manage_open();
return;
}
if (!RCT2_CALLPROC_X(0x0067726A, 0, 0, 0, 0, 0, 0, 0)) {
w->track_list.var_480 = 0xFFFF;
window_invalidate(w);
return;
}
trackDesign = track_get_info(index, NULL);
if (trackDesign->var_06 & 4)
window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1);
window_close(w);
window_track_place_open();
}
static int window_track_list_get_list_item_index_from_position(int x, int y)
{
int index;
uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
index = 0;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8)) {
y -= 10;
if (y < 0)
return index;
index++;
}
for (trackDesignItem = trackDesignList; *trackDesignItem != 0; trackDesignItem += 128) {
y -= 10;
if (y < 0)
return index;
index++;
}
return -1;
}
/**
*
* rct2: 0x006CFD76
*/
static void window_track_list_close()
{
free(RCT2_GLOBAL(0x00F44105, void*));
}
/**
*
* rct2: 0x006CFA31
*/
static void window_track_list_mouseup()
{
rct_window *w;
short widgetIndex;
window_widget_get_registers(w, widgetIndex);
switch (widgetIndex) {
case WIDX_CLOSE:
window_close(w);
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
window_close_by_id(WC_47, w->number);
window_close_by_id(WC_48, w->number);
trackmanager_load();
}
break;
case WIDX_ROTATE:
RCT2_GLOBAL(0x00F440AE, uint8)++;
RCT2_GLOBAL(0x00F440AE, uint8) %= 4;
window_invalidate(w);
break;
case WIDX_TOGGLE_SCENERY:
RCT2_GLOBAL(0x00F44152, uint8) ^= 1;
RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
window_invalidate(w);
break;
}
}
/**
*
* rct2: 0x006CFAB0
*/
static void window_track_list_scrollgetsize()
{
rct_window *w;
int height;
uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
window_get_register(w);
height = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER & 8 ? 0 : 10;
for (trackDesignItem = trackDesignList; *trackDesignItem != 0; trackDesignItem += 128)
height += 10;
#ifdef _MSC_VER
__asm mov ecx, 0
#else
__asm__ ( "mov ecx, 0 " );
#endif
#ifdef _MSC_VER
__asm mov edx, height
#else
__asm__ ( "mov edx, %[height] " : [height] "+m" (height) );
#endif
}
/**
*
* rct2: 0x006CFB39
*/
static void window_track_list_scrollmousedown()
{
rct_window *w;
short i, x, y;
window_scrollmouse_get_registers(w, x, y);
if (w->track_list.var_484 & 1)
return;
if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
return;
i = window_track_list_get_list_item_index_from_position(x, y);
if (i != -1)
window_track_list_select(w, i);
}
/**
*
* rct2: 0x006CFAD7
*/
static void window_track_list_scrollmouseover()
{
rct_window *w;
short i, x, y;
window_scrollmouse_get_registers(w, x, y);
if (w->track_list.var_484 & 1)
return;
if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
return;
i = window_track_list_get_list_item_index_from_position(x, y);
if (i != -1 && w->track_list.var_482 != i) {
w->track_list.var_482 = i;
window_invalidate(w);
}
}
/**
*
* rct2: 0x006CFD6C
*/
static void window_track_list_tooltip()
{
RCT2_GLOBAL(0x013CE952, uint16) = STR_LIST;
}
/**
*
* rct2: 0x006CF2D6
*/
static void window_track_list_invalidate()
{
rct_window *w;
rct_ride_type *entry;
rct_string_id stringId;
window_get_register(w);
entry = GET_RIDE_ENTRY(_window_track_list_item.entry_index);
stringId = entry->name;
if (!(entry->var_008 & 0x1000))
stringId = _window_track_list_item.type + 2;
RCT2_GLOBAL(0x013CE952, uint16) = stringId;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
window_track_list_widgets[WIDX_TITLE].image = STR_TRACK_DESIGNS;
window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT;
} else {
window_track_list_widgets[WIDX_TITLE].image = STR_SELECT_DESIGN;
window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP;
}
if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) || w->track_list.var_482 != 0) {
w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW;
w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN;
window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_FLATBTN;
if (RCT2_GLOBAL(0x00F44152, uint8) == 0)
w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
else
w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
} else {
w->pressed_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
window_track_list_widgets[WIDX_ROTATE].type = WWT_EMPTY;
window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_EMPTY;
}
}
/**
*
* rct2: 0x006CF387
*/
static void window_track_list_paint()
{
rct_window *w;
rct_drawpixelinfo *dpi;
rct_widget *widget;
rct_track_design *trackDesign;
uint8 *image, *trackDesignList = (uint8*)0x00F441EC;
uint16 holes, speed, drops, dropHeight, inversions;
fixed32_2dp rating;
int trackIndex, x, y, colour, gForces, airTime;
rct_g1_element tmpElement, *subsituteElement, *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element);
window_paint_get_registers(w, dpi);
window_draw_widgets(w, dpi);
trackIndex = w->track_list.var_482;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
if (*trackDesignList == 0 || trackIndex == -1)
return;
} else if (trackIndex-- == 0) {
return;
}
// Track preview
widget = &window_track_list_widgets[WIDX_TRACK_PREVIEW];
x = w->x + widget->left + 1;
y = w->y + widget->top + 1;
colour = RCT2_GLOBAL(0x0141FC44 + (w->colours[0] * 8), uint8);
gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);
trackDesign = track_get_info(trackIndex, &image);
if (trackDesign == NULL)
return;
subsituteElement = &g1Elements[0];
tmpElement = *subsituteElement;
subsituteElement->offset = image;
subsituteElement->width = 370;
subsituteElement->height = 217;
subsituteElement->x_offset = 0;
subsituteElement->y_offset = 0;
subsituteElement->flags = G1_FLAG_BMP;
gfx_draw_sprite(dpi, 0, x, y, 0);
*subsituteElement = tmpElement;
x = w->x + (widget->left + widget->right) / 2;
y = w->y + widget->bottom - 12;
// Warnings
if ((trackDesign->var_06 & 4) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) {
// Vehicle design not available
RCT2_GLOBAL(0x00F44153, uint8) = 0;
gfx_draw_string_centred_clipped(dpi, STR_VEHICLE_DESIGN_UNAVAILABLE, NULL, 0, x, y, 368);
y -= 10;
}
if (trackDesign->var_06 & 1) {
RCT2_GLOBAL(0x00F44153, uint8) = 1;
if (RCT2_GLOBAL(0x00F44152, uint8) == 0) {
// Scenery not available
gfx_draw_string_centred_clipped(dpi, STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE, NULL, 0, x, y, 368);
y -= 10;
}
}
// Track design name
window_track_list_format_name((char*)0x009BC677, trackDesignList + (trackIndex * 128), FORMAT_WINDOW_COLOUR_1);
gfx_draw_string_centred_clipped(dpi, 3165, NULL, 0, x, y, 368);
// Information
x = w->x + widget->left + 1;
y = w->y + widget->bottom + 2;
if (trackDesign->var_6C & 0x80000000) {
// Six flags logo
gfx_draw_sprite(dpi, SPR_SIX_FLAGS, w->x + widget->right - 50, y + 4, 0);
}
// Stats
rating = trackDesign->excitement * 10;
gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, 0, x, y);
y += 10;
rating = trackDesign->intensity * 10;
gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, 0, x, y);
y += 10;
rating = trackDesign->nausea * 10;
gfx_draw_string_left(dpi, STR_TRACK_LIST_NAUSEA_RATING, &rating, 0, x, y);
y += 14;
if (trackDesign->type != RIDE_TYPE_MAZE) {
if (trackDesign->type == RIDE_TYPE_MINI_GOLF) {
// Holes
holes = trackDesign->holes & 0x1F;
gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y);
y += 10;
} else {
// Maximum speed
speed = ((trackDesign->max_speed << 16) * 9) >> 18;
gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, 0, x, y);
y += 10;
// Average speed
speed = ((trackDesign->average_speed << 16) * 9) >> 18;
gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &speed, 0, x, y);
y += 10;
}
// Ride length
RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1345;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->ride_length;
gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 214);
y += 10;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (trackDesign->type * 8), uint32) & 0x80) {
// Maximum positive vertical Gs
gForces = trackDesign->max_positive_vertical_g * 32;
gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, 0, x, y);
y += 10;
// Maximum negative verical Gs
gForces = trackDesign->max_negitive_vertical_g * 32;
gfx_draw_string_left(dpi, STR_MAX_NEGATIVE_VERTICAL_G, &gForces, 0, x, y);
y += 10;
// Maximum lateral Gs
gForces = trackDesign->max_lateral_g * 32;
gfx_draw_string_left(dpi, STR_MAX_LATERAL_G, &gForces, 0, x, y);
y += 10;
if (trackDesign->var_07 / 4 >= 2) {
if (trackDesign->total_air_time != 0) {
// Total air time
airTime = trackDesign->total_air_time * 25;
gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &airTime, 0, x, y);
y += 10;
}
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (trackDesign->type * 8), uint32) & 0x400) {
// Drops
drops = trackDesign->drops & 0x3F;
gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y);
y += 10;
// Drop height is multiplied by 0.75
dropHeight = (trackDesign->highest_drop_height + (trackDesign->highest_drop_height / 2)) / 2;
gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &drops, 0, x, y);
y += 10;
}
if (trackDesign->type != RIDE_TYPE_MINI_GOLF) {
inversions = trackDesign->inversions & 0x1F;
if (inversions != 0) {
// Inversions
gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, 0, x, y);
y += 10;
}
}
y += 4;
if (trackDesign->space_required_x != 0xFF) {
// Space required
RCT2_GLOBAL(0x013CE952 + 0, uint16) = trackDesign->space_required_x;
RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->space_required_y;
gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)0x013CE952, 0, x, y);
y += 10;
}
if (trackDesign->cost != 0) {
gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &trackDesign->cost, 0, x, y);
y += 14;
}
}
/**
*
* rct2: 0x006CF8CD
*/
static void window_track_list_scrollpaint()
{
rct_window *w;
rct_drawpixelinfo *dpi;
rct_string_id stringId, stringId2;
int i, x, y, colour;
uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
window_paint_get_registers(w, dpi);
colour = RCT2_GLOBAL(0x00141FC48 + (w->colours[0] * 8), uint8);
colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
gfx_clear(dpi, colour);
i = 0;
x = 0;
y = 0;
trackDesignItem = trackDesignList;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
if (*trackDesignItem == 0) {
// No track designs
gfx_draw_string_left(dpi, STR_NO_TRACK_DESIGNS_OF_THIS_TYPE, NULL, 0, x, y - 1);
return;
}
} else {
// Build custom track item
if (i == w->track_list.var_482) {
// Highlight
gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49);
stringId = 1193;
} else {
stringId = 1191;
}
stringId2 = STR_BUILD_CUSTOM_DESIGN;
gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
y += 10;
}
i++;
while (*trackDesignItem != 0) {
if (y + 10 >= dpi->y && y < dpi->y + dpi->height) {
if (i == w->track_list.var_482) {
// Highlight
gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49);
stringId = 1193;
} else {
stringId = 1191;
}
// Draw track name
window_track_list_format_name((char*)0x009BC678, trackDesignItem, 0);
stringId2 = 3165;
gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
}
y += 10;
i++;
trackDesignItem += 128;
}
}

31
src/window_track_manage.c Normal file
View File

@@ -0,0 +1,31 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "addresses.h"
#include "window.h"
/**
*
* rct2: 0x006D348F
*/
void window_track_manage_open()
{
RCT2_CALLPROC_EBPSAFE(0x006D348F);
}

52
src/window_track_place.c Normal file
View File

@@ -0,0 +1,52 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "addresses.h"
#include "viewport.h"
#include "window.h"
/**
*
* rct2: 0x006CFCA0
*/
void window_track_place_open()
{
rct_window *w;
window_close_construction_windows();
RCT2_GLOBAL(0x00F44168, void*) = rct2_malloc(13104);
RCT2_CALLPROC_EBPSAFE(0x006D182E);
w = window_create(0, 29, 200, 124, (uint32*)0x0099405C, WC_TRACK_DESIGN_PLACE, 0);
w->widgets = (rct_widget*)0x009D7F18;
w->enabled_widgets = 4 | 8 | 0x10 | 0x20;
window_init_scroll_widgets(w);
w->colours[0] = 24;
w->colours[1] = 24;
w->colours[2] = 24;
tool_set(w, 6, 12);
RCT2_GLOBAL(0x009DE518, uint32) |= 6;
window_push_others_right(w);
show_gridlines();
RCT2_GLOBAL(0x00F440D9, uint32) |= 0x80000000;
RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF;
RCT2_GLOBAL(0x00F440AE, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
RCT2_CALLPROC_EBPSAFE(0x006D1845);
}