From 2c7f0d6ae2487018e31fb9ac5d258766750c1455 Mon Sep 17 00:00:00 2001 From: Alex Bahm Date: Mon, 28 Dec 2015 20:32:44 -0800 Subject: [PATCH 01/90] Improved mechanic selection for broken rides Switch to using manhattan distance to calculate distance. Also changed starting closestDistance to UINT_MAX and removed ternary check because it is not needed. --- src/ride/ride.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ride/ride.c b/src/ride/ride.c index c23b403a56..78da7a1230 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -2466,7 +2466,7 @@ rct_peep *find_closest_mechanic(int x, int y, int forInspection) uint16 spriteIndex; rct_peep *peep, *closestMechanic = NULL; - closestDistance = -1; + closestDistance = UINT_MAX; FOR_ALL_STAFF(spriteIndex, peep) { if (peep->staff_type != STAFF_TYPE_MECHANIC) continue; @@ -2493,15 +2493,15 @@ rct_peep *find_closest_mechanic(int x, int y, int forInspection) if (peep->x == (sint16)0x8000) continue; - // Should probably be euclidean or manhattan distance, this seems a bit naive - distance = max(abs(peep->x - x), abs(peep->y - y)); + // manhattan distance + distance = abs(peep->x - x) + abs(peep->y - y); if (distance < closestDistance) { closestDistance = distance; closestMechanic = peep; } } - return closestDistance == -1 ? NULL : closestMechanic; + return closestMechanic; } rct_peep *ride_get_assigned_mechanic(rct_ride *ride) From db95b3ada35ad9e8cc5cdb397f49e8ec1c1d9c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Thu, 31 Dec 2015 09:15:16 +0100 Subject: [PATCH 02/90] Enable strict aliasing and make sure it gets spotted --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bd8c6c612..9f1d51d61e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,8 +125,8 @@ if (APPLE) endif (APPLE) # force 32bit build for now and set necessary flags to compile code as is -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer -fno-pie") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer -fno-pie -fstrict-aliasing -Werror=strict-aliasing") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie -fstrict-aliasing -Werror=strict-aliasing") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}") From 8a5d066efe18d05aa7f86969264bd95f7096e19e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Thu, 31 Dec 2015 09:16:44 +0100 Subject: [PATCH 03/90] Fix strict aliasing violations Compiler only guarantees proper accesses to variables when using variable's native type or `char` (i.e. single byte type) [1]. This commit fixes violations of this rule. In most cases changing code to a simple cast was enough, some required a bit deeper modifications. This fixes #2596. [1] http://blog.qt.io/blog/2011/06/10/type-punning-and-strict-aliasing/ --- src/hook.c | 17 +++++++++++++++-- src/interface/window.c | 2 +- src/interface/window.h | 12 ++++++++++-- src/object.c | 10 ++++------ src/platform/shared.c | 6 +++++- src/windows/clear_scenery.c | 4 ++-- src/windows/dropdown.c | 2 +- src/windows/editor_inventions_list.c | 18 ++++++++---------- src/windows/editor_object_selection.c | 14 +++++++------- src/windows/land.c | 8 ++++---- src/windows/land_rights.c | 4 ++-- src/windows/loadsave.c | 8 ++++---- src/windows/map.c | 8 ++++---- src/windows/mapgen.c | 24 ++++++++++++------------ src/windows/ride.c | 20 ++++++++++---------- src/windows/ride_list.c | 2 +- src/windows/title_scenarioselect.c | 12 ++++++------ src/windows/water.c | 4 ++-- 18 files changed, 98 insertions(+), 77 deletions(-) diff --git a/src/hook.c b/src/hook.c index 757d873ce7..66b33e3e73 100644 --- a/src/hook.c +++ b/src/hook.c @@ -30,6 +30,14 @@ void* g_hooktableaddress = 0; int g_hooktableoffset = 0; int g_maxhooks = 1000; +// This macro writes a little-endian 4-byte long value into *data +// It is used to avoid type punning. +#define write_address_strictalias(data, addr) \ + *(data + 0) = ((addr) & 0x000000ff) >> 0; \ + *(data + 1) = ((addr) & 0x0000ff00) >> 8; \ + *(data + 2) = ((addr) & 0x00ff0000) >> 16; \ + *(data + 3) = ((addr) & 0xff000000) >> 24; + void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister) { int i = 0; @@ -118,7 +126,9 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in } data[i++] = 0xE8; // call - *((int *)&data[i]) = (newaddress - address - i - 4); i += 4; + + write_address_strictalias(&data[i], newaddress - address - i - 4); + i += 4; // returnlocation: @@ -220,7 +230,10 @@ void addhook(int address, int newaddress, int stacksize, int registerargs[], int char data[9]; int i = 0; data[i++] = 0xE9; // jmp - *((int *)&data[i]) = hookaddress - address - i - 4; i += 4; + + write_address_strictalias(&data[i], hookaddress - address - i - 4); + i += 4; + data[i++] = 0xC3; // retn #ifdef _WIN32 WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0); diff --git a/src/interface/window.c b/src/interface/window.c index 54d69c2cad..a7b3dd483c 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -41,7 +41,7 @@ rct_window* g_window_list = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window); -uint8 TextInputDescriptionArgs[8]; +uint16 TextInputDescriptionArgs[4]; widget_identifier gCurrentTextBox = { { 255, 0 }, 0 }; char gTextBoxInput[512] = { 0 }; int gMaxTextBoxInputLength = 0; diff --git a/src/interface/window.h b/src/interface/window.h index e538d69091..714f741a92 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -27,11 +27,13 @@ #include "../ride/ride.h" #include "../ride/vehicle.h" #include "../world/park.h" +#include "../management/research.h" +#include "../scenario.h" #include "colour.h" struct rct_window; union rct_window_event; -extern uint8 TextInputDescriptionArgs[8]; +extern uint16 TextInputDescriptionArgs[4]; extern char gTextBoxInput[512]; extern int gMaxTextBoxInputLength; extern int gTextBoxFrameNo; @@ -264,7 +266,13 @@ typedef struct rct_window { uint16 frame_no; // 0x48E updated every tic for motion in windows sprites uint16 list_information_type; // 0x490 0 for none, Used as current position of marquee in window_peep sint16 var_492; - uint32 highlighted_item; // 0x494 + union { // 0x494 + uint32 highlighted_item; + uint16 ride_colour; + rct_research_item* research_item; + rct_object_entry* object_entry; + rct_scenario_basic* scenario; + }; uint8 var_498[0x14]; sint16 selected_tab; // 0x4AC sint16 var_4AE; diff --git a/src/object.c b/src/object.c index 00ec3fb430..17d5ee0e12 100644 --- a/src/object.c +++ b/src/object.c @@ -358,17 +358,15 @@ int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b) if (a->flags & 0xF0) { if ((a->flags & 0x0F) != (b->flags & 0x0F)) return 0; - if (*((uint32*)a->name) != *((uint32*)b->name)) - return 0; - if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4]))) + int match = memcmp(a->name, b->name, 8); + if (match) return 0; } else { if (a->flags != b->flags) return 0; - if (*((uint32*)a->name) != *((uint32*)b->name)) - return 0; - if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4]))) + int match = memcmp(a->name, b->name, 8); + if (match) return 0; if (a->checksum != b->checksum) return 0; diff --git a/src/platform/shared.c b/src/platform/shared.c index 362cf2e84f..31436bae6a 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -242,7 +242,11 @@ void platform_draw() if (pitch == (width * 2) + padding) { uint16 *dst = pixels; for (int y = height; y > 0; y--) { - for (int x = width; x > 0; x--) { *dst++ = *(uint16 *)(&gPaletteHWMapped[*src++]); } + for (int x = width; x > 0; x--) { + const uint8 lower = *(uint8 *)(&gPaletteHWMapped[*src++]); + const uint8 upper = *(uint8 *)(&gPaletteHWMapped[*src++]); + *dst++ = (lower << 8) | upper; + } dst = (uint16*)(((uint8 *)dst) + padding); } } diff --git a/src/windows/clear_scenery.c b/src/windows/clear_scenery.c index e6ef342c3d..2bff67b0d9 100644 --- a/src/windows/clear_scenery.c +++ b/src/windows/clear_scenery.c @@ -194,8 +194,8 @@ static void window_clear_scenery_textinput(rct_window *w, int widgetIndex, char static void window_clear_scenery_inputsize(rct_window *w) { - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE; + TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE; + TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE; window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3); } diff --git a/src/windows/dropdown.c b/src/windows/dropdown.c index 43e92b9592..655bbde163 100644 --- a/src/windows/dropdown.c +++ b/src/windows/dropdown.c @@ -324,7 +324,7 @@ static void window_dropdown_paint(rct_window *w, rct_drawpixelinfo *dpi) item = gDropdownItemsFormat[i]; if (item == (uint16)-1 || item == (uint16)-2) { // Image item - image = *((uint32*)&gDropdownItemsArgs[i]); + image = (uint32)gDropdownItemsArgs[i]; if (item == (uint16)-2 && gDropdownHighlightedIndex == i) image++; diff --git a/src/windows/editor_inventions_list.c b/src/windows/editor_inventions_list.c index 6fdab5406a..5beef00b2e 100644 --- a/src/windows/editor_inventions_list.c +++ b/src/windows/editor_inventions_list.c @@ -155,8 +155,6 @@ static rct_window_event_list window_editor_inventions_list_drag_events = { rct_research_item *_editorInventionsListDraggedItem; -#define WindowHighlightedItem(w) *((rct_research_item**)&(w->highlighted_item)) - static void window_editor_inventions_list_drag_open(rct_research_item *researchItem); static void move_research_item(rct_research_item *beforeItem); @@ -437,7 +435,7 @@ static void move_research_item(rct_research_item *beforeItem) w = window_find_by_class(WC_EDITOR_INVENTION_LIST); if (w != NULL) { - WindowHighlightedItem(w) = NULL; + w->research_item = NULL; window_invalidate(w); } } @@ -549,7 +547,7 @@ void window_editor_inventions_list_open() window_init_scroll_widgets(w); w->var_4AE = 0; w->selected_tab = 0; - WindowHighlightedItem(w) = NULL; + w->research_item = NULL; _editorInventionsListDraggedItem = NULL; } @@ -668,8 +666,8 @@ static void window_editor_inventions_list_scrollmouseover(rct_window *w, int scr rct_research_item *researchItem; researchItem = window_editor_inventions_list_get_item_from_scroll_y(scrollIndex, y); - if (researchItem != WindowHighlightedItem(w)) { - WindowHighlightedItem(w) = researchItem; + if (researchItem != w->research_item) { + w->research_item = researchItem; window_invalidate(w); } } @@ -770,7 +768,7 @@ static void window_editor_inventions_list_paint(rct_window *w, rct_drawpixelinfo researchItem = _editorInventionsListDraggedItem; if (researchItem == NULL) - researchItem = WindowHighlightedItem(w); + researchItem = w->research_item; // If the research item is null or a list separator. if (researchItem == NULL || researchItem->entryIndex < 0) return; @@ -842,7 +840,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window *w, rct_drawpix continue; colour = 142; - if (WindowHighlightedItem(w) == researchItem) { + if (w->research_item == researchItem) { if (_editorInventionsListDraggedItem == NULL) { // Highlight top = itemY; @@ -939,8 +937,8 @@ static void window_editor_inventions_list_drag_cursor(rct_window *w, int widgetI inventionListWindow = window_find_by_class(WC_EDITOR_INVENTION_LIST); if (inventionListWindow != NULL) { researchItem = get_research_item_at(x, y); - if (researchItem != WindowHighlightedItem(inventionListWindow)) { - WindowHighlightedItem(inventionListWindow) = researchItem; + if (researchItem != inventionListWindow->research_item) { + inventionListWindow = (rct_window *)researchItem; window_invalidate(inventionListWindow); } } diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index ba322044fb..a1f062a6ac 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -419,7 +419,7 @@ void window_editor_object_selection_open() window->var_4AE = 0; window->selected_tab = 0; window->selected_list_item = -1; - window->highlighted_item = 0xFFFFFFFF; + window->object_entry = (rct_object_entry *) 0xFFFFFFFF; window->min_width = 600; window->min_height = 400; window->max_width = 1200; @@ -836,7 +836,7 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde visible_list_refresh(w); w->selected_list_item = -1; - w->highlighted_item = 0xFFFFFFFF; + w->object_entry = (rct_object_entry *) 0xFFFFFFFF; w->scrolls[0].v_top = 0; object_free_scenario_text(); window_invalidate(w); @@ -856,7 +856,7 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde visible_list_refresh(w); w->selected_list_item = -1; - w->highlighted_item = 0xFFFFFFFF; + w->object_entry = (rct_object_entry *) 0xFFFFFFFF; w->scrolls[0].v_top = 0; object_free_scenario_text(); window_invalidate(w); @@ -1051,7 +1051,7 @@ static void window_editor_object_selection_scroll_mouseover(rct_window *w, int s return; w->selected_list_item = selectedObject; - w->highlighted_item = (uint32)installedEntry; + w->object_entry = installedEntry; object_free_scenario_text(); if (selectedObject != -1) object_get_scenario_text(installedEntry); @@ -1342,7 +1342,7 @@ static void window_editor_object_selection_paint(rct_window *w, rct_drawpixelinf if (w->selected_list_item == -1 || stex_entry == NULL) return; - highlightedEntry = (rct_object_entry*)w->highlighted_item; + highlightedEntry = w->object_entry; type = highlightedEntry->flags & 0x0F; // Draw preview @@ -1458,7 +1458,7 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi // Highlight background colour = 142; - if (listItem->entry == (rct_object_entry*)w->highlighted_item && !(*listItem->flags & OBJECT_SELECTION_FLAG_6)) { + if (listItem->entry == w->object_entry && !(*listItem->flags & OBJECT_SELECTION_FLAG_6)) { gfx_fill_rect(dpi, 0, y, w->width, y + 11, 0x2000031); colour = 14; } @@ -1515,7 +1515,7 @@ static void window_editor_object_set_page(rct_window *w, int page) w->selected_tab = page; w->selected_list_item = -1; - w->highlighted_item = 0xFFFFFFFF; + w->object_entry = (rct_object_entry *)0xFFFFFFFF; w->scrolls[0].v_top = 0; object_free_scenario_text(); diff --git a/src/windows/land.c b/src/windows/land.c index 97b5a85f1b..c98a6ffedb 100644 --- a/src/windows/land.c +++ b/src/windows/land.c @@ -272,7 +272,7 @@ static void window_land_dropdown(rct_window *w, int widgetIndex, int dropdownInd type = (dropdownIndex == -1) ? _selectedFloorTexture : - *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS; + (uint32)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) { RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255; @@ -288,7 +288,7 @@ static void window_land_dropdown(rct_window *w, int widgetIndex, int dropdownInd type = (dropdownIndex == -1) ? _selectedWallTexture : - *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK; + (uint32)gDropdownItemsArgs[dropdownIndex] - SPR_WALL_TEXTURE_ROCK; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) { RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255; @@ -321,8 +321,8 @@ static void window_land_textinput(rct_window *w, int widgetIndex, char *text) static void window_land_inputsize(rct_window *w) { - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE; + TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE; + TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE; window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3); } diff --git a/src/windows/land_rights.c b/src/windows/land_rights.c index b59432fee9..d2e375312f 100644 --- a/src/windows/land_rights.c +++ b/src/windows/land_rights.c @@ -188,8 +188,8 @@ static void window_land_rights_textinput(rct_window *w, int widgetIndex, char *t static void window_land_rights_inputsize(rct_window *w) { - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE; + TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE; + TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE; window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3); } diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index 227483cce9..090f9cb960 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -311,7 +311,7 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) memset(filter, '\0', MAX_PATH); safe_strncpy(filter, "*", MAX_PATH); - strncat(filter, _extension, MAX_PATH); + strncat(filter, _extension, MAX_PATH - strnlen(filter, MAX_PATH) - 1); switch (_type) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) : @@ -336,7 +336,7 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) if (result) { if (!has_extension(path, _extension)) { - strncat(path, _extension, MAX_PATH); + strncat(path, _extension, sizeof(path) - strnlen(path, sizeof(path)) - 1); } window_loadsave_select(w, path); } @@ -684,7 +684,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con listItem = &_listItems[_listItemsCount]; memset(listItem->path, '\0', MAX_PATH); safe_strncpy(listItem->path, directory, MAX_PATH); - strncat(listItem->path, subDir, MAX_PATH); + strncat(listItem->path, subDir, MAX_PATH - strnlen(listItem->path, MAX_PATH) - 1); safe_strncpy(listItem->name, subDir, sizeof(listItem->name)); listItem->type = TYPE_DIRECTORY; _listItemsCount++; @@ -700,7 +700,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con listItem = &_listItems[_listItemsCount]; safe_strncpy(listItem->path, directory, sizeof(listItem->path)); - strncat(listItem->path, fileInfo.path, sizeof(listItem->path)); + strncat(listItem->path, fileInfo.path, sizeof(listItem->path) - strnlen(listItem->path, MAX_PATH) - 1); listItem->type = TYPE_FILE; listItem->date_modified = platform_file_get_modified_time(listItem->path); diff --git a/src/windows/map.c b/src/windows/map.c index 8e6b06b766..12503e84f1 100644 --- a/src/windows/map.c +++ b/src/windows/map.c @@ -935,15 +935,15 @@ static void window_map_show_default_scenario_editor_buttons(rct_window *w) { static void window_map_inputsize_land(rct_window *w) { - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE; + TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE; + TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE; window_text_input_open(w, WIDX_LAND_TOOL, 5128, 5129, STR_NONE, STR_NONE, 3); } static void window_map_inputsize_map(rct_window *w) { - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_MAP_SIZE_PRACTICAL; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_MAP_SIZE_PRACTICAL; + TextInputDescriptionArgs[0] = MINIMUM_MAP_SIZE_PRACTICAL; + TextInputDescriptionArgs[1] = MAXIMUM_MAP_SIZE_PRACTICAL; window_text_input_open(w, WIDX_MAP_SIZE_SPINNER, 5130, 5131, STR_NONE, STR_NONE, 4); } diff --git a/src/windows/mapgen.c b/src/windows/mapgen.c index f95f875ad9..9a48fc074d 100644 --- a/src/windows/mapgen.c +++ b/src/windows/mapgen.c @@ -488,19 +488,19 @@ static void window_mapgen_base_mouseup(rct_window *w, int widgetIndex) gfx_invalidate_screen(); break; case WIDX_MAP_SIZE: - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_MAP_SIZE_PRACTICAL; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_MAP_SIZE_PRACTICAL; + TextInputDescriptionArgs[0] = MINIMUM_MAP_SIZE_PRACTICAL; + TextInputDescriptionArgs[1] = MAXIMUM_MAP_SIZE_PRACTICAL; // Practical map size is 2 lower than the technical map size window_text_input_open(w, WIDX_MAP_SIZE, 5130, 5131, 5182, _mapSize - 2, 4); break; case WIDX_BASE_HEIGHT: - ((uint16*)TextInputDescriptionArgs)[0] = (BASESIZE_MIN - 12) / 2; - ((uint16*)TextInputDescriptionArgs)[1] = (BASESIZE_MAX - 12) / 2; + TextInputDescriptionArgs[0] = (BASESIZE_MIN - 12) / 2; + TextInputDescriptionArgs[1] = (BASESIZE_MAX - 12) / 2; window_text_input_open(w, WIDX_BASE_HEIGHT, 5183, 5184, 5182, (_baseHeight - 12) / 2, 3); break; case WIDX_WATER_LEVEL: - ((uint16*)TextInputDescriptionArgs)[0] = (WATERLEVEL_MIN - 12) / 2; - ((uint16*)TextInputDescriptionArgs)[1] = (WATERLEVEL_MAX - 12) / 2; + TextInputDescriptionArgs[0] = (WATERLEVEL_MIN - 12) / 2; + TextInputDescriptionArgs[1] = (WATERLEVEL_MAX - 12) / 2; window_text_input_open(w, WIDX_WATER_LEVEL, 5185, 5186, 5182, (_waterLevel - 12) / 2, 3); break; } @@ -583,7 +583,7 @@ static void window_mapgen_base_dropdown(rct_window *w, int widgetIndex, int drop type = (dropdownIndex == -1) ? _floorTexture : - *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS; + (uint32)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) { RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255; @@ -599,7 +599,7 @@ static void window_mapgen_base_dropdown(rct_window *w, int widgetIndex, int drop type = (dropdownIndex == -1) ? _wallTexture : - *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK; + (uint32)gDropdownItemsArgs[dropdownIndex] - SPR_WALL_TEXTURE_ROCK; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) { RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255; @@ -790,8 +790,8 @@ static void window_mapgen_simplex_mouseup(rct_window *w, int widgetIndex) window_mapgen_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_SIMPLEX_MAP_SIZE: - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_MAP_SIZE_PRACTICAL; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_MAP_SIZE_PRACTICAL; + TextInputDescriptionArgs[0] = MINIMUM_MAP_SIZE_PRACTICAL; + TextInputDescriptionArgs[1] = MAXIMUM_MAP_SIZE_PRACTICAL; // Practical map size is 2 lower than the technical map size window_text_input_open(w, WIDX_SIMPLEX_MAP_SIZE, 5130, 5131, 5182, _mapSize - 2, 4); break; @@ -916,7 +916,7 @@ static void window_mapgen_simplex_dropdown(rct_window *w, int widgetIndex, int d type = (dropdownIndex == -1) ? _floorTexture : - *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS; + (uint32)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) { RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255; @@ -933,7 +933,7 @@ static void window_mapgen_simplex_dropdown(rct_window *w, int widgetIndex, int d type = (dropdownIndex == -1) ? _wallTexture : - *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK; + (uint32)gDropdownItemsArgs[dropdownIndex] - SPR_WALL_TEXTURE_ROCK; if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) { RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255; diff --git a/src/windows/ride.c b/src/windows/ride.c index d43e9b55e4..5c3f5c1480 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -1183,7 +1183,7 @@ rct_window *window_ride_open(int rideIndex) w->frame_no = 0; w->list_information_type = 0; w->var_492 = 0; - w->highlighted_item = 0; + w->ride_colour = 0; window_ride_disable_tabs(w); w->min_width = 316; w->min_height = 180; @@ -3722,7 +3722,7 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y) uint8 newColourScheme; int interactionType, z, direction; - newColourScheme = (uint8)(*((uint16*)&w->highlighted_item)); + newColourScheme = (uint8)w->ride_colour; rct_xy16 mapCoord = { 0 }; get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_RIDE, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL); @@ -3812,7 +3812,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid ride = GET_RIDE(w->number); rideEntry = ride_get_entry(ride); - colourSchemeIndex = *((uint16*)&w->highlighted_item); + colourSchemeIndex = w->ride_colour; dropdownWidget = widget - 1; switch (widgetIndex) { @@ -3952,20 +3952,20 @@ static void window_ride_colour_dropdown(rct_window *w, int widgetIndex, int drop switch (widgetIndex) { case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN: - *((uint16*)&w->highlighted_item) = dropdownIndex; + w->ride_colour = (uint16)dropdownIndex; window_invalidate(w); break; case WIDX_TRACK_MAIN_COLOUR: - game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0); + game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_TRACK_ADDITIONAL_COLOUR: - game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0); + game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_TRACK_SUPPORT_COLOUR: - game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0); + game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_MAZE_STYLE_DROPDOWN: - game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0); + game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0); break; case WIDX_ENTRANCE_STYLE_DROPDOWN: game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); @@ -4052,7 +4052,7 @@ static void window_ride_colour_invalidate(rct_window *w) RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; // Track colours - int colourScheme = *((uint16*)&w->highlighted_item); + int colourScheme = w->ride_colour; trackColour = ride_get_track_colour(ride, colourScheme); // Maze style @@ -4221,7 +4221,7 @@ static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi) if (widget->type != WWT_EMPTY) gfx_fill_rect(dpi, w->x + widget->left + 1, w->y + widget->top + 1, w->x + widget->right - 1, w->y + widget->bottom - 1, 12); - trackColour = ride_get_track_colour(ride, *((uint16*)&w->highlighted_item)); + trackColour = ride_get_track_colour(ride, w->ride_colour); // if (rideEntry->shop_item == 0xFF) { diff --git a/src/windows/ride_list.c b/src/windows/ride_list.c index e42f8f7eb5..8592edd2c5 100644 --- a/src/windows/ride_list.c +++ b/src/windows/ride_list.c @@ -286,7 +286,7 @@ static void window_ride_list_dropdown(rct_window *w, int widgetIndex, int dropdo if (dropdownIndex == -1) return; - _window_ride_list_information_type = *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - STR_STATUS; + _window_ride_list_information_type = (uint32)gDropdownItemsArgs[dropdownIndex] - STR_STATUS; window_invalidate(w); } } diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 18d3511fe3..40dd3efcb0 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -127,7 +127,7 @@ void window_scenarioselect_open() window_init_scroll_widgets(window); window->viewport_focus_coordinates.var_480 = -1; - window->highlighted_item = 0; + window->scenario = NULL; window_scenarioselect_init_tabs(); @@ -176,7 +176,7 @@ static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_w { if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB5) { w->selected_tab = widgetIndex - 4; - w->highlighted_item = 0; + w->scenario = NULL; window_invalidate(w); window_event_resize_call(w); window_event_invalidate_call(w); @@ -250,8 +250,8 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex selected = scenario; break; } - if (w->highlighted_item != (uint32)selected) { - w->highlighted_item = (uint32)selected; + if (w->scenario != selected) { + w->scenario = selected; window_invalidate(w); } } @@ -289,7 +289,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) } // Return if no scenario highlighted - scenario = (rct_scenario_basic*)w->highlighted_item; + scenario = w->scenario; if (scenario == NULL) return; @@ -345,7 +345,7 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * if (y > dpi->y + dpi->height) continue; - highlighted = w->highlighted_item == (int)scenario; + highlighted = w->scenario == scenario; // Draw hover highlight if (highlighted) diff --git a/src/windows/water.c b/src/windows/water.c index 85ccc87f36..63bc6dc1e5 100644 --- a/src/windows/water.c +++ b/src/windows/water.c @@ -181,8 +181,8 @@ static void window_water_textinput(rct_window *w, int widgetIndex, char *text) static void window_water_inputsize(rct_window *w) { - ((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE; - ((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE; + TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE; + TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE; window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3); } From 4d26e4c4a179c2ffdaaed6a9c5e2ab0ae2266a9a Mon Sep 17 00:00:00 2001 From: Jonathan Haas Date: Tue, 29 Dec 2015 21:08:14 +0100 Subject: [PATCH 04/90] Refactor peep code Name various fields and constants related to peeps. This includes: - Flags for flashing peeps in map window - Animation frames for picked up peeps - Function checking if peep should start to fall - Special sprite handling for slide boards and lawn mowers - Created array for peep sprite entries, renamed some variables and constants --- src/addresses.h | 3 +- src/drawing/drawing.c | 6 +- src/interface/viewport.c | 2 +- src/interface/window.h | 10 ++- src/peep/peep.c | 116 ++++++++++++++++-------------- src/peep/peep.h | 18 +++-- src/peep/staff.c | 13 ++-- src/windows/game_bottom_toolbar.c | 2 +- src/windows/guest.c | 30 ++++---- src/windows/guest_list.c | 16 ++--- src/windows/map.c | 2 +- src/windows/news.c | 2 +- src/windows/park.c | 2 +- src/windows/ride.c | 2 +- src/windows/staff.c | 29 ++++---- src/windows/staff_list.c | 4 +- src/world/sprite.c | 2 + src/world/sprite.h | 21 ++++++ 18 files changed, 168 insertions(+), 112 deletions(-) diff --git a/src/addresses.h b/src/addresses.h index 49ada59c0f..7ab377d187 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -63,6 +63,7 @@ // are implemented in C. Sometimes memory locations are still used even if // they aren't directly referenced, for example when a game is saved and // loaded, large chunks of data is read and written to. +#define RCT2_ADDRESS_SPRITE_ENTRIES 0x00982708 #define RCT2_ADDRESS_EASTEREGG_NAMES 0x00988C20 @@ -191,7 +192,7 @@ #define RCT2_ADDRESS_TICKS_SINCE_DRAG_START 0x009DE540 -#define RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE 0x009DE550 +#define RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE 0x009DE550 #define RCT2_ADDRESS_PICKEDUP_PEEP_X 0x009DE554 #define RCT2_ADDRESS_PICKEDUP_PEEP_Y 0x009DE556 diff --git a/src/drawing/drawing.c b/src/drawing/drawing.c index cb0743544a..d2f8226595 100644 --- a/src/drawing/drawing.c +++ b/src/drawing/drawing.c @@ -485,7 +485,7 @@ void redraw_rain() void gfx_invalidate_pickedup_peep() { if (RCT2_GLOBAL(0x009ABDF2, uint32) != 0) { - int sprite = RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32); + int sprite = RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32); if (sprite != -1) { sprite = sprite & 0x7FFFF; @@ -506,10 +506,10 @@ void gfx_draw_pickedup_peep() return; // Draw picked-up peep - if (RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) != 0xFFFFFFFF) { + if (RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32) != 0xFFFFFFFF) { gfx_draw_sprite( (rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI, - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32), + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32), RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16), RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16), 0 ); diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 91e9e21707..1de8b79160 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -104,7 +104,7 @@ void viewport_init_all() RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_RESET; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1; - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) = 0; RCT2_GLOBAL(0x009DEA50, sint16) = -1; diff --git a/src/interface/window.h b/src/interface/window.h index 714f741a92..14caac8e53 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -262,10 +262,16 @@ typedef struct rct_window { error_variables error; }; sint16 page; // 0x48A - sint16 var_48C; + union { + sint16 picked_peep_old_x; // 0x48C staff/guest window: peep x gets set to 0x8000 on pickup, this is the old value + sint16 var_48C; + }; uint16 frame_no; // 0x48E updated every tic for motion in windows sprites uint16 list_information_type; // 0x490 0 for none, Used as current position of marquee in window_peep - sint16 var_492; + union { + sint16 picked_peep_frame; // 0x492 Animation frame of picked peep in staff window and guest window + sint16 var_492; + }; union { // 0x494 uint32 highlighted_item; uint16 ride_colour; diff --git a/src/peep/peep.c b/src/peep/peep.c index ba9180f355..b6d3759489 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -802,10 +802,17 @@ static void sub_68F41A(rct_peep *peep, int index) } } -/* some sort of check to see if peep is connected to the ground?? */ -int sub_68F3AE(rct_peep* peep){ +/* + * rct2: 0x68F3AE + * Set peep state to falling if path below has gone missing, return 1 if current path is valid, 0 if peep starts falling + */ +int checkForPath(rct_peep *peep){ peep->var_C4++; - if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF))return 1; + if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF)){ + // This condition makes the check happen less often so the peeps hover for a short, + // random time when a path below them has been deleted + return 1; + } rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32); @@ -818,10 +825,14 @@ int sub_68F3AE(rct_peep* peep){ do { if (map_element_get_type(map_element) == map_type){ - if (z == map_element->base_height)return 1; + if (z == map_element->base_height) { + // Found a suitable path + return 1; + } } } while (!map_element_is_last_for_tile(map_element++)); + // Found no suitable path peep_decrement_num_riders(peep); peep->state = PEEP_STATE_FALLING; peep_window_state_update(peep); @@ -829,31 +840,31 @@ int sub_68F3AE(rct_peep* peep){ } void sub_693B58(rct_peep* peep){ - int ebx; - if (peep->action >= 0xFE){ - ebx = RCT2_ADDRESS(0x981D8C, uint8)[peep->var_6D]; + uint8 action_sprite_type; + if (peep->action >= PEEP_ACTION_NONE_1){ // PEEP_ACTION_NONE_1 or PEEP_ACTION_NONE_2 + action_sprite_type = RCT2_ADDRESS(0x981D8C, uint8)[peep->special_sprite]; } else{ - ebx = RCT2_ADDRESS(0x981D8F, uint8)[peep->action]; + action_sprite_type = RCT2_ADDRESS(0x981D8F, uint8)[peep->action]; } - if (ebx == peep->action_sprite_type)return; + if (action_sprite_type == peep->action_sprite_type)return; invalidate_sprite_2((rct_sprite*)peep); - peep->action_sprite_type = ebx; + peep->action_sprite_type = action_sprite_type; - uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2]; - peep->sprite_width = edx[ebx * 4]; - peep->sprite_height_negative = edx[ebx * 4 + 1]; - peep->sprite_height_positive = edx[ebx * 4 + 2]; + rct_sprite_bounds* spriteBounds = g_sprite_entries[peep->sprite_type].sprite_bounds; + peep->sprite_width = spriteBounds[action_sprite_type].sprite_width; + peep->sprite_height_negative = spriteBounds[action_sprite_type].sprite_height_negative; + peep->sprite_height_positive = spriteBounds[action_sprite_type].sprite_height_positive; // This is pointless as nothing will have changed. invalidate_sprite_2((rct_sprite*)peep); } /* 0x00693BE5 */ void sub_693BE5(rct_peep* peep, uint8 al){ - if (al == peep->var_6D)return; + if (al == peep->special_sprite)return; - peep->var_6D = al; + peep->special_sprite = al; // If NONE_1 or NONE_2 if (peep->action >= PEEP_ACTION_NONE_1){ @@ -997,8 +1008,8 @@ int peep_update_action(sint16* x, sint16* y, sint16* xy_distance, rct_peep* peep *x = peep->x + RCT2_ADDRESS(0x981D7C, uint16)[direction / 4]; *y = peep->y + RCT2_ADDRESS(0x981D7E, uint16)[direction / 4]; peep->no_action_frame_no++; - uint32* edi = RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2]; - uint8* _edi = (uint8*)(edi[peep->action_sprite_type * 2 + 1]); + rct_sprite_image * edi = g_sprite_entries[peep->sprite_type].sprite_image; + uint8* _edi = (edi[peep->action_sprite_type]).unkn_04; if (peep->no_action_frame_no >= *_edi){ peep->no_action_frame_no = 0; } @@ -1006,8 +1017,8 @@ int peep_update_action(sint16* x, sint16* y, sint16* xy_distance, rct_peep* peep return 1; } - uint32* edi = RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2]; - uint8* _edi = (uint8*)(edi[peep->action_sprite_type * 2 + 1]); + rct_sprite_image * edi = g_sprite_entries[peep->sprite_type].sprite_image; + uint8* _edi = (edi[peep->action_sprite_type]).unkn_04; peep->action_frame++; int ebx = _edi[peep->action_frame + 1]; @@ -1089,12 +1100,12 @@ void set_sprite_type(rct_peep* peep, uint8 type){ if (peep->state == PEEP_STATE_SITTING){ peep->action = PEEP_ACTION_NONE_1; - peep->var_6F = 7; + peep->next_action_sprite_type = 7; sub_693BAB(peep); } if (peep->state == PEEP_STATE_WATCHING){ peep->action = PEEP_ACTION_NONE_1; - peep->var_6F = 2; + peep->next_action_sprite_type = 2; sub_693BAB(peep); } } @@ -1457,7 +1468,7 @@ void peep_try_get_up_from_sitting(rct_peep* peep){ */ void peep_update_sitting(rct_peep* peep){ if (peep->sub_state == 0){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; //691541 sub_693C9E(peep); @@ -1474,7 +1485,7 @@ void peep_update_sitting(rct_peep* peep){ peep->sprite_direction = ((peep->var_37 + 2) & 3) * 8; invalidate_sprite_2((rct_sprite*)peep); peep->action = 254; - peep->var_6F = 7; + peep->next_action_sprite_type = 7; sub_693BAB(peep); peep->sub_state++; @@ -3414,7 +3425,7 @@ static void peep_update_fixing(int steps, rct_peep* peep){ * rct2: 0x69185D */ static void peep_update_queuing(rct_peep* peep){ - if (!sub_68F3AE(peep)){ + if (!checkForPath(peep)){ remove_peep_from_queue(peep); return; } @@ -3465,7 +3476,7 @@ static void peep_update_queuing(rct_peep* peep){ } } else{ - if (!(peep->time_in_queue & 0x3F) && peep->action == 0xFE && peep->var_6F == 2){ + if (!(peep->time_in_queue & 0x3F) && peep->action == 0xFE && peep->next_action_sprite_type == 2){ switch (peep->sprite_type){ case 0xF: case 0x10: @@ -3518,7 +3529,7 @@ static void peep_update_queuing(rct_peep* peep){ */ static void peep_update_mowing(rct_peep* peep){ peep->var_E2 = 0; - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; invalidate_sprite_2((rct_sprite*)peep); while (1){ @@ -3566,7 +3577,7 @@ static void peep_update_mowing(rct_peep* peep){ static void peep_update_watering(rct_peep* peep){ peep->var_E2 = 0; if (peep->sub_state == 0){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return; @@ -3622,7 +3633,7 @@ static void peep_update_emptying_bin(rct_peep* peep){ peep->var_E2 = 0; if (peep->sub_state == 0){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return; @@ -3691,7 +3702,7 @@ static void peep_update_emptying_bin(rct_peep* peep){ */ static void peep_update_sweeping(rct_peep* peep){ peep->var_E2 = 0; - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; invalidate_sprite_2((rct_sprite*)peep); @@ -3726,7 +3737,7 @@ static void peep_update_sweeping(rct_peep* peep){ * rct2: 0x6902A2 */ static void peep_update_1(rct_peep* peep){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; peep_decrement_num_riders(peep); @@ -3795,7 +3806,7 @@ static void peep_update_leaving_park(rct_peep* peep){ */ static void peep_update_watching(rct_peep* peep){ if (peep->sub_state == 0){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return; @@ -3807,7 +3818,7 @@ static void peep_update_watching(rct_peep* peep){ invalidate_sprite_2((rct_sprite*)peep); peep->action = 0xFE; - peep->var_6F = 2; + peep->next_action_sprite_type = 2; sub_693BAB(peep); @@ -4132,7 +4143,7 @@ static void peep_update_walking_break_scenery(rct_peep* peep){ */ static void peep_update_buying(rct_peep* peep) { - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; rct_ride* ride = GET_RIDE(peep->current_ride); if (ride->type == RIDE_TYPE_NULL || ride->status != RIDE_STATUS_OPEN){ @@ -4225,7 +4236,7 @@ static void peep_update_buying(rct_peep* peep) */ static void peep_update_using_bin(rct_peep* peep){ if (peep->sub_state == 0){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return; @@ -4400,7 +4411,7 @@ static void peep_update_heading_to_inspect(rct_peep* peep){ return; } - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); @@ -4513,7 +4524,7 @@ static void peep_update_answering(rct_peep* peep){ return; } - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); @@ -4768,7 +4779,7 @@ static int peep_update_patrolling_find_sweeping(rct_peep* peep){ */ static void peep_update_patrolling(rct_peep* peep){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return; @@ -4808,7 +4819,7 @@ static void peep_update_patrolling(rct_peep* peep){ * rct2: 0x0069030A */ static void peep_update_walking(rct_peep* peep){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; if (peep->flags & PEEP_FLAGS_WAVING){ if (peep->action >= PEEP_ACTION_NONE_1){ @@ -5484,7 +5495,7 @@ rct_peep *peep_generate(int x, int y, int z) peep->outside_of_park = 1; peep->state = PEEP_STATE_FALLING; peep->action = PEEP_ACTION_NONE_2; - peep->var_6D = 0; + peep->special_sprite = 0; peep->action_sprite_image_offset = 0; peep->no_action_frame_no = 0; peep->action_sprite_type = 0; @@ -5492,10 +5503,10 @@ rct_peep *peep_generate(int x, int y, int z) peep->favourite_ride = 0xFF; peep->favourite_ride_rating = 0; - uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2]; - peep->sprite_width = edx[peep->action_sprite_type * 4]; - peep->sprite_height_negative = edx[peep->action_sprite_type * 4 + 1]; - peep->sprite_height_positive = edx[peep->action_sprite_type * 4 + 2]; + rct_sprite_bounds* spriteBounds = g_sprite_entries[peep->sprite_type].sprite_bounds; + peep->sprite_width = spriteBounds[peep->action_sprite_type].sprite_width; + peep->sprite_height_negative = spriteBounds[peep->action_sprite_type].sprite_height_negative; + peep->sprite_height_positive = spriteBounds[peep->action_sprite_type].sprite_height_positive; peep->sprite_direction = 0; @@ -6160,14 +6171,15 @@ void peep_set_map_tooltip(rct_peep *peep) void sub_693BAB(rct_peep* peep) { - uint8 bl = peep->var_6F; - if (bl != peep->action_sprite_type) { + // TBD: Add nextActionSpriteType as function parameter and make peep->next_action_sprite_type obsolete? + uint8 nextActionSpriteType = peep->next_action_sprite_type; + if (nextActionSpriteType != peep->action_sprite_type) { invalidate_sprite_2((rct_sprite*)peep); - peep->action_sprite_type = bl; - uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2]; - peep->sprite_width = edx[bl * 4]; - peep->sprite_height_negative = edx[bl * 4 + 1]; - peep->sprite_height_positive = edx[bl * 4 + 2]; + peep->action_sprite_type = nextActionSpriteType; + rct_sprite_bounds* spriteBounds = g_sprite_entries[peep->sprite_type].sprite_bounds; + peep->sprite_width = spriteBounds[nextActionSpriteType].sprite_width; + peep->sprite_height_negative = spriteBounds[nextActionSpriteType].sprite_height_negative; + peep->sprite_height_positive = spriteBounds[nextActionSpriteType].sprite_height_positive; invalidate_sprite_2((rct_sprite*)peep); } } @@ -6235,7 +6247,7 @@ static int peep_update_queue_position(rct_peep* peep){ return 1; peep->action = PEEP_ACTION_NONE_1; - peep->var_6F = 2; + peep->next_action_sprite_type = 2; if (RCT2_GLOBAL(0x00F1AEF1, uint8) != 0xFE) invalidate_sprite_2((rct_sprite*)peep); return 1; diff --git a/src/peep/peep.h b/src/peep/peep.h index c758f335b7..3bea736123 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -372,6 +372,12 @@ enum { PEEP_RIDE_DECISION_THINKING = 1 << 2 }; +// Flags used by peep->list_flags +enum { + PEEP_LIST_FLAGS_VISIBLE = 1 << 8, // Peep is eligible to show in summarized guest list window (is inside park?) + PEEP_LIST_FLAGS_FLASHING = 1 << 9, // Peep belongs to highlighted group (flashes red on map) +}; + typedef struct { uint8 type; //0 uint8 item; //1 @@ -389,7 +395,7 @@ typedef struct { // Height from center of sprite to bottom uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 var_0C; + uint16 list_flags; // 0x0C Used for highlighting peeps on map with staff list or guest list open sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -408,7 +414,7 @@ typedef struct { uint16 next_y; // 0x26 uint8 next_z; // 0x28 uint8 next_var_29; // 0x29 - uint8 outside_of_park; + uint8 outside_of_park; // 0x2A uint8 state; // 0x2B uint8 sub_state; // 0x2C uint8 sprite_type; // 0x2D @@ -458,9 +464,11 @@ typedef struct { uint8 standing_flags; //0x6C }; }; - uint8 var_6D; // 0x6D + // Normally 0, 1 for carrying sliding board on spiral slide ride, 2 for carrying lawn mower + uint8 special_sprite; // 0x6D uint8 action_sprite_type; // 0x6E - uint8 var_6F; + // Seems to be used like a local variable, as it's always set before calling sub_693BAB, which reads this again + uint8 next_action_sprite_type; // 0x6F uint8 action_sprite_image_offset; // 0x70 uint8 action; // 0x71 uint8 action_frame; // 0x72 @@ -488,7 +496,7 @@ typedef struct { uint8 previous_ride; // 0xAD uint16 previous_ride_time_out; // 0xAE rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0 - uint8 var_C4; // 0xC4 + uint8 var_C4; // 0xC4 has something to do with peep falling, see peep.checkForPath union { uint8 staff_id; // 0xC5 uint8 guest_heading_to_ride_id; // 0xC5 diff --git a/src/peep/staff.c b/src/peep/staff.c index 60348ac860..7ded0b1528 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -109,7 +109,8 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, int newStaffId = i; - int _eax, _ebx, _ecx = _cx, _edx; + int _eax, _ebx, _ecx = _cx; + rct_sprite_bounds *spriteBounds; _ebx = _bl; rct_peep* newPeep = &(create_sprite(_bl)->peep); @@ -129,7 +130,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, newPeep->sprite_identifier = 1; newPeep->window_invalidate_flags = 0; newPeep->action = PEEP_ACTION_NONE_2; - newPeep->var_6D = 0; + newPeep->special_sprite = 0; newPeep->action_sprite_image_offset = 0; newPeep->no_action_frame_no = 0; newPeep->action_sprite_type = 0; @@ -181,10 +182,10 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, newPeep->name_string_idx = staff_type + 0x300; newPeep->sprite_type = _eax; - _edx = RCT2_ADDRESS(0x0098270C, uint32)[_eax * 2]; - newPeep->sprite_width = *((uint8*)_edx); - newPeep->sprite_height_negative = *((uint8*)(_edx + 1)); - newPeep->sprite_height_positive = *((uint8*)(_edx + 2)); + spriteBounds = g_sprite_entries[_eax].sprite_bounds; + newPeep->sprite_width = spriteBounds->sprite_width; + newPeep->sprite_height_negative = spriteBounds->sprite_height_negative; + newPeep->sprite_height_positive = spriteBounds->sprite_height_positive; if ((gConfigGeneral.auto_staff_placement != 0) != ((SDL_GetModState() & KMOD_SHIFT) != 0)) { newPeep->state = PEEP_STATE_FALLING; diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index 9dbc2aebf4..5f97e96b05 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -551,7 +551,7 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc } } - uint32 image_id_base = *RCT2_ADDRESS(0x00982708, uint32*)[peep->sprite_type * 2]; + uint32 image_id_base = g_sprite_entries[peep->sprite_type].sprite_image->base_image; image_id_base += w->frame_no & 0xFFFFFFFC; image_id_base++; diff --git a/src/windows/guest.c b/src/windows/guest.c index 58f808db5c..b1b4421c24 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -503,7 +503,7 @@ void window_guest_open(rct_peep* peep){ window->viewport_focus_coordinates.y = 0; window->frame_no = 0; window->list_information_type = 0; - window->var_492 = 0; + window->picked_peep_frame = 0; window->highlighted_item = 0; window_guest_disable_widgets(window); window->min_width = 192; @@ -625,7 +625,7 @@ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex) return; } - w->var_48C = peep->x; + w->picked_peep_old_x = peep->x; remove_peep_from_ride(peep); invalidate_sprite_2((rct_sprite*)peep); @@ -830,7 +830,7 @@ void window_guest_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == STAFF_TYPE_ENTERTAINER) y++; - int ebx = *(RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2]) + 1; + int ebx = g_sprite_entries[peep->sprite_type].sprite_image->base_image + 1; int eax = 0; @@ -1182,7 +1182,7 @@ void window_guest_overview_tool_update(rct_window* w, int widgetIndex, int x, in map_invalidate_selection_rect(); } - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; int interactionType; get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_NONE, NULL, NULL, &interactionType, NULL, NULL); @@ -1193,19 +1193,21 @@ void window_guest_overview_tool_update(rct_window* w, int widgetIndex, int x, in y += 16; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, uint16) = y; - w->var_492++; - if (w->var_492 >= 48)w->var_492 = 0; + w->picked_peep_frame++; + if (w->picked_peep_frame >= 48) { + w->picked_peep_frame = 0; + } rct_peep* peep; peep = GET_PEEP(w->number); - int ebx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22]; - ebx += w->var_492 >> 2; + uint32 imageId = g_sprite_entries[peep->sprite_type].sprite_image[11].base_image; + imageId += w->picked_peep_frame >> 2; int ebp = peep->tshirt_colour << 19; int ecx = peep->trousers_colour << 24; - ebx |= ebp | ecx | 0xA0000000; - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) = ebx; + imageId |= ebp | ecx | 0xA0000000; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32) = imageId; } /** @@ -1254,7 +1256,7 @@ void window_guest_overview_tool_down(rct_window* w, int widgetIndex, int x, int peep->state = 0; peep_window_state_update(peep); peep->action = 0xFF; - peep->var_6D = 0; + peep->special_sprite = 0; peep->action_sprite_image_offset = 0; peep->action_sprite_type = 0xFF; peep->var_C4 = 0; @@ -1279,7 +1281,7 @@ void window_guest_overview_tool_abort(rct_window *w, int widgetIndex) if (peep->state != PEEP_STATE_PICKED) return; - sprite_move( w->var_48C, peep->y, peep->z + 8, (rct_sprite*)peep); + sprite_move(w->picked_peep_old_x, peep->y, peep->z + 8, (rct_sprite*)peep); invalidate_sprite_2((rct_sprite*)peep); if (peep->x != (sint16)0x8000){ @@ -1287,13 +1289,13 @@ void window_guest_overview_tool_abort(rct_window *w, int widgetIndex) peep->state = 0; peep_window_state_update(peep); peep->action = 0xFF; - peep->var_6D = 0; + peep->special_sprite = 0; peep->action_sprite_image_offset = 0; peep->action_sprite_type = 0; peep->var_C4 = 0; } - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; } /** diff --git a/src/windows/guest_list.c b/src/windows/guest_list.c index b1079bda40..f4989979c0 100644 --- a/src/windows/guest_list.c +++ b/src/windows/guest_list.c @@ -590,7 +590,7 @@ static void window_guest_list_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); // Tab 1 image i = (_window_guest_list_selected_tab == 0 ? w->list_information_type & 0x0FFFFFFFC : 0); - i += RCT2_ADDRESS(RCT2_GLOBAL(0x00982708, int), int)[0] + 1; + i += g_sprite_entries[0].sprite_image->base_image + 1; i |= 0xA1600000; gfx_draw_sprite( dpi, @@ -655,14 +655,14 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, // For each guest FOR_ALL_GUESTS(spriteIndex, peep) { - peep->var_0C &= ~0x200; + peep->list_flags &= ~(PEEP_LIST_FLAGS_FLASHING); if (peep->outside_of_park != 0) continue; if (_window_guest_list_selected_filter != -1) { if (window_guest_list_is_peep_in_filter(peep)) continue; RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) |= (1 << 0); - peep->var_0C |= 0x200; + peep->list_flags |= PEEP_LIST_FLAGS_FLASHING; } if (_window_guest_list_tracking_only && !(peep->flags & PEEP_FLAGS_TRACKING)) continue; @@ -841,11 +841,11 @@ static void window_guest_list_find_groups() // Set all guests to unassigned FOR_ALL_GUESTS(spriteIndex, peep) if (peep->outside_of_park == 0) - peep->var_0C |= (1 << 8); + peep->list_flags |= PEEP_LIST_FLAGS_VISIBLE; // For each guest / group FOR_ALL_GUESTS(spriteIndex, peep) { - if (peep->outside_of_park != 0 || !(peep->var_0C & (1 << 8))) + if (peep->outside_of_park != 0 || !(peep->list_flags & PEEP_LIST_FLAGS_VISIBLE)) continue; // New group, cap at 240 though @@ -856,7 +856,7 @@ static void window_guest_list_find_groups() int ax = peep->sprite_index; _window_guest_list_num_groups++; _window_guest_list_groups_num_guests[groupIndex] = 1; - peep->var_0C &= ~(1 << 8); + peep->list_flags &= ~(PEEP_LIST_FLAGS_VISIBLE); get_arguments_from_peep( peep, &_window_guest_list_groups_argument_1[groupIndex], &_window_guest_list_groups_argument_2[groupIndex]); RCT2_GLOBAL(0x00F1EDF6, uint32) = _window_guest_list_groups_argument_1[groupIndex]; @@ -868,7 +868,7 @@ static void window_guest_list_find_groups() // Find more peeps that belong to same group FOR_ALL_GUESTS(spriteIndex2, peep2) { - if (peep2->outside_of_park != 0 || !(peep2->var_0C & (1 << 8))) + if (peep2->outside_of_park != 0 || !(peep2->list_flags & PEEP_LIST_FLAGS_VISIBLE)) continue; uint32 argument1, argument2; @@ -879,7 +879,7 @@ static void window_guest_list_find_groups() // Assign guest _window_guest_list_groups_num_guests[groupIndex]++; - peep2->var_0C &= ~(1 << 8); + peep2->list_flags &= ~(PEEP_LIST_FLAGS_VISIBLE); // Add face sprite, cap at 56 though if (_window_guest_list_groups_num_guests[groupIndex] >= 56) diff --git a/src/windows/map.c b/src/windows/map.c index 12503e84f1..76921d99ee 100644 --- a/src/windows/map.c +++ b/src/windows/map.c @@ -1028,7 +1028,7 @@ static void window_map_paint_peep_overlay(rct_drawpixelinfo *dpi) color = 0x14; - if ((peep->var_0C & 0x200) != 0) { + if ((peep->list_flags & PEEP_LIST_FLAGS_FLASHING) != 0) { if (peep->type == PEEP_TYPE_STAFF) { if ((RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) & (1 << 3)) != 0) { color = 0x8A; diff --git a/src/windows/news.c b/src/windows/news.c index 5885811365..77a0760e01 100644 --- a/src/windows/news.c +++ b/src/windows/news.c @@ -344,7 +344,7 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s } } - uint32 image_id = *RCT2_ADDRESS(0x00982708, uint32*)[sprite_type * 2]; + uint32 image_id = g_sprite_entries[sprite_type].sprite_image->base_image; image_id += 0xA0000001; image_id |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24); diff --git a/src/windows/park.c b/src/windows/park.c index 15f419ede7..d8306d4d74 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -1982,7 +1982,7 @@ static void window_park_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) sprite_idx += (w->frame_no / 8) % 8; gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_3].left, w->y + w->widgets[WIDX_TAB_3].top, 0); - sprite_idx = *RCT2_GLOBAL(0x00982708, sint32*) + 1; + sprite_idx = g_sprite_entries[0].sprite_image->base_image + 1; if (w->page == WINDOW_PARK_PAGE_GUESTS) sprite_idx += w->var_492 & 0xFFFFFFFC; diff --git a/src/windows/ride.c b/src/windows/ride.c index 5c3f5c1480..13d0eb5666 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -1086,7 +1086,7 @@ static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w) if (w->page == WINDOW_RIDE_PAGE_CUSTOMER) spriteIndex = w->var_492 & ~3; - spriteIndex += RCT2_GLOBAL(RCT2_GLOBAL(0x00982708, uint32), uint32); + spriteIndex += g_sprite_entries[0].sprite_image->base_image; spriteIndex += 1; spriteIndex |= 0xA9E00000; diff --git a/src/windows/staff.c b/src/windows/staff.c index 0d3833830f..3da193a083 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -449,7 +449,7 @@ void window_staff_overview_mouseup(rct_window *w, int widgetIndex) return; } - w->var_48C = peep->x; + w->picked_peep_old_x = peep->x; remove_peep_from_ride(peep); invalidate_sprite_2((rct_sprite*)peep); @@ -987,7 +987,7 @@ void window_staff_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi) if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == STAFF_TYPE_ENTERTAINER) y++; - int ebx = *(RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2]) + 1; + int ebx = g_sprite_entries[peep->sprite_type].sprite_image->base_image + 1; int eax = 0; @@ -1096,7 +1096,7 @@ void window_staff_overview_tool_update(rct_window* w, int widgetIndex, int x, in if (widgetIndex != WIDX_PICKUP) return; - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; int interactionType; get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_NONE, NULL, NULL, &interactionType, NULL, NULL); @@ -1107,16 +1107,19 @@ void window_staff_overview_tool_update(rct_window* w, int widgetIndex, int x, in y += 16; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, uint16) = y; - w->var_492++; - if (w->var_492 >= 48)w->var_492 = 0; + w->picked_peep_frame++; + if (w->picked_peep_frame >= 48) { + w->picked_peep_frame = 0; + } rct_peep* peep; peep = GET_PEEP(w->number); - int sprite_idx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22]; - sprite_idx += w->var_492 >> 2; - sprite_idx |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000; - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) = sprite_idx; + uint32 imageId = g_sprite_entries[peep->sprite_type].sprite_image[11].base_image; + imageId += w->picked_peep_frame >> 2; + + imageId |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32) = imageId; } /** @@ -1163,7 +1166,7 @@ void window_staff_overview_tool_down(rct_window* w, int widgetIndex, int x, int peep->state = PEEP_STATE_FALLING; peep_window_state_update(peep); peep->action = 0xFF; - peep->var_6D = 0; + peep->special_sprite = 0; peep->action_sprite_image_offset = 0; peep->action_sprite_type = 0; peep->var_C4 = 0; @@ -1191,7 +1194,7 @@ void window_staff_overview_tool_abort(rct_window *w, int widgetIndex) rct_peep* peep = GET_PEEP(w->number); if (peep->state != PEEP_STATE_PICKED) return; - sprite_move(w->var_48C, peep->y, peep->z + 8, (rct_sprite*)peep); + sprite_move(w->picked_peep_old_x, peep->y, peep->z + 8, (rct_sprite*)peep); invalidate_sprite_2((rct_sprite*)peep); if (peep->x != (sint16)0x8000){ @@ -1199,13 +1202,13 @@ void window_staff_overview_tool_abort(rct_window *w, int widgetIndex) peep->state = PEEP_STATE_FALLING; peep_window_state_update(peep); peep->action = 0xFF; - peep->var_6D = 0; + peep->special_sprite = 0; peep->action_sprite_image_offset = 0; peep->action_sprite_type = 0; peep->var_C4 = 0; } - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; } else if (widgetIndex == WIDX_PATROL){ hide_gridlines(); diff --git a/src/windows/staff_list.c b/src/windows/staff_list.c index 76595b00da..afd7271fd7 100644 --- a/src/windows/staff_list.c +++ b/src/windows/staff_list.c @@ -310,10 +310,10 @@ void window_staff_list_update(rct_window *w) RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) |= (1 << 2); FOR_ALL_PEEPS(spriteIndex, peep) { if (peep->type == PEEP_TYPE_STAFF) { - peep->var_0C &= ~0x200; + peep->list_flags &= ~(PEEP_LIST_FLAGS_FLASHING); if (peep->staff_type == RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) { - peep->var_0C |= 0x200; + peep->list_flags |= PEEP_LIST_FLAGS_FLASHING; } } } diff --git a/src/world/sprite.c b/src/world/sprite.c index 40ec76621a..96a9b1eebb 100644 --- a/src/world/sprite.c +++ b/src/world/sprite.c @@ -29,6 +29,8 @@ rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite); +rct_sprite_entry* g_sprite_entries = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_ENTRIES, rct_sprite_entry); + static uint16 sprite_get_first_in_quadrant(int x, int y) { int offset = ((x & 0x1FE0) << 3) | (y >> 5); diff --git a/src/world/sprite.h b/src/world/sprite.h index 89fdb512d2..9ce80c93b7 100644 --- a/src/world/sprite.h +++ b/src/world/sprite.h @@ -300,6 +300,23 @@ typedef union { rct_crash_splash crash_splash; } rct_sprite; +typedef struct { + uint8 sprite_width; // 0x00 + uint8 sprite_height_negative; // 0x01 + uint8 sprite_height_positive; // 0x02 + uint8 unused; // 0x03 +} rct_sprite_bounds; + +typedef struct { + uint32 base_image; // 0x00 + uint8* unkn_04; // 0x04 +} rct_sprite_image; + +typedef struct { + rct_sprite_image *sprite_image; // 0x00 + rct_sprite_bounds *sprite_bounds; // 0x04 +} rct_sprite_entry; + enum { SPRITE_MISC_0, SPRITE_MISC_MONEY_EFFECT, @@ -316,6 +333,10 @@ enum { // rct2: 0x010E63BC extern rct_sprite* g_sprite_list; +// rct2: 0x00982708 +extern rct_sprite_entry* g_sprite_entries; + + rct_sprite *create_sprite(uint8 bl); void reset_sprite_list(); void reset_0x69EBE4(); From 928db1bf181f4f6ce1b6b23e471862489a44ced1 Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 1 Jan 2016 04:00:18 +0000 Subject: [PATCH 05/90] Merge Localisation/master into OpenRCT2/develop. --- data/language/korean.txt | 597 ++++++++++++++++++++------------------- 1 file changed, 300 insertions(+), 297 deletions(-) diff --git a/data/language/korean.txt b/data/language/korean.txt index 4a2dfc67dd..18e4cb45ed 100644 --- a/data/language/korean.txt +++ b/data/language/korean.txt @@ -2898,7 +2898,7 @@ STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat: (Allister Brimble) copyright {CO STR_2888 :{WINDOW_COLOUR_2}Atlantis: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2889 :{WINDOW_COLOUR_2}Wild West Kid: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2891 :{WINDOW_COLOUR_2}Blockbuster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2891 :{WINDOW_COLOUR_2}블록buster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2892 :{WINDOW_COLOUR_2}Airtime Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag: (Scott Joplin/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy: (Steve Blenkinsopp) copyright {COPYRIGHT} Chris Sawyer @@ -4070,7 +4070,7 @@ STR_CPTY :차량당 2명의 승객 [HSKELT] STR_NAME :나선 미끄럼틀 -STR_DESC :Wooden building with an internal staircase and an external spiral slide for use with slide mats +STR_DESC :내부의 계단을 타고 올라가서 외부의 나선형 미끄럼틀을 매트를 타고 내려오는 목재 건물 STR_CPTY : [MGR1] @@ -4080,8 +4080,8 @@ STR_CPTY :승객 16명 [MONBK] STR_NAME :모노레일 자전거 -STR_DESC :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders -STR_CPTY :1 rider per bicycle +STR_DESC :탑승자가 직접 페달을 밟으면 강철 모노레일 트랙 위를 움직이는 특별한 자전거 +STR_CPTY :자전거 당 1명의 탑승객 [OBS1] STR_NAME :전망탑 @@ -4105,18 +4105,18 @@ STR_CPTY :차량당 2명의 승객 [SRINGS] STR_NAME :스페이스 링 -STR_DESC :Concentric pivoting rings allowing the riders free rotation in all directions +STR_DESC :동심원 모양의 고리가 탑승자를 어느 방향이든 회전시킬 수 있는 놀이기구 STR_CPTY :각 1명 [SUBMAR] STR_NAME :잠수함 -STR_DESC :Riders ride in a submerged submarine through an underwater course +STR_DESC :수면 아래 코스를 이동하는 잠수함에 탑승하는 놀이기구 STR_CPTY :잠수함당 4명의 승객 [TRUCK1] STR_NAME :소형 트럭 -STR_DESC :Powered vehicles in the shape of pickup trucks -STR_CPTY :승객 1명 per truck +STR_DESC :소형 트럭 모양의 차량 +STR_CPTY :트럭당 승객 1명 [VCR] STR_NAME :빈티지 차량 @@ -4125,32 +4125,32 @@ STR_CPTY :차량당 2명의 승객 [AMT1] STR_NAME :탄광 열차 코스터 -STR_DESC :Mine train themed roller coaster trains career along steel roller coaster track made to look like old railway track +STR_DESC :오래된 선로 트랙처럼 보이지만 튼튼한 강철로 만든 롤러코스터 트랙을 따라 달리는, 광산 차량을 테마로 한 롤러코스터 차량 STR_CPTY :차량당 2명 또는 4명의 승객 [ARRSW1] STR_NAME :서스펜디드 스윙잉 차량 -STR_DESC :Suspended roller coaster train consisting of cars able to swing freely as the train goes around corners +STR_DESC :차량이 코너를 돌면 자유롭게 흔들거리게 만들어진 서스펜디드 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [ARRSW2] STR_NAME :서스펜디드 스윙잉 에어로플레인 차량 -STR_DESC :Suspended roller coaster train consisting of aeroplane shaped cars able to swing freely as the train goes around corners +STR_DESC :차량이 코너를 돌면 자유롭게 흔들거리게 만들어진 비행기 모양의 서스펜디드 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [ARRT1] STR_NAME :코르크스크류 롤러코스터 -STR_DESC :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_DESC :코르크스크류와 루프를 도는 구성을 지닌 강철 트랙의 롤러코스터 STR_CPTY :차량당 4명의 승객 [ARRT2] STR_NAME :하이퍼코스터 -STR_DESC :A tall non-inverting roller coaster with large drops, high speed, and comfortable trains with only lap bar restraints +STR_DESC :무릎 안전바만 채운 채로, 뒤집어지지는 않지만 큰 낙하와 빠른 속도, 편안한 승차감을 자랑하는 롤러코스터 STR_CPTY :차량당 6명의 승객 [ARRX] STR_NAME :멀티 디멘션 코스터 차량 -STR_DESC :Cars with seats capable of pitching the riders head-over-heels +STR_DESC :탑승객의 머리와 발을 뒤집어버리는 등의 회전 좌석을 가진 차량 STR_CPTY :차량당 4명의 승객 [BATFL] @@ -4160,72 +4160,72 @@ STR_CPTY :차량당 2명의 승객 [BMAIR] STR_NAME :플라잉 롤러코스터 -STR_DESC :Riders are held in comfortable seats below the track, travelling through twisted track to give the ultimate flying experience +STR_DESC :탑승객에게 정말로 나는 듯한 경험을 주기 위해, 트랙 밑에 달린 편안한 좌석에 앉아서 꼬여있는 트랙을 따라 움직이는 놀이기구 STR_CPTY :차량당 4명의 승객 [BMFL] STR_NAME :플로어리스 롤러 코스터 -STR_DESC :Wide coaster trains with no floor give the passengers an open-air feeling as they glide through twisted track and multiple inversions +STR_DESC :꼬여있는 트랙과 여러 전이를 미끄러지듯 통과하면서 승객들에게 광활한 허공을 느끼게 해주는, 바닥이 없는 넓은 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [BMRB] STR_NAME :하이퍼 트위스터 차량 (광폭형) -STR_DESC :Wide 4-across cars with raised seating and simple lap restraints +STR_DESC :향상된 탑승감과 간단한 무릎 안전바를 갖고 있는 넓은 4인승 차량 STR_CPTY :차량당 4명의 승객 [BMSD] STR_NAME :트위스터 롤러코스터 -STR_DESC :Wide roller coaster trains glide along smooth steel track, traveling through a variety of inversions +STR_DESC :여러 종류의 루프를 돌면서 부드러운 강철 트랙을 달리는 넓은 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [BMSU] STR_NAME :스탠드 업 트위스터 코스터 -STR_DESC :Riders ride in a standing position in wide coaster trains with specially designed restraints as they race down smooth drops and through multiple inversions +STR_DESC :탑승자들이 선 자세로 낙하와 여러 특수 트랙을 즐길 수 있도록 특수하게 디자인된 안전바가 있는 넓은 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [BMVD] STR_NAME :버티컬 드롭 롤러코스터 -STR_DESC :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_DESC :자유 낙하의 극한 경험을 선사하기 위해 완전히 수직 경사 트랙을 따라 하강하는 아주 폭이 넓은 차량 STR_CPTY :차량당 6명의 승객 [BOB1] STR_NAME :봅슬레이 코스터 -STR_DESC :Riders career down a twisting track in bobsleigh-shaped cars guided only by the curvature and banking of the semi-circular track +STR_DESC :반원형 트랙의 커브와 뱅킹만을 따라 이동하는 봅슬레이 모양의 차량을 타고 이리 저리 꼬여있는 트랙을 따라 내려오는 놀이기구 STR_CPTY :차량당 2명의 승객 [GOLTR] STR_NAME :하이퍼 트위스터 차량 -STR_DESC :Spacious trains with simple lap restraints +STR_DESC :간단한 무릎 안전바를 가진 널찍한 차량 STR_CPTY :차량당 6명의 승객 [INTBOB] STR_NAME :플라잉 턴 -STR_DESC :Riders career down a twisting track in large bobsleigh cars guided only by the curvature and banking of the semi-circular track +STR_DESC :반원형 트랙의 커브와 뱅킹만을 따라 이동하는 봅슬레이 모양의 차량을 타고 이리 저리 꼬여있는 트랙을 따라 내려오는 놀이기구 STR_CPTY :차량당 6명의 승객 [INTINV] STR_NAME :인버티드 임펄스 코스터 -STR_DESC :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track +STR_DESC :수직으로 솟은 트랙을 오르기 위해 역에서 급가속한 뒤, 다시 역방향으로 되돌아와 역을 통과해서 뒷쪽의 또다른 수직 트랙을 올라가는 인버티드 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [INTST] STR_NAME :기가 코스터 -STR_DESC :A giant steel roller coaster capable of smooth drops and hills of over 300ft +STR_DESC :90m 이상의 부드러운 낙하와 상승이 가능한 거대한 강철 롤러코스터 STR_CPTY :차량당 4명의 승객 [IVMC1] STR_NAME :인버티트 헤어핀 코스터 -STR_DESC :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_DESC :급회전과 급경사를 가진 지그재그 모양의 트랙 아래를 달리는 개별 차량 STR_CPTY :차량당 4명의 승객 [JSTAR1] -STR_NAME :터보건 차량 -STR_DESC :Toboggan-shaped roller coaster cars with in-line seating +STR_NAME :터보건 썰매 차량 +STR_DESC :한 줄로 탑승하는 터보건 썰매 모양의 롤러코스터 STR_CPTY :차량당 4명의 승객 [MFT] -STR_NAME :굴절 롤러코스터 차량 Roller Coaster Trains -STR_DESC :Roller coaster trains with short single-row cars and open fronts +STR_NAME :연결식 롤러코스터 차량 +STR_DESC :하나의 열로 된 짧은 차량과 개방된 전면부를 가진 롤러코스터 차량 STR_CPTY :차량당 2명의 승객 [NEMT] @@ -4501,7 +4501,7 @@ STR_CPTY :보트당 2명의 승객 [RFTBOAT] STR_NAME :리버 래프트 STR_DESC :Raft-shaped boats gently meander around a river track -STR_CPTY :raft당 4명의 승객 +STR_CPTY :래프트당 4명의 승객 [SPBOAT] STR_NAME :스플래시 보트 @@ -4599,7 +4599,7 @@ STR_NAME :핫도그 가게 STR_DESC :핫도그를 파는 가게 [ICECR1] -STR_NAME :아이스크림 가게 +STR_NAME :과일 아이스크림 가게 STR_DESC :과일 아이스크림을 파는 가게 [ICECR2] @@ -4707,43 +4707,43 @@ STR_NAME :축구 STR_NAME :테니스 공 [BEANST1] -STR_NAME :Giant Beanstalk +STR_NAME :대형 강낭콩 줄기 [BEANST2] -STR_NAME :Giant Beanstalk +STR_NAME :대형 강낭콩 줄기 [BRBASE] -STR_NAME :Base Block +STR_NAME :기본 블록 [BRBASE2] -STR_NAME :Base Block +STR_NAME :기본 블록 [BRBASE3] -STR_NAME :Base Block +STR_NAME :기본 블록 [BRCRRF1] -STR_NAME :Curved Roof +STR_NAME :곡선형 지붕 [BRCRRF2] -STR_NAME :Curved Roof +STR_NAME :곡선형 지붕 [CARROT] -STR_NAME :Giant Carrot +STR_NAME :대형 당근 [CHBBASE] -STR_NAME :Checkerboard Block +STR_NAME :체스판 블록 [CHEST1] -STR_NAME :Treasure Chest +STR_NAME :보물 상자 [CHEST2] -STR_NAME :Treasure Chest +STR_NAME :보물 상자 [CHOCROOF] -STR_NAME :Chocolate Bar +STR_NAME :초콜릿 바 [CNBALLS] -STR_NAME :Cannon Balls +STR_NAME :대포알 [CNDYRK1] STR_NAME :사탕 스틱 @@ -4752,10 +4752,10 @@ STR_NAME :사탕 스틱 STR_NAME :콜라 사탕 [CORROOF] -STR_NAME :Corrugated Steel Roof +STR_NAME :물결 무늬 강철 지붕 [CORROOF2] -STR_NAME :Corrugated Steel Base +STR_NAME :물결 무늬 강철 기반 [CWBCRV32] STR_NAME :곡선형 벽 @@ -4770,16 +4770,16 @@ STR_NAME :곡선형 벽 STR_NAME :곡선형 블록 [FERN1] -STR_NAME :Giant Fern +STR_NAME :대형 양치식물 [GGRS1] -STR_NAME :Giant Grass +STR_NAME :대형 풀 [HANG1] STR_NAME :교수대 [HELMET1] -STR_NAME :American Football Helmet +STR_NAME :아메리칸 풋볼 헬멧 [ICECUBE] STR_NAME :얼음 큐브 @@ -4794,10 +4794,10 @@ STR_NAME :젤리빈 STR_NAME :젤리빈 [JELDROP1] -STR_NAME :Fruit Drop +STR_NAME :떨어진 젤리 [JELDROP2] -STR_NAME :Fruit Drop +STR_NAME :떨어진 젤리 [JNGROOF1] STR_NAME :천장 @@ -5235,7 +5235,7 @@ STR_NAME :나무 STR_NAME :나무 [TMBJ] -STR_NAME :Meyer's Blue Juniper Tree +STR_NAME :메이어 향나무 [TMC] STR_NAME :왕느릅나무 @@ -5250,13 +5250,13 @@ STR_NAME :잔해 STR_NAME :나무 [TMM1] -STR_NAME :Graveyard Monument +STR_NAME :묘지 기념물 [TMM2] -STR_NAME :Graveyard Monument +STR_NAME :묘지 기념비 [TMM3] -STR_NAME :Graveyard Monument +STR_NAME :묘지 기념비 [TMO1] STR_NAME :화성 물체 @@ -5274,22 +5274,22 @@ STR_NAME :화성 물체 STR_NAME :화성 물체 [TMP] -STR_NAME :Monkey-Puzzle Tree +STR_NAME :칠레삼나무 [TMS1] STR_NAME :독버섯 [TMW] -STR_NAME :Wheels +STR_NAME :바퀴 [TMZP] -STR_NAME :Montezuma Pine Tree +STR_NAME :몬테수마 소나무 [TNS] -STR_NAME :Norway Spruce Tree +STR_NAME :노르웨이 가문비나무 [TNSS] -STR_NAME :Snow-covered Norway Spruce Tree +STR_NAME :눈 덮인 노르웨이 가문비나무 [TNTROOF1] STR_NAME :천막 지붕 @@ -5304,10 +5304,10 @@ STR_NAME :집 STR_NAME :건물 [TORN1] -STR_NAME :Ornamental Tree +STR_NAME :장식용 나무 [TORN2] -STR_NAME :Ornamental Tree +STR_NAME :장식용 나무 [TOS] STR_NAME :동상 @@ -5325,7 +5325,7 @@ STR_NAME :나무 STR_NAME :나무 [TOTEM1] -STR_NAME :Totem Pole +STR_NAME :토템 폴 [TP1] STR_NAME :흰색 폰 @@ -5385,16 +5385,16 @@ STR_NAME :나무 STR_NAME :나무 [TS4] -STR_NAME :Ornamental Tree +STR_NAME :장식용 나무 [TS5] -STR_NAME :Ornamental Tree +STR_NAME :장식용 나무 [TS6] -STR_NAME :Ornamental Tree +STR_NAME :장식용 나무 [TSB] -STR_NAME :Silver Birch Tree +STR_NAME :자작나무 [TSC] STR_NAME :선인장 @@ -5403,22 +5403,22 @@ STR_NAME :선인장 STR_NAME :건물 [TSCP] -STR_NAME :Space Capsule +STR_NAME :우주 캡슐 [TSD] -STR_NAME :Spade Shaped Tree +STR_NAME :스페이드 모양의 나무 [TSF1] -STR_NAME :Giant Snowflake +STR_NAME :대형 눈송이 [TSF2] -STR_NAME :Giant Snowflake +STR_NAME :대형 눈송이 [TSF3] -STR_NAME :Giant Snowflake +STR_NAME :대형 눈송이 [TSH] -STR_NAME :Horse Statue +STR_NAME :말 동상 [TSH0] STR_NAME :수풀 @@ -5445,7 +5445,7 @@ STR_NAME :눈사람 STR_NAME :눈덩이 [TSNC] -STR_NAME :Log Cabin +STR_NAME :통나무 집 [TSP] STR_NAME :스코틀랜드 소나무 @@ -5460,7 +5460,7 @@ STR_NAME :나무 STR_NAME :집 [TSQ] -STR_NAME :Squirrel Shaped Tree +STR_NAME :다람쥐 모양의 나무 [TST1] STR_NAME :독버섯 @@ -5478,7 +5478,7 @@ STR_NAME :독버섯 STR_NAME :독버섯 [TSTD] -STR_NAME :Dolphins Statue +STR_NAME :돌고래 동상 [TT1] STR_NAME :로마 사원 @@ -5490,34 +5490,34 @@ STR_NAME :과녁 STR_NAME :유니콘 동상 [TVL] -STR_NAME :Voss's Laburnam Tree +STR_NAME :나도싸리 [TWH1] STR_NAME :집 [TWH2] -STR_NAME :Pumpkin House +STR_NAME :호박 집 [TWN] -STR_NAME :Walnut Tree +STR_NAME :호두나무 [TWP] -STR_NAME :White Poplar Tree +STR_NAME :사시나무 [TWW] -STR_NAME :Weeping Willow Tree +STR_NAME :수양버들 [WAG1] -STR_NAME :Wagon +STR_NAME :마차 [WAG2] -STR_NAME :Wagon +STR_NAME :마차 [WDBASE] -STR_NAME :Wooden Block +STR_NAME :나무 블록 [TDF] -STR_NAME :Dolphin Fountain +STR_NAME :돌고래 분수 [TEF] STR_NAME :코끼리 분수 @@ -5739,7 +5739,7 @@ STR_NAME :탄광 건물 STR_NAME :갱도 [SOB] -STR_NAME :Office Block +STR_NAME :사무 빌딩 [SOH1] STR_NAME :집 @@ -5751,34 +5751,34 @@ STR_NAME :집 STR_NAME :집 [SPS] -STR_NAME :Petrol station +STR_NAME :주유소 [SSH] -STR_NAME :Space Capsule +STR_NAME :우주 캡슐 [SSK1] -STR_NAME :Skeleton +STR_NAME :해골 [SST] -STR_NAME :Satellite +STR_NAME :위성 [STB1] -STR_NAME :Castle Tower +STR_NAME :성탑 [STB2] -STR_NAME :Castle Tower +STR_NAME :성탑 [STG1] -STR_NAME :Castle Tower +STR_NAME :성탑 [STG2] -STR_NAME :Castle Tower +STR_NAME :성탑 [STH] -STR_NAME :Town Hall +STR_NAME :시청 [TAVERN] -STR_NAME :Tavern +STR_NAME :터번 [WWBANK] STR_NAME :은행 @@ -5805,28 +5805,28 @@ STR_NAME :해적선 STR_NAME :로마 콜로세움 [SIP] -STR_NAME :Ice Palace +STR_NAME :얼음성 [SMB] -STR_NAME :Martian Building +STR_NAME :화성 건물 [SPG] -STR_NAME :Pagoda +STR_NAME :탑 [SPYR] -STR_NAME :Pyramid +STR_NAME :피라미드 [SSPX] -STR_NAME :Sphinx +STR_NAME :스핑크스 [SSR] -STR_NAME :Space Rocket +STR_NAME :우주 로켓 [SVLC] -STR_NAME :Volcano +STR_NAME :화산 [WALLBADM] -STR_NAME :Badminton Racket +STR_NAME :배드민턴 라켓 [WALLBB16] STR_NAME :벽 @@ -5883,7 +5883,7 @@ STR_NAME :벽 아치 STR_NAME :창문 [WALLCO16] -STR_NAME :Corrugated Steel Wall +STR_NAME :물결 무늬 강철 벽 [WALLCW32] STR_NAME :벽 @@ -5910,13 +5910,13 @@ STR_NAME :젤리빈 벽 STR_NAME :벽 [WALLLT32] -STR_NAME :Steel Latticework +STR_NAME :강철 격자 [WALLMM16] -STR_NAME :Railings +STR_NAME :철책 [WALLMM17] -STR_NAME :Railings +STR_NAME :철책 [WALLMN32] STR_NAME :벽 @@ -5961,7 +5961,7 @@ STR_NAME :벽 STR_NAME :벽 [WALLSC16] -STR_NAME :Railings +STR_NAME :철책 [WALLSK16] STR_NAME :벽 @@ -6012,7 +6012,7 @@ STR_NAME :나무 벽 STR_NAME :나무 벽 [WALLWDPS] -STR_NAME :Wooden Post Fence +STR_NAME :나무 울타리 [WBR1] STR_NAME :벽돌 벽 @@ -6063,13 +6063,13 @@ STR_NAME :울타리 STR_NAME :나무 울타리 [WC18] -STR_NAME :Wooden Post Wall +STR_NAME :나무 울타리 [WC2] STR_NAME :성벽 [WC3] -STR_NAME :Roman Column Wall +STR_NAME :로마식 기둥 벽 [WC4] STR_NAME :성벽 @@ -6090,16 +6090,16 @@ STR_NAME :성벽 STR_NAME :성벽 [WCH] -STR_NAME :Conifer Hedge +STR_NAME :침엽수 생울타리 [WCHG] -STR_NAME :Conifer Hedge +STR_NAME :침엽수 생울타리 [WCW1] -STR_NAME :Playing Card Wall +STR_NAME :트럼프 벽 [WCW2] -STR_NAME :Playing Card Wall +STR_NAME :트럼프 벽 [WEW] STR_NAME :이집트 벽 @@ -6117,16 +6117,16 @@ STR_NAME :생울타리 STR_NAME :생울타리 [WJF] -STR_NAME :Jungle Fence +STR_NAME :정글 울타리 [WMF] -STR_NAME :Mesh Fence +STR_NAME :그물 철책 [WMFG] -STR_NAME :Mesh Fence +STR_NAME :그물 철책 [WMW] -STR_NAME :Martian Wall +STR_NAME :화성식 벽 [WMWW] STR_NAME :나무 울타리 @@ -6138,37 +6138,37 @@ STR_NAME :울타리 STR_NAME :울타리 [WPW1] -STR_NAME :Wooden Post Wall +STR_NAME :나무 울타리 [WPW2] -STR_NAME :Wooden Post Wall +STR_NAME :나무 울타리 [WPW3] STR_NAME :나무 울타리 [WRW] -STR_NAME :Roman Wall +STR_NAME :로마식 벽 [WRWA] -STR_NAME :Roman Wall +STR_NAME :로마식 벽 [WSW] -STR_NAME :Railings +STR_NAME :철책 [WSW1] -STR_NAME :Railings +STR_NAME :철책 [WSW2] -STR_NAME :Railings +STR_NAME :철책 [WSWG] -STR_NAME :Railings +STR_NAME :철책 [WWTW] -STR_NAME :Tall Wooden Fence +STR_NAME :키 큰 나무 울타리 [WWTWA] -STR_NAME :나무 울타리 Wall +STR_NAME :나무 울타리 벽 [WALLBRDR] STR_NAME :출입구 @@ -6177,13 +6177,13 @@ STR_NAME :출입구 STR_NAME :출입구 [WALLCBPC] -STR_NAME :Portcullis Door +STR_NAME :성문 [WALLCFDR] STR_NAME :출입구 [WALLCFPC] -STR_NAME :Portcullis Door +STR_NAME :성문 [WALLWF32] STR_NAME :폭포 @@ -6402,7 +6402,7 @@ STR_NAME :공원 출입구 STR_NAME :기본 공원 입구 [PKESFH] -STR_NAME :Park Entrance Building +STR_NAME :공원 입구 건물 [WTRCYAN] STR_NAME :기본 물 @@ -6507,7 +6507,7 @@ STR_CPTY :차량당 4명의 승객 [CONDORRD] STR_NAME :콘도르 라이드 STR_DESC :Passengers ride face-down in a lying position, suspended in a Condor-shaped car from the single-rail track, swinging freely from side to side around corners -STR_CPTY :승객 1명 per car +STR_CPTY :차량당 승객 1명 [CONGAEEL] STR_NAME :콩가 뱀장어 코스터 @@ -6597,7 +6597,7 @@ STR_CPTY :차량당 4명의 승객 [SPUTNIKR] STR_NAME :스푸트니크 서스펜디드 플라잉 코스터 STR_DESC :Passengers ride face-down in a lying position, suspended in a specially designed car from the single-rail track, swinging freely from side to side around corners -STR_CPTY :승객 2명 per car +STR_CPTY :차량당 승객 2명 [STGCCSTR] STR_NAME :역마차 롤러코스터 @@ -6677,7 +6677,7 @@ STR_CPTY :보트당 2명의 승객 [DOLPHINR] STR_NAME :돌고래 라이드 STR_DESC :Single-seater Dolphin-shaped vehicles which riders can drive themselves -STR_CPTY :1 rider per vehicle +STR_CPTY :차량당 1명의 탑승객 [MANDARIN] STR_NAME :원앙새 워터 라이드 @@ -6692,13 +6692,16 @@ STR_CPTY :보트당 16명의 승객 [OUTRIGGR] STR_NAME :아웃리거 라이드 STR_DESC :Long canoes which the passengers paddle themselves -STR_CPTY :canoe당 2명의 승객 +STR_CPTY :카누당 2명의 승객 [TUTLBOAT] STR_NAME :거북이 워터 라이드 STR_DESC :Small circular dinghies powered by a centrally-mounted motor controlled by the passengers STR_CPTY :보트당 2명의 승객 +[WILTLP] +STR_NAME :시들지 않는 튤립 + [1X1ATRE2] STR_NAME :덩굴 @@ -6799,64 +6802,64 @@ STR_NAME :파이프 STR_NAME :파이프 [RBRICK01] -STR_NAME :Red Brick Inverted Roof Piece +STR_NAME :Red Brick Inverted 지붕 Piece [RBRICK02] -STR_NAME :Red Brick Corner Roof Piece +STR_NAME :Red Brick Corner 지붕 Piece [RBRICK03] -STR_NAME :Red Brick Flat Roof Edge Piece +STR_NAME :Red Brick Flat 지붕 Edge Piece [RBRICK04] -STR_NAME :Red Brick Flat Roof Corner +STR_NAME :Red Brick Flat 지붕 Corner [RBRICK05] -STR_NAME :Red Brick Roof Piece 2 +STR_NAME :Red Brick 지붕 Piece 2 [RBRICK07] -STR_NAME :Red Brick Roof Piece 3 +STR_NAME :Red Brick 지붕 Piece 3 [RBRICK08] -STR_NAME :Red Brick Roof Piece 1 +STR_NAME :Red Brick 지붕 Piece 1 [RCORR01] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR02] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR03] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR04] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR05] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR07] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR08] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR09] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR10] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RCORR11] -STR_NAME :Corrugated Roof Piece +STR_NAME :Corrugated 지붕 Piece [RDRAB05] -STR_NAME :Drab Small Tower Minaret Base +STR_NAME :Drab Small Tower Minaret 기본 [RDRAB06] STR_NAME :Drab Small Tower Top or Mid-Section [RDRAB07] -STR_NAME :Drab Small Tower Base +STR_NAME :Drab Small Tower 기본 [RDRAB08] STR_NAME :Drab Minaret Piece 1 @@ -6868,52 +6871,52 @@ STR_NAME :Drab Minaret Piece 2 STR_NAME :Drab Minaret Piece 3 [RDRAB11] -STR_NAME :Drab Roof Piece 1 +STR_NAME :Drab 지붕 Piece 1 [RDRAB12] -STR_NAME :Drab Roof Piece 2 +STR_NAME :Drab 지붕 Piece 2 [RDRAB13] -STR_NAME :Drab Roof Piece 3 +STR_NAME :Drab 지붕 Piece 3 [RDRAB14] -STR_NAME :Drab Roof Piece 4 +STR_NAME :Drab 지붕 Piece 4 [RGEORG01] -STR_NAME :Georgian Roof End Piece 1 +STR_NAME :Georgian 지붕 End Piece 1 [RGEORG02] -STR_NAME :Georgian Roof End Piece 2 +STR_NAME :Georgian 지붕 End Piece 2 [RGEORG03] -STR_NAME :Georgian Roof Piece 1 +STR_NAME :Georgian 지붕 Piece 1 [RGEORG04] -STR_NAME :Georgian Roof Piece 2 +STR_NAME :Georgian 지붕 Piece 2 [RGEORG05] -STR_NAME :Georgian Roof Piece 3 +STR_NAME :Georgian 지붕 Piece 3 [RGEORG06] -STR_NAME :Georgian Roof Piece 4 +STR_NAME :Georgian 지붕 Piece 4 [RGEORG07] -STR_NAME :Georgian Roof Piece 5 +STR_NAME :Georgian 지붕 Piece 5 [RGEORG08] STR_NAME :Georgian Ground Floor Wall Piece 7 [RGEORG09] -STR_NAME :Georgian Flat Roof Edge 1 +STR_NAME :Georgian Flat 지붕 Edge 1 [RGEORG10] -STR_NAME :Georgian Flat Roof Edge 2 +STR_NAME :Georgian Flat 지붕 Edge 2 [RGEORG11] -STR_NAME :Georgian Flat Roof Corner +STR_NAME :Georgian Flat 지붕 Corner [RGEORG12] -STR_NAME :Georgian Roof Piece 7 +STR_NAME :Georgian 지붕 Piece 7 [ROOFICE1] STR_NAME :눈 지붕 @@ -6943,25 +6946,25 @@ STR_NAME :Kremlin Minaret Piece 2 STR_NAME :Kremlin Minaret Piece 3 [RKREML04] -STR_NAME :Kremlin Roof Piece 1 +STR_NAME :Kremlin 지붕 Piece 1 [RKREML05] -STR_NAME :Kremlin Roof Piece 2 +STR_NAME :Kremlin 지붕 Piece 2 [RKREML06] STR_NAME :Kremlin Small Tower Mid-Section [RKREML07] -STR_NAME :Kremlin Small Tower Base +STR_NAME :Kremlin Small Tower 기본 [RKREML11] -STR_NAME :Kremlin Small Tower Minaret Base +STR_NAME :Kremlin Small Tower Minaret 기본 [RLOG01] -STR_NAME :Log Cabin Roof Piece +STR_NAME :Log Cabin 지붕 Piece [RLOG02] -STR_NAME :Log Cabin Roof Piece +STR_NAME :Log Cabin 지붕 Piece [RLOG03] STR_NAME :Log Cabin Wall Piece @@ -6970,31 +6973,31 @@ STR_NAME :Log Cabin Wall Piece STR_NAME :Log Cabin Wall Piece [RLOG05] -STR_NAME :Log Cabin Roof Piece +STR_NAME :Log Cabin 지붕 Piece [RMARBLE1] -STR_NAME :Marble Roof +STR_NAME :Marble 지붕 [RMARBLE2] -STR_NAME :Marble Roof +STR_NAME :Marble 지붕 [RMARBLE3] -STR_NAME :Marble Roof +STR_NAME :Marble 지붕 [RMARBLE4] -STR_NAME :Marble Roof +STR_NAME :Marble 지붕 [RMUD01] -STR_NAME :Curved Mud Wall Piece +STR_NAME :곡선형 Mud Wall Piece [RMUD02] -STR_NAME :Curved Mud Wall Piece +STR_NAME :곡선형 Mud Wall Piece [RMUD03] -STR_NAME :Curved Mud Wall Piece +STR_NAME :곡선형 Mud Wall Piece [RMUD05] -STR_NAME :Mud Roof Piece +STR_NAME :Mud 지붕 Piece [ROOFIG01] STR_NAME :이글루 벽 @@ -7039,31 +7042,31 @@ STR_NAME :Iced Barrels STR_NAME :Ice Pipe Vent [PIPEBASE] -STR_NAME :Ice Pipe Base +STR_NAME :Ice Pipe 기본 [RTUDOR01] -STR_NAME :Tudor Roof Piece 1 +STR_NAME :Tudor 지붕 Piece 1 [RTUDOR02] -STR_NAME :Tudor Roof Piece 1 Extender Piece +STR_NAME :Tudor 지붕 Piece 1 Extender Piece [RTUDOR03] -STR_NAME :Tudor Roof Piece 2 +STR_NAME :Tudor 지붕 Piece 2 [RWDAUB01] -STR_NAME :Wattle & Daub Roof +STR_NAME :Wattle & Daub 지붕 [RWDAUB02] -STR_NAME :Wattle & Daub Roof +STR_NAME :Wattle & Daub 지붕 [RWDAUB03] -STR_NAME :Wattle & Daub Roof +STR_NAME :Wattle & Daub 지붕 [SB1HSPB1] -STR_NAME :Suspension Bridge Base Piece +STR_NAME :Suspension Bridge 기본 Piece [SB1HSPB2] -STR_NAME :Suspension Bridge Base Spacer Piece +STR_NAME :Suspension Bridge 기본 Spacer Piece [SB1HSPB3] STR_NAME :Suspension Bridge Mid Section Piece @@ -7072,7 +7075,7 @@ STR_NAME :Suspension Bridge Mid Section Piece STR_NAME :Cabana Porch [SB2SKY01] -STR_NAME :Stone Skyscraper Stairway Base +STR_NAME :Stone Skyscraper Stairway 기본 [SBH1TEPE] STR_NAME :Tee Pee @@ -7144,34 +7147,34 @@ STR_NAME :Skyscaper Metal Set 2 Concave Piece STR_NAME :Skyscaper Concave Piece [SBSKYS11] -STR_NAME :Skyscraper Concave Roof +STR_NAME :Skyscraper Concave 지붕 [SBSKYS12] STR_NAME :Skyscaper Convex Piece [SBSKYS13] -STR_NAME :Skyscaper Convex Roof +STR_NAME :Skyscaper Convex 지붕 [SBSKYS14] -STR_NAME :Sky Scraper Roof Piece +STR_NAME :Sky Scraper 지붕 Piece [SBSKYS15] -STR_NAME :Sky Scraper Roof Piece +STR_NAME :Sky Scraper 지붕 Piece [SBSKYS16] -STR_NAME :Sky Scraper Roof Piece +STR_NAME :Sky Scraper 지붕 Piece [SBSKYS17] -STR_NAME :Sky Scraper Roof Piece +STR_NAME :Sky Scraper 지붕 Piece [SBSKYS18] -STR_NAME :Sky Scraper Roof Piece +STR_NAME :Sky Scraper 지붕 Piece [SBWIND01] STR_NAME :Wind Sculpted Concave Wall Corner [SBWIND02] -STR_NAME :Wind Sculpted Concave Roof Corner +STR_NAME :Wind Sculpted Concave 지붕 Corner [SBWIND03] STR_NAME :Wind Sculpted Concave Wall Corner @@ -7180,16 +7183,16 @@ STR_NAME :Wind Sculpted Concave Wall Corner STR_NAME :Wind Sculpted Convex Wall Corner [SBWIND05] -STR_NAME :Wind Sculpted Convex Roof Corner +STR_NAME :Wind Sculpted Convex 지붕 Corner [SBWIND06] STR_NAME :Wind Sculpted Convex Wall Corner [SBWIND07] -STR_NAME :Wind Sculpted Rock Formation Base +STR_NAME :Wind Sculpted Rock Formation 기본 [SBWIND08] -STR_NAME :Wind Sculpted Rock Formation Base +STR_NAME :Wind Sculpted Rock Formation 기본 [SBWIND09] STR_NAME :Wind Sculpted Rock Formation Mid Section @@ -7210,13 +7213,13 @@ STR_NAME :Wind Sculpted Rock Formation Top STR_NAME :Wind Sculpted Rock Formation Top [SBWIND15] -STR_NAME :Wind Sculpted Roof Flat Roof Piece +STR_NAME :Wind Sculpted 지붕 Flat 지붕 Piece [SBWIND16] -STR_NAME :Wind Sculpted Roof Flat Roof Piece +STR_NAME :Wind Sculpted 지붕 Flat 지붕 Piece [SBWIND17] -STR_NAME :Wind Sculpted Roof Flat Roof Piece +STR_NAME :Wind Sculpted 지붕 Flat 지붕 Piece [SBWIND18] STR_NAME :Wind Sculpted Floor Piece @@ -7225,10 +7228,10 @@ STR_NAME :Wind Sculpted Floor Piece STR_NAME :Wind Sculpted Floor Piece [SBWIND20] -STR_NAME :Wind Sculpted Wall Base +STR_NAME :Wind Sculpted Wall 기본 [SBWIND21] -STR_NAME :Wind Sculpted Wall Base +STR_NAME :Wind Sculpted Wall 기본 [SBWPLM01] STR_NAME :Cabana Top @@ -7237,13 +7240,13 @@ STR_NAME :Cabana Top STR_NAME :Cabana Porch [SBWPLM03] -STR_NAME :Cabana Roof Piece +STR_NAME :Cabana 지붕 Piece [SBWPLM04] -STR_NAME :Cabana Roof Piece +STR_NAME :Cabana 지붕 Piece [SBWPLM05] -STR_NAME :Cabana Roof Piece +STR_NAME :Cabana 지붕 Piece [SBWPLM06] STR_NAME :Cabana Wall Piece @@ -7339,10 +7342,10 @@ STR_NAME :Aboriginal Art Set Piece STR_NAME :Aboriginal Art Set Piece [WAZTEC01] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC02] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC03] STR_NAME :Temple Wall Piece @@ -7381,19 +7384,19 @@ STR_NAME :Temple Wall Piece STR_NAME :Temple Wall Piece [WAZTEC15] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC16] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC17] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC18] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC19] -STR_NAME :Temple Roof Piece +STR_NAME :Temple 지붕 Piece [WAZTEC20] STR_NAME :Temple Stairway Piece @@ -7558,7 +7561,7 @@ STR_NAME :Kremlin Wall Piece 4 STR_NAME :Lost City Wall Piece [WMAYAN02] -STR_NAME :Lost City Flat Roof Piece +STR_NAME :Lost City Flat 지붕 Piece [WMAYAN03] STR_NAME :Lost City Wall Piece @@ -7612,10 +7615,10 @@ STR_NAME :Lost City Column Piece STR_NAME :Lost City Wall Piece [WMAYAN21] -STR_NAME :Lost City Flat Roof Piece +STR_NAME :Lost City Flat 지붕 Piece [WMAYAN22] -STR_NAME :Lost City Flat Roof Piece +STR_NAME :Lost City Flat 지붕 Piece [WMAYAN23] STR_NAME :Lost City Wall Corner Piece @@ -7630,19 +7633,19 @@ STR_NAME :Lost City Wall Corner Piece STR_NAME :Lost City Wall Corner Piece [WNAUTI01] -STR_NAME :Nautical Roof Piece +STR_NAME :Nautical 지붕 Piece [WNAUTI02] -STR_NAME :Nautical Roof Piece +STR_NAME :Nautical 지붕 Piece [WNAUTI03] -STR_NAME :Nautical Roof Piece +STR_NAME :Nautical 지붕 Piece [WNAUTI04] -STR_NAME :Nautical Roof Piece +STR_NAME :Nautical 지붕 Piece [WNAUTI05] -STR_NAME :Nautical Roof Piece +STR_NAME :Nautical 지붕 Piece [WTUDOR12] STR_NAME :Tudor Wall Piece 4 @@ -7756,10 +7759,10 @@ STR_NAME :Animated Balloons STR_NAME :Monumental Fountain [WROPECOR] -STR_NAME :Nautical Corner Roof Railing +STR_NAME :Nautical Corner 지붕 Railing [WROPESWA] -STR_NAME :Nautical Roof Railing +STR_NAME :Nautical 지붕 Railing [1X2ABR01] STR_NAME :Aboriginal Plain Tile @@ -7816,13 +7819,13 @@ STR_NAME :Mangrove Tree STR_NAME :1950's Rocket [BamboRf1] -STR_NAME :Bamboo Roof +STR_NAME :Bamboo 지붕 [BAMBORF2] -STR_NAME :Bamboo Roof +STR_NAME :Bamboo 지붕 [BamboRf3] -STR_NAME :Bamboo Roof +STR_NAME :Bamboo 지붕 [BIGGEOSP] STR_NAME :Big Geosphere @@ -7873,19 +7876,19 @@ STR_NAME :Washington Statue STR_NAME :Drab Large Tower Mid-Section [RDRAB02] -STR_NAME :Drab Large Tower Base +STR_NAME :Drab Large Tower 기본 [RDRAB03] STR_NAME :Drab Large Tower Top [RDRAB04] -STR_NAME :Drab Large Tower Broken Base +STR_NAME :Drab Large Tower Broken 기본 [REDWOOD] STR_NAME :Redwood Tree [RKREML08] -STR_NAME :Kremlin Large Tower Base +STR_NAME :Kremlin Large Tower 기본 [RKREML09] STR_NAME :Kremlin Large Tower Top @@ -7894,10 +7897,10 @@ STR_NAME :Kremlin Large Tower Top STR_NAME :Kremlin Large Tower Mid-Section [RTUDOR05] -STR_NAME :Tudor Roof Piece 3 +STR_NAME :Tudor 지붕 Piece 3 [RTUDOR06] -STR_NAME :Tudor Roof Piece 4 +STR_NAME :Tudor 지붕 Piece 4 [SHIVA] STR_NAME :Shiva @@ -7909,7 +7912,7 @@ STR_NAME :동상 of Liberty STR_NAME :Sputnik [TAJMCBSE] -STR_NAME :Maharaja Palace Tower Base +STR_NAME :Maharaja Palace Tower 기본 [TAJMCOLM] STR_NAME :Maharaja Palace Tower Column @@ -7984,7 +7987,7 @@ STR_NAME :Ice Formation STR_NAME :Ice Formation [MBSKYR01] -STR_NAME :Sky Scraper Roof Piece +STR_NAME :Sky Scraper 지붕 Piece [MBSKYR02] STR_NAME :Sky Scraper Tip @@ -8641,7 +8644,7 @@ STR_CPTY :승객 20명 [CYCLOPSX] STR_NAME :사이클롭스 라이드 -STR_DESC :Riders drive the Eye of a Giant Cyclops +STR_DESC :Riders drive the Eye of a 대형 Cyclops STR_CPTY :차량당 1명의 손님 [FIGTKNIT] @@ -8985,16 +8988,16 @@ STR_NAME :Art Deco Wall with Railings STR_NAME :Art Deco Wall with Railings [ARTDEC28] -STR_NAME :Art Deco Roof Section +STR_NAME :Art Deco 지붕 Section [ARTDEC29] STR_NAME :Art Deco Inverted Corner Section [BIGBASSX] -STR_NAME :Giant Bass Guitar +STR_NAME :대형 Bass Guitar [BIGGUTAR] -STR_NAME :Giant Guitar +STR_NAME :대형 Guitar [CHPRBKE1] STR_NAME :Motorcycle @@ -9027,16 +9030,16 @@ STR_NAME :Sandstone Skyscraper Mid Wall Section STR_NAME :Sandstone Skyscraper Inverted Corner Top [FUTSKY29] -STR_NAME :Sandstone Skyscraper Bottom Curved Slope +STR_NAME :Sandstone Skyscraper Bottom 곡선형 Slope [FUTSKY34] -STR_NAME :Sandstone Skyscraper Roof +STR_NAME :Sandstone Skyscraper 지붕 [FUTSKY35] -STR_NAME :Sandstone Skyscraper Mid Curved Slope +STR_NAME :Sandstone Skyscraper Mid 곡선형 Slope [FUTSKY42] -STR_NAME :Sandstone Skyscraper Curved Slope Top +STR_NAME :Sandstone Skyscraper 곡선형 Slope Top [FUTSKY52] STR_NAME :Sandstone Skyscraper Bottom Inverted Corner @@ -9045,7 +9048,7 @@ STR_NAME :Sandstone Skyscraper Bottom Inverted Corner STR_NAME :Sandstone Skyscraper Mid Corner [FUTSKY54] -STR_NAME :Obsidian SkyScraper Roof Piece +STR_NAME :Obsidian SkyScraper 지붕 Piece [GLDCHEST] STR_NAME :Treasure Chest @@ -9090,16 +9093,16 @@ STR_NAME :Heavenly Bath Window STR_NAME :Heavenly Bath Floor [HEVROF01] -STR_NAME :Heavenly Bath Roof +STR_NAME :Heavenly Bath 지붕 [HEVROF02] -STR_NAME :Heavenly Bath Roof +STR_NAME :Heavenly Bath 지붕 [HEVROF03] -STR_NAME :Heavenly Bath Roof +STR_NAME :Heavenly Bath 지붕 [HEVROF04] -STR_NAME :Heavenly Bath Roof +STR_NAME :Heavenly Bath 지붕 [HRBWAL01] STR_NAME :Harbour Wall @@ -9135,10 +9138,10 @@ STR_NAME :Industrial Wall Set STR_NAME :Industrial Wall Set [INDWAL05] -STR_NAME :Industrial Roof Corner Piece +STR_NAME :Industrial 지붕 Corner Piece [INDWAL06] -STR_NAME :Industrial Roof Corner Piece +STR_NAME :Industrial 지붕 Corner Piece [INDWAL07] STR_NAME :Industrial Wall with Doorway @@ -9180,34 +9183,34 @@ STR_NAME :Industrial Wall with Window STR_NAME :Industrial Wall with Window [INDWAL20] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL21] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL22] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL23] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL24] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL25] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL26] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL27] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL28] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL29] -STR_NAME :Industrial Roof Piece +STR_NAME :Industrial 지붕 Piece [INDWAL30] STR_NAME :Industrial Wall with Window @@ -9237,7 +9240,7 @@ STR_NAME :Prison Wall Piece STR_NAME :Prison Wall Piece [JAILXX07] -STR_NAME :Prison Wall Roof +STR_NAME :Prison Wall 지붕 [JAILXX08] STR_NAME :Prison Inverted Piece @@ -9474,22 +9477,22 @@ STR_NAME :Dark Age Village Upper Wall Piece STR_NAME :Dark Age Village Upper Wall Piece [PSNTWL14] -STR_NAME :Dark Age Village Roof Piece +STR_NAME :Dark Age Village 지붕 Piece [PSNTWL15] -STR_NAME :Dark Age Village Inverted Roof Piece +STR_NAME :Dark Age Village Inverted 지붕 Piece [PSNTWL16] -STR_NAME :Dark Age Village Roof Piece +STR_NAME :Dark Age Village 지붕 Piece [PSNTWL17] -STR_NAME :Dark Age Village Roof Piece +STR_NAME :Dark Age Village 지붕 Piece [PSNTWL20] -STR_NAME :Dark Age Village Window Box Roof +STR_NAME :Dark Age Village Window Box 지붕 [PSNTWL21] -STR_NAME :Dark Age Village Window Box Roof +STR_NAME :Dark Age Village Window Box 지붕 [PSNTWL23] STR_NAME :Dark Age Village Upper Corner Piece @@ -9501,13 +9504,13 @@ STR_NAME :Dark Age Village Window Box STR_NAME :Dark Age Village Window Box [PSNTWL29] -STR_NAME :Dark Age Village Window Box Roof +STR_NAME :Dark Age Village Window Box 지붕 [PSNTWL30] -STR_NAME :Dark Age Village Window Box Roof +STR_NAME :Dark Age Village Window Box 지붕 [PSNTWL31] -STR_NAME :Dark Age Village Corner Roof Piece +STR_NAME :Dark Age Village Corner 지붕 Piece [RDMETO03] STR_NAME :Red Meteor Crater Wall @@ -9554,7 +9557,7 @@ STR_NAME :Forest Trees STR_NAME :Smoke Stack Mid [SMOKSK03] -STR_NAME :Smoke Stack Base +STR_NAME :Smoke Stack 기본 [SPCSHP06] STR_NAME :Space Ship Cross Section @@ -9806,13 +9809,13 @@ STR_NAME :Sandstone Skyscraper Filler STR_NAME :Sandstone Skyscraper Bottom Corner [FUTSKY04] -STR_NAME :Sandstone Skyscraper Curved Slope Top +STR_NAME :Sandstone Skyscraper 곡선형 Slope Top [FUTSKY05] STR_NAME :Sandstone Skyscraper Corner Top [FUTSKY06] -STR_NAME :Sandstone Skyscraper Mid Curved Slope +STR_NAME :Sandstone Skyscraper Mid 곡선형 Slope [FUTSKY07] STR_NAME :Sandstone Skyscraper Mid Wall Section @@ -9824,7 +9827,7 @@ STR_NAME :Sandstone Skyscraper Mid Wall Section STR_NAME :Sandstone Skyscraper Mid Wall Section [FUTSKY10] -STR_NAME :Sandstone Skyscraper Bottom Slope Base +STR_NAME :Sandstone Skyscraper Bottom Slope 기본 [FUTSKY11] STR_NAME :Sandstone Skyscraper Mid Corner @@ -9833,10 +9836,10 @@ STR_NAME :Sandstone Skyscraper Mid Corner STR_NAME :Sandstone Skyscraper Mid Wall Section [FUTSKY13] -STR_NAME :Sandstone Skyscraper Roof Spire +STR_NAME :Sandstone Skyscraper 지붕 Spire [FUTSKY14] -STR_NAME :Sandstone Skyscraper Roof Spire +STR_NAME :Sandstone Skyscraper 지붕 Spire [FUTSKY15] STR_NAME :Sandstone Skyscraper Docking Bay @@ -9893,10 +9896,10 @@ STR_NAME :Animatronic Good Alien STR_NAME :Geysers [GGNTOCTO] -STR_NAME :B-Movie Giant Octopus +STR_NAME :B-Movie 대형 Octopus [GGNTSPID] -STR_NAME :B-Movie Giant Spider +STR_NAME :B-Movie 대형 Spider [GSCORPO2] STR_NAME :Animatronic attacking Scorpion @@ -10034,7 +10037,7 @@ STR_NAME :Wood Fence with Man Eating Plant STR_NAME :Wood Fence with Man Eating Plant [PSNTWL01] -STR_NAME :Dark Age Village Roof with Chimney +STR_NAME :Dark Age Village 지붕 with Chimney [RCKNROLR] STR_NAME :Cool Dude @@ -10235,16 +10238,16 @@ STR_NAME :Castle Entrance STR_NAME :Large Elm Tree [OLDNYK24] -STR_NAME :뉴욕 Inverted Corner Roof +STR_NAME :뉴욕 Inverted Corner 지붕 [OLDNYK25] -STR_NAME :뉴욕 Roof Piece +STR_NAME :뉴욕 지붕 Piece [OLDNYK26] STR_NAME :뉴욕 Entrance [OLDNYK32] -STR_NAME :뉴욕 Roof Piece +STR_NAME :뉴욕 지붕 Piece [1950SCAR] STR_NAME :1950s Car @@ -10253,7 +10256,7 @@ STR_NAME :1950s Car STR_NAME :Period Diner [4X4GMANT] -STR_NAME :Giant Mangrove Tree +STR_NAME :대형 Mangrove Tree [4X4STNHN] STR_NAME :Stone Age Temple @@ -10286,7 +10289,7 @@ STR_NAME :Ash Tree with Nymphs STR_NAME :Rock Band Tour Bus [BIGDRUMS] -STR_NAME :Giant Drum Kit +STR_NAME :대형 Drum Kit [CAVENTRA] STR_NAME :Cave Entrance @@ -10316,7 +10319,7 @@ STR_NAME :Cyclops Statue STR_NAME :Feast Table [FOOTPRNT] -STR_NAME :Giant Dinosaur Footprint +STR_NAME :대형 Dinosaur Footprint [FORBIDFT] STR_NAME :Forbidden Fruit Tree @@ -10397,7 +10400,7 @@ STR_NAME :Meteor Crater Corner STR_NAME :Meteor Crater Inverted Corner [OLDNYK20] -STR_NAME :뉴욕 Roof Piece +STR_NAME :뉴욕 지붕 Piece [OLDNYK21] STR_NAME :뉴욕 벽 조각 @@ -10442,13 +10445,13 @@ STR_NAME :Plough STR_NAME :Period Sailing Yacht [PSNTWL26] -STR_NAME :Dark Age Village Roof Piece +STR_NAME :Dark Age Village 지붕 Piece [PSNTWL27] -STR_NAME :Dark Age Village Corner Roof Piece +STR_NAME :Dark Age Village Corner 지붕 Piece [PSNTWL28] -STR_NAME :Dark Age Village Inverted Roof Piece +STR_NAME :Dark Age Village Inverted 지붕 Piece [RDMET2X2] STR_NAME :Small Red Meteor Crater From 855e122b55dd128054ebe6c1f043cdb63647a088 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Wed, 2 Dec 2015 20:20:55 +0100 Subject: [PATCH 06/90] Printing path and addition names in tile inspector. --- src/windows/tile_inspector.c | 16 +++++++++------- src/world/footpath.c | 3 +++ src/world/map.h | 2 +- src/world/scenery.h | 1 + 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index c3425d6d77..6fb031945a 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -332,21 +332,23 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * break; case MAP_ELEMENT_TYPE_PATH: { - // TODO: use these - uint8 pathType, pathDirection; - pathType = element->properties.path.type >> 2; - pathDirection = element->properties.path.type & 3; + rct_map_element_path_properties *path = &element->properties.path; + uint8 pathType = path->type >> 4; + uint8 pathDirection = path->type & 3; + uint8 pathAdditionType = path->additions & 0xF; if (footpath_element_is_queue(element)) { sprintf( buffer, "Queue for (%d)", - element->properties.path.ride_index + path->ride_index ); } else { sprintf( buffer, - "Path (%s)", - "" // TODO: queue? has bins? has benches? e.t.c. + "Path (%s)%s%s", + language_get_string(g_pathSceneryEntries[pathType]->name), + (path->additions & 0xF) ? " with " : "", + (path->additions & 0xF) ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "" ); } } diff --git a/src/world/footpath.c b/src/world/footpath.c index 298f239354..83b3c5c720 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -249,12 +249,15 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement if (flags & GAME_COMMAND_FLAG_4) return MONEY32_UNDEFINED; + // Try placing a ghost if (flags & GAME_COMMAND_FLAG_GHOST) { + // Check if there is something on the path already if (mapElement->properties.path.additions & 0x0F) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NONE; return MONEY32_UNDEFINED; } + // There is nothing yet - check if we should place a ghost if (flags & GAME_COMMAND_FLAG_APPLY) mapElement->properties.path.additions |= 0x80; } diff --git a/src/world/map.h b/src/world/map.h index 3466048755..2d2ceb5e79 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -31,7 +31,7 @@ typedef struct { } rct_map_element_surface_properties; typedef struct { - uint8 type; //4 + uint8 type; //4 0xF0 Path type, 0x08 Unknown/Unused, 0x04 Set when path is diagonal, 0x03 Rotation uint8 additions; //5 uint8 edges; //6 union { diff --git a/src/world/scenery.h b/src/world/scenery.h index a98578eb04..1869069998 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -163,6 +163,7 @@ enum { #define g_largeSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].chunks) #define g_wallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_WALLS].chunks) #define g_bannerSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_BANNERS].chunks) +#define g_pathSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_PATHS].chunks) // Often 0x009ADA50 is used for pathBits this is 1 entry before g_pathBitSceneryEntries and is used // because 0 represents no path bits on a path. So remember to remove 1 when using it for 0x009ADA50 From 955bf7b26fcf86e181eafae029c428154a81b7ad Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Thu, 3 Dec 2015 16:14:30 +0100 Subject: [PATCH 07/90] Displaying more path info for queue. Added some helper functions. --- src/windows/tile_inspector.c | 18 ++++++++++-------- src/world/footpath.c | 15 +++++++++++++++ src/world/footpath.h | 4 ++++ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 6fb031945a..445e0cc027 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -332,23 +332,25 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * break; case MAP_ELEMENT_TYPE_PATH: { - rct_map_element_path_properties *path = &element->properties.path; - uint8 pathType = path->type >> 4; - uint8 pathDirection = path->type & 3; - uint8 pathAdditionType = path->additions & 0xF; + rct_map_element_path_properties *pathProperties = &element->properties.path; + uint8 pathType = footpath_element_get_type(pathProperties); + uint8 pathAdditionType = footpath_element_get_addition_type(pathProperties); if (footpath_element_is_queue(element)) { sprintf( buffer, - "Queue for (%d)", - path->ride_index + "Queue (%s)%s%s for (%d)", + language_get_string(g_pathSceneryEntries[pathType]->name), + pathAdditionType ? " with " : "", + pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "", + pathProperties->ride_index ); } else { sprintf( buffer, "Path (%s)%s%s", language_get_string(g_pathSceneryEntries[pathType]->name), - (path->additions & 0xF) ? " with " : "", - (path->additions & 0xF) ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "" + pathAdditionType ? " with " : "", + pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "" ); } } diff --git a/src/world/footpath.c b/src/world/footpath.c index 83b3c5c720..a6cdeb9346 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -1597,6 +1597,21 @@ bool footpath_element_is_wide(rct_map_element *mapElement) return mapElement->type & 2; } +uint8 footpath_element_get_type(rct_map_element_path_properties *pathProperties) +{ + return pathProperties->type >> 4; +} + +uint8 footpath_element_get_direction(rct_map_element_path_properties *pathProperties) +{ + return pathProperties->type & 3; +} + +uint8 footpath_element_get_addition_type(rct_map_element_path_properties *pathProperties) +{ + return pathProperties->additions & 0xF; +} + /** * * rct2: 0x006A8B12 diff --git a/src/world/footpath.h b/src/world/footpath.h index 05c5ad43ad..f77630fe63 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -73,6 +73,10 @@ bool footpath_element_is_sloped(rct_map_element *mapElement); int footpath_element_get_slope_direction(rct_map_element *mapElement); bool footpath_element_is_queue(rct_map_element *mapElement); bool footpath_element_is_wide(rct_map_element *mapElement); +uint8 footpath_element_get_type(rct_map_element_path_properties *pathProperties); +uint8 footpath_element_get_direction(rct_map_element_path_properties *pathProperties); +uint8 footpath_element_get_addition_type(rct_map_element_path_properties *pathProperties); +uint8 footpath_element_get_addition_type(rct_map_element_path_properties *pathProperties); void footpath_remove_edges_at(int x, int y, rct_map_element *mapElement); #endif From 370c08f7964e3c386becfc217d313a142daeca94 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Thu, 3 Dec 2015 16:20:05 +0100 Subject: [PATCH 08/90] Added comments to path info --- src/windows/tile_inspector.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 445e0cc027..86018bedd4 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -337,20 +337,18 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * uint8 pathAdditionType = footpath_element_get_addition_type(pathProperties); if (footpath_element_is_queue(element)) { sprintf( - buffer, - "Queue (%s)%s%s for (%d)", - language_get_string(g_pathSceneryEntries[pathType]->name), - pathAdditionType ? " with " : "", - pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "", - pathProperties->ride_index + buffer, "Queue (%s)%s%s for (%d)", + language_get_string(g_pathSceneryEntries[pathType]->name), // Path name + pathAdditionType ? " with " : "", // Adds " with " when there is something on the path + pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "", // Path addition name + pathProperties->ride_index // Ride index for queue ); } else { sprintf( - buffer, - "Path (%s)%s%s", - language_get_string(g_pathSceneryEntries[pathType]->name), - pathAdditionType ? " with " : "", - pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "" + buffer, "Path (%s)%s%s", + language_get_string(g_pathSceneryEntries[pathType]->name), // Path name + pathAdditionType ? " with " : "", // Adds " with " when there is something on the path + pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "" // Path addition name ); } } From b82504c5e450b01d45c09e60fb95068042182c7d Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Thu, 3 Dec 2015 23:49:26 +0100 Subject: [PATCH 09/90] Better consistensy with already existing helper functions --- src/windows/tile_inspector.c | 16 ++++++++-------- src/world/footpath.c | 19 ++++++++++++------- src/world/footpath.h | 10 +++++----- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 86018bedd4..ecd29809e8 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -332,23 +332,23 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * break; case MAP_ELEMENT_TYPE_PATH: { - rct_map_element_path_properties *pathProperties = &element->properties.path; - uint8 pathType = footpath_element_get_type(pathProperties); - uint8 pathAdditionType = footpath_element_get_addition_type(pathProperties); + const uint8 pathType = footpath_element_get_type(element); + const uint8 pathHasScenery = footpath_element_has_path_scenery(element); + const uint8 pathAdditionType = footpath_element_get_path_scenery_index(element); if (footpath_element_is_queue(element)) { sprintf( buffer, "Queue (%s)%s%s for (%d)", language_get_string(g_pathSceneryEntries[pathType]->name), // Path name - pathAdditionType ? " with " : "", // Adds " with " when there is something on the path - pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "", // Path addition name - pathProperties->ride_index // Ride index for queue + pathHasScenery ? " with " : "", // Adds " with " when there is something on the path + pathHasScenery ? language_get_string(g_pathBitSceneryEntries[pathAdditionType]->name) : "", // Path addition name + element->properties.path.ride_index // Ride index for queue ); } else { sprintf( buffer, "Path (%s)%s%s", language_get_string(g_pathSceneryEntries[pathType]->name), // Path name - pathAdditionType ? " with " : "", // Adds " with " when there is something on the path - pathAdditionType ? language_get_string(g_pathBitSceneryEntries[pathAdditionType - 1]->name) : "" // Path addition name + pathHasScenery ? " with " : "", // Adds " with " when there is something on the path + pathHasScenery ? language_get_string(g_pathBitSceneryEntries[pathAdditionType]->name) : "" // Path addition name ); } } diff --git a/src/world/footpath.c b/src/world/footpath.c index a6cdeb9346..8eb39db1cc 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -1582,7 +1582,7 @@ bool footpath_element_is_sloped(rct_map_element *mapElement) return mapElement->properties.path.type & 4; } -int footpath_element_get_slope_direction(rct_map_element *mapElement) +uint8 footpath_element_get_slope_direction(rct_map_element *mapElement) { return mapElement->properties.path.type & 3; } @@ -1597,19 +1597,24 @@ bool footpath_element_is_wide(rct_map_element *mapElement) return mapElement->type & 2; } -uint8 footpath_element_get_type(rct_map_element_path_properties *pathProperties) +bool footpath_element_has_path_scenery(rct_map_element *mapElement) { - return pathProperties->type >> 4; + return (mapElement->properties.path.additions & 0xF) > 0; } -uint8 footpath_element_get_direction(rct_map_element_path_properties *pathProperties) +uint8 footpath_element_get_path_scenery(rct_map_element *mapElement) { - return pathProperties->type & 3; + return mapElement->properties.path.additions & 0xF; } -uint8 footpath_element_get_addition_type(rct_map_element_path_properties *pathProperties) +uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement) { - return pathProperties->additions & 0xF; + return footpath_element_get_path_scenery(mapElement) - 1; +} + +uint8 footpath_element_get_type(rct_map_element *mapElement) +{ + return mapElement->properties.path.type >> 4; } /** diff --git a/src/world/footpath.h b/src/world/footpath.h index f77630fe63..f0db78154d 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -70,13 +70,13 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags); bool footpath_element_is_sloped(rct_map_element *mapElement); -int footpath_element_get_slope_direction(rct_map_element *mapElement); +uint8 footpath_element_get_slope_direction(rct_map_element *mapElement); bool footpath_element_is_queue(rct_map_element *mapElement); bool footpath_element_is_wide(rct_map_element *mapElement); -uint8 footpath_element_get_type(rct_map_element_path_properties *pathProperties); -uint8 footpath_element_get_direction(rct_map_element_path_properties *pathProperties); -uint8 footpath_element_get_addition_type(rct_map_element_path_properties *pathProperties); -uint8 footpath_element_get_addition_type(rct_map_element_path_properties *pathProperties); +uint8 footpath_element_get_type(rct_map_element *mapElement); +bool footpath_element_has_path_scenery(rct_map_element *mapElement); +uint8 footpath_element_get_path_scenery(rct_map_element *mapElement); +uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement); void footpath_remove_edges_at(int x, int y, rct_map_element *mapElement); #endif From 6f0d14b65f25b5cfde26b03777228287ae37aecd Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Fri, 4 Dec 2015 21:09:49 +0100 Subject: [PATCH 10/90] Using ghost helper funcitons for getting and setting the bit now. --- src/peep/peep.c | 20 ++++++++++---------- src/rct1.c | 6 +++--- src/world/footpath.c | 24 +++++++++++++++++++----- src/world/footpath.h | 2 ++ src/world/fountain.c | 3 ++- src/world/scenery.c | 3 ++- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index ba9180f355..de8ec307ea 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -203,7 +203,7 @@ static uint8 peep_assess_surroundings(sint16 center_x, sint16 center_y, sint16 c break; scenery = g_pathBitSceneryEntries[(mapElement->properties.path.additions & 0x0F) - 1]; - if (mapElement->properties.path.additions & (1 << 7)) + if (footpath_element_path_scenery_is_ghost(mapElement)) break; if (scenery->path_bit.var_06 & @@ -620,7 +620,7 @@ static void sub_68F41A(rct_peep *peep, int index) continue; uint8 additions = mapElement->properties.path.additions & 0xF; - if (additions != 0 && mapElement->properties.path.additions & (1 << 7)){ + if (additions != 0 && footpath_element_path_scenery_is_ghost(mapElement)){ rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additions - 1]; if (sceneryEntry->path_bit.var_06 & (1 << 8)){ found = 1; @@ -3670,7 +3670,7 @@ static void peep_update_emptying_bin(rct_peep* peep){ if ( !(scenery_entry->path_bit.var_06 & 1) || map_element->flags & (1 << 5) - || map_element->properties.path.additions & (1 << 7) + || footpath_element_path_scenery_is_ghost(map_element) ) { peep_state_reset(peep); return; @@ -3934,7 +3934,7 @@ static int peep_update_walking_find_bench(rct_peep* peep){ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0; - if (map_element->properties.path.additions & 0x80)return 0; + if (footpath_element_path_scenery_is_ghost(map_element)) return 0; int edges = (map_element->properties.path.edges & 0xF) ^ 0xF; if (edges == 0) return 0; @@ -4011,7 +4011,7 @@ static int peep_update_walking_find_bin(rct_peep* peep){ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0; - if (map_element->properties.path.additions & 0x80)return 0; + if (footpath_element_path_scenery_is_ghost(map_element)) return 0; int edges = (map_element->properties.path.edges & 0xF) ^ 0xF; if (edges == 0) return 0; @@ -4094,7 +4094,7 @@ static void peep_update_walking_break_scenery(rct_peep* peep){ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return; - if (map_element->properties.path.additions & 0x80)return; + if (footpath_element_path_scenery_is_ghost(map_element))return; int edges = map_element->properties.path.edges & 0xF; if (edges == 0xF) return; @@ -4272,7 +4272,7 @@ static void peep_update_using_bin(rct_peep* peep){ return; } - if (map_element->properties.path.additions & 0x80){ + if (footpath_element_path_scenery_is_ghost(map_element)){ peep_state_reset(peep); return; } @@ -4668,7 +4668,7 @@ static int peep_update_patrolling_find_bin(rct_peep* peep){ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN) return 0; - if (map_element->properties.path.additions & 0x80) + if (footpath_element_path_scenery_is_ghost(map_element)) return 0; uint8 bin_positions = map_element->properties.path.edges & 0xF; @@ -4962,8 +4962,8 @@ static void peep_update_walking(rct_peep* peep){ int ebp = 15; - if (additions){ - if (!(map_element->properties.path.additions & 0x80)){ + if (additions) { + if (!footpath_element_path_scenery_is_ghost(map_element)) { rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; if (!(sceneryEntry->path_bit.var_06 & 0x2)) ebp = 9; diff --git a/src/rct1.c b/src/rct1.c index 2c37679cff..148be8750f 100644 --- a/src/rct1.c +++ b/src/rct1.c @@ -776,7 +776,7 @@ static void rct1_fix_paths() mapElement->type &= 0xFC; mapElement->flags &= ~0x60; mapElement->properties.path.type &= 0x0F; - mapElement->properties.path.additions &= 0x7F; + footpath_scenery_set_is_ghost(mapElement, false); if (pathType & 0x80) { mapElement->type |= 1; } @@ -785,8 +785,8 @@ static void rct1_fix_paths() // Additions additions = mapElement->properties.path.additions & 0x0F; additions = RCT1PathAdditionConversionTable[additions]; - if (additions & 0x80) { - additions &= ~0x80; + if (footpath_element_path_scenery_is_ghost(mapElement)) { + footpath_scenery_set_is_ghost(mapElement, false); mapElement->flags |= MAP_ELEMENT_FLAG_BROKEN; } else { mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN; diff --git a/src/world/footpath.c b/src/world/footpath.c index 8eb39db1cc..1295ba74bd 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -249,17 +249,17 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement if (flags & GAME_COMMAND_FLAG_4) return MONEY32_UNDEFINED; - // Try placing a ghost + // Should place a ghost? if (flags & GAME_COMMAND_FLAG_GHOST) { // Check if there is something on the path already - if (mapElement->properties.path.additions & 0x0F) { + if (footpath_element_has_path_scenery(mapElement)) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NONE; return MONEY32_UNDEFINED; } // There is nothing yet - check if we should place a ghost if (flags & GAME_COMMAND_FLAG_APPLY) - mapElement->properties.path.additions |= 0x80; + footpath_scenery_set_is_ghost(mapElement, true); } if (!(flags & GAME_COMMAND_FLAG_APPLY)) @@ -267,9 +267,9 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement if ( (pathItemType != 0 && !(flags & GAME_COMMAND_FLAG_GHOST)) || - (pathItemType == 0 && (mapElement->properties.path.additions & 0x80)) + (pathItemType == 0 && footpath_element_path_scenery_is_ghost(mapElement)) ) { - mapElement->properties.path.additions &= ~0x80; + footpath_scenery_set_is_ghost(mapElement, false); } mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathItemType; @@ -1612,6 +1612,20 @@ uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement) return footpath_element_get_path_scenery(mapElement) - 1; } +bool footpath_element_path_scenery_is_ghost(rct_map_element *mapElement) +{ + return (mapElement->properties.path.additions & 0x80) == 0x80; +} + +void footpath_scenery_set_is_ghost(rct_map_element *mapElement, bool isGhost) +{ + // Remove ghost flag + mapElement->properties.path.additions &= ~0x80; + // Set flag if it should be a ghost + if (isGhost) + mapElement->properties.path.additions |= 0x80; +} + uint8 footpath_element_get_type(rct_map_element *mapElement) { return mapElement->properties.path.type >> 4; diff --git a/src/world/footpath.h b/src/world/footpath.h index f0db78154d..a2be5b7180 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -77,6 +77,8 @@ uint8 footpath_element_get_type(rct_map_element *mapElement); bool footpath_element_has_path_scenery(rct_map_element *mapElement); uint8 footpath_element_get_path_scenery(rct_map_element *mapElement); uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement); +bool footpath_element_path_scenery_is_ghost(rct_map_element *mapElement); +void footpath_scenery_set_is_ghost(rct_map_element *mapElement, bool isGhost); void footpath_remove_edges_at(int x, int y, rct_map_element *mapElement); #endif diff --git a/src/world/fountain.c b/src/world/fountain.c index b043fcfe69..08310b89da 100644 --- a/src/world/fountain.c +++ b/src/world/fountain.c @@ -24,6 +24,7 @@ #include "map.h" #include "scenery.h" #include "sprite.h" +#include "footpath.h" enum { PATTERN_CYCLIC_SQUARES, @@ -297,7 +298,7 @@ static bool is_jumping_fountain(int type, int x, int y, int z) continue; if (mapElement->base_height != z) continue; - if (mapElement->properties.path.additions & 0x80) + if (footpath_element_path_scenery_is_ghost(mapElement)) continue; int additions = mapElement->properties.path.additions & 0x0F; diff --git a/src/world/scenery.c b/src/world/scenery.c index 84a3833496..6b6d92389e 100644 --- a/src/world/scenery.c +++ b/src/world/scenery.c @@ -28,6 +28,7 @@ #include "map.h" #include "park.h" #include "scenery.h" +#include "footpath.h" void scenery_increase_age(int x, int y, rct_map_element *mapElement); @@ -41,7 +42,7 @@ void scenery_update_tile(int x, int y) scenery_update_age(x, y, mapElement); } else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) { int additions = mapElement->properties.path.additions & 0x0F; - if (additions != 0 && !(mapElement->properties.path.additions & 0x80)) { + if (additions != 0 && !footpath_element_path_scenery_is_ghost(mapElement)) { rct_scenery_entry *sceneryEntry; sceneryEntry = g_pathBitSceneryEntries[additions - 1]; if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER) { From f04c97fbc1c659742f24a1df927061dd5240636d Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sat, 5 Dec 2015 00:08:34 +0100 Subject: [PATCH 11/90] Getting path scenery type and index using helper functions throughout the entire project. --- src/interface/viewport_interaction.c | 2 +- src/peep/peep.c | 53 +++++++++++---------------- src/rct1.c | 7 ++-- src/windows/cheats.c | 6 +-- src/windows/editor_object_selection.c | 9 ++--- src/world/footpath.c | 11 ++++-- src/world/footpath.h | 1 + src/world/fountain.c | 6 +-- src/world/scenery.c | 5 +-- 9 files changed, 46 insertions(+), 54 deletions(-) diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index b8ef2602e1..7734113ede 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -291,7 +291,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info return info->type; case VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM: - sceneryEntry = g_pathBitSceneryEntries[(mapElement->properties.path.additions & 0x0F) - 1]; + sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(mapElement)]; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1164; if (mapElement->flags & 0x20) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = 3124; diff --git a/src/peep/peep.c b/src/peep/peep.c index de8ec307ea..7e13282a18 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -199,10 +199,10 @@ static uint8 peep_assess_surroundings(sint16 center_x, sint16 center_y, sint16 c switch (map_element_get_type(mapElement)){ case MAP_ELEMENT_TYPE_PATH: - if ((mapElement->properties.path.additions & 0xF) == 0) + if (!footpath_element_has_path_scenery(mapElement)) break; - scenery = g_pathBitSceneryEntries[(mapElement->properties.path.additions & 0x0F) - 1]; + scenery = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(mapElement)]; if (footpath_element_path_scenery_is_ghost(mapElement)) break; @@ -619,9 +619,10 @@ static void sub_68F41A(rct_peep *peep, int index) if (mapElement->base_height != peep->next_z) continue; - uint8 additions = mapElement->properties.path.additions & 0xF; - if (additions != 0 && footpath_element_path_scenery_is_ghost(mapElement)){ - rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + // Check if the footpath has ghost path scenery on it + if (footpath_element_has_path_scenery(mapElement) && footpath_element_path_scenery_is_ghost(mapElement)){ + uint8 pathSceneryIndex = footpath_element_get_path_scenery_index(mapElement); + rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[pathSceneryIndex]; if (sceneryEntry->path_bit.var_06 & (1 << 8)){ found = 1; } @@ -3661,12 +3662,12 @@ static void peep_update_emptying_bin(rct_peep* peep){ } } - if ((map_element->properties.path.additions & 0x0F) == 0) { + if (!footpath_element_has_path_scenery(map_element)) { peep_state_reset(peep); return; } - rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[(map_element->properties.path.additions & 0xF) - 1]; + rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if ( !(scenery_entry->path_bit.var_06 & 1) || map_element->flags & (1 << 5) @@ -3925,10 +3926,8 @@ static int peep_update_walking_find_bench(rct_peep* peep){ } } - uint8 additions = map_element->properties.path.additions & 0xF; - - if (!additions) return 0; - rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + if (!footpath_element_has_path_scenery(map_element)) return 0; + rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if (!(sceneryEntry->path_bit.var_06 & 0x2))return 0; @@ -4002,10 +4001,8 @@ static int peep_update_walking_find_bin(rct_peep* peep){ } } - uint8 additions = map_element->properties.path.additions & 0xF; - - if (!additions) return 0; - rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + if (!footpath_element_has_path_scenery(map_element)) return 0; + rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if (!(sceneryEntry->path_bit.var_06 & 0x1))return 0; @@ -4085,10 +4082,8 @@ static void peep_update_walking_break_scenery(rct_peep* peep){ } } - uint8 additions = map_element->properties.path.additions & 0xF; - - if (!additions) return; - rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + if (!footpath_element_has_path_scenery(map_element)) return; + rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if (!(sceneryEntry->path_bit.var_06 & 0x4))return; @@ -4255,13 +4250,12 @@ static void peep_update_using_bin(rct_peep* peep){ } } - uint8 additions = map_element->properties.path.additions & 0x0F; - if (!additions){ + if (!footpath_element_has_path_scenery(map_element)){ peep_state_reset(peep); return; } - rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if (!(sceneryEntry->path_bit.var_06 & 1)){ peep_state_reset(peep); return; @@ -4656,11 +4650,8 @@ static int peep_update_patrolling_find_bin(rct_peep* peep){ return 0; } - uint8 additions = map_element->properties.path.additions & 0xF; - - if (additions == 0)return 0; - - rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + if (!footpath_element_has_path_scenery(map_element)) return 0; + rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if (!(sceneryEntry->path_bit.var_06 & 1)) return 0; @@ -4958,13 +4949,11 @@ static void peep_update_walking(rct_peep* peep){ } } - uint8 additions = map_element->properties.path.additions & 0xF; - int ebp = 15; - if (additions) { + if (footpath_element_has_path_scenery(map_element)) { if (!footpath_element_path_scenery_is_ghost(map_element)) { - rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)]; if (!(sceneryEntry->path_bit.var_06 & 0x2)) ebp = 9; } @@ -6629,7 +6618,7 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e // 0x00F1AEE2 bool vandalism_present = false; - if ((map_element->properties.path.additions & 0xF) != 0 && + if (footpath_element_has_path_scenery(map_element) && (map_element->flags & MAP_ELEMENT_FLAG_BROKEN) && (map_element->properties.path.edges & 0xF) != 0xF){ vandalism_present = 1; diff --git a/src/rct1.c b/src/rct1.c index 148be8750f..8cca8fbe1a 100644 --- a/src/rct1.c +++ b/src/rct1.c @@ -783,16 +783,15 @@ static void rct1_fix_paths() mapElement->properties.path.type |= pathType << 4; // Additions - additions = mapElement->properties.path.additions & 0x0F; - additions = RCT1PathAdditionConversionTable[additions]; + additions = RCT1PathAdditionConversionTable[footpath_element_get_path_scenery(mapElement)]; if (footpath_element_path_scenery_is_ghost(mapElement)) { footpath_scenery_set_is_ghost(mapElement, false); mapElement->flags |= MAP_ELEMENT_FLAG_BROKEN; } else { mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN; } - mapElement->properties.path.additions &= 0xF0; - mapElement->properties.path.additions |= additions; + + footpath_element_set_path_scenery(mapElement, additions); break; case MAP_ELEMENT_TYPE_ENTRANCE: if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) { diff --git a/src/windows/cheats.c b/src/windows/cheats.c index 9713ca8ba3..5a9a635b85 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -483,7 +483,7 @@ static void cheat_fix_vandalism() if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) continue; - if ((it.element->properties.path.additions & 0x0F) == 0) + if (!footpath_element_has_path_scenery(it.element)) continue; it.element->flags &= ~MAP_ELEMENT_FLAG_BROKEN; @@ -511,10 +511,10 @@ static void cheat_remove_litter() if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) continue; - if ((it.element->properties.path.additions & 0x0F) == 0) + if (!footpath_element_has_path_scenery(it.element)) continue; - sceneryEntry = g_pathBitSceneryEntries[(it.element->properties.path.additions & 0xF) - 1]; + sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(it.element)]; if(sceneryEntry->path_bit.var_06 & (1 << 0)) it.element->properties.path.addition_status = 0xFF; diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index a1f062a6ac..63ed78a400 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -36,6 +36,7 @@ #include "dropdown.h" #include "error.h" #include "../util/util.h" +#include "../world/footpath.h" enum { @@ -577,7 +578,6 @@ static void setup_in_use_selection_flags(){ map_element_iterator_begin(&iter); do { uint16 type; - uint8 path_additions; rct_banner* banner; switch (map_element_get_type(iter.element)) { @@ -591,10 +591,9 @@ static void setup_in_use_selection_flags(){ assert(type < object_entry_group_counts[OBJECT_TYPE_PATHS]); RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_PATHS][type] |= (1 << 0); - path_additions = iter.element->properties.path.additions & 0xF; - if (path_additions){ - path_additions--; - RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_PATH_BITS][path_additions] |= (1 << 0); + if (footpath_element_has_path_scenery(iter.element)) { + uint8 path_additions = footpath_element_get_path_scenery_index(iter.element); + RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_PATH_BITS][path_additions] |= 1; } break; case MAP_ELEMENT_TYPE_SCENERY: diff --git a/src/world/footpath.c b/src/world/footpath.c index 1295ba74bd..57b7fd3b1a 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -210,7 +210,7 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement } else if (pathItemType != 0) { if ( !(flags & GAME_COMMAND_FLAG_GHOST) && - (mapElement->properties.path.additions & 0x0F) == pathItemType && + footpath_element_get_path_scenery(mapElement) == pathItemType && !(mapElement->flags & MAP_ELEMENT_FLAG_BROKEN) ) { if (flags & GAME_COMMAND_FLAG_4) @@ -272,7 +272,7 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement footpath_scenery_set_is_ghost(mapElement, false); } - mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathItemType; + footpath_element_set_path_scenery(mapElement, pathItemType); mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN; if (pathItemType != 0) { rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[pathItemType - 1]; @@ -295,7 +295,7 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement mapElement->properties.path.type = (mapElement->properties.path.type & 0x0F) | (type << 4); mapElement->type = (mapElement->type & 0xFE) | (type >> 7); - mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathItemType; + footpath_element_set_path_scenery(mapElement, pathItemType); mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN; loc_6A6620(flags, x, y, mapElement); @@ -1607,6 +1607,11 @@ uint8 footpath_element_get_path_scenery(rct_map_element *mapElement) return mapElement->properties.path.additions & 0xF; } +void footpath_element_set_path_scenery(rct_map_element *mapElement, uint8 pathSceneryType) +{ + mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathSceneryType; +} + uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement) { return footpath_element_get_path_scenery(mapElement) - 1; diff --git a/src/world/footpath.h b/src/world/footpath.h index a2be5b7180..7f67b982af 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -76,6 +76,7 @@ bool footpath_element_is_wide(rct_map_element *mapElement); uint8 footpath_element_get_type(rct_map_element *mapElement); bool footpath_element_has_path_scenery(rct_map_element *mapElement); uint8 footpath_element_get_path_scenery(rct_map_element *mapElement); +void footpath_element_set_path_scenery(rct_map_element *mapElement, uint8 pathSceneryType); uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement); bool footpath_element_path_scenery_is_ghost(rct_map_element *mapElement); void footpath_scenery_set_is_ghost(rct_map_element *mapElement, bool isGhost); diff --git a/src/world/fountain.c b/src/world/fountain.c index 08310b89da..38cb1811b2 100644 --- a/src/world/fountain.c +++ b/src/world/fountain.c @@ -301,11 +301,11 @@ static bool is_jumping_fountain(int type, int x, int y, int z) if (footpath_element_path_scenery_is_ghost(mapElement)) continue; - int additions = mapElement->properties.path.additions & 0x0F; - if (additions == 0) + if (!footpath_element_has_path_scenery(mapElement)) continue; - rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + uint8 additionIndex = footpath_element_get_path_scenery_index(mapElement); + rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additionIndex]; if (!(sceneryEntry->path_bit.var_06 & pathBitFlagMask)) continue; diff --git a/src/world/scenery.c b/src/world/scenery.c index 6b6d92389e..21c19b2dde 100644 --- a/src/world/scenery.c +++ b/src/world/scenery.c @@ -41,10 +41,9 @@ void scenery_update_tile(int x, int y) if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY) { scenery_update_age(x, y, mapElement); } else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) { - int additions = mapElement->properties.path.additions & 0x0F; - if (additions != 0 && !footpath_element_path_scenery_is_ghost(mapElement)) { + if (footpath_element_has_path_scenery(mapElement) && !footpath_element_path_scenery_is_ghost(mapElement)) { rct_scenery_entry *sceneryEntry; - sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(mapElement)]; if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER) { jumping_fountain_begin(JUMPING_FOUNTAIN_TYPE_WATER, x, y, mapElement); } else if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW) { From 35bf18bcb6def44dfbd556e3a98df2823d7dc798 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Mon, 21 Dec 2015 00:52:42 +0100 Subject: [PATCH 12/90] Added empty button that swaps the top two map elements --- src/windows/tile_inspector.c | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index ecd29809e8..775d28ada9 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -32,6 +32,7 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_TITLE, WIDX_CLOSE, WIDX_CORRUPT, + WIDX_SWAP, WIDX_CONTENT_PANEL, WIDX_SCROLL }; @@ -41,11 +42,19 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { #define MIN_WH 150 #define MAX_WH 800 +#define BTNW 160 // Button width +#define BTNH 16 // Button height +#define RXPL(COL) ((sint16)((WW - 3 - 6 * COL - BTNW * (COL + 1)))) // A button's left position, building up columns from the right +#define RXPR(COL) ((sint16)(RXPL(COL) + BTNW)) // A button's right position +#define YPT(ROW) ((sint16)(18 + ROW * (BTNH + 5))) // +#define YPB(ROW) ((sint16)(YPT(ROW) + BTNH)) // + rct_widget window_tile_inspector_widgets[] = { { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button - { WWT_CLOSEBOX, 1, WW - 150, WW - 3, 18, 39, STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, + { WWT_CLOSEBOX, 1, RXPL(0), RXPR(0), YPT(0), YPB(0), STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button + { WWT_CLOSEBOX, 1, RXPL(1), RXPR(1), YPT(0), YPB(0), STR_NONE, STR_NONE }, // Swap top elements button { WWT_RESIZE, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, STR_NONE }, // content panel { WWT_SCROLL, 1, 3, WW - 3, 65, WH - 30, 2, STR_NONE }, // scroll area { WIDGETS_END }, @@ -118,7 +127,7 @@ void window_tile_inspector_open() ); window->widgets = window_tile_inspector_widgets; window->enabled_widgets = (1 << WIDX_CLOSE); - window->disabled_widgets = (1 << WIDX_CORRUPT); + window->disabled_widgets = (1 << WIDX_CORRUPT) | (1 << WIDX_SWAP); window_init_scroll_widgets(window); window->colours[0] = 7; @@ -151,6 +160,30 @@ void corrupt_element(int x, int y) { mapElement->type = (8 << 2); } +void swap_top_elements(int x, int y) +{ + rct_map_element* mapElement; + mapElement = map_get_first_element_at(x, y); + + // Quit when there's only one tile element + if (map_element_is_last_for_tile(mapElement)) + return; + + // Fine the last and second-last elements + while (!map_element_is_last_for_tile(++mapElement)); + rct_map_element* lastmapElement = mapElement; + rct_map_element* secondLastmapElement = mapElement - 1; + + // Swap their memory + rct_map_element temp = *lastmapElement; + *lastmapElement = *secondLastmapElement; + *secondLastmapElement = temp; + + // Fix the 'last map element for tile' flag + lastmapElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE; + secondLastmapElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE; +} + static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { @@ -163,6 +196,10 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) w->scrolls[0].v_top = 0; window_invalidate(w); break; + case WIDX_SWAP: + swap_top_elements(window_tile_inspector_tile_x, window_tile_inspector_tile_y); + window_invalidate(w); + break; } } @@ -229,8 +266,8 @@ static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int window_tile_inspector_item_count = numItems; - w->enabled_widgets |= (1 << WIDX_CORRUPT); - w->disabled_widgets &= ~(1ULL << WIDX_CORRUPT); + w->enabled_widgets |= (1 << WIDX_CORRUPT) | (1 << WIDX_SWAP); + w->disabled_widgets &= ~((1ULL << WIDX_CORRUPT) | (1ULL << WIDX_SWAP)); w->scrolls[0].v_top = 0; window_invalidate(w); From d68ed3614700f5dce26f1a8b9ed070f787dd85cb Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Mon, 28 Dec 2015 23:11:36 +0100 Subject: [PATCH 13/90] Recreated UI for tile inspector. Added swap functionality. --- data/language/english_uk.txt | 2 + src/windows/tile_inspector.c | 224 +++++++++++++++++++++++++---------- 2 files changed, 162 insertions(+), 64 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 202cc767e4..731d1dd628 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3945,6 +3945,8 @@ STR_5603 :Guest has left ride STR_5604 :Guest has bought item STR_5605 :Guest has used facility STR_5606 :Guest has died +STR_5607 :Remove +STR_5608 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. ##################### # Rides/attractions # diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 775d28ada9..ae446a6077 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -31,35 +31,48 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_BACKGROUND, WIDX_TITLE, WIDX_CLOSE, + WIDX_LIST, WIDX_CORRUPT, - WIDX_SWAP, - WIDX_CONTENT_PANEL, - WIDX_SCROLL + WIDX_REMOVE, + WIDX_MOVE_DOWN, + WIDX_MOVE_UP, }; #define WW 500 #define WH 400 +#define MIN_WW WW +#define MAX_WW 1000 #define MIN_WH 150 #define MAX_WH 800 -#define BTNW 160 // Button width -#define BTNH 16 // Button height -#define RXPL(COL) ((sint16)((WW - 3 - 6 * COL - BTNW * (COL + 1)))) // A button's left position, building up columns from the right -#define RXPR(COL) ((sint16)(RXPL(COL) + BTNW)) // A button's right position -#define YPT(ROW) ((sint16)(18 + ROW * (BTNH + 5))) // -#define YPB(ROW) ((sint16)(YPT(ROW) + BTNH)) // +#define BX 3 // Button's left side +#define BW (BX + 148) // Button's right side +#define BY 52 // Button's Top +#define BH (BY + 11) // Button's Bottom +#define BS 18 + +#define SCROLL_BOTTOM_OFFSET 15 +#define LIST_ITEM_HEIGHT 11 rct_widget window_tile_inspector_widgets[] = { - { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar - { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button - { WWT_CLOSEBOX, 1, RXPL(0), RXPR(0), YPT(0), YPB(0), STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button - { WWT_CLOSEBOX, 1, RXPL(1), RXPR(1), YPT(0), YPB(0), STR_NONE, STR_NONE }, // Swap top elements button - { WWT_RESIZE, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, STR_NONE }, // content panel - { WWT_SCROLL, 1, 3, WW - 3, 65, WH - 30, 2, STR_NONE }, // scroll area + { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + + // Map element list + { WWT_SCROLL, 1, BW + 3, WW - 3, 30 + BS, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area + + // Buttons + { WWT_CLOSEBOX, 1, BX, BW, BY, BH, STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button + { WWT_CLOSEBOX, 1, BX, BW, BY + BS, BH + BS, 5607, 5608 }, // Remove button + { WWT_CLOSEBOX, 1, BX, BX + BW / 2 - 1, BY + BS * 3, BH + BS * 3, 5375, 5390 }, // Move down + { WWT_CLOSEBOX, 1, BX + BW / 2, BW, BY + BS * 3, BH + BS * 3, 5376, 5391 }, // Move up + { WIDGETS_END }, }; +static sint16 window_tile_inspector_highlighted_index = -1; + static int window_tile_inspector_tile_x; static int window_tile_inspector_tile_y; static int window_tile_inspector_item_count; @@ -67,15 +80,19 @@ static int window_tile_inspector_item_count; static void window_tile_inspector_close(rct_window *w); static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex); static void window_tile_inspector_resize(rct_window *w); +static void window_title_editor_update(rct_window *w); static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y); static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int x, int y); static void window_tile_inspector_tool_abort(rct_window *w, int widgetIndex); static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); +static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); static void window_tile_inspector_invalidate(rct_window *w); static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); +static void window_tile_inspector_auto_set_arrow_buttons(rct_window *w); + static rct_window_event_list window_tile_inspector_events = { window_tile_inspector_close, window_tile_inspector_mouseup, @@ -83,7 +100,7 @@ static rct_window_event_list window_tile_inspector_events = { NULL, NULL, NULL, - NULL, + window_title_editor_update, NULL, NULL, window_tile_inspector_tool_update, @@ -93,7 +110,7 @@ static rct_window_event_list window_tile_inspector_events = { window_tile_inspector_tool_abort, NULL, window_tile_inspector_scrollgetsize, - NULL, + window_tile_inspector_scrollmousedown, NULL, window_tile_inspector_scrollmouseover, NULL, @@ -127,16 +144,17 @@ void window_tile_inspector_open() ); window->widgets = window_tile_inspector_widgets; window->enabled_widgets = (1 << WIDX_CLOSE); - window->disabled_widgets = (1 << WIDX_CORRUPT) | (1 << WIDX_SWAP); + window->disabled_widgets = (1 << WIDX_CORRUPT) | (1 << WIDX_MOVE_UP) | (1 << WIDX_MOVE_DOWN) | (1 << WIDX_REMOVE); window_init_scroll_widgets(window); window->colours[0] = 7; window->colours[1] = 7; window->colours[2] = 7; - window->min_width = WW; + window->min_width = MIN_WW; window->min_height = MIN_WH; - window->max_width = WW; + window->max_width = MAX_WW; window->max_height = MAX_WH; + window->selected_list_item = -1; window_tile_inspector_tile_x = -1; window_tile_inspector_tile_y = -1; @@ -160,28 +178,39 @@ void corrupt_element(int x, int y) { mapElement->type = (8 << 2); } -void swap_top_elements(int x, int y) +// Swap element with its parent +void swap_elements(sint16 first, sint16 second) { - rct_map_element* mapElement; - mapElement = map_get_first_element_at(x, y); + rct_map_element *mapElement; + rct_map_element *firstElement = NULL; + rct_map_element *secondElement = NULL; + mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); - // Quit when there's only one tile element - if (map_element_is_last_for_tile(mapElement)) - return; + // swap_elements shouldn't be called when there is only one element on the tile + assert(!map_element_is_last_for_tile(mapElement)); - // Fine the last and second-last elements - while (!map_element_is_last_for_tile(++mapElement)); - rct_map_element* lastmapElement = mapElement; - rct_map_element* secondLastmapElement = mapElement - 1; + // Search for the elements + sint16 i = 0; + do { + if (i == first) firstElement = mapElement; + if (i == second) secondElement = mapElement; + i++; + + // Check if both elements have been found + if (firstElement != NULL && secondElement != NULL) + break; + } while (!map_element_is_last_for_tile(mapElement++)); // Swap their memory - rct_map_element temp = *lastmapElement; - *lastmapElement = *secondLastmapElement; - *secondLastmapElement = temp; + rct_map_element temp = *firstElement; + *firstElement = *secondElement; + *secondElement = temp; - // Fix the 'last map element for tile' flag - lastmapElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE; - secondLastmapElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE; + // Swap the 'last map element for tile' flag if either one of them was last + if (map_element_is_last_for_tile(firstElement) || map_element_is_last_for_tile(secondElement)) { + firstElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE; + secondElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE; + } } static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) @@ -196,9 +225,21 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) w->scrolls[0].v_top = 0; window_invalidate(w); break; - case WIDX_SWAP: - swap_top_elements(window_tile_inspector_tile_x, window_tile_inspector_tile_y); - window_invalidate(w); + case WIDX_REMOVE: + w->selected_list_item = 2; + widget_invalidate(w, WIDX_LIST); + break; + case WIDX_MOVE_DOWN: + swap_elements(w->selected_list_item, w->selected_list_item + 1); + w->selected_list_item++; + window_tile_inspector_auto_set_arrow_buttons(w); + widget_invalidate(w, WIDX_LIST); + break; + case WIDX_MOVE_UP: + swap_elements(w->selected_list_item - 1, w->selected_list_item); + w->selected_list_item--; + window_tile_inspector_auto_set_arrow_buttons(w); + widget_invalidate(w, WIDX_LIST); break; } } @@ -217,6 +258,16 @@ static void window_tile_inspector_resize(rct_window *w) } } +static void window_title_editor_update(rct_window *w) +{ + // Check if the mouse is hovering over the list + if (!widget_is_highlighted(w, WIDX_LIST)) + { + window_tile_inspector_highlighted_index = -1; + widget_invalidate(w, WIDX_LIST); + } +} + static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y) { int direction; @@ -266,8 +317,13 @@ static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int window_tile_inspector_item_count = numItems; - w->enabled_widgets |= (1 << WIDX_CORRUPT) | (1 << WIDX_SWAP); - w->disabled_widgets &= ~((1ULL << WIDX_CORRUPT) | (1ULL << WIDX_SWAP)); + // Enable 'insert corrupt element' button + w->enabled_widgets |= (1 << WIDX_CORRUPT); + w->disabled_widgets &= ~(1ULL << WIDX_CORRUPT); + // undo selection and buttons affecting it + w->selected_list_item = -1; + w->disabled_widgets |= (1ULL << WIDX_MOVE_UP) | (1ULL << WIDX_MOVE_DOWN) | (1ULL << WIDX_REMOVE); + w->enabled_widgets &= ~((1ULL << WIDX_MOVE_UP) | (1ULL << WIDX_MOVE_DOWN) | (1ULL << WIDX_REMOVE)); w->scrolls[0].v_top = 0; window_invalidate(w); @@ -281,12 +337,55 @@ static void window_tile_inspector_tool_abort(rct_window *w, int widgetIndex) static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) { *width = WW - 30; - *height = window_tile_inspector_item_count * 11; + *height = window_tile_inspector_item_count * LIST_ITEM_HEIGHT; +} + +static void window_tile_inspector_auto_set_arrow_buttons(rct_window *w) +{ + // Enable/disable up arrow buttons when at the top + if (w->selected_list_item == 0) { // Top element in list + w->disabled_widgets |= (1ULL << WIDX_MOVE_UP); + w->enabled_widgets &= ~(1ULL << WIDX_MOVE_UP); + } else { // Not the top element in the list + w->enabled_widgets |= (1ULL << WIDX_MOVE_UP); + w->disabled_widgets &= ~(1ULL << WIDX_MOVE_UP); + } + widget_invalidate(w, WIDX_MOVE_UP); + + if (w->selected_list_item == window_tile_inspector_item_count - 1) { // Bottom element in list + w->disabled_widgets |= (1ULL << WIDX_MOVE_DOWN); + w->enabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN); + } else { // Not the bottom element in the list + w->enabled_widgets |= (1ULL << WIDX_MOVE_DOWN); + w->disabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN); + } + widget_invalidate(w, WIDX_MOVE_DOWN); +} + +static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) +{ + // Because the list items are displayed in reverse order, subtract the number from the amount of elements + sint16 index = window_tile_inspector_item_count - (y - 1) / LIST_ITEM_HEIGHT - 1; + if (index < 0 || index >= window_tile_inspector_item_count) + return; + w->selected_list_item = index; + + // Enable 'remove' button + w->disabled_widgets &= ~(1ULL << WIDX_REMOVE); + w->enabled_widgets |= (1ULL << WIDX_REMOVE); + // Enable/disable arrow buttons + window_tile_inspector_auto_set_arrow_buttons(w); } static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) { - window_invalidate(w); + sint16 index = window_tile_inspector_item_count - (y - 1) / LIST_ITEM_HEIGHT - 1; + if (index < 0 || index >= window_tile_inspector_item_count) + window_tile_inspector_highlighted_index = -1; + else + window_tile_inspector_highlighted_index = index; + + widget_invalidate(w, WIDX_LIST); } static void window_tile_inspector_invalidate(rct_window *w) @@ -295,9 +394,9 @@ static void window_tile_inspector_invalidate(rct_window *w) window_tile_inspector_widgets[WIDX_BACKGROUND].bottom = w->height - 1; window_tile_inspector_widgets[WIDX_CLOSE].left = w->width - 13; window_tile_inspector_widgets[WIDX_CLOSE].right = w->width - 3; - window_tile_inspector_widgets[WIDX_CONTENT_PANEL].right = w->width - 1; - window_tile_inspector_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1; - window_tile_inspector_widgets[WIDX_SCROLL].bottom = w->height - 30; + window_tile_inspector_widgets[WIDX_TITLE].right = w->width - 2; + window_tile_inspector_widgets[WIDX_LIST].right = w->width - 3; + window_tile_inspector_widgets[WIDX_LIST].bottom = w->height - SCROLL_BOTTOM_OFFSET; } static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -328,8 +427,8 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) } - y += 25; - + // Draw header labels + x = w->x + 155; draw_string_left_underline(dpi, STR_TILE_INSPECTOR_ELEMENT_TYPE, NULL, 12, x, y); draw_string_left_underline(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT, NULL, 12, x + 200, y); draw_string_left_underline(dpi, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT, NULL, 12, x + 280, y); @@ -339,7 +438,9 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { - int x = 15, y = 11 * (window_tile_inspector_item_count - 1), i = 0; + int x = 3; + int y = LIST_ITEM_HEIGHT * (window_tile_inspector_item_count - 1); + int i = 0; char buffer[256]; if (window_tile_inspector_tile_x == -1) @@ -348,14 +449,18 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); do { - int type = map_element_get_type(element); char *type_name; int base_height = element->base_height; int clearance_height = element->clearance_height; - if ((i & 1) != 0) - gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + 11, ColourMapA[w->colours[1]].lighter | 0x1000000); + // Fill colour for current list element + if (i == w->selected_list_item) // Currently selected element + gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000); + else if (i == window_tile_inspector_highlighted_index) // Hovering + gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000); + else if ((i & 1) != 0) // odd / even check + gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000); switch (type) { case MAP_ELEMENT_TYPE_SURFACE: @@ -440,18 +545,9 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * gfx_draw_string_left(dpi, 5182, &base_height, 12, x + 200, y); gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + 280, y); - uint8 flags = element->flags; - char j; + // TODO: Add small columns for ghost, broken, last element for tile (G, B, L) - buffer[8] = '\0'; - - for (j = 7; j >= 0; j--, flags >>= 1) { - buffer[j] = flags & 1 ? '1' : '0'; - } - - gfx_draw_string(dpi, buffer, 12, x + 390, y); - - y -= 11; + y -= LIST_ITEM_HEIGHT; i++; } while (!map_element_is_last_for_tile(element++)); From d226012d94867023c696fb9d6bee28bad0bfca98 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 29 Dec 2015 15:43:49 +0100 Subject: [PATCH 14/90] Function to remove elements using the tile inspector. --- src/windows/tile_inspector.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index ae446a6077..6dcf6fd3fc 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -178,6 +178,14 @@ void corrupt_element(int x, int y) { mapElement->type = (8 << 2); } +void remove_element(int index) +{ + assert(index < window_tile_inspector_item_count); + rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); + mapElement += index; + map_element_remove(mapElement); +} + // Swap element with its parent void swap_elements(sint16 first, sint16 second) { @@ -226,7 +234,8 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) window_invalidate(w); break; case WIDX_REMOVE: - w->selected_list_item = 2; + remove_element(w->selected_list_item); + w->selected_list_item = -1; widget_invalidate(w, WIDX_LIST); break; case WIDX_MOVE_DOWN: @@ -456,11 +465,11 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * // Fill colour for current list element if (i == w->selected_list_item) // Currently selected element - gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000); + gfx_fill_rect(dpi, x, y, x + MAX_WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000); else if (i == window_tile_inspector_highlighted_index) // Hovering - gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000); + gfx_fill_rect(dpi, x, y, x + MAX_WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000); else if ((i & 1) != 0) // odd / even check - gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000); + gfx_fill_rect(dpi, x, y, x + MAX_WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000); switch (type) { case MAP_ELEMENT_TYPE_SURFACE: From 2a3aefdb4ee7ca5428659096e44339f6d3edf88a Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 29 Dec 2015 15:45:24 +0100 Subject: [PATCH 15/90] fixed list issue after removing element. --- src/windows/tile_inspector.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 6dcf6fd3fc..b79f241e11 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -184,6 +184,7 @@ void remove_element(int index) rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); mapElement += index; map_element_remove(mapElement); + window_tile_inspector_item_count--; } // Swap element with its parent From db270d85c2924b0b99b676830827829051655057 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 29 Dec 2015 17:55:35 +0100 Subject: [PATCH 16/90] automatically en/disabling buttons when needed. Selecting corrupt element when added. --- src/windows/tile_inspector.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index b79f241e11..b6aa69a85e 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -91,7 +91,7 @@ static void window_tile_inspector_invalidate(rct_window *w); static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); -static void window_tile_inspector_auto_set_arrow_buttons(rct_window *w); +static void window_tile_inspector_auto_set_buttons(rct_window *w); static rct_window_event_list window_tile_inspector_events = { window_tile_inspector_close, @@ -232,6 +232,7 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) corrupt_element(window_tile_inspector_tile_x, window_tile_inspector_tile_y); window_tile_inspector_item_count++; w->scrolls[0].v_top = 0; + w->selected_list_item = 0; window_invalidate(w); break; case WIDX_REMOVE: @@ -242,13 +243,13 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) case WIDX_MOVE_DOWN: swap_elements(w->selected_list_item, w->selected_list_item + 1); w->selected_list_item++; - window_tile_inspector_auto_set_arrow_buttons(w); + window_tile_inspector_auto_set_buttons(w); widget_invalidate(w, WIDX_LIST); break; case WIDX_MOVE_UP: swap_elements(w->selected_list_item - 1, w->selected_list_item); w->selected_list_item--; - window_tile_inspector_auto_set_arrow_buttons(w); + window_tile_inspector_auto_set_buttons(w); widget_invalidate(w, WIDX_LIST); break; } @@ -350,9 +351,19 @@ static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, *height = window_tile_inspector_item_count * LIST_ITEM_HEIGHT; } -static void window_tile_inspector_auto_set_arrow_buttons(rct_window *w) +static void window_tile_inspector_auto_set_buttons(rct_window *w) { - // Enable/disable up arrow buttons when at the top + // Remove button + if (w->selected_list_item == -1) { // Check if anything is selected + w->disabled_widgets |= (1ULL << WIDX_REMOVE); + w->enabled_widgets &= ~(1ULL << WIDX_REMOVE); + } else { // Nothing is selected + w->disabled_widgets &= ~(1ULL << WIDX_REMOVE); + w->enabled_widgets |= (1ULL << WIDX_REMOVE); + } + widget_invalidate(w, WIDX_REMOVE); + + // Move Up button if (w->selected_list_item == 0) { // Top element in list w->disabled_widgets |= (1ULL << WIDX_MOVE_UP); w->enabled_widgets &= ~(1ULL << WIDX_MOVE_UP); @@ -362,6 +373,7 @@ static void window_tile_inspector_auto_set_arrow_buttons(rct_window *w) } widget_invalidate(w, WIDX_MOVE_UP); + // Move Down button if (w->selected_list_item == window_tile_inspector_item_count - 1) { // Bottom element in list w->disabled_widgets |= (1ULL << WIDX_MOVE_DOWN); w->enabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN); @@ -380,11 +392,8 @@ static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex return; w->selected_list_item = index; - // Enable 'remove' button - w->disabled_widgets &= ~(1ULL << WIDX_REMOVE); - w->enabled_widgets |= (1ULL << WIDX_REMOVE); - // Enable/disable arrow buttons - window_tile_inspector_auto_set_arrow_buttons(w); + // Enable/disable buttons + window_tile_inspector_auto_set_buttons(w); } static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) From 64312957a0ce4c03c3ad6ac808ad5d677424061f Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 29 Dec 2015 23:19:01 +0100 Subject: [PATCH 17/90] Added column headers instead of labels, and added columns for the flags. --- data/language/english_uk.txt | 10 +++++- src/localisation/string_ids.h | 8 +++++ src/windows/tile_inspector.c | 62 ++++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 731d1dd628..9deeb751d7 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3946,7 +3946,15 @@ STR_5604 :Guest has bought item STR_5605 :Guest has used facility STR_5606 :Guest has died STR_5607 :Remove -STR_5608 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}Ghost flag +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}Broken flag +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag ##################### # Rides/attractions # diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index ba7d04c483..43be830387 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2004,9 +2004,17 @@ enum { STR_TILE_INSPECTOR_ENTRANCE_START = 5335, STR_TILE_INSPECTOR_ELEMENT_TYPE = 5338, STR_TILE_INSPECTOR_BASE_HEIGHT = 5339, + STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT = 5608, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT = 5340, + STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT = 5609, STR_TILE_INSPECTOR_FLAGS = 5341, STR_TILE_INSPECTOR_CHOOSE_MSG = 5342, + STR_TILE_INSPECTOR_FLAG_GHOST_SHORT = 5611, + STR_TILE_INSPECTOR_FLAG_GHOST = 5612, + STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT = 5613, + STR_TILE_INSPECTOR_FLAG_BROKEN = 5614, + STR_TILE_INSPECTOR_FLAG_LAST_SHORT = 5615, + STR_TILE_INSPECTOR_FLAG_LAST = 5616, STR_AUTO_STAFF_PLACEMENT = 5343, diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index b6aa69a85e..3eb124e83b 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -36,6 +36,7 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_REMOVE, WIDX_MOVE_DOWN, WIDX_MOVE_UP, + WIDX_COLUMN_LAST = 13, }; #define WW 500 @@ -54,13 +55,21 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { #define SCROLL_BOTTOM_OFFSET 15 #define LIST_ITEM_HEIGHT 11 +// Column offsets +#define COL_X_TYPE (BW + 3) // Type +#define COL_X_BH (COL_X_TYPE + 200) // Base height +#define COL_X_CH (COL_X_BH + 25) // Clearance height +#define COL_X_GF (COL_X_CH + 25) // Ghost flag +#define COL_X_BF (COL_X_GF + 15) // Broken flag +#define COL_X_LF (COL_X_BF + 15) // Last for tile flag + rct_widget window_tile_inspector_widgets[] = { { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button // Map element list - { WWT_SCROLL, 1, BW + 3, WW - 3, 30 + BS, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area + { WWT_SCROLL, 1, BW + 3, WW - 3, 29, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area // Buttons { WWT_CLOSEBOX, 1, BX, BW, BY, BH, STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button @@ -68,6 +77,14 @@ rct_widget window_tile_inspector_widgets[] = { { WWT_CLOSEBOX, 1, BX, BX + BW / 2 - 1, BY + BS * 3, BH + BS * 3, 5375, 5390 }, // Move down { WWT_CLOSEBOX, 1, BX + BW / 2, BW, BY + BS * 3, BH + BS * 3, 5376, 5391 }, // Move up + // Column headers + { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 16, 16 + 13, STR_TILE_INSPECTOR_ELEMENT_TYPE, STR_NONE }, + { WWT_13, 1, COL_X_BH, COL_X_CH - 1, 16, 16 + 13, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, STR_TILE_INSPECTOR_BASE_HEIGHT }, + { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT }, + { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, STR_TILE_INSPECTOR_FLAG_GHOST }, + { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, STR_TILE_INSPECTOR_FLAG_BROKEN }, + { WWT_13, 1, COL_X_LF, WW - 2, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, + { WIDGETS_END }, }; @@ -416,6 +433,7 @@ static void window_tile_inspector_invalidate(rct_window *w) window_tile_inspector_widgets[WIDX_TITLE].right = w->width - 2; window_tile_inspector_widgets[WIDX_LIST].right = w->width - 3; window_tile_inspector_widgets[WIDX_LIST].bottom = w->height - SCROLL_BOTTOM_OFFSET; + window_tile_inspector_widgets[WIDX_COLUMN_LAST].right = w->width - 2; } static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -426,15 +444,11 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); x = w->x + 20; - y = w->y + 25; + y = w->y + 15; - if (window_tile_inspector_tile_x == -1) { - - // No tile selected + if (window_tile_inspector_tile_x == -1) { // No tile selected gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_CHOOSE_MSG, NULL, 12, x, y); - } else { - sprintf( buffer, "X: %d, Y: %d", @@ -443,16 +457,7 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) ); gfx_draw_string(dpi, buffer, 12, x, y); - } - - // Draw header labels - x = w->x + 155; - draw_string_left_underline(dpi, STR_TILE_INSPECTOR_ELEMENT_TYPE, NULL, 12, x, y); - draw_string_left_underline(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT, NULL, 12, x + 200, y); - draw_string_left_underline(dpi, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT, NULL, 12, x + 280, y); - draw_string_left_underline(dpi, STR_TILE_INSPECTOR_FLAGS, NULL, 12, x + 390, y); - } static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) @@ -474,12 +479,13 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * int clearance_height = element->clearance_height; // Fill colour for current list element + const int list_width = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left; if (i == w->selected_list_item) // Currently selected element - gfx_fill_rect(dpi, x, y, x + MAX_WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000); + gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000); else if (i == window_tile_inspector_highlighted_index) // Hovering - gfx_fill_rect(dpi, x, y, x + MAX_WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000); + gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000); else if ((i & 1) != 0) // odd / even check - gfx_fill_rect(dpi, x, y, x + MAX_WW - 20, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000); + gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000); switch (type) { case MAP_ELEMENT_TYPE_SURFACE: @@ -560,15 +566,19 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * type_name = buffer; } - gfx_draw_string(dpi, type_name, 12, x, y); - gfx_draw_string_left(dpi, 5182, &base_height, 12, x + 200, y); - gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + 280, y); - - // TODO: Add small columns for ghost, broken, last element for tile (G, B, L) + // Undo relative scroll offset, but keep the 3 pixel padding + x = -w->widgets[WIDX_LIST].left + 3; + const int ghost = element->flags & MAP_ELEMENT_FLAG_GHOST ? 1 : 0; + const int broken = element->flags & MAP_ELEMENT_FLAG_BROKEN ? 1 : 0; + const int last = element->flags & MAP_ELEMENT_FLAG_LAST_TILE ? 1 : 0; + gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE, y); + gfx_draw_string_left(dpi, 5182, &base_height, 12, x + COL_X_BH, y); + gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + COL_X_CH, y); + gfx_draw_string_left(dpi, 5182, &ghost, 12, x + COL_X_GF, y); + gfx_draw_string_left(dpi, 5182, &broken, 12, x + COL_X_BF, y); + gfx_draw_string_left(dpi, 5182, &last, 12, x + COL_X_LF, y); y -= LIST_ITEM_HEIGHT; i++; - } while (!map_element_is_last_for_tile(element++)); - } From 38867b7462713a451bfabbd22dbf62c8118a068a Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 29 Dec 2015 23:20:54 +0100 Subject: [PATCH 18/90] Fixed old typo in string ID name. --- src/localisation/string_ids.h | 2 +- src/windows/tile_inspector.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 43be830387..291aa14748 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2005,7 +2005,7 @@ enum { STR_TILE_INSPECTOR_ELEMENT_TYPE = 5338, STR_TILE_INSPECTOR_BASE_HEIGHT = 5339, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT = 5608, - STR_TILE_INSPECTOR_CLEARANGE_HEIGHT = 5340, + STR_TILE_INSPECTOR_CLEARANCE_HEIGHT = 5340, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT = 5609, STR_TILE_INSPECTOR_FLAGS = 5341, STR_TILE_INSPECTOR_CHOOSE_MSG = 5342, diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 3eb124e83b..396b5d0759 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -80,7 +80,7 @@ rct_widget window_tile_inspector_widgets[] = { // Column headers { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 16, 16 + 13, STR_TILE_INSPECTOR_ELEMENT_TYPE, STR_NONE }, { WWT_13, 1, COL_X_BH, COL_X_CH - 1, 16, 16 + 13, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, STR_TILE_INSPECTOR_BASE_HEIGHT }, - { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT }, + { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, STR_TILE_INSPECTOR_FLAG_GHOST }, { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, STR_TILE_INSPECTOR_FLAG_BROKEN }, { WWT_13, 1, COL_X_LF, WW - 2, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, From 6f824c9c2e559d51eaa9134896042680fb526fa2 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 29 Dec 2015 23:23:22 +0100 Subject: [PATCH 19/90] Resolved warnings. --- src/windows/tile_inspector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 396b5d0759..725a0f3cb3 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -568,9 +568,9 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * // Undo relative scroll offset, but keep the 3 pixel padding x = -w->widgets[WIDX_LIST].left + 3; - const int ghost = element->flags & MAP_ELEMENT_FLAG_GHOST ? 1 : 0; - const int broken = element->flags & MAP_ELEMENT_FLAG_BROKEN ? 1 : 0; - const int last = element->flags & MAP_ELEMENT_FLAG_LAST_TILE ? 1 : 0; + int ghost = element->flags & MAP_ELEMENT_FLAG_GHOST ? 1 : 0; + int broken = element->flags & MAP_ELEMENT_FLAG_BROKEN ? 1 : 0; + int last = element->flags & MAP_ELEMENT_FLAG_LAST_TILE ? 1 : 0; gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE, y); gfx_draw_string_left(dpi, 5182, &base_height, 12, x + COL_X_BH, y); gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + COL_X_CH, y); From 389249abfdcbbf5f8493432ae00a984bb4bfafbb Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Wed, 30 Dec 2015 00:11:55 +0100 Subject: [PATCH 20/90] Better UI spacing. --- data/language/english_uk.txt | 4 ++-- src/windows/tile_inspector.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 9deeb751d7..370cbc9720 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3677,8 +3677,8 @@ STR_5335 :Ride entrance STR_5336 :Ride exit STR_5337 :Park entrance STR_5338 :Element type -STR_5339 :Base height -STR_5340 :Clearance height +STR_5339 :{SMALLFONT}{BLACK}Base height +STR_5340 :{SMALLFONT}{BLACK}Clearance height STR_5341 :Flags STR_5342 :Choose a map tile STR_5343 :Automatically place staff diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 725a0f3cb3..b13810b76f 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -58,10 +58,10 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { // Column offsets #define COL_X_TYPE (BW + 3) // Type #define COL_X_BH (COL_X_TYPE + 200) // Base height -#define COL_X_CH (COL_X_BH + 25) // Clearance height -#define COL_X_GF (COL_X_CH + 25) // Ghost flag -#define COL_X_BF (COL_X_GF + 15) // Broken flag -#define COL_X_LF (COL_X_BF + 15) // Last for tile flag +#define COL_X_CH (COL_X_BH + 20) // Clearance height +#define COL_X_GF (COL_X_CH + 20) // Ghost flag +#define COL_X_BF (COL_X_GF + 12) // Broken flag +#define COL_X_LF (COL_X_BF + 12) // Last for tile flag rct_widget window_tile_inspector_widgets[] = { { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background @@ -69,7 +69,7 @@ rct_widget window_tile_inspector_widgets[] = { { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button // Map element list - { WWT_SCROLL, 1, BW + 3, WW - 3, 29, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area + { WWT_SCROLL, 1, BW + 3, WW - 3, 31, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area // Buttons { WWT_CLOSEBOX, 1, BX, BW, BY, BH, STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button @@ -83,7 +83,7 @@ rct_widget window_tile_inspector_widgets[] = { { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, STR_TILE_INSPECTOR_FLAG_GHOST }, { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, STR_TILE_INSPECTOR_FLAG_BROKEN }, - { WWT_13, 1, COL_X_LF, WW - 2, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, + { WWT_13, 1, COL_X_LF, WW - 3, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, { WIDGETS_END }, }; @@ -433,7 +433,7 @@ static void window_tile_inspector_invalidate(rct_window *w) window_tile_inspector_widgets[WIDX_TITLE].right = w->width - 2; window_tile_inspector_widgets[WIDX_LIST].right = w->width - 3; window_tile_inspector_widgets[WIDX_LIST].bottom = w->height - SCROLL_BOTTOM_OFFSET; - window_tile_inspector_widgets[WIDX_COLUMN_LAST].right = w->width - 2; + window_tile_inspector_widgets[WIDX_COLUMN_LAST].right = w->width - 3; } static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) From 05e807a9cac2ba4d1c8891adca4949883748e059 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Wed, 30 Dec 2015 00:51:40 +0100 Subject: [PATCH 21/90] Displayng ride type for tracks --- src/windows/tile_inspector.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index b13810b76f..2ee157faa9 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -522,7 +522,12 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * type_name = buffer; break; case MAP_ELEMENT_TYPE_TRACK: - type_name = "Track"; // TODO: show type? + sprintf( + buffer, + "Track (%s)", + language_get_string(2 + GET_RIDE(element->properties.track.ride_index)->type) + ); + type_name = buffer; break; case MAP_ELEMENT_TYPE_SCENERY: sprintf( From 2b7a88297fd7437b4e6d640b8fbc203312979988 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Wed, 30 Dec 2015 01:18:12 +0100 Subject: [PATCH 22/90] Moved some UI elements and changed default size. Updated changelog. --- distribution/changelog.txt | 1 + src/windows/tile_inspector.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 6650f90d21..10572450f9 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -5,6 +5,7 @@ - Feature: Add SI units as a new measurement system for distance / speed. - Feature: Update alternative font selection mechanism for all platforms. - Feature: Allow enabling / disabling of different notifications. +- Feature: Improved tile inspector. - Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug) - Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 2ee157faa9..5716c8c897 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -39,16 +39,16 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_COLUMN_LAST = 13, }; -#define WW 500 -#define WH 400 +#define WW 450 +#define WH 200 #define MIN_WW WW #define MAX_WW 1000 #define MIN_WH 150 #define MAX_WH 800 #define BX 3 // Button's left side -#define BW (BX + 148) // Button's right side -#define BY 52 // Button's Top +#define BW (BX + 138) // Button's right side +#define BY 32 // Button's Top #define BH (BY + 11) // Button's Bottom #define BS 18 @@ -438,14 +438,13 @@ static void window_tile_inspector_invalidate(rct_window *w) static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) { - int x, y; - char buffer[256]; - window_draw_widgets(w, dpi); - x = w->x + 20; - y = w->y + 15; + char buffer[256]; + int x = w->x /*+ w->widgets[WIDX_LIST].left*/ + 3; + int y = w->y + w->height - 13; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM; if (window_tile_inspector_tile_x == -1) { // No tile selected gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_CHOOSE_MSG, NULL, 12, x, y); } else { @@ -472,6 +471,7 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM; do { int type = map_element_get_type(element); char *type_name; From a1f506df58012c650a4131a3010a3665d1c5467a Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Fri, 1 Jan 2016 17:21:48 +0100 Subject: [PATCH 23/90] Fix all buttons after deleting a map element. --- src/windows/tile_inspector.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 5716c8c897..f573dc7f54 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -255,6 +255,7 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) case WIDX_REMOVE: remove_element(w->selected_list_item); w->selected_list_item = -1; + window_tile_inspector_auto_set_buttons(w); widget_invalidate(w, WIDX_LIST); break; case WIDX_MOVE_DOWN: From ae4ff5fc6c7b237c7e3cd0b79ff3cce5ed4b0d08 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Fri, 1 Jan 2016 19:29:41 +0100 Subject: [PATCH 24/90] Redesigned UI to be more consistent with the ride/staff windows. --- data/language/english_uk.txt | 2 +- src/windows/tile_inspector.c | 61 ++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 370cbc9720..1ab505fb91 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3945,7 +3945,7 @@ STR_5603 :Guest has left ride STR_5604 :Guest has bought item STR_5605 :Guest has used facility STR_5606 :Guest has died -STR_5607 :Remove +STR_5607 :{SMALLFONT}{BLACK}Forcefully remove selected map element. STR_5608 :BH STR_5609 :CH STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index f573dc7f54..9bb6e979c5 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -26,6 +26,7 @@ #include "../world/scenery.h" #include "../world/map.h" #include "../world/footpath.h" +#include "../sprites.h" enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_BACKGROUND, @@ -39,51 +40,51 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_COLUMN_LAST = 13, }; -#define WW 450 +#define WW 400 #define WH 200 #define MIN_WW WW -#define MAX_WW 1000 +#define MAX_WW WW #define MIN_WH 150 #define MAX_WH 800 -#define BX 3 // Button's left side -#define BW (BX + 138) // Button's right side -#define BY 32 // Button's Top -#define BH (BY + 11) // Button's Bottom -#define BS 18 +#define BW (WW - 5) // Button's right side +#define BX (BW - 23) // Button's left side +#define BY 17 // Button's Top +#define BH (BY + 23) // Button's Bottom +#define BS 24 #define SCROLL_BOTTOM_OFFSET 15 #define LIST_ITEM_HEIGHT 11 // Column offsets -#define COL_X_TYPE (BW + 3) // Type -#define COL_X_BH (COL_X_TYPE + 200) // Base height +#define COL_X_TYPE 2 // Type +#define COL_X_BH (COL_X_TYPE + 300) // Base height #define COL_X_CH (COL_X_BH + 20) // Clearance height #define COL_X_GF (COL_X_CH + 20) // Ghost flag #define COL_X_BF (COL_X_GF + 12) // Broken flag #define COL_X_LF (COL_X_BF + 12) // Last for tile flag rct_widget window_tile_inspector_widgets[] = { - { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar - { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button // Map element list - { WWT_SCROLL, 1, BW + 3, WW - 3, 31, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area + { WWT_SCROLL, 1, 2, WW - 3, 57, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area // Buttons - { WWT_CLOSEBOX, 1, BX, BW, BY, BH, STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button - { WWT_CLOSEBOX, 1, BX, BW, BY + BS, BH + BS, 5607, 5608 }, // Remove button - { WWT_CLOSEBOX, 1, BX, BX + BW / 2 - 1, BY + BS * 3, BH + BS * 3, 5375, 5390 }, // Move down - { WWT_CLOSEBOX, 1, BX + BW / 2, BW, BY + BS * 3, BH + BS * 3, 5376, 5391 }, // Move up + { WWT_FLATBTN, 1, BX, BW, BY, BH, SPR_MAP, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button + { WWT_FLATBTN, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, 5607 }, // Remove button + { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, 5375, 5390 }, // Move down + { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, 5376, 5391 }, // Move up // Column headers - { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 16, 16 + 13, STR_TILE_INSPECTOR_ELEMENT_TYPE, STR_NONE }, - { WWT_13, 1, COL_X_BH, COL_X_CH - 1, 16, 16 + 13, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, STR_TILE_INSPECTOR_BASE_HEIGHT }, - { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, - { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, STR_TILE_INSPECTOR_FLAG_GHOST }, - { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, STR_TILE_INSPECTOR_FLAG_BROKEN }, - { WWT_13, 1, COL_X_LF, WW - 3, 16, 16 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, + { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_TILE_INSPECTOR_ELEMENT_TYPE, STR_NONE }, + { WWT_13, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, STR_TILE_INSPECTOR_BASE_HEIGHT }, + { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, + { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 42, 42 + 13, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, STR_TILE_INSPECTOR_FLAG_GHOST }, + { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 42, 42 + 13, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, STR_TILE_INSPECTOR_FLAG_BROKEN }, + { WWT_13, 1, COL_X_LF, WW - 3, 42, 42 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, { WIDGETS_END }, }; @@ -247,10 +248,10 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) break; case WIDX_CORRUPT: corrupt_element(window_tile_inspector_tile_x, window_tile_inspector_tile_y); - window_tile_inspector_item_count++; w->scrolls[0].v_top = 0; - w->selected_list_item = 0; - window_invalidate(w); + w->selected_list_item = window_tile_inspector_item_count++; + window_tile_inspector_auto_set_buttons(w); + widget_invalidate(w, WIDX_LIST); break; case WIDX_REMOVE: remove_element(w->selected_list_item); @@ -382,7 +383,7 @@ static void window_tile_inspector_auto_set_buttons(rct_window *w) widget_invalidate(w, WIDX_REMOVE); // Move Up button - if (w->selected_list_item == 0) { // Top element in list + if (w->selected_list_item <= 0) { // Top element in list, or -1 w->disabled_widgets |= (1ULL << WIDX_MOVE_UP); w->enabled_widgets &= ~(1ULL << WIDX_MOVE_UP); } else { // Not the top element in the list @@ -392,7 +393,7 @@ static void window_tile_inspector_auto_set_buttons(rct_window *w) widget_invalidate(w, WIDX_MOVE_UP); // Move Down button - if (w->selected_list_item == window_tile_inspector_item_count - 1) { // Bottom element in list + if (w->selected_list_item == window_tile_inspector_item_count - 1 || w->selected_list_item == -1) { // Bottom element in list, or -1 w->disabled_widgets |= (1ULL << WIDX_MOVE_DOWN); w->enabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN); } else { // Not the bottom element in the list @@ -573,11 +574,11 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * } // Undo relative scroll offset, but keep the 3 pixel padding - x = -w->widgets[WIDX_LIST].left + 3; + x = -w->widgets[WIDX_LIST].left; int ghost = element->flags & MAP_ELEMENT_FLAG_GHOST ? 1 : 0; int broken = element->flags & MAP_ELEMENT_FLAG_BROKEN ? 1 : 0; int last = element->flags & MAP_ELEMENT_FLAG_LAST_TILE ? 1 : 0; - gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE, y); + gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE + 3, y); // 3px padding gfx_draw_string_left(dpi, 5182, &base_height, 12, x + COL_X_BH, y); gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + COL_X_CH, y); gfx_draw_string_left(dpi, 5182, &ghost, 12, x + COL_X_GF, y); From bf7e45939ac1693d6faffa558742d93f483fe5ea Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Fri, 1 Jan 2016 20:06:00 +0100 Subject: [PATCH 25/90] Pixel correct paddings for list and column headers --- src/windows/tile_inspector.c | 62 ++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 9bb6e979c5..51f9b31e6a 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -37,7 +37,12 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { WIDX_REMOVE, WIDX_MOVE_DOWN, WIDX_MOVE_UP, - WIDX_COLUMN_LAST = 13, + WIDX_COLUMN_TYPE, + WIDX_COLUMN_BASEHEIGHT, + WIDX_COLUMN_CLEARANCEHEIGHT, + WIDX_COLUMN_GHOSTFLAG, + WIDX_COLUMN_BROKENFLAG, + WIDX_COLUMN_LASTFLAG, }; #define WW 400 @@ -57,7 +62,7 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { #define LIST_ITEM_HEIGHT 11 // Column offsets -#define COL_X_TYPE 2 // Type +#define COL_X_TYPE 3 // Type #define COL_X_BH (COL_X_TYPE + 300) // Base height #define COL_X_CH (COL_X_BH + 20) // Clearance height #define COL_X_GF (COL_X_CH + 20) // Ghost flag @@ -70,21 +75,21 @@ rct_widget window_tile_inspector_widgets[] = { { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button // Map element list - { WWT_SCROLL, 1, 2, WW - 3, 57, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area + { WWT_SCROLL, 1, 3, WW - 4, 57, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area // Buttons { WWT_FLATBTN, 1, BX, BW, BY, BH, SPR_MAP, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button - { WWT_FLATBTN, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, 5607 }, // Remove button - { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, 5375, 5390 }, // Move down - { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, 5376, 5391 }, // Move up + { WWT_FLATBTN, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, 5607 }, // Remove button + { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, 5375, 5390 }, // Move down + { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, 5376, 5391 }, // Move up // Column headers - { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_TILE_INSPECTOR_ELEMENT_TYPE, STR_NONE }, - { WWT_13, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, STR_TILE_INSPECTOR_BASE_HEIGHT }, - { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, - { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 42, 42 + 13, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, STR_TILE_INSPECTOR_FLAG_GHOST }, - { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 42, 42 + 13, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, STR_TILE_INSPECTOR_FLAG_BROKEN }, - { WWT_13, 1, COL_X_LF, WW - 3, 42, 42 + 13, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, STR_TILE_INSPECTOR_FLAG_LAST }, + { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_NONE, STR_NONE }, // Type + { WWT_13, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_BASE_HEIGHT }, // Base height + { WWT_13, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, // Clearance height + { WWT_13, 1, COL_X_GF, COL_X_BF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_GHOST }, // Ghost flag + { WWT_13, 1, COL_X_BF, COL_X_LF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_BROKEN }, // Broken flag + { WWT_13, 1, COL_X_LF, WW - 3, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_LAST }, // Last of tile flag { WIDGETS_END }, }; @@ -433,9 +438,9 @@ static void window_tile_inspector_invalidate(rct_window *w) window_tile_inspector_widgets[WIDX_CLOSE].left = w->width - 13; window_tile_inspector_widgets[WIDX_CLOSE].right = w->width - 3; window_tile_inspector_widgets[WIDX_TITLE].right = w->width - 2; - window_tile_inspector_widgets[WIDX_LIST].right = w->width - 3; + window_tile_inspector_widgets[WIDX_LIST].right = w->width - 4; window_tile_inspector_widgets[WIDX_LIST].bottom = w->height - SCROLL_BOTTOM_OFFSET; - window_tile_inspector_widgets[WIDX_COLUMN_LAST].right = w->width - 3; + window_tile_inspector_widgets[WIDX_COLUMN_LASTFLAG].right = w->width - 3; } static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -446,7 +451,36 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi) int x = w->x /*+ w->widgets[WIDX_LIST].left*/ + 3; int y = w->y + w->height - 13; + // Set medium font size RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM; + + // Draw column headers + rct_widget *widget; + if ((widget= &w->widgets[WIDX_COLUMN_TYPE])->type != WWT_EMPTY) { + gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_ELEMENT_TYPE, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left); + } + if ((widget = &w->widgets[WIDX_COLUMN_BASEHEIGHT])->type != WWT_EMPTY) + { + gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left); + } + if ((widget = &w->widgets[WIDX_COLUMN_CLEARANCEHEIGHT])->type != WWT_EMPTY) + { + gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left); + } + if ((widget = &w->widgets[WIDX_COLUMN_GHOSTFLAG])->type != WWT_EMPTY) + { + gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left); + } + if ((widget = &w->widgets[WIDX_COLUMN_BROKENFLAG])->type != WWT_EMPTY) + { + gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left); + } + if ((widget = &w->widgets[WIDX_COLUMN_LASTFLAG])->type != WWT_EMPTY) + { + gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left); + } + + // Draw coordinates if (window_tile_inspector_tile_x == -1) { // No tile selected gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_CHOOSE_MSG, NULL, 12, x, y); } else { From 829c3a333960567dc4c166a724f3db919800a86f Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Fri, 1 Jan 2016 20:13:32 +0100 Subject: [PATCH 26/90] Added correct tooltips for moving up/down buttons. --- data/language/english_uk.txt | 2 ++ src/windows/tile_inspector.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 1ab505fb91..b954ea29b5 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3955,6 +3955,8 @@ STR_5613 :B STR_5614 :{SMALLFONT}{BLACK}Broken flag STR_5615 :L STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag +STR_5617 :{SMALLFONT}{BLACK}Move selected element up. +STR_5618 :{SMALLFONT}{BLACK}Move selected element down. ##################### # Rides/attractions # diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 51f9b31e6a..9ba976774f 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -80,8 +80,8 @@ rct_widget window_tile_inspector_widgets[] = { // Buttons { WWT_FLATBTN, 1, BX, BW, BY, BH, SPR_MAP, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button { WWT_FLATBTN, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, 5607 }, // Remove button - { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, 5375, 5390 }, // Move down - { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, 5376, 5391 }, // Move up + { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, 5375, 5617 }, // Move down + { WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, 5376, 5618 }, // Move up // Column headers { WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_NONE, STR_NONE }, // Type From 560a4357485b8794a397ddd0b7775a1394410a6d Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Fri, 1 Jan 2016 20:35:08 +0100 Subject: [PATCH 27/90] Drawing checkmarks for set flags --- src/windows/tile_inspector.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index 9ba976774f..c0dde9e3ea 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -609,15 +609,15 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * // Undo relative scroll offset, but keep the 3 pixel padding x = -w->widgets[WIDX_LIST].left; - int ghost = element->flags & MAP_ELEMENT_FLAG_GHOST ? 1 : 0; - int broken = element->flags & MAP_ELEMENT_FLAG_BROKEN ? 1 : 0; - int last = element->flags & MAP_ELEMENT_FLAG_LAST_TILE ? 1 : 0; + const bool ghost = (element->flags & MAP_ELEMENT_FLAG_GHOST) != 0; + const bool broken = (element->flags & MAP_ELEMENT_FLAG_BROKEN) != 0; + const bool last = (element->flags & MAP_ELEMENT_FLAG_LAST_TILE) != 0; gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE + 3, y); // 3px padding gfx_draw_string_left(dpi, 5182, &base_height, 12, x + COL_X_BH, y); gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + COL_X_CH, y); - gfx_draw_string_left(dpi, 5182, &ghost, 12, x + COL_X_GF, y); - gfx_draw_string_left(dpi, 5182, &broken, 12, x + COL_X_BF, y); - gfx_draw_string_left(dpi, 5182, &last, 12, x + COL_X_LF, y); + if (ghost) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_GF, y); + if (broken) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_BF, y); + if (last) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_LF, y); y -= LIST_ITEM_HEIGHT; i++; From 17e5a0d356f267a6646bb6294b056dc6497f8f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sat, 2 Jan 2016 00:08:18 +0100 Subject: [PATCH 28/90] Use strndup when setting last_run_version gConfigGeneral.last_run_version should have the string value copied to, otherwise the SafeFree in config_set_property could try freeing value from stack if used. --- src/openrct2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2.c b/src/openrct2.c index eb41a4457f..469a610c29 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -203,7 +203,7 @@ bool openrct2_initialise() gOpenRCT2ShowChangelog = true; if (gConfigGeneral.last_run_version != NULL && (strcmp(gConfigGeneral.last_run_version, OPENRCT2_VERSION) == 0)) gOpenRCT2ShowChangelog = false; - gConfigGeneral.last_run_version = OPENRCT2_VERSION; + gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION)); config_save_default(); // TODO add configuration option to allow multiple instances From c1d33e7308b93044026dcff13f99a83ae8ad9c2b Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 2 Jan 2016 04:00:17 +0000 Subject: [PATCH 29/90] Merge Localisation/master into OpenRCT2/develop. --- data/language/japanese.txt | 488 ++++++++++++++++++------------------- 1 file changed, 244 insertions(+), 244 deletions(-) diff --git a/data/language/japanese.txt b/data/language/japanese.txt index dacfabf07d..2719237d84 100644 --- a/data/language/japanese.txt +++ b/data/language/japanese.txt @@ -604,172 +604,172 @@ STR_0599 :A compact roller coaster with individual cars and smooth twisting d STR_0600 :Powered mine trains career along a smooth and twisted track layout STR_0601 : STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions -STR_0603 :Guest {INT32} -STR_0604 :Guest {INT32} -STR_0605 :Guest {INT32} -STR_0606 :Guest {INT32} -STR_0607 :Guest {INT32} -STR_0608 :Guest {INT32} -STR_0609 :Guest {INT32} -STR_0610 :Guest {INT32} -STR_0611 :Guest {INT32} -STR_0612 :Guest {INT32} -STR_0613 :Guest {INT32} -STR_0614 :Guest {INT32} -STR_0615 :Guest {INT32} -STR_0616 :Guest {INT32} -STR_0617 :Guest {INT32} -STR_0618 :Guest {INT32} -STR_0619 :Guest {INT32} -STR_0620 :Guest {INT32} -STR_0621 :Guest {INT32} -STR_0622 :Guest {INT32} -STR_0623 :Guest {INT32} -STR_0624 :Guest {INT32} -STR_0625 :Guest {INT32} -STR_0626 :Guest {INT32} -STR_0627 :Guest {INT32} -STR_0628 :Guest {INT32} -STR_0629 :Guest {INT32} -STR_0630 :Guest {INT32} -STR_0631 :Guest {INT32} -STR_0632 :Guest {INT32} -STR_0633 :Guest {INT32} -STR_0634 :Guest {INT32} -STR_0635 :Guest {INT32} -STR_0636 :Guest {INT32} -STR_0637 :Guest {INT32} -STR_0638 :Guest {INT32} -STR_0639 :Guest {INT32} -STR_0640 :Guest {INT32} -STR_0641 :Guest {INT32} -STR_0642 :Guest {INT32} -STR_0643 :Guest {INT32} -STR_0644 :Guest {INT32} -STR_0645 :Guest {INT32} -STR_0646 :Guest {INT32} -STR_0647 :Guest {INT32} -STR_0648 :Guest {INT32} -STR_0649 :Guest {INT32} -STR_0650 :Guest {INT32} -STR_0651 :Guest {INT32} -STR_0652 :Guest {INT32} -STR_0653 :Guest {INT32} -STR_0654 :Guest {INT32} -STR_0655 :Guest {INT32} -STR_0656 :Guest {INT32} -STR_0657 :Guest {INT32} -STR_0658 :Guest {INT32} -STR_0659 :Guest {INT32} -STR_0660 :Guest {INT32} -STR_0661 :Guest {INT32} -STR_0662 :Guest {INT32} -STR_0663 :Guest {INT32} -STR_0664 :Guest {INT32} -STR_0665 :Guest {INT32} -STR_0666 :Guest {INT32} -STR_0667 :Guest {INT32} -STR_0668 :Guest {INT32} -STR_0669 :Guest {INT32} -STR_0670 :Guest {INT32} -STR_0671 :Guest {INT32} -STR_0672 :Guest {INT32} -STR_0673 :Guest {INT32} -STR_0674 :Guest {INT32} -STR_0675 :Guest {INT32} -STR_0676 :Guest {INT32} -STR_0677 :Guest {INT32} -STR_0678 :Guest {INT32} -STR_0679 :Guest {INT32} -STR_0680 :Guest {INT32} -STR_0681 :Guest {INT32} -STR_0682 :Guest {INT32} -STR_0683 :Guest {INT32} -STR_0684 :Guest {INT32} -STR_0685 :Guest {INT32} -STR_0686 :Guest {INT32} -STR_0687 :Guest {INT32} -STR_0688 :Guest {INT32} -STR_0689 :Guest {INT32} -STR_0690 :Guest {INT32} -STR_0691 :Guest {INT32} -STR_0692 :Guest {INT32} -STR_0693 :Guest {INT32} -STR_0694 :Guest {INT32} -STR_0695 :Guest {INT32} -STR_0696 :Guest {INT32} -STR_0697 :Guest {INT32} -STR_0698 :Guest {INT32} -STR_0699 :Guest {INT32} -STR_0700 :Guest {INT32} -STR_0701 :Guest {INT32} -STR_0702 :Guest {INT32} -STR_0703 :Guest {INT32} -STR_0704 :Guest {INT32} -STR_0705 :Guest {INT32} -STR_0706 :Guest {INT32} -STR_0707 :Guest {INT32} -STR_0708 :Guest {INT32} -STR_0709 :Guest {INT32} -STR_0710 :Guest {INT32} -STR_0711 :Guest {INT32} -STR_0712 :Guest {INT32} -STR_0713 :Guest {INT32} -STR_0714 :Guest {INT32} -STR_0715 :Guest {INT32} -STR_0716 :Guest {INT32} -STR_0717 :Guest {INT32} -STR_0718 :Guest {INT32} -STR_0719 :Guest {INT32} -STR_0720 :Guest {INT32} -STR_0721 :Guest {INT32} -STR_0722 :Guest {INT32} -STR_0723 :Guest {INT32} -STR_0724 :Guest {INT32} -STR_0725 :Guest {INT32} -STR_0726 :Guest {INT32} -STR_0727 :Guest {INT32} -STR_0728 :Guest {INT32} -STR_0729 :Guest {INT32} -STR_0730 :Guest {INT32} -STR_0731 :Guest {INT32} -STR_0732 :Guest {INT32} -STR_0733 :Guest {INT32} -STR_0734 :Guest {INT32} -STR_0735 :Guest {INT32} -STR_0736 :Guest {INT32} -STR_0737 :Guest {INT32} -STR_0738 :Guest {INT32} -STR_0739 :Guest {INT32} -STR_0740 :Guest {INT32} -STR_0741 :Guest {INT32} -STR_0742 :Guest {INT32} -STR_0743 :Guest {INT32} -STR_0744 :Guest {INT32} -STR_0745 :Guest {INT32} -STR_0746 :Guest {INT32} -STR_0747 :Guest {INT32} -STR_0748 :Guest {INT32} -STR_0749 :Guest {INT32} -STR_0750 :Guest {INT32} -STR_0751 :Guest {INT32} -STR_0752 :Guest {INT32} -STR_0753 :Guest {INT32} -STR_0754 :Guest {INT32} -STR_0755 :Guest {INT32} -STR_0756 :Guest {INT32} -STR_0757 :Guest {INT32} -STR_0758 :Guest {INT32} -STR_0759 :Guest {INT32} -STR_0760 :Guest {INT32} -STR_0761 :Guest {INT32} -STR_0762 :Guest {INT32} -STR_0763 :Guest {INT32} -STR_0764 :Guest {INT32} -STR_0765 :Guest {INT32} -STR_0766 :Guest {INT32} -STR_0767 :Guest {INT32} -STR_0768 :Handyman {INT32} +STR_0603 :来客{INT32} +STR_0604 :来客{INT32} +STR_0605 :来客{INT32} +STR_0606 :来客{INT32} +STR_0607 :来客{INT32} +STR_0608 :来客{INT32} +STR_0609 :来客{INT32} +STR_0610 :来客{INT32} +STR_0611 :来客{INT32} +STR_0612 :来客{INT32} +STR_0613 :来客{INT32} +STR_0614 :来客{INT32} +STR_0615 :来客{INT32} +STR_0616 :来客{INT32} +STR_0617 :来客{INT32} +STR_0618 :来客{INT32} +STR_0619 :来客{INT32} +STR_0620 :来客{INT32} +STR_0621 :来客{INT32} +STR_0622 :来客{INT32} +STR_0623 :来客{INT32} +STR_0624 :来客{INT32} +STR_0625 :来客{INT32} +STR_0626 :来客{INT32} +STR_0627 :来客{INT32} +STR_0628 :来客{INT32} +STR_0629 :来客{INT32} +STR_0630 :来客{INT32} +STR_0631 :来客{INT32} +STR_0632 :来客{INT32} +STR_0633 :来客{INT32} +STR_0634 :来客{INT32} +STR_0635 :来客{INT32} +STR_0636 :来客{INT32} +STR_0637 :来客{INT32} +STR_0638 :来客{INT32} +STR_0639 :来客{INT32} +STR_0640 :来客{INT32} +STR_0641 :来客{INT32} +STR_0642 :来客{INT32} +STR_0643 :来客{INT32} +STR_0644 :来客{INT32} +STR_0645 :来客{INT32} +STR_0646 :来客{INT32} +STR_0647 :来客{INT32} +STR_0648 :来客{INT32} +STR_0649 :来客{INT32} +STR_0650 :来客{INT32} +STR_0651 :来客{INT32} +STR_0652 :来客{INT32} +STR_0653 :来客{INT32} +STR_0654 :来客{INT32} +STR_0655 :来客{INT32} +STR_0656 :来客{INT32} +STR_0657 :来客{INT32} +STR_0658 :来客{INT32} +STR_0659 :来客{INT32} +STR_0660 :来客{INT32} +STR_0661 :来客{INT32} +STR_0662 :来客{INT32} +STR_0663 :来客{INT32} +STR_0664 :来客{INT32} +STR_0665 :来客{INT32} +STR_0666 :来客{INT32} +STR_0667 :来客{INT32} +STR_0668 :来客{INT32} +STR_0669 :来客{INT32} +STR_0670 :来客{INT32} +STR_0671 :来客{INT32} +STR_0672 :来客{INT32} +STR_0673 :来客{INT32} +STR_0674 :来客{INT32} +STR_0675 :来客{INT32} +STR_0676 :来客{INT32} +STR_0677 :来客{INT32} +STR_0678 :来客{INT32} +STR_0679 :来客{INT32} +STR_0680 :来客{INT32} +STR_0681 :来客{INT32} +STR_0682 :来客{INT32} +STR_0683 :来客{INT32} +STR_0684 :来客{INT32} +STR_0685 :来客{INT32} +STR_0686 :来客{INT32} +STR_0687 :来客{INT32} +STR_0688 :来客{INT32} +STR_0689 :来客{INT32} +STR_0690 :来客{INT32} +STR_0691 :来客{INT32} +STR_0692 :来客{INT32} +STR_0693 :来客{INT32} +STR_0694 :来客{INT32} +STR_0695 :来客{INT32} +STR_0696 :来客{INT32} +STR_0697 :来客{INT32} +STR_0698 :来客{INT32} +STR_0699 :来客{INT32} +STR_0700 :来客{INT32} +STR_0701 :来客{INT32} +STR_0702 :来客{INT32} +STR_0703 :来客{INT32} +STR_0704 :来客{INT32} +STR_0705 :来客{INT32} +STR_0706 :来客{INT32} +STR_0707 :来客{INT32} +STR_0708 :来客{INT32} +STR_0709 :来客{INT32} +STR_0710 :来客{INT32} +STR_0711 :来客{INT32} +STR_0712 :来客{INT32} +STR_0713 :来客{INT32} +STR_0714 :来客{INT32} +STR_0715 :来客{INT32} +STR_0716 :来客{INT32} +STR_0717 :来客{INT32} +STR_0718 :来客{INT32} +STR_0719 :来客{INT32} +STR_0720 :来客{INT32} +STR_0721 :来客{INT32} +STR_0722 :来客{INT32} +STR_0723 :来客{INT32} +STR_0724 :来客{INT32} +STR_0725 :来客{INT32} +STR_0726 :来客{INT32} +STR_0727 :来客{INT32} +STR_0728 :来客{INT32} +STR_0729 :来客{INT32} +STR_0730 :来客{INT32} +STR_0731 :来客{INT32} +STR_0732 :来客{INT32} +STR_0733 :来客{INT32} +STR_0734 :来客{INT32} +STR_0735 :来客{INT32} +STR_0736 :来客{INT32} +STR_0737 :来客{INT32} +STR_0738 :来客{INT32} +STR_0739 :来客{INT32} +STR_0740 :来客{INT32} +STR_0741 :来客{INT32} +STR_0742 :来客{INT32} +STR_0743 :来客{INT32} +STR_0744 :来客{INT32} +STR_0745 :来客{INT32} +STR_0746 :来客{INT32} +STR_0747 :来客{INT32} +STR_0748 :来客{INT32} +STR_0749 :来客{INT32} +STR_0750 :来客{INT32} +STR_0751 :来客{INT32} +STR_0752 :来客{INT32} +STR_0753 :来客{INT32} +STR_0754 :来客{INT32} +STR_0755 :来客{INT32} +STR_0756 :来客{INT32} +STR_0757 :来客{INT32} +STR_0758 :来客{INT32} +STR_0759 :来客{INT32} +STR_0760 :来客{INT32} +STR_0761 :来客{INT32} +STR_0762 :来客{INT32} +STR_0763 :来客{INT32} +STR_0764 :来客{INT32} +STR_0765 :来客{INT32} +STR_0766 :来客{INT32} +STR_0767 :来客{INT32} +STR_0768 :便利屋 {INT32} STR_0769 :Mechanic {INT32} STR_0770 :Security Guard {INT32} STR_0771 :Entertainer {INT32} @@ -779,7 +779,7 @@ STR_0774 :Unnamed park{POP16}{POP16} STR_0775 :Unnamed park{POP16}{POP16} STR_0776 :Unnamed park{POP16}{POP16} STR_0777 :Unnamed park{POP16}{POP16} -STR_0778 :Sign +STR_0778 :バナー STR_0779 :1日 STR_0780 :2日 STR_0781 :3日 @@ -893,7 +893,7 @@ STR_0887 :Quit Scenario Editor STR_0888 :Quit Roller Coaster Designer STR_0889 :Quit Track Designs Manager STR_0890 :SCR{COMMA16}.BMP -STR_0891 :Screenshot +STR_0891 :スクリーンショット STR_0892 :Screenshot saved to disk as '{STRINGID}' STR_0893 :Screenshot failed ! STR_0894 :Landscape data area full ! @@ -974,7 +974,7 @@ STR_0968 :+360{DEGREE} STR_0969 :+405{DEGREE} STR_0970 :+450{DEGREE} STR_0971 :+495{DEGREE} -STR_0972 :Cancel +STR_0972 :キャンセル STR_0973 :OK STR_0974 :Rides STR_0975 :Shops and Stalls @@ -1170,7 +1170,7 @@ STR_1164 :{STRINGID}{NEWLINE}(Right-Click to Remove) STR_1165 :{STRINGID} - {STRINGID} {COMMA16} STR_1166 :Can't lower water level here... STR_1167 :Can't raise water level here... -STR_1168 :Options +STR_1168 :設定 STR_1169 :(None) STR_1170 :{STRING} STR_1171 :{RED}Closed - - @@ -1465,7 +1465,7 @@ STR_1459 :Track style STR_1460 :{SMALLFONT}{BLACK}'U' shaped open track STR_1461 :{SMALLFONT}{BLACK}'O' shaped enclosed track STR_1462 :Too steep for lift hill -STR_1463 :Guests +STR_1463 :来客 STR_1464 :Helix up (small) STR_1465 :Helix up (large) STR_1466 :Helix down (small) @@ -1695,14 +1695,14 @@ STR_1689 :Block brakes STR_1690 :{WINDOW_COLOUR_2}{STRINGID}{NEWLINE}{BLACK}{STRINGID} STR_1691 :{WINDOW_COLOUR_2} Cost: {BLACK}{CURRENCY} STR_1692 :{WINDOW_COLOUR_2} Cost: {BLACK}from {CURRENCY} -STR_1693 :{SMALLFONT}{BLACK}Guests +STR_1693 :{SMALLFONT}{BLACK}来客 STR_1694 :{SMALLFONT}{BLACK}Staff STR_1695 :{SMALLFONT}{BLACK}Income and costs STR_1696 :{SMALLFONT}{BLACK}Customer information STR_1697 :Cannot place these on queue line area STR_1698 :Can only place these on queue area STR_1699 :Too many people in game -STR_1700 :Hire new Handyman +STR_1700 :便利屋を雇います STR_1701 :Hire new Mechanic STR_1702 :Hire new Security Guard STR_1703 :Hire new Entertainer @@ -1756,8 +1756,8 @@ STR_1750 :{DURATION} STR_1751 :Can't change time limit for ride... STR_1752 :{SMALLFONT}{BLACK}Show list of individual guests in park STR_1753 :{SMALLFONT}{BLACK}Show summarised list of guests in park -STR_1754 :{BLACK}{COMMA16} guests -STR_1755 :{BLACK}{COMMA16} guest +STR_1754 :{BLACK}{COMMA16} 来客 +STR_1755 :{BLACK}{COMMA16} 来客 STR_1756 :{WINDOW_COLOUR_2}Admission price: STR_1757 :{WINDOW_COLOUR_2}Reliability: {MOVE_X}{255}{BLACK}{COMMA16}% STR_1758 :{SMALLFONT}{BLACK}Build mode @@ -1848,9 +1848,9 @@ STR_1842 :Favourite of: {COMMA16} guest STR_1843 :Favourite of: {COMMA16} guests STR_1844 :{SMALLFONT}{BLACK}Select information type to show in ride/attraction list STR_1845 :{MONTHYEAR} -STR_1846 :{COMMA16} guests -STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} guests -STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} guests +STR_1846 :{COMMA16}人の来客 +STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16}人の来客 +STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16}人の来客 STR_1849 :{WINDOW_COLOUR_2}Play music STR_1850 :{SMALLFONT}{BLACK}Select whether music should be played for this ride STR_1851 :{WINDOW_COLOUR_2}Running cost: {BLACK}{CURRENCY2DP} per hour @@ -1861,11 +1861,11 @@ STR_1855 :{WINDOW_COLOUR_2}Built: {BLACK}{COMMA16} Years Ago STR_1856 :{WINDOW_COLOUR_2}Profit per item sold: {BLACK}{CURRENCY2DP} STR_1857 :{WINDOW_COLOUR_2}Loss per item sold: {BLACK}{CURRENCY2DP} STR_1858 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY2DP} per month -STR_1859 :Handymen +STR_1859 :便利屋 STR_1860 :Mechanics STR_1861 :Security Guards STR_1862 :Entertainers -STR_1863 :Handyman +STR_1863 :便利屋 STR_1864 :Mechanic STR_1865 :Security Guard STR_1866 :Entertainer @@ -1880,15 +1880,15 @@ STR_1874 :{WINDOW_COLOUR_2}Profit: {BLACK}{CURRENCY2DP} per hour STR_1875 :{BLACK} {SPRITE}{BLACK} {STRINGID} STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Inspect Rides STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Fix Rides -STR_1878 :{WINDOW_COLOUR_2}Inspection: -STR_1879 :Every 10 minutes -STR_1880 :Every 20 minutes -STR_1881 :Every 30 minutes -STR_1882 :Every 45 minutes -STR_1883 :Every hour -STR_1884 :Every 2 hours -STR_1885 :Never -STR_1886 :Inspecting {STRINGID} +STR_1878 :{WINDOW_COLOUR_2}改めるの: +STR_1879 :毎10分 +STR_1880 :毎20分 +STR_1881 :毎30分 +STR_1882 :毎45分 +STR_1883 :毎1時間 +STR_1884 :毎2時間 +STR_1885 :改めない +STR_1886 :{STRINGID}を改めります STR_1887 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}{COMMA16} minutes STR_1888 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}more than 4 hours STR_1889 :{WINDOW_COLOUR_2}Down-Time: {MOVE_X}{255}{BLACK}{COMMA16}% @@ -2025,24 +2025,24 @@ STR_2017 :Cuddly Toys STR_2018 :Park Maps STR_2019 :On-Ride Photos STR_2020 :Umbrellas -STR_2021 :Drinks -STR_2022 :Burgers -STR_2023 :Chips -STR_2024 :Ice Creams -STR_2025 :Candyfloss -STR_2026 :Empty Cans -STR_2027 :Rubbish +STR_2021 :ドリンク +STR_2022 :バーガー +STR_2023 :フライ +STR_2024 :ソフトクリーム +STR_2025 :綿菓子 +STR_2026 :空き缶 +STR_2027 :ごみ STR_2028 :Empty Burger Boxes -STR_2029 :Pizzas +STR_2029 :ピザ STR_2030 :Vouchers -STR_2031 :Popcorn -STR_2032 :Hot Dogs +STR_2031 :ポップコーン +STR_2032 :ホットドッグ STR_2033 :Tentacles -STR_2034 :Hats +STR_2034 :帽子 STR_2035 :Toffee Apples -STR_2036 :T-Shirts -STR_2037 :Doughnuts -STR_2038 :Coffees +STR_2036 :ティーシャツ +STR_2037 :ドーナツ +STR_2038 :コーヒー STR_2039 :Empty Cups STR_2040 :Fried Chicken STR_2041 :Lemonade @@ -2331,13 +2331,13 @@ STR_2323 :{WINDOW_COLOUR_2}Park size: {BLACK}{COMMA32}m{SQUARED} STR_2324 :{WINDOW_COLOUR_2}Park size: {BLACK}{COMMA32}sq.ft. STR_2325 :{SMALLFONT}{BLACK}Buy land to extend park STR_2326 :{SMALLFONT}{BLACK}Buy construction rights to allow construction above or below land outside the park -STR_2327 :Options -STR_2328 :{WINDOW_COLOUR_2}Currency: -STR_2329 :{WINDOW_COLOUR_2}Distance and Speed: -STR_2330 :{WINDOW_COLOUR_2}Temperature: -STR_2331 :{WINDOW_COLOUR_2}Height Labels: -STR_2332 :Units -STR_2333 :Sound +STR_2327 :設定 +STR_2328 :{WINDOW_COLOUR_2}通貨: +STR_2329 :{WINDOW_COLOUR_2}距離と速力: +STR_2330 :{WINDOW_COLOUR_2}温度: +STR_2331 :{WINDOW_COLOUR_2}高さのマーカー: +STR_2332 :単位 +STR_2333 :効果音 STR_2334 :パウンド ({POUND}) STR_2335 :ドル ($) STR_2336 :フラン (F) @@ -2345,7 +2345,7 @@ STR_2337 :ドイツマルク (DM) STR_2338 :円 ({YEN}) STR_2339 :ペセタ (Pts) STR_2340 :リラ (L) -STR_2341 :Guilders (fl.) +STR_2341 :フローリン (fl.) STR_2342 :クローナ (kr) STR_2343 :ユーロ ({EURO}) STR_2344 :Imperial @@ -2440,7 +2440,7 @@ STR_2432 :{BLACK}Vouchers for half-price entry to {STRINGID} STR_2433 :{BLACK}Vouchers for free {STRINGID} STR_2434 :{BLACK}Advertising campaign for {STRINGID} STR_2435 :{BLACK}Advertising campaign for {STRINGID} -STR_2436 :1 week +STR_2436 :1週間 STR_2437 : STR_2438 : STR_2439 : @@ -2727,26 +2727,26 @@ STR_2718 :Up STR_2719 :New file STR_2720 :{UINT16}秒 STR_2721 :{UINT16}秒 -STR_2722 :{UINT16}分:{UINT16}sec -STR_2723 :{UINT16}分:{UINT16}secs -STR_2724 :{UINT16}分:{UINT16}sec -STR_2725 :{UINT16}分:{UINT16}secs +STR_2722 :{UINT16}分{UINT16}秒 +STR_2723 :{UINT16}分{UINT16}秒 +STR_2724 :{UINT16}分{UINT16}秒 +STR_2725 :{UINT16}分{UINT16}秒 STR_2726 :{UINT16}分 STR_2727 :{UINT16}分 -STR_2728 :{UINT16}時間:{UINT16}min -STR_2729 :{UINT16}時間:{UINT16}mins -STR_2730 :{UINT16}時間:{UINT16}min -STR_2731 :{UINT16}時間:{UINT16}mins +STR_2728 :{UINT16}時{UINT16}分 +STR_2729 :{UINT16}時{UINT16}分 +STR_2730 :{UINT16}時{UINT16}分 +STR_2731 :{UINT16}時{UINT16}分 STR_2732 :{COMMA16}ft STR_2733 :{COMMA16}m STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h -STR_2736 :{MONTH}, 第{COMMA16}年 -STR_2737 :{STRINGID} {MONTH}, 第{COMMA16}年 +STR_2736 :{MONTH}月 {COMMA16}年 +STR_2737 :{STRINGID} {MONTH}月 {COMMA16}年 STR_2738 :Title screen music: STR_2739 :None -STR_2740 :ローラーコースター タイクーン 1 -STR_2741 :ローラーコースター タイクーン 2 +STR_2740 :RollerCoaster Tycoon 1 +STR_2741 :RollerCoaster Tycoon 2 STR_2742 :css50.dat not found STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation. STR_2744 :[ @@ -2782,7 +2782,7 @@ STR_2772 :Faster Gamespeed STR_2773 :Windowed STR_2774 :Fullscreen STR_2775 :Fullscreen (desktop) -STR_2776 :Language: +STR_2776 :言語: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} STR_2779 :Viewport #{COMMA16} @@ -2998,7 +2998,7 @@ STR_2987 :{SMALLFONT}{BLACK}Set this banner as a 'no-entry' sign for guests STR_2988 :{SMALLFONT}{BLACK}Demolish this banner STR_2989 :{SMALLFONT}{BLACK}Select main colour STR_2990 :{SMALLFONT}{BLACK}Select text colour -STR_2991 :Sign +STR_2991 :バナー STR_2992 :Sign text STR_2993 :Enter new text for this sign: STR_2994 :{SMALLFONT}{BLACK}Change text on sign @@ -3138,7 +3138,7 @@ STR_3127 :{WINDOW_COLOUR_2}Nausea Factor: {BLACK}+{COMMA16}% STR_3128 :Save Track Design STR_3129 :Save Track Design with Scenery STR_3130 :Save -STR_3131 :Cancel +STR_3131 :キャンセル STR_3132 :{BLACK}Click items of scenery to select them to be saved with track design... STR_3133 :Unable to build this on a slope STR_3134 :{RED}(Design includes scenery which is unavailable) @@ -3449,11 +3449,11 @@ STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could cust STR_3437 :{SMALLFONT}{BLACK}Clear large areas of scenery from landscape STR_3438 :Unable to remove all scenery from here... STR_3439 :Clear Scenery -STR_3440 :Page 1 -STR_3441 :Page 2 -STR_3442 :Page 3 -STR_3443 :Page 4 -STR_3444 :Page 5 +STR_3440 :1ページ目 +STR_3441 :2ページ目 +STR_3442 :3ページ目 +STR_3443 :4ページ目 +STR_3444 :5ページ目 STR_3445 :Set Patrol Area STR_3446 :Cancel Patrol Area @@ -3498,10 +3498,10 @@ STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the t STR_5157 :Unlock all prices STR_5158 :Quit to menu STR_5159 :Exit OpenRCT2 -STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Year {POP16}{COMMA16} +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID} {POP16}{COMMA16}年 STR_5161 :Date Format: -STR_5162 :Day/Month/Year -STR_5163 :Month/Day/Year +STR_5162 :日月年 +STR_5163 :月日年 STR_5164 :Twitch Channel name STR_5165 :Name peeps after followers STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers @@ -3634,8 +3634,8 @@ STR_5292 :{SMALLFONT}{BLACK}Force a breakdown STR_5293 :{SMALLFONT}{BLACK}Close ride/attraction STR_5294 :{SMALLFONT}{BLACK}Test ride/attraction STR_5295 :{SMALLFONT}{BLACK}Open ride/attraction -STR_5296 :{SMALLFONT}{BLACK}Close park -STR_5297 :{SMALLFONT}{BLACK}Open park +STR_5296 :{SMALLFONT}{BLACK}遊園地を閉める +STR_5297 :{SMALLFONT}{BLACK}遊園地を開ける STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} STR_5300 :{SMALLFONT}{BLACK}Quick fire staff @@ -3643,10 +3643,10 @@ STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan STR_5302 :Clear loan STR_5303 :Allow building in pause mode STR_5304 :Title Sequence: -STR_5305 :ローラーコースター タイクーン 1 -STR_5306 :ローラーコースター タイクーン 1 (AA) -STR_5307 :ローラーコースター タイクーン 1 (AA + 遊園地再生計画) -STR_5308 :ローラーコースター タイクーン 2 +STR_5305 :RollerCoaster Tycoon 1 +STR_5306 :RollerCoaster Tycoon 1 (AA) +STR_5307 :RollerCoaster Tycoon 1 (AA + LL) +STR_5308 :RollerCoaster Tycoon 2 STR_5309 :OpenRCT2 STR_5310 :ランダム STR_5311 :{SMALLFONT}{BLACK}デバグツール @@ -3888,9 +3888,9 @@ STR_5546 :{SMALLFONT}{BLACK}Bright pink STR_5547 :{SMALLFONT}{BLACK}Light pink STR_5548 :Show all operating modes STR_5549 :年月日 -STR_5550 :{POP16}{POP16}第{COMMA16}年, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} -STR_5551 :Year/Day/Month -STR_5552 :{POP16}{POP16}第{COMMA16}年, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} +STR_5550 :{POP16}{POP16}{COMMA16}年 {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} +STR_5551 :年日月 +STR_5552 :{POP16}{POP16}{COMMA16}年 {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} STR_5553 :Pause game when Steam overlay is open STR_5554 :{SMALLFONT}{BLACK}Enable mountain tool STR_5555 :Show vehicles from other track types From 89a2e32f285bd86e435682c308460d7465c0b26a Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 2 Jan 2016 00:11:46 +0900 Subject: [PATCH 30/90] Add Japanese to the list of available languages. --- src/localisation/language.cpp | 8 ++++++++ src/localisation/language.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/localisation/language.cpp b/src/localisation/language.cpp index f9d36eb779..dc70f285cd 100644 --- a/src/localisation/language.cpp +++ b/src/localisation/language.cpp @@ -47,6 +47,13 @@ enum { RCT2_LANGUAGE_ID_END = 255 }; +static TTFFontSetDescriptor TTFFontMSGothic = {{ + { "msgothic_02.ttf", "MS PGothic", 9, 1, 0, 15, nullptr }, + { "msgothic_02.ttf", "MS PGothic", 12, 1, 0, 17, nullptr }, + { "msgothic_02.ttf", "MS PGothic", 12, 1, 0, 17, nullptr }, + { "msgothic_02.ttf", "MS PGothic", 13, 1, 0, 20, nullptr }, +}}; + static TTFFontSetDescriptor TTFFontMingLiu = {{ { "msjh.ttc", "JhengHei", 9, -1, -3, 6, nullptr }, { "mingliu.ttc", "MingLiU", 11, 1, 1, 12, nullptr }, @@ -94,6 +101,7 @@ const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = { { "ko", "Korean", "Korean", "korean", &TTFFontGulim, RCT2_LANGUAGE_ID_KOREAN }, // LANGUAGE_KOREAN { "ru-RU", "Russian", "Russian", "russian", &TTFFontArial, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_RUSSIAN { "cz-CZ", "Czech", "Czech", "czech", &TTFFontArial, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_CZECH + { "jp-JP", "Japanese", "Japanese", "japanese", &TTFFontMSGothic, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_JAPANESE }; int gCurrentLanguage = LANGUAGE_UNDEFINED; diff --git a/src/localisation/language.h b/src/localisation/language.h index 3adf76de0f..deb19f23a3 100644 --- a/src/localisation/language.h +++ b/src/localisation/language.h @@ -43,6 +43,7 @@ enum { LANGUAGE_KOREAN, LANGUAGE_RUSSIAN, LANGUAGE_CZECH, + LANGUAGE_JAPANESE, LANGUAGE_COUNT }; From b6c1f3a6c4155b5a993a3496cfbff439dd968559 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sat, 2 Jan 2016 11:42:51 +0100 Subject: [PATCH 31/90] Fix #2609 disabling hotkeys for game speed while playing online. --- src/interface/keyboard_shortcut.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/interface/keyboard_shortcut.c b/src/interface/keyboard_shortcut.c index 606b45a181..a10fd4f5c4 100644 --- a/src/interface/keyboard_shortcut.c +++ b/src/interface/keyboard_shortcut.c @@ -472,12 +472,14 @@ static void shortcut_screenshot() static void shortcut_reduce_game_speed() { - game_reduce_game_speed(); + if (network_get_mode() == NETWORK_MODE_NONE) + game_reduce_game_speed(); } static void shortcut_increase_game_speed() { - game_increase_game_speed(); + if (network_get_mode() == NETWORK_MODE_NONE) + game_increase_game_speed(); } static void shortcut_open_cheat_window() From eadb03426e334c6d504a575a485c1b3686cf3fd1 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sat, 2 Jan 2016 14:59:16 +0100 Subject: [PATCH 32/90] fix #2620 and preventing names with dots from breaking. --- src/util/util.c | 2 +- src/windows/loadsave.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/util.c b/src/util/util.c index cfd0566eb7..86585ec6e7 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -109,7 +109,7 @@ void path_remove_extension(utf8 *path) { // Find last dot in filename, and replace it with a null-terminator char *lastDot = strrchr(path, '.'); - if (*lastDot) *lastDot = '\0'; + if (lastDot != NULL) *lastDot = '\0'; } bool readentirefile(const utf8 *path, void **outBuffer, int *outLength) diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index 090f9cb960..8356f6a2b6 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -160,7 +160,6 @@ rct_window *window_loadsave_open(int type, char *defaultName) if (!str_is_null_or_empty(defaultName)) { safe_strncpy(_defaultName, defaultName, sizeof(_defaultName)); - path_remove_extension(_defaultName); } w = window_bring_to_front_by_class(WC_LOADSAVE); From f31a5f2248e4221b4c64e32e7f13d3bfb64c7367 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sat, 2 Jan 2016 18:57:11 +0100 Subject: [PATCH 33/90] More secure checks for removing and setting file extensions. --- src/ride/track.c | 2 +- src/util/util.c | 16 +++++++++++----- src/util/util.h | 2 +- src/windows/editor_bottom_toolbar.c | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/ride/track.c b/src/ride/track.c index 8d1e34711b..71e0b2f640 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3116,7 +3116,7 @@ int save_track_design(uint8 rideIndex){ return 1; } - path_set_extension(path, "TD6"); + path_set_extension(path, "TD6", false); save_track_to_file(RCT2_ADDRESS(0x009D8178, rct_track_td6), path); diff --git a/src/util/util.c b/src/util/util.c index 86585ec6e7..42fbf2bbe3 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -67,7 +67,6 @@ const char *path_get_filename(const utf8 *path) // Checks if the path is valid (e.g. not just a file name) if (filename == NULL) { - log_warning("Invalid path given: %s", path); // Return the input string to keep things working return path; } @@ -78,6 +77,8 @@ const char *path_get_filename(const utf8 *path) return filename; } +// Returns the extension (dot inclusive) from the given path, or the end of the +// string when no extension was found. const char *path_get_extension(const utf8 *path) { // Get the filename from the path @@ -93,23 +94,28 @@ const char *path_get_extension(const utf8 *path) return extension; } -void path_set_extension(utf8 *path, const utf8 *newExtension) +void path_set_extension(utf8 *path, const utf8 *newExtension, bool replaceExistingExtension) { + // First remove the current extension + if (replaceExistingExtension) + path_remove_extension(path); + // Append a dot to the filename if the new extension doesn't start with it char *endOfString = strrchr(path, '\0'); if (newExtension[0] != '.') *endOfString++ = '.'; // Append the extension to the path - // No existing extensions should be removed ("ride.TD6" -> "ride.TD6.TD6") safe_strncpy(endOfString, newExtension, MAX_PATH - (endOfString - path) - 1); } void path_remove_extension(utf8 *path) { // Find last dot in filename, and replace it with a null-terminator - char *lastDot = strrchr(path, '.'); - if (lastDot != NULL) *lastDot = '\0'; + char *lastDot = strrchr(path_get_filename(path), '.'); + if (lastDot != NULL) { + *lastDot = '\0'; + } } bool readentirefile(const utf8 *path, void **outBuffer, int *outLength) diff --git a/src/util/util.h b/src/util/util.h index 9dff48bc3d..c9c753dffe 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -32,7 +32,7 @@ bool filename_valid_characters(const utf8 *filename); const char *path_get_filename(const utf8 *path); const char *path_get_extension(const utf8 *path); -void path_set_extension(utf8 *path, const utf8 *newExtension); +void path_set_extension(utf8 *path, const utf8 *newExtension, bool replaceExistingExtension); void path_remove_extension(utf8 *path); bool readentirefile(const utf8 *path, void **outBuffer, int *outLength); diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index b03d98acb0..96677b889a 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -375,7 +375,7 @@ void window_editor_bottom_toolbar_jump_forward_to_save_scenario() s6Info->editor_step = 255; // Ensure path has .SC6 extension - path_set_extension(path, ".SC6"); + path_set_extension(path, ".SC6", false); // Save the scenario parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32); From bc2ac2e28ba9bba661fdf9b1456c4f28705eb0ba Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sat, 2 Jan 2016 20:45:00 +0100 Subject: [PATCH 34/90] Split extension setter into two functions --- src/ride/track.c | 2 +- src/util/util.c | 16 +++++++++++----- src/util/util.h | 3 ++- src/windows/editor_bottom_toolbar.c | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/ride/track.c b/src/ride/track.c index 71e0b2f640..978c71b91e 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3116,7 +3116,7 @@ int save_track_design(uint8 rideIndex){ return 1; } - path_set_extension(path, "TD6", false); + path_append_extension(path, "TD6"); save_track_to_file(RCT2_ADDRESS(0x009D8178, rct_track_td6), path); diff --git a/src/util/util.c b/src/util/util.c index 42fbf2bbe3..c20876a1f9 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -94,12 +94,17 @@ const char *path_get_extension(const utf8 *path) return extension; } -void path_set_extension(utf8 *path, const utf8 *newExtension, bool replaceExistingExtension) +void path_set_extension(utf8 *path, const utf8 *newExtension) { - // First remove the current extension - if (replaceExistingExtension) + // Remove existing extension (check first if there is one) + if (path_get_extension(path) < strrchr(path, '\0')) path_remove_extension(path); + // Append new extension + path_append_extension(path, newExtension); +} +void path_append_extension(utf8 *path, const utf8 *newExtension) +{ // Append a dot to the filename if the new extension doesn't start with it char *endOfString = strrchr(path, '\0'); if (newExtension[0] != '.') @@ -113,9 +118,10 @@ void path_remove_extension(utf8 *path) { // Find last dot in filename, and replace it with a null-terminator char *lastDot = strrchr(path_get_filename(path), '.'); - if (lastDot != NULL) { + if (lastDot != NULL) *lastDot = '\0'; - } + else + log_warning("No extension found. (path = %s)", path); } bool readentirefile(const utf8 *path, void **outBuffer, int *outLength) diff --git a/src/util/util.h b/src/util/util.h index c9c753dffe..fad8a6bbc6 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -32,7 +32,8 @@ bool filename_valid_characters(const utf8 *filename); const char *path_get_filename(const utf8 *path); const char *path_get_extension(const utf8 *path); -void path_set_extension(utf8 *path, const utf8 *newExtension, bool replaceExistingExtension); +void path_set_extension(utf8 *path, const utf8 *newExtension); +void path_append_extension(utf8 *path, const utf8 *newExtension); void path_remove_extension(utf8 *path); bool readentirefile(const utf8 *path, void **outBuffer, int *outLength); diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index 96677b889a..f0e6f15499 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -375,7 +375,7 @@ void window_editor_bottom_toolbar_jump_forward_to_save_scenario() s6Info->editor_step = 255; // Ensure path has .SC6 extension - path_set_extension(path, ".SC6", false); + path_append_extension(path, ".SC6"); // Save the scenario parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32); From 448d4fb657534996eba6e6df38f5e69b0891ef82 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 26 Dec 2015 18:32:18 +0900 Subject: [PATCH 35/90] New string ids for scenario select screen. --- data/language/english_uk.txt | 12 ++++++++++++ src/localisation/string_ids.h | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index b954ea29b5..09ef63ffa1 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3957,6 +3957,18 @@ STR_5615 :L STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag STR_5617 :{SMALLFONT}{BLACK}Move selected element up. STR_5618 :{SMALLFONT}{BLACK}Move selected element down. +STR_5619 :RCT1 Classic +STR_5620 :Corkscrew Follies +STR_5621 :Loopy Landscapes +STR_5622 :RCT2 Vanilla +STR_5623 :Wacky Worlds +STR_5624 :Time Twister +STR_5625 :{OPENQUOTES}Real{ENDQUOTES} Parks +STR_5626 :Other Parks +STR_5627 :Group scenario list by: +STR_5628 :Source game +STR_5629 :Difficulty level +STR_5630 :Enable unlocking of scenarios ##################### # Rides/attractions # diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 291aa14748..3dcfce3d49 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2240,6 +2240,20 @@ enum { STR_NOTIFICATION_GUEST_USED_FACILITY = 5605, STR_NOTIFICATION_GUEST_DIED = 5606, + STR_SCENARIO_CATEGORY_RCT1_CLASSIC = 5619, + STR_SCENARIO_CATEGORY_RCT1_CF = 5620, + STR_SCENARIO_CATEGORY_RCT1_LL = 5621, + STR_SCENARIO_CATEGORY_RCT2_VANILLA = 5622, + STR_SCENARIO_CATEGORY_RCT2_WW = 5623, + STR_SCENARIO_CATEGORY_RCT2_TT = 5624, + STR_SCENARIO_CATEGORY_REAL_PARKS = 5625, + STR_SCENARIO_CATEGORY_OTHER_PARKS = 5626, + + STR_OPTIONS_SCENARIO_GROUPING = 5627, + STR_OPTIONS_SCENARIO_ORIGIN = 5628, + STR_OPTIONS_SCENARIO_DIFFICULTY = 5629, + STR_OPTIONS_SCENARIO_UNLOCKING = 5630, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 }; From 3999ebd03180cf8c88a96c1a9d807a70479dd2bc Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 26 Dec 2015 18:32:44 +0900 Subject: [PATCH 36/90] WIP: adding new tabs to scenario select window; extended window size. --- src/windows/title_scenarioselect.c | 118 +++++++++++++++-------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 40dd3efcb0..28e1385143 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -40,20 +40,26 @@ enum { WIDX_TAB3, WIDX_TAB4, WIDX_TAB5, + WIDX_TAB6, + WIDX_TAB7, + WIDX_TAB8, WIDX_SCENARIOLIST }; static rct_widget window_scenarioselect_widgets[] = { - { WWT_FRAME, 0, 0, 609, 0, 333, -1, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, 608, 1, 14, STR_SELECT_SCENARIO, STR_WINDOW_TITLE_TIP }, // title bar - { WWT_CLOSEBOX, 0, 597, 607, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button - { WWT_IMGBTN, 1, 0, 609, 50, 333, -1, STR_NONE }, // tab content panel + { WWT_FRAME, 0, 0, 733, 0, 333, -1, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 732, 1, 14, STR_SELECT_SCENARIO, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 721, 731, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_IMGBTN, 1, 0, 733, 50, 333, -1, STR_NONE }, // tab content panel { WWT_TAB, 1, 3, 93, 17, 50, 0x200015BC, STR_NONE }, // tab 1 { WWT_TAB, 1, 94, 184, 17, 50, 0x200015BC, STR_NONE }, // tab 2 { WWT_TAB, 1, 185, 275, 17, 50, 0x200015BC, STR_NONE }, // tab 3 { WWT_TAB, 1, 276, 366, 17, 50, 0x200015BC, STR_NONE }, // tab 4 { WWT_TAB, 1, 367, 457, 17, 50, 0x200015BC, STR_NONE }, // tab 5 - { WWT_SCROLL, 1, 3, 433, 54, 329, 2, STR_NONE }, // level list + { WWT_TAB, 1, 458, 593, 17, 50, 0x200015BC, STR_NONE }, // tab 6 + { WWT_TAB, 1, 594, 684, 17, 50, 0x200015BC, STR_NONE }, // tab 7 + { WWT_TAB, 1, 685, 775, 17, 50, 0x200015BC, STR_NONE }, // tab 8 + { WWT_SCROLL, 1, 3, 555, 54, 329, 2, STR_NONE }, // level list { WIDGETS_END }, }; @@ -114,7 +120,7 @@ void window_scenarioselect_open() scenario_load_list(); window = window_create_centred( - 610, + 733, 334, &window_scenarioselect_events, WC_SCENARIO_SELECT, @@ -123,7 +129,8 @@ void window_scenarioselect_open() window->widgets = window_scenarioselect_widgets; window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) - | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5); + | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5) + | (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8); window_init_scroll_widgets(window); window->viewport_focus_coordinates.var_480 = -1; @@ -140,23 +147,20 @@ void window_scenarioselect_open() */ static void window_scenarioselect_init_tabs() { - int i, x, show_pages; - rct_widget* widget; - rct_scenario_basic* scenario; - - show_pages = 0; - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; + int show_pages = 0; + for (int i = 0; i < gScenarioListCount; i++) { + printf("%s\n", gScenarioList[i].name); + rct_scenario_basic* scenario = &gScenarioList[i]; if (scenario->flags & SCENARIO_FLAGS_VISIBLE) show_pages |= 1 << scenario->category; } - x = 3; - for (i = 0; i < 5; i++) { - widget = &window_scenarioselect_widgets[i + 4]; + int x = 3; + for (int i = 0; i < 8; i++) { + rct_widget* widget = &window_scenarioselect_widgets[i + 4]; if (!(show_pages & (1 << i))) { - widget->type = WWT_EMPTY; - continue; +// widget->type = WWT_EMPTY; +// continue; } widget->type = WWT_TAB; @@ -174,7 +178,7 @@ static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex) static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB5) { + if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB8) { w->selected_tab = widgetIndex - 4; w->scenario = NULL; window_invalidate(w); @@ -187,12 +191,9 @@ static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_w static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) { - int i; - rct_scenario_basic *scenario; - *height = 0; - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; + for (int i = 0; i < gScenarioListCount; i++) { + rct_scenario_basic *scenario = &gScenarioList[i]; if (scenario->category != w->selected_tab) continue; if (scenario->flags & SCENARIO_FLAGS_VISIBLE) @@ -206,11 +207,8 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, */ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { - int i; - rct_scenario_basic *scenario; - - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; + for (int i = 0; i < gScenarioListCount; i++) { + rct_scenario_basic *scenario = &gScenarioList[i]; if (scenario->category != w->selected_tab) continue; if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) @@ -232,15 +230,10 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex */ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) { - int i; - rct_scenario_basic *scenario, *selected; - - selected = NULL; - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; - if (scenario->category != w->selected_tab) - continue; - if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) + rct_scenario_basic *selected = NULL; + for (int i = 0; i < gScenarioListCount; i++) { + rct_scenario_basic *scenario = &gScenarioList[i]; + if (scenario->category != w->selected_tab || !(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; y -= 24; @@ -261,11 +254,15 @@ static void window_scenarioselect_invalidate(rct_window *w) colour_scheme_update(w); w->pressed_widgets &= ~( (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) - | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5) ); + | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5) + | (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8) ); w->pressed_widgets |= 1LL << (w->selected_tab + 4); } +int gScenarioGroupingStyle = 1; // 1 = new, 2 = classic +bool gScenarioEnableUnlocking = true; + static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) { int i, x, y, format; @@ -277,15 +274,20 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) format = (theme_get_preset()->features.rct1_scenario_font) ? 5138 : 1193; // Text for each tab - for (i = 0; i < 5; i++) { + for (i = 0; i < 8; i++) { widget = &window_scenarioselect_widgets[WIDX_TAB1 + i]; if (widget->type == WWT_EMPTY) continue; x = (widget->left + widget->right) / 2 + w->x; y = (widget->top + widget->bottom) / 2 + w->y - 3; - RCT2_GLOBAL(0x013CE952 + 0, short) = STR_BEGINNER_PARKS + i; - gfx_draw_string_centred_wrapped(dpi, (void*)0x013CE952, x, y, 87, format, 10); + + if (gScenarioGroupingStyle == 1) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1_CLASSIC + i; + } else { // old-style + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_BEGINNER_PARKS + i; + } + gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 87, format, 10); } // Return if no scenario highlighted @@ -297,28 +299,28 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) x = w->x + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right + 4; y = w->y + window_scenarioselect_widgets[WIDX_TABCONTENT].top + 5; safe_strncpy((char*)0x009BC677, scenario->name, 64); - RCT2_GLOBAL(0x013CE952 + 0, short) = 3165; - gfx_draw_string_centred_clipped(dpi, 1193, (void*)0x013CE952, 0, x + 85, y, 170); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string + gfx_draw_string_centred_clipped(dpi, 1193, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x + 85, y, 170); y += 15; // Scenario details safe_strncpy((char*)0x009BC677, scenario->details, 256); - RCT2_GLOBAL(0x013CE952 + 0, short) = 3165; - y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, 1191, 0) + 5; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string + y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, 1191, 0) + 5; // Scenario objective - RCT2_GLOBAL(0x013CE952 + 0, short) = scenario->objective_type + STR_OBJECTIVE_NONE; - RCT2_GLOBAL(0x013CE952 + 2, short) = scenario->objective_arg_3; - RCT2_GLOBAL(0x013CE952 + 4, short) = date_get_total_months(MONTH_OCTOBER, scenario->objective_arg_1); - RCT2_GLOBAL(0x013CE952 + 6, int) = scenario->objective_arg_2; - y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, STR_OBJECTIVE, 0) + 5; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = scenario->objective_type + STR_OBJECTIVE_NONE; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, short) = scenario->objective_arg_3; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, short) = date_get_total_months(MONTH_OCTOBER, scenario->objective_arg_1); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, int) = scenario->objective_arg_2; + y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_OBJECTIVE, 0) + 5; // Scenario score if (scenario->flags & SCENARIO_FLAGS_COMPLETED) { safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); - RCT2_GLOBAL(0x013CE952 + 0, short) = 3165; - RCT2_GLOBAL(0x013CE952 + 2, int) = scenario->company_value; - y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, int) = scenario->company_value; + y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0); } } @@ -354,18 +356,18 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * // Draw scenario name safe_strncpy((char*)0x009BC677, scenario->name, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; - gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, 210, y + 1, 0, (void*)0x013CE952); + gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, 270, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); // Check if scenario is completed if (scenario->flags & SCENARIO_FLAGS_COMPLETED) { // Draw completion tick - gfx_draw_sprite(dpi, 0x5A9F, 395, y + 1, 0); + gfx_draw_sprite(dpi, 0x5A9F, 500, y + 1, 0); // Draw completion score safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793; RCT2_GLOBAL(0x013CE954, short) = 3165; - gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, 210, y + 11, 0, (void*)0x013CE952); + gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, 270, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); } y += 24; From e78d37f03cb1777ad417ee91c8f39559ec6422cf Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 01:37:18 +0900 Subject: [PATCH 37/90] Add information on scenario source games. --- src/scenario.c | 1 + src/scenario.h | 13 ++++ src/scenario_sources.h | 170 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 src/scenario_sources.h diff --git a/src/scenario.c b/src/scenario.c index 9bc0f7e262..1ec19dc646 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -36,6 +36,7 @@ #include "platform/platform.h" #include "ride/ride.h" #include "scenario.h" +#include "scenario_sources.h" #include "title.h" #include "util/sawyercoding.h" #include "util/util.h" diff --git a/src/scenario.h b/src/scenario.h index 6f34f904a6..1da4609a82 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -72,6 +72,17 @@ typedef struct { uint32 scenario_count; // 0x0C } rct_scenario_scores_header; +typedef enum { + SCENARIO_SOURCE_RCT1_CLASSIC, + SCENARIO_SOURCE_RCT1_CORKSCREW, + SCENARIO_SOURCE_RCT1_LOOPY, + SCENARIO_SOURCE_RCT2_VANILLA, + SCENARIO_SOURCE_RCT2_WACKY, + SCENARIO_SOURCE_RCT2_TIME, + SCENARIO_SOURCE_REAL, + SCENARIO_SOURCE_OTHER +} scenario_source; + /** * Scenario basic structure, mainly for scenario select * size: 0x02B0 @@ -89,6 +100,8 @@ typedef struct { sint32 flags; // 0x0268 uint32 company_value; // 0x026C char completed_by[64]; // 0x0270 + scenario_source source_game;// new in OpenRCT2 + sint16 source_index; // new in OpenRCT2 } rct_scenario_basic; typedef struct { diff --git a/src/scenario_sources.h b/src/scenario_sources.h new file mode 100644 index 0000000000..248669d7bf --- /dev/null +++ b/src/scenario_sources.h @@ -0,0 +1,170 @@ +#define NUM_ORIGINAL_SCENARIOS 136 +#define NUM_ALIASES 5 + +#define SCENARIO_SOURCE_RCT1_CLASSIC_INDEX 0 +#define SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX 22 +#define SCENARIO_SOURCE_RCT1_LOOPY_INDEX 52 +#define SCENARIO_SOURCE_RCT2_VANILLA_INDEX 82 +#define SCENARIO_SOURCE_RCT2_WACKY_INDEX 97 +#define SCENARIO_SOURCE_RCT2_TIME_INDEX 114 +#define SCENARIO_SOURCE_REAL_INDEX 128 + +const char * const scenario_aliases[NUM_ALIASES * 2] = { + "Katie's World", "Katie's Dreamland", + "Dinky Park", "Pokey Park", + "Aqua Park", "White Water Park", + "Mothball Mountain","Mystic Mountain", + "Big Pier", "Paradise Pier" +}; + +const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { + // RCT Classic + "Forest Frontiers", + "Dynamite Dunes", + "Leafy Lake", + "Diamond Heights", + "Evergreen Gardens", + "Bumbly Beach", + "Trinity Islands", + "Katie's Dreamland", + "Pokey Park", + "White Water Park", + "Millennium Mines", + "Karts & Coasters", + "Mel's World", + "Mystic Mountain", + "Pacific Pyramids", + "Crumbly Woods", + "Paradise Pier", + "Lightning Peaks", + "Ivory Towers", + "Rainbow Valley", + "Thunder Rock", + "Mega Park", + + // RCT: Corkscrew Follies + "Whispering Cliffs", + "Three Monkeys Park", + "Canary Mines", + "Barony Bridge", + "Funtopia", + "Haunted Harbor", + "Fun Fortress", + "Future World", + "Gentle Glen", + "Jolly Jungle", + "Hydro Hills", + "Sprightly Park", + "Magic Quarters", + "Fruit Farm", + "Butterfly Dam", + "Coaster Canyon", + "Thunderstorm Park", + "Harmonic Hills", + "Roman Village", + "Swamp Cove", + "Adrenaline Heights", + "Utopia Park", + "Rotting Heights", + "Fiasco Forest", + "Pickle Park", + "Giggle Downs", + "Mineral Park", + "Coaster Crazy", + "Urban Park", + "Geoffrey Gardens", + + // RCT: Loopy Landscapes + "Iceberg Islands", + "Volcania", + "Arid Heights", + "Razor Rocks", + "Crater Lake", + "Vertigo Views", + "Big Pier 2", + "Dragon's Cove", + "Good Knight Park", + "Wacky Warren", + "Grand Glacier", + "Crazy Craters", + "Dusty Desert", + "Woodworm Park", + "Icarus Park", + "Sunny Swamps", + "Frightmare Hills", + "Thunder Rocks", + "Octagon Park", + "Pleasure Island", + "Icicle Worlds", + "Tiny Towers", + "Southern Sands", + "Nevermore Park", + "Pacifica", + "Urban Jungle", + "Terror Town", + "Megaworld Park", + "Venus Ponds", + "Micro Park", + + // RCT2 Vanilla + "Crazy Castle", + "Electric Fields", + "Factory Capers", + "Amity Airfield", + "Botany Breakers", + "Bumbly Bazaar", + "Dusty Greens", + "Fungus Woods", + "Gravity Gardens", + "Infernal Views", + "Alpine Adventures", + "Extreme Heights", + "Ghost Town", + "Lucky Lake", + "Rainbow Summit", + + // RCT2 Wacky Worlds + "Africa - Victoria Falls", + "Asia - Great Wall of China Tourism Enhancement", + "North America - Grand Canyon", + "South America - Rio Carnival", + "Africa - African Diamond Mine", + "Asia - Maharaja Palace", + "Australasia - Ayers Rock", + "Europe - European Cultural Festival", + "North America - Rollercoaster Heaven", + "South America - Inca Lost City", + "Africa - Oasis", + "Antarctic - Ecological Salvage", + "Asia - Japanese Coastal Reclaim", + "Australasia - Fun at the Beach", + "Europe - Renovation", + "N. America - Extreme Hawaiian Island", + "South America - Rain Forest Plateau", + + // RCT2 Time Twister + "Dark Age - Robin Hood", + "Prehistoric - After the Asteroid", + "Roaring Twenties - Prison Island", + "Rock 'n' Roll - Flower Power", + "Dark Age - Castle", + "Future - First Encounters", + "Mythological - Animatronic Film Set", + "Prehistoric - Jurassic Safari", + "Roaring Twenties - Schneider Cup", + "Future - Future World", + "Mythological - Cradle of Civilisation", + "Prehistoric - Stone Age", + "Roaring Twenties - Skyscrapers", + "Rock 'n' Roll - Rock 'n' Roll", + + // Real parks + "Alton Towers", + "Heide-Park", + "Blackpool Pleasure Beach", + "Six Flags Belgium", + "Six Flags Great Adventure", + "Six Flags Holland", + "Six Flags Magic Mountain", + "Six Flags over Texas" +}; From cf935d45c6f6e7e5eddd76e5e3284f58b2af5083 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 01:40:46 +0900 Subject: [PATCH 38/90] Add configuration bits for scenario select mode and unlocking. Note this lacks an interface in the options window as of yet. --- src/config.c | 3 +++ src/config.h | 2 ++ src/windows/title_scenarioselect.c | 5 +---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/config.c b/src/config.c index 031ce02f72..056c2740b9 100644 --- a/src/config.c +++ b/src/config.c @@ -203,6 +203,9 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, show_fps), "show_fps", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, trap_cursor), "trap_cursor", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, auto_open_shops), "auto_open_shops", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(general_configuration, scenario_select_mode), "scenario_select_mode", CONFIG_VALUE_TYPE_UINT8, 1, NULL }, + { offsetof(general_configuration, scenario_unlocking_enabled), "scenario_unlocking_enabled", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + }; config_property_definition _interfaceDefinitions[] = { diff --git a/src/config.h b/src/config.h index e85c5d66d1..f3d0cbb2d6 100644 --- a/src/config.h +++ b/src/config.h @@ -172,6 +172,8 @@ typedef struct { uint8 show_fps; uint8 trap_cursor; uint8 auto_open_shops; + uint8 scenario_select_mode; + uint8 scenario_unlocking_enabled; } general_configuration; typedef struct { diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 28e1385143..99ace8d24f 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -260,9 +260,6 @@ static void window_scenarioselect_invalidate(rct_window *w) w->pressed_widgets |= 1LL << (w->selected_tab + 4); } -int gScenarioGroupingStyle = 1; // 1 = new, 2 = classic -bool gScenarioEnableUnlocking = true; - static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) { int i, x, y, format; @@ -282,7 +279,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) x = (widget->left + widget->right) / 2 + w->x; y = (widget->top + widget->bottom) / 2 + w->y - 3; - if (gScenarioGroupingStyle == 1) { + if (gConfigGeneral.scenario_select_mode == 1) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1_CLASSIC + i; } else { // old-style RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_BEGINNER_PARKS + i; From 3bad0870fb9e9a7ffdab20d48fb904b23fd5ca1d Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 03:19:52 +0900 Subject: [PATCH 39/90] Added routines to find scenario index and source from predefined listings. --- src/scenario.c | 1 - src/scenario_list.c | 35 ++++++++++++++++++++++++++++++ src/windows/title_scenarioselect.c | 1 - 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/scenario.c b/src/scenario.c index 1ec19dc646..9bc0f7e262 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -36,7 +36,6 @@ #include "platform/platform.h" #include "ride/ride.h" #include "scenario.h" -#include "scenario_sources.h" #include "title.h" #include "util/sawyercoding.h" #include "util/util.h" diff --git a/src/scenario_list.c b/src/scenario_list.c index f69f4b59c2..8fcd4cdeee 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -22,6 +22,7 @@ #include "platform/platform.h" #include "util/util.h" #include "scenario.h" +#include "scenario_sources.h" // Scenario list int gScenarioListCount = 0; @@ -43,6 +44,37 @@ rct_scenario_basic *get_scenario_by_filename(const char *filename) return NULL; } +sint16 get_scenario_index(rct_scenario_basic *scenario) +{ + for (int i = 0; i < NUM_ORIGINAL_SCENARIOS; i++) { + if (strcmp(original_scenario_names[i], scenario->name) == 0) + return i; + } + + return -1; +} + +scenario_source source_by_index(uint8 index) +{ + if (index >= SCENARIO_SOURCE_RCT1_CLASSIC_INDEX && index < SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX) { + return SCENARIO_SOURCE_RCT1_CLASSIC; + } else if (index >= SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX && index < SCENARIO_SOURCE_RCT1_LOOPY_INDEX) { + return SCENARIO_SOURCE_RCT1_CORKSCREW; + } else if (index >= SCENARIO_SOURCE_RCT1_LOOPY_INDEX && index < SCENARIO_SOURCE_RCT2_VANILLA_INDEX) { + return SCENARIO_SOURCE_RCT1_LOOPY; + } else if (index >= SCENARIO_SOURCE_RCT2_VANILLA_INDEX && index < SCENARIO_SOURCE_RCT2_WACKY_INDEX) { + return SCENARIO_SOURCE_RCT2_VANILLA; + } else if (index >= SCENARIO_SOURCE_RCT2_WACKY_INDEX && index < SCENARIO_SOURCE_RCT2_TIME_INDEX) { + return SCENARIO_SOURCE_RCT2_WACKY; + } else if (index >= SCENARIO_SOURCE_RCT2_TIME_INDEX && index < SCENARIO_SOURCE_REAL_INDEX) { + return SCENARIO_SOURCE_RCT2_TIME; + } else if (index >= SCENARIO_SOURCE_REAL_INDEX && index < NUM_ORIGINAL_SCENARIOS) { + return SCENARIO_SOURCE_REAL; + } else { + return SCENARIO_SOURCE_OTHER; + } +} + /** * * rct2: 0x006775A8 @@ -130,6 +162,9 @@ static void scenario_list_add(const char *path) safe_strncpy(scenario->name, s6Info.name, 64); safe_strncpy(scenario->details, s6Info.details, 256); } + + sint16 index = get_scenario_index(scenario); + printf("Name: %-50s -- Index: %d -- Source: %d\n", scenario->name, index, source_by_index(index)); } /** diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 99ace8d24f..2004a819ea 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -149,7 +149,6 @@ static void window_scenarioselect_init_tabs() { int show_pages = 0; for (int i = 0; i < gScenarioListCount; i++) { - printf("%s\n", gScenarioList[i].name); rct_scenario_basic* scenario = &gScenarioList[i]; if (scenario->flags & SCENARIO_FLAGS_VISIBLE) show_pages |= 1 << scenario->category; From eb87c5284ff683dbf8a35222a450fcdab157087a Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 17:15:34 +0900 Subject: [PATCH 40/90] Adapt scenario select screen based on scenario source game. --- src/scenario_list.c | 47 ++++++++++++++++++++++++++---- src/windows/title_scenarioselect.c | 32 +++++++++++++++----- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/scenario_list.c b/src/scenario_list.c index 8fcd4cdeee..73ff7caab4 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -19,6 +19,7 @@ *****************************************************************************/ #include "addresses.h" +#include "config.h" #include "platform/platform.h" #include "util/util.h" #include "scenario.h" @@ -31,7 +32,8 @@ rct_scenario_basic *gScenarioList = NULL; static void scenario_list_add(const char *path); static void scenario_list_sort(); -static int scenario_list_sort_compare(const void *a, const void *b); +static int scenario_list_sort_by_name(const void *a, const void *b); +static int scenario_list_sort_by_index(const void *a, const void *b); static int scenario_scores_load(); rct_scenario_basic *get_scenario_by_filename(const char *filename) @@ -54,6 +56,26 @@ sint16 get_scenario_index(rct_scenario_basic *scenario) return -1; } +void normalize_scenario_name(rct_scenario_basic *scenario) +{ + char* name = scenario->name; + + // Strip "RCT2 " prefix off scenario names. + if (name[0] == 'R' && name[1] == 'C' && name[2] == 'T' && name[3] == '2') { + log_verbose("Stripping RCT2 from name: %s", name); + safe_strncpy(scenario->name, name + 5, 64); + } + + // American scenario titles should be handled by their British counterpart, internally. + for (int i = 0; i < NUM_ALIASES; i++) { + if (strcmp(scenario_aliases[i * 2], name) == 0) + { + log_verbose("Found alias: %s; will treat as: %s", scenario->name, scenario_aliases[i * 2 + 1]); + safe_strncpy(scenario->name, scenario_aliases[i * 2 + 1], 64); + } + } +} + scenario_source source_by_index(uint8 index) { if (index >= SCENARIO_SOURCE_RCT1_CLASSIC_INDEX && index < SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX) { @@ -163,8 +185,12 @@ static void scenario_list_add(const char *path) safe_strncpy(scenario->details, s6Info.details, 256); } - sint16 index = get_scenario_index(scenario); - printf("Name: %-50s -- Index: %d -- Source: %d\n", scenario->name, index, source_by_index(index)); + // Normalize the name to make the scenario as recognisable as possible. + normalize_scenario_name(scenario); + + // Look up and store information regarding the origins of this scenario. + scenario->source_index = get_scenario_index(scenario); + scenario->source_game = source_by_index(scenario->source_index); } /** @@ -175,14 +201,25 @@ static void scenario_list_add(const char *path) */ static void scenario_list_sort() { - qsort(gScenarioList, gScenarioListCount, sizeof(rct_scenario_basic), scenario_list_sort_compare); + if (gConfigGeneral.scenario_select_mode == 1) // and not tabIndex > REAL, OTHER + qsort(gScenarioList, gScenarioListCount, sizeof(rct_scenario_basic), scenario_list_sort_by_index); + else + qsort(gScenarioList, gScenarioListCount, sizeof(rct_scenario_basic), scenario_list_sort_by_name); +} + +static int scenario_list_sort_by_index(const void *a, const void *b) +{ + if (((rct_scenario_basic*)a)->source_game == SCENARIO_SOURCE_OTHER && ((rct_scenario_basic*)b)->source_game == SCENARIO_SOURCE_OTHER) + return scenario_list_sort_by_name(a, b); + + return ((rct_scenario_basic*)a)->source_index - ((rct_scenario_basic*)b)->source_index; } /** * Basic scenario information compare function for sorting. * rct2: 0x00677C08 */ -static int scenario_list_sort_compare(const void *a, const void *b) +static int scenario_list_sort_by_name(const void *a, const void *b) { return strcmp(((rct_scenario_basic*)a)->name, ((rct_scenario_basic*)b)->name); } diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 2004a819ea..afb7f4d123 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -151,15 +151,20 @@ static void window_scenarioselect_init_tabs() for (int i = 0; i < gScenarioListCount; i++) { rct_scenario_basic* scenario = &gScenarioList[i]; if (scenario->flags & SCENARIO_FLAGS_VISIBLE) - show_pages |= 1 << scenario->category; + { + if (gConfigGeneral.scenario_select_mode == 1) + show_pages |= 1 << scenario->source_game; + else + show_pages |= 1 << scenario->category; + } } int x = 3; for (int i = 0; i < 8; i++) { rct_widget* widget = &window_scenarioselect_widgets[i + 4]; if (!(show_pages & (1 << i))) { -// widget->type = WWT_EMPTY; -// continue; + widget->type = WWT_EMPTY; + continue; } widget->type = WWT_TAB; @@ -193,8 +198,11 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, *height = 0; for (int i = 0; i < gScenarioListCount; i++) { rct_scenario_basic *scenario = &gScenarioList[i]; - if (scenario->category != w->selected_tab) + + if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) continue; + if (scenario->flags & SCENARIO_FLAGS_VISIBLE) *height += 24; } @@ -208,8 +216,11 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex { for (int i = 0; i < gScenarioListCount; i++) { rct_scenario_basic *scenario = &gScenarioList[i]; - if (scenario->category != w->selected_tab) + + if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) continue; + if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; @@ -232,7 +243,11 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex rct_scenario_basic *selected = NULL; for (int i = 0; i < gScenarioListCount; i++) { rct_scenario_basic *scenario = &gScenarioList[i]; - if (scenario->category != w->selected_tab || !(scenario->flags & SCENARIO_FLAGS_VISIBLE)) + if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) + continue; + + if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; y -= 24; @@ -335,8 +350,11 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * y = 0; for (i = 0; i < gScenarioListCount; i++) { scenario = &gScenarioList[i]; - if (scenario->category != w->selected_tab) + + if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) continue; + if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; From 3bb1588cfa1ecc786096c98a7aaa9d05dbdc66fc Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 17:32:05 +0900 Subject: [PATCH 41/90] Shrink window when showing scenarios by difficulty level. --- src/windows/title_scenarioselect.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index afb7f4d123..43a7277c17 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -112,6 +112,7 @@ static rct_window_event_list window_scenarioselect_events = { void window_scenarioselect_open() { rct_window* window; + int window_width; if (window_bring_to_front_by_class(WC_SCENARIO_SELECT) != NULL) return; @@ -119,8 +120,22 @@ void window_scenarioselect_open() // Load scenario list scenario_load_list(); + // Shrink the window if we're showing scenarios by difficulty level. + if (gConfigGeneral.scenario_select_mode == 2) + { + window_width = 610; + window_scenarioselect_widgets[WIDX_BACKGROUND].right = 609; + window_scenarioselect_widgets[WIDX_TITLEBAR].right = 608; + window_scenarioselect_widgets[WIDX_CLOSE].left = 597; + window_scenarioselect_widgets[WIDX_CLOSE].right = 607; + window_scenarioselect_widgets[WIDX_TABCONTENT].right = 609; + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right = 433; + } + else + window_width = 733; + window = window_create_centred( - 733, + window_width, 334, &window_scenarioselect_events, WC_SCENARIO_SELECT, @@ -347,6 +362,8 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193; unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191; + bool wide = gConfigGeneral.scenario_select_mode == 1; + y = 0; for (i = 0; i < gScenarioListCount; i++) { scenario = &gScenarioList[i]; @@ -370,18 +387,18 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * // Draw scenario name safe_strncpy((char*)0x009BC677, scenario->name, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; - gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, 270, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, wide ? 270 : 210, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); // Check if scenario is completed if (scenario->flags & SCENARIO_FLAGS_COMPLETED) { // Draw completion tick - gfx_draw_sprite(dpi, 0x5A9F, 500, y + 1, 0); + gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0); // Draw completion score safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793; RCT2_GLOBAL(0x013CE954, short) = 3165; - gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, 270, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); } y += 24; From 15782b88c469ed9b198a3d59bb5f4532bbd9700f Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 20:38:14 +0900 Subject: [PATCH 42/90] Experimental: optional unlocking of scenarios ("campaign mode") in scenario select screen. --- data/language/english_uk.txt | 1 + src/windows/title_scenarioselect.c | 61 ++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 09ef63ffa1..be5f6534f3 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3969,6 +3969,7 @@ STR_5627 :Group scenario list by: STR_5628 :Source game STR_5629 :Difficulty level STR_5630 :Enable unlocking of scenarios +STR_5631 :{GREY}{STRINGID} ##################### # Rides/attractions # diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 43a7277c17..b87c5added 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -229,6 +229,7 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, */ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { + int num_unlocks = 5; for (int i = 0; i < gScenarioListCount; i++) { rct_scenario_basic *scenario = &gScenarioList[i]; @@ -239,6 +240,18 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; + if (gConfigGeneral.scenario_unlocking_enabled) { + if (num_unlocks <= 0) + break; + + bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED; + if (is_completed) { + num_unlocks++; + } else { + num_unlocks--; + } + } + y -= 24; if (y >= 0) continue; @@ -256,6 +269,7 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) { rct_scenario_basic *selected = NULL; + int num_unlocks = 5; for (int i = 0; i < gScenarioListCount; i++) { rct_scenario_basic *scenario = &gScenarioList[i]; if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || @@ -265,6 +279,14 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; + if (gConfigGeneral.scenario_unlocking_enabled) { + if (num_unlocks <= 0) + break; + + bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED; + num_unlocks += is_completed ? 1 : -1; + } + y -= 24; if (y >= 0) continue; @@ -352,21 +374,20 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { - int i, y, colour, highlighted, highlighted_format, unhighlighted_format; - rct_scenario_basic *scenario; - - colour = ColourMapA[w->colours[1]].mid_light; + int colour = ColourMapA[w->colours[1]].mid_light; colour = (colour << 24) | (colour << 16) | (colour << 8) | colour; gfx_clear(dpi, colour); - highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193; - unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191; + int highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193; + int unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191; + int disabled_format = 5619; bool wide = gConfigGeneral.scenario_select_mode == 1; - y = 0; - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; + int y = 0; + int num_unlocks = 5; + for (int i = 0; i < gScenarioListCount; i++) { + rct_scenario_basic *scenario = &gScenarioList[i]; if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) @@ -378,19 +399,29 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * if (y > dpi->y + dpi->height) continue; - highlighted = w->scenario == scenario; - // Draw hover highlight - if (highlighted) + bool is_highlighted = w->highlighted_item == (int)scenario; + if (is_highlighted) gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); + bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED; + bool is_disabled = false; + if (gConfigGeneral.scenario_unlocking_enabled) { + if (num_unlocks <= 0) + is_disabled = true; + + num_unlocks += is_completed ? 1 : -1; + } + + int format = is_disabled ? 5619 : (is_highlighted ? highlighted_format : unhighlighted_format); + // Draw scenario name safe_strncpy((char*)0x009BC677, scenario->name, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; - gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, wide ? 270 : 210, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); // Check if scenario is completed - if (scenario->flags & SCENARIO_FLAGS_COMPLETED) { + if (is_completed) { // Draw completion tick gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0); @@ -398,7 +429,7 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793; RCT2_GLOBAL(0x013CE954, short) = 3165; - gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); } y += 24; From f49e3eea1cb9b70162f4937d8688695e99abfb88 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 28 Dec 2015 20:39:17 +0900 Subject: [PATCH 43/90] WIP: misery: adding scenario options to options screen. --- src/windows/options.c | 44 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/windows/options.c b/src/windows/options.c index 1609ec8b27..c1f1b84527 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -135,6 +135,8 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_TOOLBAR_SHOW_CHEATS, WIDX_TOOLBAR_SHOW_NEWS, WIDX_SELECT_BY_TRACK_TYPE, + WIDX_SCENARIO_GROUPING, + WIDX_SCENARIO_UNLOCKING, // Misc WIDX_REAL_NAME_CHECKBOX = WIDX_PAGE_START, @@ -162,7 +164,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { }; #define WW 310 -#define WH 280 +#define WH 300 #define MAIN_OPTIONS_WIDGETS \ { WWT_FRAME, 0, 0, WW-1, 0, WH-1, STR_NONE, STR_NONE }, \ @@ -253,6 +255,8 @@ static rct_widget window_options_controls_and_interface_widgets[] = { { WWT_CHECKBOX, 2, 155, 299, 229, 240, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_NONE }, // Recent messages { WWT_CHECKBOX, 2, 10, 299, 254, 265, STR_SELECT_BY_TRACK_TYPE, STR_SELECT_BY_TRACK_TYPE_TIP }, // Select by track type + { WWT_DROPDOWN, 2, 155, 299, 267, 278, STR_NONE, STR_NONE }, // Scenario select mode + { WWT_CHECKBOX, 2, 10, 299, 281, 292, STR_OPTIONS_SCENARIO_UNLOCKING, STR_NONE }, // Unlocking of scenarios { WIDGETS_END }, }; @@ -418,7 +422,9 @@ static uint32 window_options_page_enabled_widgets[] = { (1 << WIDX_THEMES) | (1 << WIDX_THEMES_DROPDOWN) | (1 << WIDX_THEMES_BUTTON) | - (1 << WIDX_SELECT_BY_TRACK_TYPE), + (1 << WIDX_SELECT_BY_TRACK_TYPE) | + (1 << WIDX_SCENARIO_GROUPING) | + (1 << WIDX_SCENARIO_UNLOCKING), MAIN_OPTIONS_ENABLED_WIDGETS | (1 << WIDX_REAL_NAME_CHECKBOX) | @@ -642,6 +648,11 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) window_invalidate_by_class(WC_RIDE); window_invalidate_by_class(WC_CONSTRUCT_RIDE); break; + case WIDX_SCENARIO_GROUPING: + case WIDX_SCENARIO_UNLOCKING: + config_save_default(); + window_invalidate_by_class(WC_SCENARIO_SELECT); + break; } break; @@ -940,6 +951,23 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* dropdown_set_checked(gCurrentTheme, true); } break; + + case WIDX_SCENARIO_GROUPING: + num_items = 2; + + gDropdownItemsFormat[0] = 1142; + gDropdownItemsArgs[0] = STR_OPTIONS_SCENARIO_ORIGIN; + gDropdownItemsFormat[1] = 1142; + gDropdownItemsArgs[1] = STR_OPTIONS_SCENARIO_DIFFICULTY; + + window_options_show_dropdown(w, widget, num_items); + + if (gConfigGeneral.scenario_select_mode == 1) { + dropdown_set_checked(0, true); + } else { + dropdown_set_checked(1, true); + } + break; } break; @@ -1139,6 +1167,14 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown } config_save_default(); break; + case WIDX_SCENARIO_GROUPING: +// if (dropdownIndex != -1) { +// if (dropdownIndex == 0 || dropdownIndex == 1) +// dropdownIndex ^= 1; +// theme_change_preset(dropdownIndex); +// } + config_save_default(); + break; } break; @@ -1320,6 +1356,7 @@ static void window_options_invalidate(rct_window *w) widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_CHEATS, gConfigInterface.toolbar_show_cheats); widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_NEWS, gConfigInterface.toolbar_show_news); widget_set_checkbox_value(w, WIDX_SELECT_BY_TRACK_TYPE, gConfigInterface.select_by_track_type); + widget_set_checkbox_value(w, WIDX_SCENARIO_UNLOCKING, gConfigGeneral.scenario_unlocking_enabled); window_options_controls_and_interface_widgets[WIDX_THEMES].type = WWT_DROPDOWN; window_options_controls_and_interface_widgets[WIDX_THEMES_DROPDOWN].type = WWT_DROPDOWN_BUTTON; @@ -1332,6 +1369,8 @@ static void window_options_invalidate(rct_window *w) window_options_controls_and_interface_widgets[WIDX_TOOLBAR_SHOW_CHEATS].type = WWT_CHECKBOX; window_options_controls_and_interface_widgets[WIDX_TOOLBAR_SHOW_NEWS].type = WWT_CHECKBOX; window_options_controls_and_interface_widgets[WIDX_SELECT_BY_TRACK_TYPE].type = WWT_CHECKBOX; + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].type = WWT_DROPDOWN; + window_options_controls_and_interface_widgets[WIDX_SCENARIO_UNLOCKING].type = WWT_CHECKBOX; break; case WINDOW_OPTIONS_PAGE_MISC: @@ -1473,6 +1512,7 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) gfx_draw_string_left(dpi, STR_SHOW_TOOLBAR_BUTTONS_FOR, w, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_TOOLBAR_BUTTONS_GROUP].top + 15); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&gConfigThemes.presets[gCurrentTheme].name; gfx_draw_string_left(dpi, 5238, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_THEMES].top + 1); + gfx_draw_string_left(dpi, STR_OPTIONS_SCENARIO_GROUPING, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top + 1); gfx_draw_string_left_clipped( dpi, 1170, From f7d33f3cabfbf2c4785450566438c9ee2b0c9951 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 30 Dec 2015 01:20:40 +0900 Subject: [PATCH 44/90] Rename constants et al per code reviewer's request. --- data/language/english_uk.txt | 6 +++--- src/localisation/string_ids.h | 6 +++--- src/scenario.h | 14 +++++++------- src/scenario_list.c | 28 ++++++++++++++-------------- src/scenario_sources.h | 12 ++++++------ src/windows/title_scenarioselect.c | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index be5f6534f3..abd1a8ea03 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3957,10 +3957,10 @@ STR_5615 :L STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag STR_5617 :{SMALLFONT}{BLACK}Move selected element up. STR_5618 :{SMALLFONT}{BLACK}Move selected element down. -STR_5619 :RCT1 Classic -STR_5620 :Corkscrew Follies +STR_5619 :RollerCoaster Tycoon +STR_5620 :Added Attractions STR_5621 :Loopy Landscapes -STR_5622 :RCT2 Vanilla +STR_5622 :RollerCoaster Tycoon 2 STR_5623 :Wacky Worlds STR_5624 :Time Twister STR_5625 :{OPENQUOTES}Real{ENDQUOTES} Parks diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 3dcfce3d49..e62e622dc0 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2240,10 +2240,10 @@ enum { STR_NOTIFICATION_GUEST_USED_FACILITY = 5605, STR_NOTIFICATION_GUEST_DIED = 5606, - STR_SCENARIO_CATEGORY_RCT1_CLASSIC = 5619, - STR_SCENARIO_CATEGORY_RCT1_CF = 5620, + STR_SCENARIO_CATEGORY_RCT1 = 5619, + STR_SCENARIO_CATEGORY_RCT1_AA = 5620, STR_SCENARIO_CATEGORY_RCT1_LL = 5621, - STR_SCENARIO_CATEGORY_RCT2_VANILLA = 5622, + STR_SCENARIO_CATEGORY_RCT2 = 5622, STR_SCENARIO_CATEGORY_RCT2_WW = 5623, STR_SCENARIO_CATEGORY_RCT2_TT = 5624, STR_SCENARIO_CATEGORY_REAL_PARKS = 5625, diff --git a/src/scenario.h b/src/scenario.h index 1da4609a82..19f3d84bab 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -73,12 +73,12 @@ typedef struct { } rct_scenario_scores_header; typedef enum { - SCENARIO_SOURCE_RCT1_CLASSIC, - SCENARIO_SOURCE_RCT1_CORKSCREW, - SCENARIO_SOURCE_RCT1_LOOPY, - SCENARIO_SOURCE_RCT2_VANILLA, - SCENARIO_SOURCE_RCT2_WACKY, - SCENARIO_SOURCE_RCT2_TIME, + SCENARIO_SOURCE_RCT1, + SCENARIO_SOURCE_RCT1_AA, + SCENARIO_SOURCE_RCT1_LL, + SCENARIO_SOURCE_RCT2, + SCENARIO_SOURCE_RCT2_WW, + SCENARIO_SOURCE_RCT2_TT, SCENARIO_SOURCE_REAL, SCENARIO_SOURCE_OTHER } scenario_source; @@ -100,7 +100,7 @@ typedef struct { sint32 flags; // 0x0268 uint32 company_value; // 0x026C char completed_by[64]; // 0x0270 - scenario_source source_game;// new in OpenRCT2 + uint8 source_game; // new in OpenRCT2 sint16 source_index; // new in OpenRCT2 } rct_scenario_basic; diff --git a/src/scenario_list.c b/src/scenario_list.c index 73ff7caab4..8980250d97 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -56,7 +56,7 @@ sint16 get_scenario_index(rct_scenario_basic *scenario) return -1; } -void normalize_scenario_name(rct_scenario_basic *scenario) +void normalise_scenario_name(rct_scenario_basic *scenario) { char* name = scenario->name; @@ -78,18 +78,18 @@ void normalize_scenario_name(rct_scenario_basic *scenario) scenario_source source_by_index(uint8 index) { - if (index >= SCENARIO_SOURCE_RCT1_CLASSIC_INDEX && index < SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX) { - return SCENARIO_SOURCE_RCT1_CLASSIC; - } else if (index >= SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX && index < SCENARIO_SOURCE_RCT1_LOOPY_INDEX) { - return SCENARIO_SOURCE_RCT1_CORKSCREW; - } else if (index >= SCENARIO_SOURCE_RCT1_LOOPY_INDEX && index < SCENARIO_SOURCE_RCT2_VANILLA_INDEX) { - return SCENARIO_SOURCE_RCT1_LOOPY; - } else if (index >= SCENARIO_SOURCE_RCT2_VANILLA_INDEX && index < SCENARIO_SOURCE_RCT2_WACKY_INDEX) { - return SCENARIO_SOURCE_RCT2_VANILLA; - } else if (index >= SCENARIO_SOURCE_RCT2_WACKY_INDEX && index < SCENARIO_SOURCE_RCT2_TIME_INDEX) { - return SCENARIO_SOURCE_RCT2_WACKY; - } else if (index >= SCENARIO_SOURCE_RCT2_TIME_INDEX && index < SCENARIO_SOURCE_REAL_INDEX) { - return SCENARIO_SOURCE_RCT2_TIME; + if (index >= SCENARIO_SOURCE_RCT1_INDEX && index < SCENARIO_SOURCE_RCT1_AA_INDEX) { + return SCENARIO_SOURCE_RCT1; + } else if (index >= SCENARIO_SOURCE_RCT1_AA_INDEX && index < SCENARIO_SOURCE_RCT1_LL_INDEX) { + return SCENARIO_SOURCE_RCT1_AA; + } else if (index >= SCENARIO_SOURCE_RCT1_LL_INDEX && index < SCENARIO_SOURCE_RCT2_INDEX) { + return SCENARIO_SOURCE_RCT1_LL; + } else if (index >= SCENARIO_SOURCE_RCT2_INDEX && index < SCENARIO_SOURCE_RCT2_WW_INDEX) { + return SCENARIO_SOURCE_RCT2; + } else if (index >= SCENARIO_SOURCE_RCT2_WW_INDEX && index < SCENARIO_SOURCE_RCT2_TT_INDEX) { + return SCENARIO_SOURCE_RCT2_WW; + } else if (index >= SCENARIO_SOURCE_RCT2_TT_INDEX && index < SCENARIO_SOURCE_REAL_INDEX) { + return SCENARIO_SOURCE_RCT2_TT; } else if (index >= SCENARIO_SOURCE_REAL_INDEX && index < NUM_ORIGINAL_SCENARIOS) { return SCENARIO_SOURCE_REAL; } else { @@ -186,7 +186,7 @@ static void scenario_list_add(const char *path) } // Normalize the name to make the scenario as recognisable as possible. - normalize_scenario_name(scenario); + normalise_scenario_name(scenario); // Look up and store information regarding the origins of this scenario. scenario->source_index = get_scenario_index(scenario); diff --git a/src/scenario_sources.h b/src/scenario_sources.h index 248669d7bf..9c82307844 100644 --- a/src/scenario_sources.h +++ b/src/scenario_sources.h @@ -1,12 +1,12 @@ #define NUM_ORIGINAL_SCENARIOS 136 #define NUM_ALIASES 5 -#define SCENARIO_SOURCE_RCT1_CLASSIC_INDEX 0 -#define SCENARIO_SOURCE_RCT1_CORKSCREW_INDEX 22 -#define SCENARIO_SOURCE_RCT1_LOOPY_INDEX 52 -#define SCENARIO_SOURCE_RCT2_VANILLA_INDEX 82 -#define SCENARIO_SOURCE_RCT2_WACKY_INDEX 97 -#define SCENARIO_SOURCE_RCT2_TIME_INDEX 114 +#define SCENARIO_SOURCE_RCT1_INDEX 0 +#define SCENARIO_SOURCE_RCT1_AA_INDEX 22 +#define SCENARIO_SOURCE_RCT1_LL_INDEX 52 +#define SCENARIO_SOURCE_RCT2_INDEX 82 +#define SCENARIO_SOURCE_RCT2_WW_INDEX 97 +#define SCENARIO_SOURCE_RCT2_TT_INDEX 114 #define SCENARIO_SOURCE_REAL_INDEX 128 const char * const scenario_aliases[NUM_ALIASES * 2] = { diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index b87c5added..62bb58e979 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -331,7 +331,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) y = (widget->top + widget->bottom) / 2 + w->y - 3; if (gConfigGeneral.scenario_select_mode == 1) { - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1_CLASSIC + i; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1 + i; } else { // old-style RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_BEGINNER_PARKS + i; } From 63529a5213a02db7733ff5ddd83af677422533c8 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 30 Dec 2015 22:30:54 +0000 Subject: [PATCH 45/90] fix option widgets for scenario grouping --- src/windows/options.c | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/windows/options.c b/src/windows/options.c index c1f1b84527..881d947839 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -136,6 +136,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_TOOLBAR_SHOW_NEWS, WIDX_SELECT_BY_TRACK_TYPE, WIDX_SCENARIO_GROUPING, + WIDX_SCENARIO_GROUPING_DROPDOWN, WIDX_SCENARIO_UNLOCKING, // Misc @@ -256,6 +257,7 @@ static rct_widget window_options_controls_and_interface_widgets[] = { { WWT_CHECKBOX, 2, 10, 299, 254, 265, STR_SELECT_BY_TRACK_TYPE, STR_SELECT_BY_TRACK_TYPE_TIP }, // Select by track type { WWT_DROPDOWN, 2, 155, 299, 267, 278, STR_NONE, STR_NONE }, // Scenario select mode + { WWT_DROPDOWN_BUTTON, 2, 288, 298, 268, 277, STR_DROPDOWN_GLYPH, STR_NONE }, { WWT_CHECKBOX, 2, 10, 299, 281, 292, STR_OPTIONS_SCENARIO_UNLOCKING, STR_NONE }, // Unlocking of scenarios { WIDGETS_END }, }; @@ -424,6 +426,7 @@ static uint32 window_options_page_enabled_widgets[] = { (1 << WIDX_THEMES_BUTTON) | (1 << WIDX_SELECT_BY_TRACK_TYPE) | (1 << WIDX_SCENARIO_GROUPING) | + (1 << WIDX_SCENARIO_GROUPING_DROPDOWN) | (1 << WIDX_SCENARIO_UNLOCKING), MAIN_OPTIONS_ENABLED_WIDGETS | @@ -648,8 +651,8 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) window_invalidate_by_class(WC_RIDE); window_invalidate_by_class(WC_CONSTRUCT_RIDE); break; - case WIDX_SCENARIO_GROUPING: case WIDX_SCENARIO_UNLOCKING: + gConfigGeneral.scenario_unlocking_enabled ^= 1; config_save_default(); window_invalidate_by_class(WC_SCENARIO_SELECT); break; @@ -952,21 +955,25 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* } break; - case WIDX_SCENARIO_GROUPING: + case WIDX_SCENARIO_GROUPING_DROPDOWN: num_items = 2; gDropdownItemsFormat[0] = 1142; - gDropdownItemsArgs[0] = STR_OPTIONS_SCENARIO_ORIGIN; + gDropdownItemsArgs[0] = STR_OPTIONS_SCENARIO_DIFFICULTY; gDropdownItemsFormat[1] = 1142; - gDropdownItemsArgs[1] = STR_OPTIONS_SCENARIO_DIFFICULTY; + gDropdownItemsArgs[1] = STR_OPTIONS_SCENARIO_ORIGIN; - window_options_show_dropdown(w, widget, num_items); + window_dropdown_show_text_custom_width( + w->x + widget->left, + w->y + widget->top, + widget->bottom - widget->top + 1, + w->colours[1], + DROPDOWN_FLAG_STAY_OPEN, + num_items, + widget->right - widget->left - 3 + ); - if (gConfigGeneral.scenario_select_mode == 1) { - dropdown_set_checked(0, true); - } else { - dropdown_set_checked(1, true); - } + dropdown_set_checked(gConfigGeneral.scenario_select_mode, true); break; } break; @@ -1167,13 +1174,12 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown } config_save_default(); break; - case WIDX_SCENARIO_GROUPING: -// if (dropdownIndex != -1) { -// if (dropdownIndex == 0 || dropdownIndex == 1) -// dropdownIndex ^= 1; -// theme_change_preset(dropdownIndex); -// } - config_save_default(); + case WIDX_SCENARIO_GROUPING_DROPDOWN: + if (dropdownIndex != gConfigGeneral.scenario_select_mode) { + gConfigGeneral.scenario_select_mode = dropdownIndex; + config_save_default(); + window_invalidate(w); + } break; } break; @@ -1512,7 +1518,6 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) gfx_draw_string_left(dpi, STR_SHOW_TOOLBAR_BUTTONS_FOR, w, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_TOOLBAR_BUTTONS_GROUP].top + 15); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&gConfigThemes.presets[gCurrentTheme].name; gfx_draw_string_left(dpi, 5238, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_THEMES].top + 1); - gfx_draw_string_left(dpi, STR_OPTIONS_SCENARIO_GROUPING, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top + 1); gfx_draw_string_left_clipped( dpi, 1170, @@ -1521,7 +1526,17 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) w->x + window_options_controls_and_interface_widgets[WIDX_THEMES].left + 1, w->y + window_options_controls_and_interface_widgets[WIDX_THEMES].top, window_options_controls_and_interface_widgets[WIDX_THEMES_DROPDOWN].left - window_options_controls_and_interface_widgets[WIDX_THEMES].left - 4 - ); + ); + gfx_draw_string_left(dpi, STR_OPTIONS_SCENARIO_GROUPING, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top + 1); + gfx_draw_string_left_clipped( + dpi, + gConfigGeneral.scenario_select_mode == 0 ? STR_OPTIONS_SCENARIO_DIFFICULTY : STR_OPTIONS_SCENARIO_ORIGIN, + NULL, + w->colours[1], + w->x + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].left + 1, + w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top, + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING_DROPDOWN].left - window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].left - 4 + ); break; case WINDOW_OPTIONS_PAGE_MISC: gfx_draw_string_left(dpi, 2700, w, w->colours[1], w->x + 10, w->y + window_options_misc_widgets[WIDX_AUTOSAVE].top + 1); From 6a768c4a3cfd341f84be83bd595e70f269180045 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 31 Dec 2015 02:59:08 +0000 Subject: [PATCH 46/90] redo entire scenario highscore load / saving - load and save highscores to new file format (highscores.dat) - scan scenarios from RCT2 data and user data - load highscores from legacy file (scores.dat) - fix various issues with new scenario select window --- openrct2.vcxproj | 1 + openrct2.vcxproj.filters | 1 + src/config.c | 2 +- src/config.h | 5 + src/scenario.c | 75 ++-- src/scenario.h | 47 ++- src/scenario_list.c | 567 +++++++++++++++++++---------- src/scenario_sources.h | 27 +- src/util/util.c | 64 ++++ src/util/util.h | 3 + src/windows/options.c | 5 +- src/windows/title_scenarioselect.c | 93 ++--- test/tests.h | 4 +- 13 files changed, 595 insertions(+), 299 deletions(-) diff --git a/openrct2.vcxproj b/openrct2.vcxproj index a430d4746c..e104ee19a7 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -264,6 +264,7 @@ + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index 4d1a1f4363..eee82ee7c2 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -845,5 +845,6 @@ Source + \ No newline at end of file diff --git a/src/config.c b/src/config.c index 056c2740b9..ed5dcdd3bc 100644 --- a/src/config.c +++ b/src/config.c @@ -203,7 +203,7 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, show_fps), "show_fps", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, trap_cursor), "trap_cursor", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, auto_open_shops), "auto_open_shops", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(general_configuration, scenario_select_mode), "scenario_select_mode", CONFIG_VALUE_TYPE_UINT8, 1, NULL }, + { offsetof(general_configuration, scenario_select_mode), "scenario_select_mode", CONFIG_VALUE_TYPE_UINT8, SCENARIO_SELECT_MODE_ORIGIN, NULL }, { offsetof(general_configuration, scenario_unlocking_enabled), "scenario_unlocking_enabled", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, }; diff --git a/src/config.h b/src/config.h index f3d0cbb2d6..daa64f9e2b 100644 --- a/src/config.h +++ b/src/config.h @@ -128,6 +128,11 @@ enum { SORT_DATE_DESCENDING, }; +enum { + SCENARIO_SELECT_MODE_DIFFICULTY, + SCENARIO_SELECT_MODE_ORIGIN, +}; + typedef struct { uint8 play_intro; uint8 confirmation_prompt; diff --git a/src/scenario.c b/src/scenario.c index 9bc0f7e262..80b9a61304 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -219,19 +219,6 @@ int scenario_load(const char *path) return 0; } -/** - * - * rct2: 0x00678282 - * scenario (ebx) - */ -int scenario_load_and_play(const rct_scenario_basic *scenario) -{ - char path[MAX_PATH]; - - substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), scenario->path); - return scenario_load_and_play_from_path(path); -} - int scenario_load_and_play_from_path(const char *path) { window_close_construction_windows(); @@ -437,29 +424,35 @@ void scenario_failure() */ void scenario_success() { - int i; - rct_scenario_basic* scenario; - uint32 current_val = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, uint32); + const money32 companyValue = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, money32); - RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = current_val; + RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = companyValue; peep_applause(); - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; + uint8 scenarioRoot = SCENARIO_ROOT_RCT2; + scenario_index_entry *scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); + if (scenario == NULL) { + scenarioRoot = SCENARIO_ROOT_USER; + scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); + } - if (strequals(scenario->path, _scenarioFileName, 256, true)) { - // Check if record company value has been broken - if ((scenario->flags & SCENARIO_FLAGS_COMPLETED) && scenario->company_value >= current_val) - break; + if (scenario != NULL) { + // Check if record company value has been broken + if (scenario->highscore == NULL || scenario->highscore->company_value < companyValue) { + if (scenario->highscore == NULL) { + scenario->highscore = scenario_highscore_insert(); + } else { + scenario_highscore_free(scenario->highscore); + } + scenario->highscore->fileNameRoot = scenarioRoot; + scenario->highscore->fileName = (utf8*)path_get_filename(scenario->path); + scenario->highscore->name = NULL; + scenario->highscore->company_value = companyValue; // Allow name entry RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_SCENARIO_COMPLETE_NAME_INPUT; - scenario->company_value = current_val; - scenario->flags |= SCENARIO_FLAGS_COMPLETED; - scenario->completed_by[0] = 0; - RCT2_GLOBAL(0x013587C0, uint32) = current_val; + RCT2_GLOBAL(0x013587C0, money32) = companyValue; scenario_scores_save(); - break; } } scenario_end(); @@ -471,21 +464,19 @@ void scenario_success() */ void scenario_success_submit_name(const char *name) { - int i; - rct_scenario_basic* scenario; - uint32 scenarioWinCompanyValue; + uint8 scenarioRoot = SCENARIO_ROOT_RCT2; + scenario_index_entry *scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); + if (scenario == NULL) { + scenarioRoot = SCENARIO_ROOT_USER; + scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); + } - for (i = 0; i < gScenarioListCount; i++) { - scenario = &gScenarioList[i]; - - if (strequals(scenario->path, _scenarioFileName, 256, true)) { - scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, uint32); - if (scenario->company_value == scenarioWinCompanyValue) { - safe_strncpy(scenario->completed_by, name, 64); - safe_strncpy((char*)0x013587D8, name, 32); - scenario_scores_save(); - } - break; + if (scenario != NULL) { + money32 scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, money32); + if (scenario->highscore->company_value == scenarioWinCompanyValue) { + scenario->highscore->name = _strdup(name); + safe_strncpy((char*)0x013587D8, name, 32); + scenario_scores_save(); } } diff --git a/src/scenario.h b/src/scenario.h index 19f3d84bab..b547d1269a 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -100,8 +100,8 @@ typedef struct { sint32 flags; // 0x0268 uint32 company_value; // 0x026C char completed_by[64]; // 0x0270 - uint8 source_game; // new in OpenRCT2 - sint16 source_index; // new in OpenRCT2 + // uint8 source_game; // new in OpenRCT2 + // sint16 source_index; // new in OpenRCT2 } rct_scenario_basic; typedef struct { @@ -420,20 +420,55 @@ enum { OBJECTIVE_MONTHLY_FOOD_INCOME }; +typedef struct { + uint8 fileNameRoot; + utf8 *fileName; + utf8 *name; + money32 company_value; +} scenario_highscore_entry; + +typedef struct { + utf8 path[MAX_PATH]; + + // Category / sequence + uint8 flags; + uint8 category; + uint8 source_game; + sint16 source_index; + + // Objective + uint8 objective_type; + uint8 objective_arg_1; + sint32 objective_arg_2; + sint16 objective_arg_3; + scenario_highscore_entry *highscore; + + utf8 name[64]; + utf8 details[256]; +} scenario_index_entry; + +enum { + SCENARIO_ROOT_RCT2, + SCENARIO_ROOT_USER, +}; + // Scenario list extern int gScenarioListCount; extern int gScenarioListCapacity; -extern rct_scenario_basic *gScenarioList; +extern scenario_index_entry *gScenarioList; extern char gScenarioSavePath[MAX_PATH]; extern int gFirstTimeSave; -int scenario_scores_save(); +bool scenario_scores_save(); void scenario_load_list(); -rct_scenario_basic *get_scenario_by_filename(const char *filename); +void scenario_list_dispose(); +scenario_index_entry *scenario_list_find_by_path(const utf8 *path); +scenario_index_entry *scenario_list_find_by_root_path(uint8 root, const utf8 *filename); +scenario_highscore_entry *scenario_highscore_insert(); +void scenario_highscore_free(scenario_highscore_entry *highscore); int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info); int scenario_load(const char *path); -int scenario_load_and_play(const rct_scenario_basic *scenario); int scenario_load_and_play_from_path(const char *path); void scenario_begin(); void scenario_update(); diff --git a/src/scenario_list.c b/src/scenario_list.c index 8980250d97..24e7f35159 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -28,55 +28,194 @@ // Scenario list int gScenarioListCount = 0; int gScenarioListCapacity = 0; -rct_scenario_basic *gScenarioList = NULL; +scenario_index_entry *gScenarioList = NULL; +int gScenarioHighscoreListCount = 0; +int gScenarioHighscoreListCapacity = 0; +scenario_highscore_entry *gScenarioHighscoreList = NULL; + +static void scenario_list_include(const utf8 *directory); static void scenario_list_add(const char *path); static void scenario_list_sort(); static int scenario_list_sort_by_name(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); -static int scenario_scores_load(); +static sint32 get_scenario_index(utf8 *name); +static void normalise_scenario_name(utf8 *name); +static scenario_source source_by_index(sint32 index); -rct_scenario_basic *get_scenario_by_filename(const char *filename) +static bool scenario_scores_load(); +static bool scenario_scores_legacy_load(); +static void scenario_highscore_remove(scenario_highscore_entry *higscore); +static void scenario_highscore_list_dispose(); +static utf8 *io_read_string(SDL_RWops *file); +static void io_write_string(SDL_RWops *file, utf8 *source); + +/** + * Searches and grabs the metadata for all the scenarios. + */ +void scenario_load_list() { - int i; - for (i = 0; i < gScenarioListCount; i++) - if (strcmp(gScenarioList[i].path, filename) == 0) - return &gScenarioList[i]; + utf8 directory[MAX_PATH]; - return NULL; + // Clear scenario list + gScenarioListCount = 0; + + // Get scenario directory from RCT2 + safe_strncpy(directory, gConfigGeneral.game_path, sizeof(directory)); + safe_strcat_path(directory, "Scenarios", sizeof(directory)); + scenario_list_include(directory); + + // Get scenario directory from user directory + platform_get_user_directory(directory, "scenario"); + scenario_list_include(directory); + + scenario_list_sort(); + scenario_scores_load(); + scenario_scores_legacy_load(); } -sint16 get_scenario_index(rct_scenario_basic *scenario) +static void scenario_list_include(const utf8 *directory) { - for (int i = 0; i < NUM_ORIGINAL_SCENARIOS; i++) { - if (strcmp(original_scenario_names[i], scenario->name) == 0) - return i; + int handle; + file_info fileInfo; + + // Scenarios in this directory + utf8 pattern[MAX_PATH]; + safe_strncpy(pattern, directory, sizeof(pattern)); + safe_strcat_path(pattern, "*.sc6", sizeof(pattern)); + + handle = platform_enumerate_files_begin(pattern); + while (platform_enumerate_files_next(handle, &fileInfo)) { + utf8 path[MAX_PATH]; + safe_strncpy(path, directory, sizeof(pattern)); + safe_strcat_path(path, fileInfo.path, sizeof(pattern)); + scenario_list_add(path); + } + platform_enumerate_files_end(handle); + + // Include sub-directories + utf8 subDirectory[MAX_PATH]; + handle = platform_enumerate_directories_begin(directory); + while (platform_enumerate_directories_next(handle, subDirectory)) { + utf8 path[MAX_PATH]; + safe_strncpy(path, directory, sizeof(pattern)); + safe_strcat_path(path, subDirectory, sizeof(pattern)); + scenario_list_include(path); + } + platform_enumerate_directories_end(handle); +} + +static void scenario_list_add(const utf8 *path) +{ + // Load the basic scenario information + rct_s6_header s6Header; + rct_s6_info s6Info; + if (!scenario_load_basic(path, &s6Header, &s6Info)) { + return; } + // Increase cache size + if (gScenarioListCount == gScenarioListCapacity) { + gScenarioListCapacity = max(8, gScenarioListCapacity * 2); + gScenarioList = (scenario_index_entry*)realloc(gScenarioList, gScenarioListCapacity * sizeof(scenario_index_entry)); + } + scenario_index_entry *newEntry = &gScenarioList[gScenarioListCount]; + gScenarioListCount++; + + // Set new entry + safe_strncpy(newEntry->path, path, sizeof(newEntry->path)); + newEntry->category = s6Info.category; + newEntry->flags = SCENARIO_FLAGS_VISIBLE; + newEntry->objective_type = s6Info.objective_type; + newEntry->objective_arg_1 = s6Info.objective_arg_1; + newEntry->objective_arg_2 = s6Info.objective_arg_2; + newEntry->objective_arg_3 = s6Info.objective_arg_3; + newEntry->highscore = NULL; + safe_strncpy(newEntry->name, s6Info.name, sizeof(newEntry->name)); + safe_strncpy(newEntry->details, s6Info.details, sizeof(newEntry->details)); + + // Normalise the name to make the scenario as recognisable as possible. + normalise_scenario_name(newEntry->name); + + // Look up and store information regarding the origins of this scenario. + newEntry->source_index = get_scenario_index(newEntry->name); + newEntry->source_game = source_by_index(newEntry->source_index); +} + +void scenario_list_dispose() +{ + gScenarioListCapacity = 0; + gScenarioListCount = 0; + SafeFree(gScenarioList); +} + +static void scenario_list_sort() +{ + int(*compareFunc)(void const*, void const*); + + compareFunc = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN ? + scenario_list_sort_by_index : + scenario_list_sort_by_name; + + qsort(gScenarioList, gScenarioListCount, sizeof(scenario_index_entry), compareFunc); +} + +static int scenario_list_sort_by_name(const void *a, const void *b) +{ + const scenario_index_entry *entryA = (const scenario_index_entry*)a; + const scenario_index_entry *entryB = (const scenario_index_entry*)b; + + return strcmp(entryA->name, entryB->name); +} + +static int scenario_list_sort_by_index(const void *a, const void *b) +{ + const scenario_index_entry *entryA = (const scenario_index_entry*)a; + const scenario_index_entry *entryB = (const scenario_index_entry*)b; + + if (entryA->source_game == SCENARIO_SOURCE_OTHER && entryB->source_game == SCENARIO_SOURCE_OTHER) { + return scenario_list_sort_by_name(a, b); + } + return entryA->source_index - entryB->source_index; +} + +static sint32 get_scenario_index(utf8 *name) +{ + for (sint32 i = 0; i < NUM_ORIGINAL_SCENARIOS; i++) { + if (_strcmpi(original_scenario_names[i], name) == 0) { + return i; + } + } return -1; } -void normalise_scenario_name(rct_scenario_basic *scenario) +static void normalise_scenario_name(utf8 *name) { - char* name = scenario->name; + size_t nameLength = strlen(name); - // Strip "RCT2 " prefix off scenario names. - if (name[0] == 'R' && name[1] == 'C' && name[2] == 'T' && name[3] == '2') { - log_verbose("Stripping RCT2 from name: %s", name); - safe_strncpy(scenario->name, name + 5, 64); + // Strip "RCT(1|2)? *" prefix off scenario names. + if (nameLength >= 3 && (name[0] == 'R' && name[1] == 'C' && name[2] == 'T')) { + if (nameLength >= 4 && (name[3] == '1' || name[3] == '2')) { + log_verbose("Stripping RCT/1/2 from name: %s", name); + safe_strncpy(name, name + 4, 64); + } else { + safe_strncpy(name, name + 3, 64); + } + + safe_strtrimleft(name, name, 64); } - // American scenario titles should be handled by their British counterpart, internally. + // American scenario titles should be converted to British name + // Don't worry, names will be translated using language packs later for (int i = 0; i < NUM_ALIASES; i++) { - if (strcmp(scenario_aliases[i * 2], name) == 0) - { - log_verbose("Found alias: %s; will treat as: %s", scenario->name, scenario_aliases[i * 2 + 1]); - safe_strncpy(scenario->name, scenario_aliases[i * 2 + 1], 64); + if (strcmp(scenario_aliases[(i * 2) + 1], name) == 0) { + log_verbose("Found alias: %s; will treat as: %s", name, scenario_aliases[i * 2]); + safe_strncpy(name, scenario_aliases[i * 2], 64); } } } -scenario_source source_by_index(uint8 index) +static scenario_source source_by_index(sint32 index) { if (index >= SCENARIO_SOURCE_RCT1_INDEX && index < SCENARIO_SOURCE_RCT1_AA_INDEX) { return SCENARIO_SOURCE_RCT1; @@ -97,168 +236,65 @@ scenario_source source_by_index(uint8 index) } } -/** - * - * rct2: 0x006775A8 - */ -void scenario_load_list() +scenario_index_entry *scenario_list_find_by_path(const utf8 *path) { - int i, enumFileHandle; - file_info enumFileInfo; - - // Load scores - scenario_scores_load(); - - // Set all scenarios to be invisible - for (i = 0; i < gScenarioListCount; i++) - gScenarioList[i].flags &= ~SCENARIO_FLAGS_VISIBLE; - - // Enumerate through each scenario in the directory - enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char)); - if (enumFileHandle != INVALID_HANDLE) { - while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) { - scenario_list_add(enumFileInfo.path); + for (int i = 0; i < gScenarioListCount; i++) { + if (_strcmpi(path, gScenarioList[i].path) == 0) { + return &gScenarioList[i]; } - platform_enumerate_files_end(enumFileHandle); } - - // Sort alphabetically - scenario_list_sort(); - - // Save the scores - scenario_scores_save(); + return NULL; } -static void scenario_list_add(const char *path) +scenario_index_entry *scenario_list_find_by_root_path(uint8 root, const utf8 *filename) { - char scenarioPath[MAX_PATH]; - rct_scenario_basic *scenario; - rct_s6_header s6Header; - rct_s6_info s6Info; - - // Get absolute path - substitute_path(scenarioPath, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), path); - - // Load the basic scenario information - if (!scenario_load_basic(scenarioPath, &s6Header, &s6Info)) - return; - - // Ignore scenarios where first header byte is not 255 - if (s6Info.editor_step != 255) - return; - - // Check if scenario already exists in list, likely if in scores - scenario = get_scenario_by_filename(path); - if (scenario != NULL) { - // Update the scenario information - scenario->flags |= SCENARIO_FLAGS_VISIBLE; - scenario->category = s6Info.category; - scenario->objective_type = s6Info.objective_type; - scenario->objective_arg_1 = s6Info.objective_arg_1; - scenario->objective_arg_2 = s6Info.objective_arg_2; - scenario->objective_arg_3 = s6Info.objective_arg_3; - safe_strncpy(scenario->name, s6Info.name, 64); - safe_strncpy(scenario->details, s6Info.details, 256); + // Derive path + utf8 path[MAX_PATH]; + if (root == SCENARIO_ROOT_RCT2) { + safe_strncpy(path, gConfigGeneral.game_path, sizeof(path)); + safe_strcat_path(path, "Scenarios", sizeof(path)); } else { - // Check if the scenario list buffer has room for another scenario - if (gScenarioListCount >= gScenarioListCapacity) { - // Allocate more room - gScenarioListCapacity += 16; - gScenarioList = realloc(gScenarioList, gScenarioListCapacity * sizeof(rct_scenario_basic)); - } - - // Increment the number of scenarios - scenario = &gScenarioList[gScenarioListCount]; - gScenarioListCount++; - - // Add this new scenario to the list - safe_strncpy(scenario->path, path, 256); - scenario->flags = SCENARIO_FLAGS_VISIBLE; - if (RCT2_GLOBAL(0x009AA00C, uint8) & 1) - scenario->flags |= SCENARIO_FLAGS_SIXFLAGS; - scenario->category = s6Info.category; - scenario->objective_type = s6Info.objective_type; - scenario->objective_arg_1 = s6Info.objective_arg_1; - scenario->objective_arg_2 = s6Info.objective_arg_2; - scenario->objective_arg_3 = s6Info.objective_arg_3; - safe_strncpy(scenario->name, s6Info.name, 64); - safe_strncpy(scenario->details, s6Info.details, 256); + platform_get_user_directory(path, "scenario"); } + safe_strcat_path(path, filename, sizeof(path)); - // Normalize the name to make the scenario as recognisable as possible. - normalise_scenario_name(scenario); - - // Look up and store information regarding the origins of this scenario. - scenario->source_index = get_scenario_index(scenario); - scenario->source_game = source_by_index(scenario->source_index); -} - -/** -* Sort the list of scenarios. This used to be an insertion sort which took -* place as each scenario loaded. It has now been changed to a quicksort which -* takes place after all the scenarios have been loaded in. -* rct2: 0x00677C3B -*/ -static void scenario_list_sort() -{ - if (gConfigGeneral.scenario_select_mode == 1) // and not tabIndex > REAL, OTHER - qsort(gScenarioList, gScenarioListCount, sizeof(rct_scenario_basic), scenario_list_sort_by_index); - else - qsort(gScenarioList, gScenarioListCount, sizeof(rct_scenario_basic), scenario_list_sort_by_name); -} - -static int scenario_list_sort_by_index(const void *a, const void *b) -{ - if (((rct_scenario_basic*)a)->source_game == SCENARIO_SOURCE_OTHER && ((rct_scenario_basic*)b)->source_game == SCENARIO_SOURCE_OTHER) - return scenario_list_sort_by_name(a, b); - - return ((rct_scenario_basic*)a)->source_index - ((rct_scenario_basic*)b)->source_index; -} - -/** - * Basic scenario information compare function for sorting. - * rct2: 0x00677C08 - */ -static int scenario_list_sort_by_name(const void *a, const void *b) -{ - return strcmp(((rct_scenario_basic*)a)->name, ((rct_scenario_basic*)b)->name); + // Find matching scenario entry + return scenario_list_find_by_path(path); } /** * Gets the path for the scenario scores path. */ static void scenario_scores_get_path(utf8 *outPath) +{ + platform_get_user_directory(outPath, NULL); + strcat(outPath, "highscores.dat"); +} + +/** + * Gets the path for the scenario scores path. + */ +static void scenario_scores_legacy_get_path(utf8 *outPath) { platform_get_user_directory(outPath, NULL); strcat(outPath, "scores.dat"); } /** - * - * rct2: 0x006775A8 + * Loads the original scores.dat file and replaces any highscores that + * are better for matching scenarios. */ -static int scenario_scores_load() +static bool scenario_scores_legacy_load() { - SDL_RWops *file; - char scoresPath[MAX_PATH]; - - scenario_scores_get_path(scoresPath); - - // Free scenario list if already allocated - if (gScenarioList != NULL) { - free(gScenarioList); - gScenarioList = NULL; - } - - // Try and load the scores file + utf8 scoresPath[MAX_PATH]; + scenario_scores_legacy_get_path(scoresPath); // First check user folder and then fallback to install directory - file = SDL_RWFromFile(scoresPath, "rb"); + SDL_RWops *file = SDL_RWFromFile(scoresPath, "rb"); if (file == NULL) { file = SDL_RWFromFile(get_file_path(PATH_ID_SCORES), "rb"); if (file == NULL) { - log_error("Unable to load scenario scores."); - return 0; + return false; } } @@ -266,53 +302,208 @@ static int scenario_scores_load() rct_scenario_scores_header header; if (SDL_RWread(file, &header, 16, 1) != 1) { SDL_RWclose(file); - log_error("Invalid header in scenario scores file."); - return 0; - } - gScenarioListCount = header.scenario_count; - - // Load scenario information with scores - int scenarioListBufferSize = gScenarioListCount * sizeof(rct_scenario_basic); - gScenarioListCapacity = gScenarioListCount; - gScenarioList = malloc(scenarioListBufferSize); - if (SDL_RWread(file, gScenarioList, scenarioListBufferSize, 1) == 1) { - SDL_RWclose(file); - return 1; + log_error("Invalid header in legacy scenario scores file."); + return false; } - // Unable to load scores, free scenario list + // Read scenarios + bool highscoresDirty = false; + for (uint32 i = 0; i < header.scenario_count; i++) { + // Read legacy entry + rct_scenario_basic scBasic; + if (SDL_RWread(file, &scBasic, sizeof(rct_scenario_basic), 1) != 1) { + break; + } + + // Ignore non-completed scenarios + if (!(scBasic.flags & SCENARIO_FLAGS_COMPLETED)) { + continue; + } + + // Find matching scenario entry + scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_root_path(SCENARIO_ROOT_RCT2, scBasic.path); + if (scenarioIndexEntry != NULL) { + // Check if legacy highscore is better + scenario_highscore_entry *highscore = scenarioIndexEntry->highscore; + if (highscore == NULL) { + highscore = scenario_highscore_insert(); + scenarioIndexEntry->highscore = highscore; + } else if (highscore->company_value < (money32)scBasic.company_value) { + scenario_highscore_free(highscore); + // Re-use highscore entry + } else { + highscore = NULL; + } + + // Set new highscore + if (highscore != NULL) { + highscore->fileNameRoot = SCENARIO_ROOT_RCT2; + highscore->fileName = _strdup(scBasic.path); + highscore->name = _strdup(scBasic.completed_by); + highscore->company_value = (money32)scBasic.company_value; + highscoresDirty = true; + } + + // Exit loop + break; + } + } SDL_RWclose(file); - gScenarioListCount = 0; - gScenarioListCapacity = 0; - free(gScenarioList); - gScenarioList = NULL; - return 0; + + if (highscoresDirty) { + scenario_scores_save(); + } + return true; +} + +static bool scenario_scores_load() +{ + utf8 scoresPath[MAX_PATH]; + scenario_scores_get_path(scoresPath); + + // Load scores file + SDL_RWops *file = SDL_RWFromFile(scoresPath, "rb"); + if (file == NULL) { + return false; + } + + // Check file version + uint32 fileVersion; + SDL_RWread(file, &fileVersion, sizeof(fileVersion), 1); + if (fileVersion != 1) { + log_error("Invalid or incompatible highscores file."); + return false; + } + + // Read and allocate the highscore list + scenario_highscore_list_dispose(); + SDL_RWread(file, &gScenarioHighscoreListCount, sizeof(gScenarioHighscoreListCount), 1); + gScenarioHighscoreListCapacity = gScenarioHighscoreListCount; + gScenarioHighscoreList = malloc(gScenarioHighscoreListCapacity * sizeof(scenario_highscore_entry)); + + // Read highscores + for (int i = 0; i < gScenarioHighscoreListCount; i++) { + scenario_highscore_entry *highscore = &gScenarioHighscoreList[i]; + + SDL_RWread(file, &highscore->fileNameRoot, sizeof(highscore->fileNameRoot), 1); + highscore->fileName = io_read_string(file); + highscore->name = io_read_string(file); + SDL_RWread(file, &highscore->company_value, sizeof(highscore->company_value), 1); + + // Attach highscore to correct scenario entry + scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_root_path(highscore->fileNameRoot, highscore->fileName); + if (scenarioIndexEntry != NULL) { + scenarioIndexEntry->highscore = highscore; + } + } + + SDL_RWclose(file); + return true; } /** * * rct2: 0x00677B50 */ -int scenario_scores_save() +bool scenario_scores_save() { - SDL_RWops *file; utf8 scoresPath[MAX_PATH]; - scenario_scores_get_path(scoresPath); - file = SDL_RWFromFile(scoresPath, "wb"); + SDL_RWops *file = SDL_RWFromFile(scoresPath, "wb"); if (file == NULL) { log_error("Unable to save scenario scores."); - return 0; + return false; } - rct_scenario_scores_header header; - header.scenario_count = gScenarioListCount; - - SDL_RWwrite(file, &header, sizeof(header), 1); - if (gScenarioListCount > 0) - SDL_RWwrite(file, gScenarioList, gScenarioListCount * sizeof(rct_scenario_basic), 1); + const uint32 fileVersion = 1; + SDL_RWwrite(file, &fileVersion, sizeof(fileVersion), 1); + SDL_RWwrite(file, &gScenarioHighscoreListCount, sizeof(gScenarioHighscoreListCount), 1); + for (int i = 0; i < gScenarioHighscoreListCount; i++) { + scenario_highscore_entry *highscore = &gScenarioHighscoreList[i]; + SDL_RWwrite(file, &highscore->fileNameRoot, sizeof(highscore->fileNameRoot), 1); + io_write_string(file, highscore->fileName); + io_write_string(file, highscore->name); + SDL_RWwrite(file, &highscore->company_value, sizeof(highscore->company_value), 1); + } SDL_RWclose(file); - return 1; + + return true; +} + +scenario_highscore_entry *scenario_highscore_insert() +{ + if (gScenarioHighscoreListCount >= gScenarioHighscoreListCapacity) { + gScenarioHighscoreListCapacity = max(8, gScenarioHighscoreListCapacity * 2); + gScenarioHighscoreList = realloc(gScenarioHighscoreList, gScenarioHighscoreListCapacity * sizeof(scenario_highscore_entry)); + } + return &gScenarioHighscoreList[gScenarioHighscoreListCount++]; +} + +static void scenario_highscore_remove(scenario_highscore_entry *highscore) +{ + for (int i = 0; i < gScenarioHighscoreListCount; i++) { + if (&gScenarioHighscoreList[i] == highscore) { + size_t moveSize = (gScenarioHighscoreListCount - i - 1) * sizeof(scenario_highscore_entry); + if (moveSize > 0) { + memmove(&gScenarioHighscoreList[i], &gScenarioHighscoreList[i + 1], moveSize); + } + return; + } + } +} + +void scenario_highscore_free(scenario_highscore_entry *highscore) +{ + SafeFree(highscore->fileName); + SafeFree(highscore->name); +} + +static void scenario_highscore_list_dispose() +{ + for (int i = 0; i < gScenarioHighscoreListCount; i++) { + scenario_highscore_free(&gScenarioHighscoreList[i]); + } + gScenarioHighscoreListCapacity = 0; + gScenarioHighscoreListCount = 0; + SafeFree(gScenarioHighscoreList); +} + +static utf8 *io_read_string(SDL_RWops *file) +{ + size_t bufferCount = 0; + size_t bufferCapacity = 0; + utf8 *buffer = NULL; + + utf8 ch; + do { + SDL_RWread(file, &ch, sizeof(ch), 1); + if (ch == '\0' && buffer == NULL) { + break; + } + + if (bufferCount >= bufferCapacity) { + bufferCapacity = max(32, bufferCapacity * 2); + buffer = realloc(buffer, bufferCapacity * sizeof(uint8)); + } + + buffer[bufferCount] = ch; + bufferCount++; + } while (ch != '\0'); + + if (bufferCount < bufferCapacity) { + buffer = realloc(buffer, bufferCount); + } + return buffer; +} + +static void io_write_string(SDL_RWops *file, utf8 *source) +{ + if (source == NULL) { + utf8 empty = 0; + SDL_RWwrite(file, &empty, sizeof(utf8), 1); + } else { + SDL_RWwrite(file, source, strlen(source) + 1, 1); + } } diff --git a/src/scenario_sources.h b/src/scenario_sources.h index 9c82307844..78efee823a 100644 --- a/src/scenario_sources.h +++ b/src/scenario_sources.h @@ -1,5 +1,5 @@ #define NUM_ORIGINAL_SCENARIOS 136 -#define NUM_ALIASES 5 +#define NUM_ALIASES 6 #define SCENARIO_SOURCE_RCT1_INDEX 0 #define SCENARIO_SOURCE_RCT1_AA_INDEX 22 @@ -10,15 +10,16 @@ #define SCENARIO_SOURCE_REAL_INDEX 128 const char * const scenario_aliases[NUM_ALIASES * 2] = { - "Katie's World", "Katie's Dreamland", - "Dinky Park", "Pokey Park", - "Aqua Park", "White Water Park", - "Mothball Mountain","Mystic Mountain", - "Big Pier", "Paradise Pier" + "Katie's Dreamland", "Katie's World", + "Pokey Park", "Dinky Park", + "White Water Park", "Aqua Park", + "Mystic Mountain", "Mothball Mountain", + "Paradise Pier", "Big Pier", + "Paradise Pier 2", "Big Pier 2", }; const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { - // RCT Classic + // RCT "Forest Frontiers", "Dynamite Dunes", "Leafy Lake", @@ -42,7 +43,7 @@ const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { "Thunder Rock", "Mega Park", - // RCT: Corkscrew Follies + // RCT: Added Attractions "Whispering Cliffs", "Three Monkeys Park", "Canary Mines", @@ -81,7 +82,7 @@ const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { "Razor Rocks", "Crater Lake", "Vertigo Views", - "Big Pier 2", + "Paradise Pier 2", "Dragon's Cove", "Good Knight Park", "Wacky Warren", @@ -106,7 +107,7 @@ const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { "Venus Ponds", "Micro Park", - // RCT2 Vanilla + // RCT2 "Crazy Castle", "Electric Fields", "Factory Capers", @@ -123,7 +124,7 @@ const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { "Lucky Lake", "Rainbow Summit", - // RCT2 Wacky Worlds + // RCT2: Wacky Worlds "Africa - Victoria Falls", "Asia - Great Wall of China Tourism Enhancement", "North America - Grand Canyon", @@ -142,7 +143,7 @@ const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { "N. America - Extreme Hawaiian Island", "South America - Rain Forest Plateau", - // RCT2 Time Twister + // RCT2: Time Twister "Dark Age - Robin Hood", "Prehistoric - After the Asteroid", "Roaring Twenties - Prison Island", @@ -158,7 +159,7 @@ const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { "Roaring Twenties - Skyscrapers", "Rock 'n' Roll - Rock 'n' Roll", - // Real parks + // Real parks "Alton Towers", "Heide-Park", "Blackpool Pleasure Beach", diff --git a/src/util/util.c b/src/util/util.c index c20876a1f9..bc18de7d65 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -222,6 +222,70 @@ char *safe_strncpy(char * destination, const char * source, size_t size) return result; } +char *safe_strcat(char *destination, const char *source, size_t size) +{ + assert(destination != NULL); + assert(source != NULL); + + if (size == 0) { + return destination; + } + + char *result = destination; + + size_t i; + for (i = 0; i < size; i++) { + if (*destination == '\0') { + break; + } else { + destination++; + } + } + + bool terminated = false; + for (; i < size; i++) { + if (*source != '\0') { + *destination++ = *source++; + } else { + *destination = *source; + terminated = true; + break; + } + } + + if (!terminated) { + result[size - 1] = '\0'; + log_warning("Truncating string \"%s\" to %d bytes.", result, size); + } + + return result; +} + +char *safe_strcat_path(char *destination, const char *source, size_t size) +{ + const char pathSeparator = platform_get_path_separator(); + + size_t length = strlen(destination); + if (length >= size - 1) { + return destination; + } + + if (destination[length - 1] != pathSeparator) { + destination[length] = pathSeparator; + destination[length + 1] = '\0'; + } + + return safe_strcat(destination, source, size); +} + +char *safe_strtrimleft(char *destination, const char *source, size_t size) +{ + while (*source == ' ' && *source != '\0') { + source++; + } + return safe_strncpy(destination, source, size); +} + bool utf8_is_bom(const char *str) { return str[0] == (char)0xEF && str[1] == (char)0xBB && str[2] == (char)0xBF; diff --git a/src/util/util.h b/src/util/util.h index fad8a6bbc6..6cef39d0c5 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -42,6 +42,9 @@ int bitcount(int source); bool strequals(const char *a, const char *b, int length, bool caseInsensitive); int strcicmp(char const *a, char const *b); char *safe_strncpy(char * destination, const char * source, size_t num); +char *safe_strcat(char *destination, const char *source, size_t size); +char *safe_strcat_path(char *destination, const char *source, size_t size); +char *safe_strtrimleft(char *destination, const char *source, size_t size); bool utf8_is_bom(const char *str); bool str_is_null_or_empty(const char *str); diff --git a/src/windows/options.c b/src/windows/options.c index 881d947839..173aa49445 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -1179,6 +1179,7 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown gConfigGeneral.scenario_select_mode = dropdownIndex; config_save_default(); window_invalidate(w); + window_close_by_class(WC_SCENARIO_SELECT); } break; } @@ -1530,7 +1531,9 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) gfx_draw_string_left(dpi, STR_OPTIONS_SCENARIO_GROUPING, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top + 1); gfx_draw_string_left_clipped( dpi, - gConfigGeneral.scenario_select_mode == 0 ? STR_OPTIONS_SCENARIO_DIFFICULTY : STR_OPTIONS_SCENARIO_ORIGIN, + gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY ? + STR_OPTIONS_SCENARIO_DIFFICULTY : + STR_OPTIONS_SCENARIO_ORIGIN, NULL, w->colours[1], w->x + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].left + 1, diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 62bb58e979..f2b44a3340 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -121,8 +121,7 @@ void window_scenarioselect_open() scenario_load_list(); // Shrink the window if we're showing scenarios by difficulty level. - if (gConfigGeneral.scenario_select_mode == 2) - { + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY) { window_width = 610; window_scenarioselect_widgets[WIDX_BACKGROUND].right = 609; window_scenarioselect_widgets[WIDX_TITLEBAR].right = 608; @@ -130,9 +129,9 @@ void window_scenarioselect_open() window_scenarioselect_widgets[WIDX_CLOSE].right = 607; window_scenarioselect_widgets[WIDX_TABCONTENT].right = 609; window_scenarioselect_widgets[WIDX_SCENARIOLIST].right = 433; - } - else + } else { window_width = 733; + } window = window_create_centred( window_width, @@ -164,15 +163,15 @@ static void window_scenarioselect_init_tabs() { int show_pages = 0; for (int i = 0; i < gScenarioListCount; i++) { - rct_scenario_basic* scenario = &gScenarioList[i]; - if (scenario->flags & SCENARIO_FLAGS_VISIBLE) - { - if (gConfigGeneral.scenario_select_mode == 1) + scenario_index_entry *scenario = &gScenarioList[i]; + if (scenario->flags & SCENARIO_FLAGS_VISIBLE) { + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { show_pages |= 1 << scenario->source_game; - else + } else { show_pages |= 1 << scenario->category; } } + } int x = 3; for (int i = 0; i < 8; i++) { @@ -212,10 +211,10 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, { *height = 0; for (int i = 0; i < gScenarioListCount; i++) { - rct_scenario_basic *scenario = &gScenarioList[i]; + scenario_index_entry *scenario = &gScenarioList[i]; - if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) + if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) continue; if (scenario->flags & SCENARIO_FLAGS_VISIBLE) @@ -231,20 +230,20 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex { int num_unlocks = 5; for (int i = 0; i < gScenarioListCount; i++) { - rct_scenario_basic *scenario = &gScenarioList[i]; + scenario_index_entry *scenario = &gScenarioList[i]; - if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) + if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) continue; if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; - if (gConfigGeneral.scenario_unlocking_enabled) { + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && gConfigGeneral.scenario_unlocking_enabled) { if (num_unlocks <= 0) break; - bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED; + bool is_completed = scenario->highscore != NULL; if (is_completed) { num_unlocks++; } else { @@ -257,7 +256,7 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex continue; audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0); - scenario_load_and_play(scenario); + scenario_load_and_play_from_path(scenario->path); break; } } @@ -268,22 +267,22 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex */ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) { - rct_scenario_basic *selected = NULL; + scenario_index_entry *selected = NULL; int num_unlocks = 5; for (int i = 0; i < gScenarioListCount; i++) { - rct_scenario_basic *scenario = &gScenarioList[i]; - if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) + scenario_index_entry *scenario = &gScenarioList[i]; + if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) continue; if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) continue; - if (gConfigGeneral.scenario_unlocking_enabled) { + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && gConfigGeneral.scenario_unlocking_enabled) { if (num_unlocks <= 0) break; - bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED; + bool is_completed = scenario->highscore != NULL; num_unlocks += is_completed ? 1 : -1; } @@ -315,7 +314,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) { int i, x, y, format; rct_widget *widget; - rct_scenario_basic *scenario; + scenario_index_entry *scenario; window_draw_widgets(w, dpi); @@ -330,7 +329,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) x = (widget->left + widget->right) / 2 + w->x; y = (widget->top + widget->bottom) / 2 + w->y - 3; - if (gConfigGeneral.scenario_select_mode == 1) { + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1 + i; } else { // old-style RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_BEGINNER_PARKS + i; @@ -339,7 +338,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) } // Return if no scenario highlighted - scenario = w->scenario; + scenario = (scenario_index_entry*)w->highlighted_item; if (scenario == NULL) return; @@ -364,10 +363,10 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_OBJECTIVE, 0) + 5; // Scenario score - if (scenario->flags & SCENARIO_FLAGS_COMPLETED) { - safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); + if (scenario->highscore != NULL) { + safe_strncpy((char*)0x009BC677, scenario->highscore->name, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, int) = scenario->company_value; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, int) = scenario->highscore->company_value; y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0); } } @@ -382,15 +381,15 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * int unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191; int disabled_format = 5619; - bool wide = gConfigGeneral.scenario_select_mode == 1; + bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN; int y = 0; int num_unlocks = 5; for (int i = 0; i < gScenarioListCount; i++) { - rct_scenario_basic *scenario = &gScenarioList[i]; + scenario_index_entry *scenario = &gScenarioList[i]; - if ((gConfigGeneral.scenario_select_mode == 1 && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == 2 && scenario->category != w->selected_tab)) + if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) continue; if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) @@ -401,24 +400,26 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * // Draw hover highlight bool is_highlighted = w->highlighted_item == (int)scenario; - if (is_highlighted) + if (is_highlighted) { gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); + } - bool is_completed = scenario->flags & SCENARIO_FLAGS_COMPLETED; + bool is_completed = scenario->highscore != NULL; bool is_disabled = false; - if (gConfigGeneral.scenario_unlocking_enabled) { - if (num_unlocks <= 0) + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && gConfigGeneral.scenario_unlocking_enabled) { + if (num_unlocks <= 0) { is_disabled = true; - + } num_unlocks += is_completed ? 1 : -1; } - int format = is_disabled ? 5619 : (is_highlighted ? highlighted_format : unhighlighted_format); // Draw scenario name - safe_strncpy((char*)0x009BC677, scenario->name, 64); - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; - gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + rct_string_id placeholderStringId = 3165; + safe_strncpy((char*)language_get_string(placeholderStringId), scenario->name, 64); + int format = is_disabled ? 865 : (is_highlighted ? highlighted_format : unhighlighted_format); + colour = is_disabled ? w->colours[1] | 0x40 : COLOUR_BLACK; + gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, &placeholderStringId); // Check if scenario is completed if (is_completed) { @@ -426,9 +427,9 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0); // Draw completion score - safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793; - RCT2_GLOBAL(0x013CE954, short) = 3165; + safe_strncpy((char*)language_get_string(placeholderStringId), scenario->highscore->name, 64); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = 2793; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, rct_string_id) = placeholderStringId; gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); } diff --git a/test/tests.h b/test/tests.h index 7691a3dd88..06619ec167 100644 --- a/test/tests.h +++ b/test/tests.h @@ -33,11 +33,11 @@ int run_all_tests(); #include "../src/scenario.h" static void test_load_scenario(CuTest* tc, const char* file_name) { - const rct_scenario_basic* scenario = get_scenario_by_filename(file_name); + const scenario_index_entry* scenario = scenario_list_find_by_path(file_name); if (scenario == NULL) { CuFail(tc, "Could not load scenario"); } - scenario_load_and_play(scenario); + scenario_load_and_play_from_path(scenario->name); } #endif From 72e820dead127689190dda8d4298025ce12d0d9d Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 31 Dec 2015 18:26:25 +0000 Subject: [PATCH 47/90] add horizontal rule headings to scenario list --- src/scenario_list.c | 3 + src/windows/title_scenarioselect.c | 356 ++++++++++++++++++++--------- 2 files changed, 253 insertions(+), 106 deletions(-) diff --git a/src/scenario_list.c b/src/scenario_list.c index 24e7f35159..a3b6e86b3a 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -165,6 +165,9 @@ static int scenario_list_sort_by_name(const void *a, const void *b) const scenario_index_entry *entryA = (const scenario_index_entry*)a; const scenario_index_entry *entryB = (const scenario_index_entry*)b; + if (entryA->source_game != entryB->source_game) { + return entryA->source_game - entryB->source_game; + } return strcmp(entryA->name, entryB->name); } diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index f2b44a3340..c754a293e6 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -30,6 +30,29 @@ #include "../interface/themes.h" #include "../util/util.h" +#define INITIAL_NUM_UNLOCKED_SCENARIOS 5 + +enum { + LIST_ITEM_TYPE_HEADING, + LIST_ITEM_TYPE_SCENARIO, + LIST_ITEM_TYPE_END, +}; + +typedef struct { + uint8 type; + union { + struct { + rct_string_id string_id; + } heading; + struct { + scenario_index_entry *scenario; + bool is_locked; + } scenario; + }; +} sc_list_item; + +static sc_list_item *_listItems = NULL; + enum { WIDX_BACKGROUND, WIDX_TITLEBAR, @@ -65,6 +88,7 @@ static rct_widget window_scenarioselect_widgets[] = { static void window_scenarioselect_init_tabs(); +static void window_scenarioselect_close(rct_window *w); static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex); static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); @@ -75,7 +99,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); static rct_window_event_list window_scenarioselect_events = { - NULL, + window_scenarioselect_close, window_scenarioselect_mouseup, NULL, window_scenarioselect_mousedown, @@ -105,6 +129,11 @@ static rct_window_event_list window_scenarioselect_events = { window_scenarioselect_scrollpaint }; +static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, int left, int right, int y, rct_string_id stringId); +static void initialise_list_items(rct_window *w); +static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario); +static bool is_locking_enabled(rct_window *w); + /** * * rct2: 0x006781B5 @@ -112,7 +141,8 @@ static rct_window_event_list window_scenarioselect_events = { void window_scenarioselect_open() { rct_window* window; - int window_width; + int windowWidth; + int windowHeight = 334; if (window_bring_to_front_by_class(WC_SCENARIO_SELECT) != NULL) return; @@ -122,37 +152,30 @@ void window_scenarioselect_open() // Shrink the window if we're showing scenarios by difficulty level. if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY) { - window_width = 610; - window_scenarioselect_widgets[WIDX_BACKGROUND].right = 609; - window_scenarioselect_widgets[WIDX_TITLEBAR].right = 608; - window_scenarioselect_widgets[WIDX_CLOSE].left = 597; - window_scenarioselect_widgets[WIDX_CLOSE].right = 607; - window_scenarioselect_widgets[WIDX_TABCONTENT].right = 609; - window_scenarioselect_widgets[WIDX_SCENARIOLIST].right = 433; + windowWidth = 610; } else { - window_width = 733; + windowWidth = 733; } window = window_create_centred( - window_width, - 334, + windowWidth, + windowHeight, &window_scenarioselect_events, WC_SCENARIO_SELECT, WF_10 ); window->widgets = window_scenarioselect_widgets; - window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5) | (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8); - - window_init_scroll_widgets(window); - window->viewport_focus_coordinates.var_480 = -1; - window->scenario = NULL; - window_scenarioselect_init_tabs(); window->selected_tab = 0; + initialise_list_items(window); + + window_init_scroll_widgets(window); + window->viewport_focus_coordinates.var_480 = -1; + window->highlighted_item = 0; } /** @@ -169,9 +192,9 @@ static void window_scenarioselect_init_tabs() show_pages |= 1 << scenario->source_game; } else { show_pages |= 1 << scenario->category; + } } } - } int x = 3; for (int i = 0; i < 8; i++) { @@ -188,17 +211,24 @@ static void window_scenarioselect_init_tabs() } } +static void window_scenarioselect_close(rct_window *w) +{ + SafeFree(_listItems); +} + static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex) { - if (widgetIndex == WIDX_CLOSE) + if (widgetIndex == WIDX_CLOSE) { window_close(w); } +} static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB8) { w->selected_tab = widgetIndex - 4; - w->scenario = NULL; + w->highlighted_item = 0; + initialise_list_items(w); window_invalidate(w); window_event_resize_call(w); window_event_invalidate_call(w); @@ -209,17 +239,18 @@ static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_w static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) { - *height = 0; - for (int i = 0; i < gScenarioListCount; i++) { - scenario_index_entry *scenario = &gScenarioList[i]; - - if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) - continue; - - if (scenario->flags & SCENARIO_FLAGS_VISIBLE) - *height += 24; + int y = 0; + for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { + switch (listItem->type) { + case LIST_ITEM_TYPE_HEADING: + y += 18; + break; + case LIST_ITEM_TYPE_SCENARIO: + y += 24; + break; + } } + *height = y; } /** @@ -228,37 +259,23 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, */ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { - int num_unlocks = 5; - for (int i = 0; i < gScenarioListCount; i++) { - scenario_index_entry *scenario = &gScenarioList[i]; - - if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) - continue; - - if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) - continue; - - if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && gConfigGeneral.scenario_unlocking_enabled) { - if (num_unlocks <= 0) + for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { + switch (listItem->type) { + case LIST_ITEM_TYPE_HEADING: + y -= 18; break; - - bool is_completed = scenario->highscore != NULL; - if (is_completed) { - num_unlocks++; - } else { - num_unlocks--; - } - } - + case LIST_ITEM_TYPE_SCENARIO: y -= 24; - if (y >= 0) - continue; - + if (y < 0 && !listItem->scenario.is_locked) { audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0); - scenario_load_and_play_from_path(scenario->path); + scenario_load_and_play_from_path(listItem->scenario.scenario->path); + } break; } + if (y < 0) { + break; +} + } } /** @@ -268,33 +285,25 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) { scenario_index_entry *selected = NULL; - int num_unlocks = 5; - for (int i = 0; i < gScenarioListCount; i++) { - scenario_index_entry *scenario = &gScenarioList[i]; - if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) - continue; - - if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) - continue; - - if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && gConfigGeneral.scenario_unlocking_enabled) { - if (num_unlocks <= 0) + for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { + switch (listItem->type) { + case LIST_ITEM_TYPE_HEADING: + y -= 18; + break; + case LIST_ITEM_TYPE_SCENARIO: + y -= 24; + if (y < 0 && !listItem->scenario.is_locked) { + selected = listItem->scenario.scenario; + } break; - - bool is_completed = scenario->highscore != NULL; - num_unlocks += is_completed ? 1 : -1; } - - y -= 24; - if (y >= 0) - continue; - - selected = scenario; + if (y < 0) { break; } - if (w->scenario != selected) { - w->scenario = selected; + } + + if (w->highlighted_item != (uint32)selected) { + w->highlighted_item = (uint32)selected; window_invalidate(w); } } @@ -308,6 +317,19 @@ static void window_scenarioselect_invalidate(rct_window *w) | (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8) ); w->pressed_widgets |= 1LL << (w->selected_tab + 4); + + int windowWidth = w->width; + window_scenarioselect_widgets[WIDX_BACKGROUND].right = windowWidth - 1; + window_scenarioselect_widgets[WIDX_TITLEBAR].right = windowWidth - 2; + window_scenarioselect_widgets[WIDX_CLOSE].left = windowWidth - 13; + window_scenarioselect_widgets[WIDX_CLOSE].right = windowWidth - 3; + window_scenarioselect_widgets[WIDX_TABCONTENT].right = windowWidth - 1; + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right = windowWidth - 179; + + int windowHeight = w->height; + window_scenarioselect_widgets[WIDX_BACKGROUND].bottom = windowHeight - 1; + window_scenarioselect_widgets[WIDX_TABCONTENT].bottom = windowHeight - 1; + window_scenarioselect_widgets[WIDX_SCENARIOLIST].bottom = windowHeight - 5; } static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -383,46 +405,41 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN; + rct_widget *listWidget = &w->widgets[WIDX_SCENARIOLIST]; + int listWidth = listWidget->right - listWidget->left - 12; + int y = 0; - int num_unlocks = 5; - for (int i = 0; i < gScenarioListCount; i++) { - scenario_index_entry *scenario = &gScenarioList[i]; - - if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab)) - continue; - - if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) - continue; - - if (y > dpi->y + dpi->height) + for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { + if (y > dpi->y + dpi->height) { continue; + } + switch (listItem->type) { + case LIST_ITEM_TYPE_HEADING:; + const int horizontalRuleMargin = 4; + draw_category_heading(w, dpi, horizontalRuleMargin, listWidth - horizontalRuleMargin, y + 2, listItem->heading.string_id); + y += 18; + break; + case LIST_ITEM_TYPE_SCENARIO:; // Draw hover highlight - bool is_highlighted = w->highlighted_item == (int)scenario; - if (is_highlighted) { + scenario_index_entry *scenario = listItem->scenario.scenario; + bool isHighlighted = w->highlighted_item == (uint32)scenario; + if (isHighlighted) { gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); } - bool is_completed = scenario->highscore != NULL; - bool is_disabled = false; - if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && gConfigGeneral.scenario_unlocking_enabled) { - if (num_unlocks <= 0) { - is_disabled = true; - } - num_unlocks += is_completed ? 1 : -1; - } - + bool isCompleted = scenario->highscore != NULL; + bool isDisabled = listItem->scenario.is_locked; // Draw scenario name rct_string_id placeholderStringId = 3165; safe_strncpy((char*)language_get_string(placeholderStringId), scenario->name, 64); - int format = is_disabled ? 865 : (is_highlighted ? highlighted_format : unhighlighted_format); - colour = is_disabled ? w->colours[1] | 0x40 : COLOUR_BLACK; + int format = isDisabled ? 865 : (isHighlighted ? highlighted_format : unhighlighted_format); + colour = isDisabled ? w->colours[1] | 0x40 : COLOUR_BLACK; gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, &placeholderStringId); // Check if scenario is completed - if (is_completed) { + if (isCompleted) { // Draw completion tick gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0); @@ -434,5 +451,132 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * } y += 24; + break; + } } } + +static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, int left, int right, int y, rct_string_id stringId) +{ + uint8 baseColour = w->colours[1]; + uint8 lightColour = ColourMapA[baseColour].lighter; + uint8 darkColour = ColourMapA[baseColour].mid_dark; + + // Draw string + int centreX = (left + right) / 2; + gfx_draw_string_centred(dpi, stringId, centreX, y, baseColour, NULL); + + // Get string dimensions + utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, utf8); + format_string(buffer, stringId, NULL); + int categoryStringHalfWidth = (gfx_get_string_width(buffer) / 2) + 4; + int strLeft = centreX - categoryStringHalfWidth; + int strRight = centreX + categoryStringHalfWidth; + + // Draw light horizontal rule + int lineY = y + 4; + gfx_draw_line(dpi, left, lineY, strLeft, lineY, lightColour); + gfx_draw_line(dpi, strRight, lineY, right, lineY, lightColour); + + // Draw dark horizontal rule + lineY++; + gfx_draw_line(dpi, left, lineY, strLeft, lineY, darkColour); + gfx_draw_line(dpi, strRight, lineY, right, lineY, darkColour); + } + +static void initialise_list_items(rct_window *w) +{ + SafeFree(_listItems); + + int capacity = gScenarioListCount + 16; + int length = 0; + _listItems = malloc(capacity * sizeof(sc_list_item)); + + int numUnlocks = INITIAL_NUM_UNLOCKED_SCENARIOS; + uint8 currentHeading = UINT8_MAX; + for (int i = 0; i < gScenarioListCount; i++) { + scenario_index_entry *scenario = &gScenarioList[i]; + if (!is_scenario_visible(w, scenario)) { + continue; + } + + sc_list_item *listItem; + + // Category heading + rct_string_id headingStringId = STR_NONE; + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { + if (currentHeading != scenario->category) { + currentHeading = scenario->category; + headingStringId = STR_BEGINNER_PARKS + currentHeading; + } + } else { + if (currentHeading != scenario->source_game) { + currentHeading = scenario->source_game; + headingStringId = STR_SCENARIO_CATEGORY_RCT1 + currentHeading; + } + } + if (headingStringId != (rct_string_id)STR_NONE) { + // Ensure list capacity + if (length == capacity) { + capacity += 32; + _listItems = realloc(_listItems, capacity * sizeof(sc_list_item)); + } + listItem = &_listItems[length++]; + + listItem->type = LIST_ITEM_TYPE_HEADING; + listItem->heading.string_id = headingStringId; + } + + // Ensure list capacity + if (length == capacity) { + capacity += 32; + _listItems = realloc(_listItems, capacity * sizeof(sc_list_item)); + } + listItem = &_listItems[length++]; + + // Scenario + listItem->type = LIST_ITEM_TYPE_SCENARIO; + listItem->scenario.scenario = scenario; + if (is_locking_enabled(w)) { + listItem->scenario.is_locked = numUnlocks <= 0; + if (scenario->highscore == NULL) { + numUnlocks--; + } + } else { + listItem->scenario.is_locked = false; + } + } + + length++; + _listItems = realloc(_listItems, length * sizeof(sc_list_item)); + _listItems[length - 1].type = LIST_ITEM_TYPE_END; +} + +static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario) +{ + if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || + (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab) + ) { + return false; + } + + if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) { + return false; + } + + return true; +} + +static bool is_locking_enabled(rct_window *w) +{ + if (gConfigGeneral.scenario_select_mode != SCENARIO_SELECT_MODE_ORIGIN) { + return false; + } + if (!gConfigGeneral.scenario_unlocking_enabled) { + return false; + } + if (w->selected_tab >= 6) { + return false; + } + return true; +} From af67cf5703424e8322c45c25415ff4aa3fbb314a Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 31 Dec 2015 19:30:11 +0000 Subject: [PATCH 48/90] refactor scenario sources and improve scenario select window --- openrct2.vcxproj | 2 +- openrct2.vcxproj.filters | 4 +- src/scenario.h | 3 + src/scenario_list.c | 70 +------- src/scenario_sources.c | 248 +++++++++++++++++++++++++++++ src/scenario_sources.h | 171 -------------------- src/windows/title_scenarioselect.c | 4 +- 7 files changed, 263 insertions(+), 239 deletions(-) create mode 100644 src/scenario_sources.c delete mode 100644 src/scenario_sources.h diff --git a/openrct2.vcxproj b/openrct2.vcxproj index e104ee19a7..019cc6419d 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -264,7 +264,7 @@ - + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index eee82ee7c2..2e1f69fbca 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -561,6 +561,9 @@ Source + + Source + @@ -845,6 +848,5 @@ Source - \ No newline at end of file diff --git a/src/scenario.h b/src/scenario.h index b547d1269a..d5ba798073 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -484,4 +484,7 @@ void scenario_success(); void scenario_success_submit_name(const char *name); void scenario_autosave_check(); +bool scenario_get_index_and_source(const utf8 *name, scenario_source *source, sint32 *index); +void scenario_normalise_name(utf8 *name); + #endif diff --git a/src/scenario_list.c b/src/scenario_list.c index a3b6e86b3a..ed7e7d747c 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -23,7 +23,6 @@ #include "platform/platform.h" #include "util/util.h" #include "scenario.h" -#include "scenario_sources.h" // Scenario list int gScenarioListCount = 0; @@ -39,9 +38,6 @@ static void scenario_list_add(const char *path); static void scenario_list_sort(); static int scenario_list_sort_by_name(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); -static sint32 get_scenario_index(utf8 *name); -static void normalise_scenario_name(utf8 *name); -static scenario_source source_by_index(sint32 index); static bool scenario_scores_load(); static bool scenario_scores_legacy_load(); @@ -135,11 +131,14 @@ static void scenario_list_add(const utf8 *path) safe_strncpy(newEntry->details, s6Info.details, sizeof(newEntry->details)); // Normalise the name to make the scenario as recognisable as possible. - normalise_scenario_name(newEntry->name); + scenario_normalise_name(newEntry->name); // Look up and store information regarding the origins of this scenario. - newEntry->source_index = get_scenario_index(newEntry->name); - newEntry->source_game = source_by_index(newEntry->source_index); + scenario_source source; + sint32 index; + scenario_get_index_and_source(newEntry->name, &source, &index); + newEntry->source_index = index; + newEntry->source_game = source; } void scenario_list_dispose() @@ -182,63 +181,6 @@ static int scenario_list_sort_by_index(const void *a, const void *b) return entryA->source_index - entryB->source_index; } -static sint32 get_scenario_index(utf8 *name) -{ - for (sint32 i = 0; i < NUM_ORIGINAL_SCENARIOS; i++) { - if (_strcmpi(original_scenario_names[i], name) == 0) { - return i; - } - } - return -1; -} - -static void normalise_scenario_name(utf8 *name) -{ - size_t nameLength = strlen(name); - - // Strip "RCT(1|2)? *" prefix off scenario names. - if (nameLength >= 3 && (name[0] == 'R' && name[1] == 'C' && name[2] == 'T')) { - if (nameLength >= 4 && (name[3] == '1' || name[3] == '2')) { - log_verbose("Stripping RCT/1/2 from name: %s", name); - safe_strncpy(name, name + 4, 64); - } else { - safe_strncpy(name, name + 3, 64); - } - - safe_strtrimleft(name, name, 64); - } - - // American scenario titles should be converted to British name - // Don't worry, names will be translated using language packs later - for (int i = 0; i < NUM_ALIASES; i++) { - if (strcmp(scenario_aliases[(i * 2) + 1], name) == 0) { - log_verbose("Found alias: %s; will treat as: %s", name, scenario_aliases[i * 2]); - safe_strncpy(name, scenario_aliases[i * 2], 64); - } - } -} - -static scenario_source source_by_index(sint32 index) -{ - if (index >= SCENARIO_SOURCE_RCT1_INDEX && index < SCENARIO_SOURCE_RCT1_AA_INDEX) { - return SCENARIO_SOURCE_RCT1; - } else if (index >= SCENARIO_SOURCE_RCT1_AA_INDEX && index < SCENARIO_SOURCE_RCT1_LL_INDEX) { - return SCENARIO_SOURCE_RCT1_AA; - } else if (index >= SCENARIO_SOURCE_RCT1_LL_INDEX && index < SCENARIO_SOURCE_RCT2_INDEX) { - return SCENARIO_SOURCE_RCT1_LL; - } else if (index >= SCENARIO_SOURCE_RCT2_INDEX && index < SCENARIO_SOURCE_RCT2_WW_INDEX) { - return SCENARIO_SOURCE_RCT2; - } else if (index >= SCENARIO_SOURCE_RCT2_WW_INDEX && index < SCENARIO_SOURCE_RCT2_TT_INDEX) { - return SCENARIO_SOURCE_RCT2_WW; - } else if (index >= SCENARIO_SOURCE_RCT2_TT_INDEX && index < SCENARIO_SOURCE_REAL_INDEX) { - return SCENARIO_SOURCE_RCT2_TT; - } else if (index >= SCENARIO_SOURCE_REAL_INDEX && index < NUM_ORIGINAL_SCENARIOS) { - return SCENARIO_SOURCE_REAL; - } else { - return SCENARIO_SOURCE_OTHER; - } -} - scenario_index_entry *scenario_list_find_by_path(const utf8 *path) { for (int i = 0; i < gScenarioListCount; i++) { diff --git a/src/scenario_sources.c b/src/scenario_sources.c new file mode 100644 index 0000000000..66c140e1ed --- /dev/null +++ b/src/scenario_sources.c @@ -0,0 +1,248 @@ +#include "scenario.h" +#include "util/util.h" + +typedef struct { + const utf8 *original; + const utf8 *alternative; +} scenario_alias; + +const scenario_alias ScenarioAliases[] = { + { "Katie's Dreamland", "Katie's World" }, + { "Pokey Park", "Dinky Park" }, + { "White Water Park", "Aqua Park" }, + { "Mystic Mountain", "Mothball Mountain" }, + { "Paradise Pier", "Big Pier" }, + { "Paradise Pier 2", "Big Pier 2" }, +}; + +// RCT +const utf8 * const ScenarioTitlesRCT1[] = { + "Forest Frontiers", + "Dynamite Dunes", + "Leafy Lake", + "Diamond Heights", + "Evergreen Gardens", + "Bumbly Beach", + "Trinity Islands", + "Katie's Dreamland", + "Pokey Park", + "White Water Park", + "Millennium Mines", + "Karts & Coasters", + "Mel's World", + "Mystic Mountain", + "Pacific Pyramids", + "Crumbly Woods", + "Paradise Pier", + "Lightning Peaks", + "Ivory Towers", + "Rainbow Valley", + "Thunder Rock", + "Mega Park", +}; + +// RCT: Added Attractions +const utf8 * const ScenarioTitlesRCT1AA[] = { + "Whispering Cliffs", + "Three Monkeys Park", + "Canary Mines", + "Barony Bridge", + "Funtopia", + "Haunted Harbor", + "Fun Fortress", + "Future World", + "Gentle Glen", + "Jolly Jungle", + "Hydro Hills", + "Sprightly Park", + "Magic Quarters", + "Fruit Farm", + "Butterfly Dam", + "Coaster Canyon", + "Thunderstorm Park", + "Harmonic Hills", + "Roman Village", + "Swamp Cove", + "Adrenaline Heights", + "Utopia", + "Rotting Heights", + "Fiasco Forest", + "Pickle Park", + "Giggle Downs", + "Mineral Park", + "Coaster Crazy", + "Urban Park", + "Geoffrey Gardens", +}; + +// RCT: Loopy Landscapes +const utf8 * const ScenarioTitlesRCT1LL[] = { + "Iceberg Islands", + "Volcania", + "Arid Heights", + "Razor Rocks", + "Crater Lake", + "Vertigo Views", + "Paradise Pier 2", + "Dragon's Cove", + "Good Knight Park", + "Wacky Warren", + "Grand Glacier", + "Crazy Craters", + "Dusty Desert", + "Woodworm Park", + "Icarus Park", + "Sunny Swamps", + "Frightmare Hills", + "Thunder Rocks", + "Octagon Park", + "Pleasure Island", + "Icicle Worlds", + "Tiny Towers", + "Southern Sands", + "Nevermore Park", + "Pacifica", + "Urban Jungle", + "Terror Town", + "Megaworld Park", + "Venus Ponds", + "Micro Park", +}; + +// RCT2 +const utf8 * const ScenarioTitlesRCT2[] = { + "Crazy Castle", + "Electric Fields", + "Factory Capers", + "Amity Airfield", + "Botany Breakers", + "Bumbly Bazaar", + "Dusty Greens", + "Fungus Woods", + "Gravity Gardens", + "Infernal Views", + "Alpine Adventures", + "Extreme Heights", + "Ghost Town", + "Lucky Lake", + "Rainbow Summit", +}; + +// RCT2: Wacky Worlds +const utf8 * const ScenarioTitlesRCT2WW[] = { + "Africa - Victoria Falls", + "Asia - Great Wall of China Tourism Enhancement", + "North America - Grand Canyon", + "South America - Rio Carnival", + "Africa - African Diamond Mine", + "Asia - Maharaja Palace", + "Australasia - Ayers Rock", + "Europe - European Cultural Festival", + "North America - Rollercoaster Heaven", + "South America - Inca Lost City", + "Africa - Oasis", + "Antarctic - Ecological Salvage", + "Asia - Japanese Coastal Reclaim", + "Australasia - Fun at the Beach", + "Europe - Renovation", + "N. America - Extreme Hawaiian Island", + "South America - Rain Forest Plateau", +}; + +// RCT2: Time Twister +const utf8 * const ScenarioTitlesRCT2TT[] = { + "Dark Age - Robin Hood", + "Prehistoric - After the Asteroid", + "Roaring Twenties - Prison Island", + "Rock 'n' Roll - Flower Power", + "Dark Age - Castle", + "Future - First Encounters", + "Mythological - Animatronic Film Set", + "Prehistoric - Jurassic Safari", + "Roaring Twenties - Schneider Cup", + "Future - Future World", + "Mythological - Cradle of Civilisation", + "Prehistoric - Stone Age", + "Roaring Twenties - Skyscrapers", + "Rock 'n' Roll - Rock 'n' Roll", +}; + +// Real parks +const utf8 * const ScenarioTitlesRealParks[] = { + "Alton Towers", + "Heide-Park", + "Blackpool Pleasure Beach", + "Six Flags Belgium", + "Six Flags Great Adventure", + "Six Flags Holland", + "Six Flags Magic Mountain", + "Six Flags over Texas", +}; + +// Other parks +const utf8 * const ScenarioTitlesRCT2BuildYourOwnParks[] = { + "Build your own Six Flags Belgium", + "Build your own Six Flags Great Adventure", + "Build your own Six Flags Holland", + "Build your own Six Flags Magic Mountain", + "Build your own Six Flags Park", + "Build your own Six Flags over Texas", +}; + +const struct { + int count; + const utf8 * const * titles; +} ScenarioTitlesBySource[] = { + { countof(ScenarioTitlesRCT1), ScenarioTitlesRCT1 }, + { countof(ScenarioTitlesRCT1AA), ScenarioTitlesRCT1AA }, + { countof(ScenarioTitlesRCT1LL), ScenarioTitlesRCT1LL }, + { countof(ScenarioTitlesRCT2), ScenarioTitlesRCT2 }, + { countof(ScenarioTitlesRCT2WW), ScenarioTitlesRCT2WW }, + { countof(ScenarioTitlesRCT2TT), ScenarioTitlesRCT2TT }, + { countof(ScenarioTitlesRealParks), ScenarioTitlesRealParks }, +}; + +bool scenario_get_index_and_source(const utf8 *name, scenario_source *source, sint32 *index) +{ + sint32 currentIndex = 0; + for (int i = 0; i < countof(ScenarioTitlesBySource); i++) { + for (int j = 0; j < ScenarioTitlesBySource[i].count; j++) { + if (_strcmpi(name, ScenarioTitlesBySource[i].titles[j]) == 0) { + *source = (scenario_source)i; + *index = currentIndex; + return true; + } + currentIndex++; + } + } + + *source = SCENARIO_SOURCE_OTHER; + *index = -1; + return false; +} + +void scenario_normalise_name(utf8 *name) +{ + size_t nameLength = strlen(name); + + // Strip "RCT(1|2)? *" prefix off scenario names. + if (nameLength >= 3 && (name[0] == 'R' && name[1] == 'C' && name[2] == 'T')) { + if (nameLength >= 4 && (name[3] == '1' || name[3] == '2')) { + log_verbose("Stripping RCT/1/2 from name: %s", name); + safe_strncpy(name, name + 4, 64); + } else { + safe_strncpy(name, name + 3, 64); + } + + safe_strtrimleft(name, name, 64); + } + + // American scenario titles should be converted to British name + // Don't worry, names will be translated using language packs later + for (int i = 0; i < countof(ScenarioAliases); i++) { + if (strcmp(ScenarioAliases[i].alternative, name) == 0) { + log_verbose("Found alias: %s; will treat as: %s", name, ScenarioAliases[i].original); + safe_strncpy(name, ScenarioAliases[i].original, 64); + } + } +} diff --git a/src/scenario_sources.h b/src/scenario_sources.h deleted file mode 100644 index 78efee823a..0000000000 --- a/src/scenario_sources.h +++ /dev/null @@ -1,171 +0,0 @@ -#define NUM_ORIGINAL_SCENARIOS 136 -#define NUM_ALIASES 6 - -#define SCENARIO_SOURCE_RCT1_INDEX 0 -#define SCENARIO_SOURCE_RCT1_AA_INDEX 22 -#define SCENARIO_SOURCE_RCT1_LL_INDEX 52 -#define SCENARIO_SOURCE_RCT2_INDEX 82 -#define SCENARIO_SOURCE_RCT2_WW_INDEX 97 -#define SCENARIO_SOURCE_RCT2_TT_INDEX 114 -#define SCENARIO_SOURCE_REAL_INDEX 128 - -const char * const scenario_aliases[NUM_ALIASES * 2] = { - "Katie's Dreamland", "Katie's World", - "Pokey Park", "Dinky Park", - "White Water Park", "Aqua Park", - "Mystic Mountain", "Mothball Mountain", - "Paradise Pier", "Big Pier", - "Paradise Pier 2", "Big Pier 2", -}; - -const char * const original_scenario_names[NUM_ORIGINAL_SCENARIOS] = { - // RCT - "Forest Frontiers", - "Dynamite Dunes", - "Leafy Lake", - "Diamond Heights", - "Evergreen Gardens", - "Bumbly Beach", - "Trinity Islands", - "Katie's Dreamland", - "Pokey Park", - "White Water Park", - "Millennium Mines", - "Karts & Coasters", - "Mel's World", - "Mystic Mountain", - "Pacific Pyramids", - "Crumbly Woods", - "Paradise Pier", - "Lightning Peaks", - "Ivory Towers", - "Rainbow Valley", - "Thunder Rock", - "Mega Park", - - // RCT: Added Attractions - "Whispering Cliffs", - "Three Monkeys Park", - "Canary Mines", - "Barony Bridge", - "Funtopia", - "Haunted Harbor", - "Fun Fortress", - "Future World", - "Gentle Glen", - "Jolly Jungle", - "Hydro Hills", - "Sprightly Park", - "Magic Quarters", - "Fruit Farm", - "Butterfly Dam", - "Coaster Canyon", - "Thunderstorm Park", - "Harmonic Hills", - "Roman Village", - "Swamp Cove", - "Adrenaline Heights", - "Utopia Park", - "Rotting Heights", - "Fiasco Forest", - "Pickle Park", - "Giggle Downs", - "Mineral Park", - "Coaster Crazy", - "Urban Park", - "Geoffrey Gardens", - - // RCT: Loopy Landscapes - "Iceberg Islands", - "Volcania", - "Arid Heights", - "Razor Rocks", - "Crater Lake", - "Vertigo Views", - "Paradise Pier 2", - "Dragon's Cove", - "Good Knight Park", - "Wacky Warren", - "Grand Glacier", - "Crazy Craters", - "Dusty Desert", - "Woodworm Park", - "Icarus Park", - "Sunny Swamps", - "Frightmare Hills", - "Thunder Rocks", - "Octagon Park", - "Pleasure Island", - "Icicle Worlds", - "Tiny Towers", - "Southern Sands", - "Nevermore Park", - "Pacifica", - "Urban Jungle", - "Terror Town", - "Megaworld Park", - "Venus Ponds", - "Micro Park", - - // RCT2 - "Crazy Castle", - "Electric Fields", - "Factory Capers", - "Amity Airfield", - "Botany Breakers", - "Bumbly Bazaar", - "Dusty Greens", - "Fungus Woods", - "Gravity Gardens", - "Infernal Views", - "Alpine Adventures", - "Extreme Heights", - "Ghost Town", - "Lucky Lake", - "Rainbow Summit", - - // RCT2: Wacky Worlds - "Africa - Victoria Falls", - "Asia - Great Wall of China Tourism Enhancement", - "North America - Grand Canyon", - "South America - Rio Carnival", - "Africa - African Diamond Mine", - "Asia - Maharaja Palace", - "Australasia - Ayers Rock", - "Europe - European Cultural Festival", - "North America - Rollercoaster Heaven", - "South America - Inca Lost City", - "Africa - Oasis", - "Antarctic - Ecological Salvage", - "Asia - Japanese Coastal Reclaim", - "Australasia - Fun at the Beach", - "Europe - Renovation", - "N. America - Extreme Hawaiian Island", - "South America - Rain Forest Plateau", - - // RCT2: Time Twister - "Dark Age - Robin Hood", - "Prehistoric - After the Asteroid", - "Roaring Twenties - Prison Island", - "Rock 'n' Roll - Flower Power", - "Dark Age - Castle", - "Future - First Encounters", - "Mythological - Animatronic Film Set", - "Prehistoric - Jurassic Safari", - "Roaring Twenties - Schneider Cup", - "Future - Future World", - "Mythological - Cradle of Civilisation", - "Prehistoric - Stone Age", - "Roaring Twenties - Skyscrapers", - "Rock 'n' Roll - Rock 'n' Roll", - - // Real parks - "Alton Towers", - "Heide-Park", - "Blackpool Pleasure Beach", - "Six Flags Belgium", - "Six Flags Great Adventure", - "Six Flags Holland", - "Six Flags Magic Mountain", - "Six Flags over Texas" -}; diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index c754a293e6..208b4ae989 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -505,12 +505,12 @@ static void initialise_list_items(rct_window *w) // Category heading rct_string_id headingStringId = STR_NONE; if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { - if (currentHeading != scenario->category) { + if (w->selected_tab != 6 && currentHeading != scenario->category) { currentHeading = scenario->category; headingStringId = STR_BEGINNER_PARKS + currentHeading; } } else { - if (currentHeading != scenario->source_game) { + if (w->selected_tab < 3 && currentHeading != scenario->source_game) { currentHeading = scenario->source_game; headingStringId = STR_SCENARIO_CATEGORY_RCT1 + currentHeading; } From 8aa14f876e9a41bec032026a5e831d5f19c96a45 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 31 Dec 2015 20:08:31 +0000 Subject: [PATCH 49/90] identify highscores using scenario filenames only --- src/scenario.c | 18 +++--------------- src/scenario.h | 2 ++ src/scenario_list.c | 30 +++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/scenario.c b/src/scenario.c index 80b9a61304..6585378823 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -429,13 +429,7 @@ void scenario_success() RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = companyValue; peep_applause(); - uint8 scenarioRoot = SCENARIO_ROOT_RCT2; - scenario_index_entry *scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); - if (scenario == NULL) { - scenarioRoot = SCENARIO_ROOT_USER; - scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); - } - + scenario_index_entry *scenario = scenario_list_find_by_filename(_scenarioFileName); if (scenario != NULL) { // Check if record company value has been broken if (scenario->highscore == NULL || scenario->highscore->company_value < companyValue) { @@ -444,7 +438,7 @@ void scenario_success() } else { scenario_highscore_free(scenario->highscore); } - scenario->highscore->fileNameRoot = scenarioRoot; + scenario->highscore->fileNameRoot = scenario->path_root; scenario->highscore->fileName = (utf8*)path_get_filename(scenario->path); scenario->highscore->name = NULL; scenario->highscore->company_value = companyValue; @@ -464,13 +458,7 @@ void scenario_success() */ void scenario_success_submit_name(const char *name) { - uint8 scenarioRoot = SCENARIO_ROOT_RCT2; - scenario_index_entry *scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); - if (scenario == NULL) { - scenarioRoot = SCENARIO_ROOT_USER; - scenario = scenario_list_find_by_root_path(scenarioRoot, _scenarioFileName); - } - + scenario_index_entry *scenario = scenario_list_find_by_filename(_scenarioFileName); if (scenario != NULL) { money32 scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, money32); if (scenario->highscore->company_value == scenarioWinCompanyValue) { diff --git a/src/scenario.h b/src/scenario.h index d5ba798073..d186a1dbc4 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -428,6 +428,7 @@ typedef struct { } scenario_highscore_entry; typedef struct { + uint8 path_root; utf8 path[MAX_PATH]; // Category / sequence @@ -463,6 +464,7 @@ extern int gFirstTimeSave; bool scenario_scores_save(); void scenario_load_list(); void scenario_list_dispose(); +scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename); scenario_index_entry *scenario_list_find_by_path(const utf8 *path); scenario_index_entry *scenario_list_find_by_root_path(uint8 root, const utf8 *filename); scenario_highscore_entry *scenario_highscore_insert(); diff --git a/src/scenario_list.c b/src/scenario_list.c index ed7e7d747c..aec4895635 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -33,8 +33,8 @@ int gScenarioHighscoreListCount = 0; int gScenarioHighscoreListCapacity = 0; scenario_highscore_entry *gScenarioHighscoreList = NULL; -static void scenario_list_include(const utf8 *directory); -static void scenario_list_add(const char *path); +static void scenario_list_include(uint8 pathRoot, const utf8 *directory); +static void scenario_list_add(uint8 pathRoot, const char *path); static void scenario_list_sort(); static int scenario_list_sort_by_name(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); @@ -59,18 +59,18 @@ void scenario_load_list() // Get scenario directory from RCT2 safe_strncpy(directory, gConfigGeneral.game_path, sizeof(directory)); safe_strcat_path(directory, "Scenarios", sizeof(directory)); - scenario_list_include(directory); + scenario_list_include(SCENARIO_ROOT_RCT2, directory); // Get scenario directory from user directory platform_get_user_directory(directory, "scenario"); - scenario_list_include(directory); + scenario_list_include(SCENARIO_ROOT_USER, directory); scenario_list_sort(); scenario_scores_load(); scenario_scores_legacy_load(); } -static void scenario_list_include(const utf8 *directory) +static void scenario_list_include(uint8 pathRoot, const utf8 *directory) { int handle; file_info fileInfo; @@ -85,7 +85,7 @@ static void scenario_list_include(const utf8 *directory) utf8 path[MAX_PATH]; safe_strncpy(path, directory, sizeof(pattern)); safe_strcat_path(path, fileInfo.path, sizeof(pattern)); - scenario_list_add(path); + scenario_list_add(pathRoot, path); } platform_enumerate_files_end(handle); @@ -96,12 +96,12 @@ static void scenario_list_include(const utf8 *directory) utf8 path[MAX_PATH]; safe_strncpy(path, directory, sizeof(pattern)); safe_strcat_path(path, subDirectory, sizeof(pattern)); - scenario_list_include(path); + scenario_list_include(pathRoot, path); } platform_enumerate_directories_end(handle); } -static void scenario_list_add(const utf8 *path) +static void scenario_list_add(uint8 pathRoot, const utf8 *path) { // Load the basic scenario information rct_s6_header s6Header; @@ -119,6 +119,7 @@ static void scenario_list_add(const utf8 *path) gScenarioListCount++; // Set new entry + newEntry->path_root = pathRoot; safe_strncpy(newEntry->path, path, sizeof(newEntry->path)); newEntry->category = s6Info.category; newEntry->flags = SCENARIO_FLAGS_VISIBLE; @@ -181,6 +182,17 @@ static int scenario_list_sort_by_index(const void *a, const void *b) return entryA->source_index - entryB->source_index; } +scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename) +{ + for (int i = 0; i < gScenarioListCount; i++) { + const utf8 *scenarioFilename = path_get_filename(gScenarioList[i].path); + if (_strcmpi(filename, scenarioFilename) == 0) { + return &gScenarioList[i]; + } + } + return NULL; +} + scenario_index_entry *scenario_list_find_by_path(const utf8 *path) { for (int i = 0; i < gScenarioListCount; i++) { @@ -336,7 +348,7 @@ static bool scenario_scores_load() SDL_RWread(file, &highscore->company_value, sizeof(highscore->company_value), 1); // Attach highscore to correct scenario entry - scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_root_path(highscore->fileNameRoot, highscore->fileName); + scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_filename(highscore->fileName); if (scenarioIndexEntry != NULL) { scenarioIndexEntry->highscore = highscore; } From 95ee0be3c51dd04b349dfdf0730997d1fe5f6e43 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 31 Dec 2015 21:13:49 +0000 Subject: [PATCH 50/90] handle scenario conflicts --- src/scenario.c | 1 - src/scenario.h | 10 +-- src/scenario_list.c | 101 +++++++++++++++-------------- src/windows/options.c | 3 +- src/windows/title_scenarioselect.c | 82 +++++++++++++---------- 5 files changed, 101 insertions(+), 96 deletions(-) diff --git a/src/scenario.c b/src/scenario.c index 6585378823..a764a6140d 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -438,7 +438,6 @@ void scenario_success() } else { scenario_highscore_free(scenario->highscore); } - scenario->highscore->fileNameRoot = scenario->path_root; scenario->highscore->fileName = (utf8*)path_get_filename(scenario->path); scenario->highscore->name = NULL; scenario->highscore->company_value = companyValue; diff --git a/src/scenario.h b/src/scenario.h index d186a1dbc4..0748172cbb 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -421,18 +421,16 @@ enum { }; typedef struct { - uint8 fileNameRoot; utf8 *fileName; utf8 *name; money32 company_value; } scenario_highscore_entry; typedef struct { - uint8 path_root; utf8 path[MAX_PATH]; + uint64 timestamp; // Category / sequence - uint8 flags; uint8 category; uint8 source_game; sint16 source_index; @@ -448,11 +446,6 @@ typedef struct { utf8 details[256]; } scenario_index_entry; -enum { - SCENARIO_ROOT_RCT2, - SCENARIO_ROOT_USER, -}; - // Scenario list extern int gScenarioListCount; extern int gScenarioListCapacity; @@ -466,7 +459,6 @@ void scenario_load_list(); void scenario_list_dispose(); scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename); scenario_index_entry *scenario_list_find_by_path(const utf8 *path); -scenario_index_entry *scenario_list_find_by_root_path(uint8 root, const utf8 *filename); scenario_highscore_entry *scenario_highscore_insert(); void scenario_highscore_free(scenario_highscore_entry *highscore); int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info); diff --git a/src/scenario_list.c b/src/scenario_list.c index aec4895635..86ec20f150 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -33,14 +33,15 @@ int gScenarioHighscoreListCount = 0; int gScenarioHighscoreListCapacity = 0; scenario_highscore_entry *gScenarioHighscoreList = NULL; -static void scenario_list_include(uint8 pathRoot, const utf8 *directory); -static void scenario_list_add(uint8 pathRoot, const char *path); +static void scenario_list_include(const utf8 *directory); +static void scenario_list_add(const utf8 *path, uint64 timestamp); static void scenario_list_sort(); static int scenario_list_sort_by_name(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); static bool scenario_scores_load(); -static bool scenario_scores_legacy_load(); +static void scenario_scores_legacy_get_path(utf8 *outPath); +static bool scenario_scores_legacy_load(const utf8 *path); static void scenario_highscore_remove(scenario_highscore_entry *higscore); static void scenario_highscore_list_dispose(); static utf8 *io_read_string(SDL_RWops *file); @@ -59,18 +60,23 @@ void scenario_load_list() // Get scenario directory from RCT2 safe_strncpy(directory, gConfigGeneral.game_path, sizeof(directory)); safe_strcat_path(directory, "Scenarios", sizeof(directory)); - scenario_list_include(SCENARIO_ROOT_RCT2, directory); + scenario_list_include(directory); // Get scenario directory from user directory platform_get_user_directory(directory, "scenario"); - scenario_list_include(SCENARIO_ROOT_USER, directory); + scenario_list_include(directory); scenario_list_sort(); scenario_scores_load(); - scenario_scores_legacy_load(); + + + utf8 scoresPath[MAX_PATH]; + scenario_scores_legacy_get_path(scoresPath); + scenario_scores_legacy_load(scoresPath); + scenario_scores_legacy_load(get_file_path(PATH_ID_SCORES)); } -static void scenario_list_include(uint8 pathRoot, const utf8 *directory) +static void scenario_list_include(const utf8 *directory) { int handle; file_info fileInfo; @@ -85,7 +91,7 @@ static void scenario_list_include(uint8 pathRoot, const utf8 *directory) utf8 path[MAX_PATH]; safe_strncpy(path, directory, sizeof(pattern)); safe_strcat_path(path, fileInfo.path, sizeof(pattern)); - scenario_list_add(pathRoot, path); + scenario_list_add(path, fileInfo.last_modified); } platform_enumerate_files_end(handle); @@ -96,12 +102,12 @@ static void scenario_list_include(uint8 pathRoot, const utf8 *directory) utf8 path[MAX_PATH]; safe_strncpy(path, directory, sizeof(pattern)); safe_strcat_path(path, subDirectory, sizeof(pattern)); - scenario_list_include(pathRoot, path); + scenario_list_include(path); } platform_enumerate_directories_end(handle); } -static void scenario_list_add(uint8 pathRoot, const utf8 *path) +static void scenario_list_add(const utf8 *path, uint64 timestamp) { // Load the basic scenario information rct_s6_header s6Header; @@ -110,19 +116,44 @@ static void scenario_list_add(uint8 pathRoot, const utf8 *path) return; } - // Increase cache size - if (gScenarioListCount == gScenarioListCapacity) { - gScenarioListCapacity = max(8, gScenarioListCapacity * 2); - gScenarioList = (scenario_index_entry*)realloc(gScenarioList, gScenarioListCapacity * sizeof(scenario_index_entry)); + scenario_index_entry *newEntry = NULL; + + const utf8 *filename = path_get_filename(path); + scenario_index_entry *existingEntry = scenario_list_find_by_filename(filename); + if (existingEntry != NULL) { + bool bail = false; + const utf8 *conflictPath; + if (existingEntry->timestamp > timestamp) { + // Existing entry is more recent + conflictPath = existingEntry->path; + + // Overwrite existing entry with this one + newEntry = existingEntry; + } else { + // This entry is more recent + conflictPath = path; + bail = true; + } + printf("Scenario conflict: '%s' ignored because it is newer.\n", conflictPath); + if (bail) { + return; + } + } + + if (newEntry == NULL) { + // Increase list size + if (gScenarioListCount == gScenarioListCapacity) { + gScenarioListCapacity = max(8, gScenarioListCapacity * 2); + gScenarioList = (scenario_index_entry*)realloc(gScenarioList, gScenarioListCapacity * sizeof(scenario_index_entry)); + } + newEntry = &gScenarioList[gScenarioListCount]; + gScenarioListCount++; } - scenario_index_entry *newEntry = &gScenarioList[gScenarioListCount]; - gScenarioListCount++; // Set new entry - newEntry->path_root = pathRoot; safe_strncpy(newEntry->path, path, sizeof(newEntry->path)); + newEntry->timestamp = timestamp; newEntry->category = s6Info.category; - newEntry->flags = SCENARIO_FLAGS_VISIBLE; newEntry->objective_type = s6Info.objective_type; newEntry->objective_arg_1 = s6Info.objective_arg_1; newEntry->objective_arg_2 = s6Info.objective_arg_2; @@ -203,22 +234,6 @@ scenario_index_entry *scenario_list_find_by_path(const utf8 *path) return NULL; } -scenario_index_entry *scenario_list_find_by_root_path(uint8 root, const utf8 *filename) -{ - // Derive path - utf8 path[MAX_PATH]; - if (root == SCENARIO_ROOT_RCT2) { - safe_strncpy(path, gConfigGeneral.game_path, sizeof(path)); - safe_strcat_path(path, "Scenarios", sizeof(path)); - } else { - platform_get_user_directory(path, "scenario"); - } - safe_strcat_path(path, filename, sizeof(path)); - - // Find matching scenario entry - return scenario_list_find_by_path(path); -} - /** * Gets the path for the scenario scores path. */ @@ -241,18 +256,12 @@ static void scenario_scores_legacy_get_path(utf8 *outPath) * Loads the original scores.dat file and replaces any highscores that * are better for matching scenarios. */ -static bool scenario_scores_legacy_load() +static bool scenario_scores_legacy_load(const utf8 *path) { - utf8 scoresPath[MAX_PATH]; - scenario_scores_legacy_get_path(scoresPath); - // First check user folder and then fallback to install directory - SDL_RWops *file = SDL_RWFromFile(scoresPath, "rb"); + SDL_RWops *file = SDL_RWFromFile(path, "rb"); if (file == NULL) { - file = SDL_RWFromFile(get_file_path(PATH_ID_SCORES), "rb"); - if (file == NULL) { - return false; - } + return false; } // Load header @@ -278,7 +287,7 @@ static bool scenario_scores_legacy_load() } // Find matching scenario entry - scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_root_path(SCENARIO_ROOT_RCT2, scBasic.path); + scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_filename(scBasic.path); if (scenarioIndexEntry != NULL) { // Check if legacy highscore is better scenario_highscore_entry *highscore = scenarioIndexEntry->highscore; @@ -294,7 +303,6 @@ static bool scenario_scores_legacy_load() // Set new highscore if (highscore != NULL) { - highscore->fileNameRoot = SCENARIO_ROOT_RCT2; highscore->fileName = _strdup(scBasic.path); highscore->name = _strdup(scBasic.completed_by); highscore->company_value = (money32)scBasic.company_value; @@ -341,8 +349,6 @@ static bool scenario_scores_load() // Read highscores for (int i = 0; i < gScenarioHighscoreListCount; i++) { scenario_highscore_entry *highscore = &gScenarioHighscoreList[i]; - - SDL_RWread(file, &highscore->fileNameRoot, sizeof(highscore->fileNameRoot), 1); highscore->fileName = io_read_string(file); highscore->name = io_read_string(file); SDL_RWread(file, &highscore->company_value, sizeof(highscore->company_value), 1); @@ -379,7 +385,6 @@ bool scenario_scores_save() SDL_RWwrite(file, &gScenarioHighscoreListCount, sizeof(gScenarioHighscoreListCount), 1); for (int i = 0; i < gScenarioHighscoreListCount; i++) { scenario_highscore_entry *highscore = &gScenarioHighscoreList[i]; - SDL_RWwrite(file, &highscore->fileNameRoot, sizeof(highscore->fileNameRoot), 1); io_write_string(file, highscore->fileName); io_write_string(file, highscore->name); SDL_RWwrite(file, &highscore->company_value, sizeof(highscore->company_value), 1); diff --git a/src/windows/options.c b/src/windows/options.c index 173aa49445..650e6e07ee 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -664,8 +664,7 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) case WIDX_DEBUGGING_TOOLS: gConfigGeneral.debugging_tools ^= 1; config_save_default(); - window_invalidate(w); - window_invalidate_by_class(WC_TOP_TOOLBAR); + gfx_invalidate_screen(); break; case WIDX_TEST_UNFINISHED_TRACKS: gConfigGeneral.test_unfinished_tracks ^= 1; diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 208b4ae989..1b6e706acf 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -187,14 +187,12 @@ static void window_scenarioselect_init_tabs() int show_pages = 0; for (int i = 0; i < gScenarioListCount; i++) { scenario_index_entry *scenario = &gScenarioList[i]; - if (scenario->flags & SCENARIO_FLAGS_VISIBLE) { if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { show_pages |= 1 << scenario->source_game; } else { show_pages |= 1 << scenario->category; } } - } int x = 3; for (int i = 0; i < 8; i++) { @@ -220,7 +218,7 @@ static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex) { if (widgetIndex == WIDX_CLOSE) { window_close(w); -} + } } static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) @@ -263,18 +261,18 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex switch (listItem->type) { case LIST_ITEM_TYPE_HEADING: y -= 18; - break; + break; case LIST_ITEM_TYPE_SCENARIO: - y -= 24; + y -= 24; if (y < 0 && !listItem->scenario.is_locked) { - audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0); + audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0); scenario_load_and_play_from_path(listItem->scenario.scenario->path); } - break; - } + break; + } if (y < 0) { break; -} + } } } @@ -295,11 +293,11 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex if (y < 0 && !listItem->scenario.is_locked) { selected = listItem->scenario.scenario; } - break; + break; } if (y < 0) { - break; - } + break; + } } if (w->highlighted_item != (uint32)selected) { @@ -329,7 +327,9 @@ static void window_scenarioselect_invalidate(rct_window *w) int windowHeight = w->height; window_scenarioselect_widgets[WIDX_BACKGROUND].bottom = windowHeight - 1; window_scenarioselect_widgets[WIDX_TABCONTENT].bottom = windowHeight - 1; - window_scenarioselect_widgets[WIDX_SCENARIOLIST].bottom = windowHeight - 5; + + const int bottomMargin = gConfigGeneral.debugging_tools ? 17 : 5; + window_scenarioselect_widgets[WIDX_SCENARIOLIST].bottom = windowHeight - bottomMargin; } static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -364,6 +364,12 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) if (scenario == NULL) return; + // Scenario path + if (gConfigGeneral.debugging_tools) { + const utf8 *path = scenario->path; + gfx_draw_string_left(dpi, 1170, (void*)&path, w->colours[1], w->x + 3, w->y + w->height - 3 - 11); + } + // Scenario name x = w->x + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right + 4; y = w->y + window_scenarioselect_widgets[WIDX_TABCONTENT].top + 5; @@ -386,7 +392,11 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) // Scenario score if (scenario->highscore != NULL) { - safe_strncpy((char*)0x009BC677, scenario->highscore->name, 64); + const utf8 *completedByName = "???"; + if (!str_is_null_or_empty(scenario->highscore->name)) { + completedByName = scenario->highscore->name; + } + safe_strncpy((char*)0x009BC677, completedByName, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, int) = scenario->highscore->company_value; y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0); @@ -421,36 +431,40 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * y += 18; break; case LIST_ITEM_TYPE_SCENARIO:; - // Draw hover highlight + // Draw hover highlight scenario_index_entry *scenario = listItem->scenario.scenario; bool isHighlighted = w->highlighted_item == (uint32)scenario; if (isHighlighted) { - gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); - } + gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); + } bool isCompleted = scenario->highscore != NULL; bool isDisabled = listItem->scenario.is_locked; - // Draw scenario name - rct_string_id placeholderStringId = 3165; - safe_strncpy((char*)language_get_string(placeholderStringId), scenario->name, 64); + // Draw scenario name + rct_string_id placeholderStringId = 3165; + safe_strncpy((char*)language_get_string(placeholderStringId), scenario->name, 64); int format = isDisabled ? 865 : (isHighlighted ? highlighted_format : unhighlighted_format); colour = isDisabled ? w->colours[1] | 0x40 : COLOUR_BLACK; - gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, &placeholderStringId); + gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, &placeholderStringId); - // Check if scenario is completed + // Check if scenario is completed if (isCompleted) { - // Draw completion tick - gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0); + // Draw completion tick + gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0); - // Draw completion score - safe_strncpy((char*)language_get_string(placeholderStringId), scenario->highscore->name, 64); - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = 2793; - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, rct_string_id) = placeholderStringId; - gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); - } + // Draw completion score + const utf8 *completedByName = "???"; + if (!str_is_null_or_empty(scenario->highscore->name)) { + completedByName = scenario->highscore->name; + } + safe_strncpy((char*)language_get_string(placeholderStringId), completedByName, 64); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = 2793; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, rct_string_id) = placeholderStringId; + gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + } - y += 24; + y += 24; break; } } @@ -482,7 +496,7 @@ static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, int lef lineY++; gfx_draw_line(dpi, left, lineY, strLeft, lineY, darkColour); gfx_draw_line(dpi, strRight, lineY, right, lineY, darkColour); - } +} static void initialise_list_items(rct_window *w) { @@ -560,10 +574,6 @@ static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario) return false; } - if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE)) { - return false; - } - return true; } From bb84558ae394c9a2b9c12122cc5e021c473546ca Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 31 Dec 2015 22:11:36 +0000 Subject: [PATCH 51/90] fix localisation issues with scenarios --- src/scenario.c | 53 +++++++----------------------------------- src/scenario.h | 2 +- src/scenario_list.c | 29 ++++++++++++++++++++++- src/scenario_sources.c | 7 +++--- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/scenario.c b/src/scenario.c index a764a6140d..46c627731f 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -58,13 +58,11 @@ static void scenario_objective_check(); * Loads only the basic information from a scenario. * rct2: 0x006761D6 */ -int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info) +bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info) { - SDL_RWops* rw; - log_verbose("loading scenario details, %s", path); - rw = SDL_RWFromFile(path, "rb"); + SDL_RWops* rw = SDL_RWFromFile(path, "rb"); if (rw != NULL) { // Read first chunk sawyercoding_read_chunk(rw, (uint8*)header); @@ -72,49 +70,16 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in // Read second chunk sawyercoding_read_chunk(rw, (uint8*)info); SDL_RWclose(rw); - RCT2_GLOBAL(0x009AA00C, uint8) = 0; - - // Get filename - utf8 filename[MAX_PATH]; - const char *temp_filename = path_get_filename(path); - int len = strnlen(temp_filename, MAX_PATH); - safe_strncpy(filename, temp_filename, MAX_PATH); - if (len == MAX_PATH) - { - filename[MAX_PATH - 1] = '\0'; - log_warning("truncated string %s", filename); - } - path_remove_extension(filename); - - rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(filename, localisedStringIds)) { - if (localisedStringIds[0] != (rct_string_id)STR_NONE) { - safe_strncpy(info->name, language_get_string(localisedStringIds[0]), 64); - } - if (localisedStringIds[2] != (rct_string_id)STR_NONE) { - safe_strncpy(info->details, language_get_string(localisedStringIds[2]), 256); - } - } else { - // Checks for a scenario string object (possibly for localisation) - if ((info->entry.flags & 0xFF) != 255) { - if (object_get_scenario_text(&info->entry)) { - rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); - format_string(info->name, stex_entry->scenario_name, NULL); - format_string(info->details, stex_entry->details, NULL); - RCT2_GLOBAL(0x009AA00C, uint8) = stex_entry->var_06; - object_free_scenario_text(); - } - } - } - return 1; + return true; + } else { + log_error("invalid scenario, %s", path); + SDL_RWclose(rw); + return false; } - SDL_RWclose(rw); } - log_error("invalid scenario, %s", path); - // RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, sint8) = -1; - // RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, sint16) = 3011; - return 0; + log_error("unable to open scenario, %s", path); + return false; } /** diff --git a/src/scenario.h b/src/scenario.h index 0748172cbb..0092db6802 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -461,7 +461,7 @@ scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename); scenario_index_entry *scenario_list_find_by_path(const utf8 *path); scenario_highscore_entry *scenario_highscore_insert(); void scenario_highscore_free(scenario_highscore_entry *highscore); -int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info); +bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info); int scenario_load(const char *path); int scenario_load_and_play_from_path(const char *path); void scenario_begin(); diff --git a/src/scenario_list.c b/src/scenario_list.c index 86ec20f150..fc5ddd41ec 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -20,9 +20,10 @@ #include "addresses.h" #include "config.h" +#include "localisation/localisation.h" #include "platform/platform.h" -#include "util/util.h" #include "scenario.h" +#include "util/util.h" // Scenario list int gScenarioListCount = 0; @@ -171,6 +172,32 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) scenario_get_index_and_source(newEntry->name, &source, &index); newEntry->source_index = index; newEntry->source_game = source; + + // Translate scenario name and details + utf8 filenameWithoutExtension[MAX_PATH]; + safe_strncpy(filenameWithoutExtension, filename, sizeof(filenameWithoutExtension)); + path_remove_extension(filenameWithoutExtension); + + rct_string_id localisedStringIds[3]; + if (language_get_localised_scenario_strings(filename, localisedStringIds)) { + if (localisedStringIds[0] != (rct_string_id)STR_NONE) { + safe_strncpy(newEntry->name, language_get_string(localisedStringIds[0]), 64); + } + if (localisedStringIds[2] != (rct_string_id)STR_NONE) { + safe_strncpy(newEntry->details, language_get_string(localisedStringIds[2]), 256); + } + } else { + // Checks for a scenario string object (possibly for localisation) + if ((s6Info.entry.flags & 0xFF) != 255) { + if (object_get_scenario_text(&s6Info.entry)) { + rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); + format_string(newEntry->name, stex_entry->scenario_name, NULL); + format_string(newEntry->details, stex_entry->details, NULL); + object_free_scenario_text(); + } + } + } + } void scenario_list_dispose() diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 66c140e1ed..116ec3cc48 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -225,7 +225,7 @@ void scenario_normalise_name(utf8 *name) { size_t nameLength = strlen(name); - // Strip "RCT(1|2)? *" prefix off scenario names. + // Strip "RCT(1|2)?" prefix off scenario names. if (nameLength >= 3 && (name[0] == 'R' && name[1] == 'C' && name[2] == 'T')) { if (nameLength >= 4 && (name[3] == '1' || name[3] == '2')) { log_verbose("Stripping RCT/1/2 from name: %s", name); @@ -233,9 +233,10 @@ void scenario_normalise_name(utf8 *name) } else { safe_strncpy(name, name + 3, 64); } - - safe_strtrimleft(name, name, 64); } + + // Trim (for the sake of the above and WW / TT scenarios + safe_strtrimleft(name, name, 64); // American scenario titles should be converted to British name // Don't worry, names will be translated using language packs later From 950722292cc70a33acdd404189f454e6fd9fef13 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 02:18:06 +0000 Subject: [PATCH 52/90] use user path for default scenario save location --- src/windows/loadsave.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index 8356f6a2b6..0a665ef22a 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -220,21 +220,12 @@ rct_window *window_loadsave_open(int type, char *defaultName) window_loadsave_populate_list(w, includeNewItem, path, ".sc6"); break; case LOADSAVETYPE_SCENARIO: - /* - Uncomment when user scenarios are separated - platform_get_user_directory(path, "scenario"); if (!platform_ensure_directory_exists(path)) { - log_error("Unable to create scenarios directory."); - window_close(w); - return NULL; + log_error("Unable to create scenarios directory."); + window_close(w); + return NULL; } - */ - - safe_strncpy(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), MAX_PATH); - ch = strchr(path, '*'); - if (ch != NULL) - *ch = 0; window_loadsave_populate_list(w, includeNewItem, path, ".sc6"); break; From 6747f202381718f8f721d74c52e02b9869b8b4a1 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 13:29:13 +0000 Subject: [PATCH 53/90] hardcode difficulty for original scenarios --- src/editor.c | 4 +- src/scenario.h | 10 +- src/scenario_list.c | 20 ++- src/scenario_sources.c | 324 +++++++++++++++++++++-------------------- 4 files changed, 191 insertions(+), 167 deletions(-) diff --git a/src/editor.c b/src/editor.c index 7b566001ca..a9fc456a8d 100644 --- a/src/editor.c +++ b/src/editor.c @@ -138,7 +138,7 @@ void editor_convert_save_to_scenario_callback(int result) RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_SCENARIO_EDITOR; s6Info->editor_step = EDITOR_STEP_OBJECTIVE_SELECTION; - s6Info->category = SCENARIO_CATEGORY_BUILDYOUROWN; + s6Info->category = SCENARIO_CATEGORY_OTHER; viewport_init_all(); news_item_init_queue(); window_editor_main_open(); @@ -328,7 +328,7 @@ static int editor_read_s6(const char *path) s6Info->editor_step = EDITOR_STEP_LANDSCAPE_EDITOR; } else { s6Info->editor_step = EDITOR_STEP_LANDSCAPE_EDITOR; - s6Info->category = SCENARIO_CATEGORY_BUILDYOUROWN; + s6Info->category = SCENARIO_CATEGORY_OTHER; format_string(s6Info->details, STR_NO_DETAILS_YET, NULL); } diff --git a/src/scenario.h b/src/scenario.h index 0092db6802..a113f78460 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -402,7 +402,7 @@ enum { SCENARIO_CATEGORY_CHALLENGING, SCENARIO_CATEGORY_EXPERT, SCENARIO_CATEGORY_REAL, - SCENARIO_CATEGORY_BUILDYOUROWN + SCENARIO_CATEGORY_OTHER }; enum { @@ -446,6 +446,12 @@ typedef struct { utf8 details[256]; } scenario_index_entry; +typedef struct { + uint8 source; + sint32 index; + uint8 category; +} source_desc; + // Scenario list extern int gScenarioListCount; extern int gScenarioListCapacity; @@ -478,7 +484,7 @@ void scenario_success(); void scenario_success_submit_name(const char *name); void scenario_autosave_check(); -bool scenario_get_index_and_source(const utf8 *name, scenario_source *source, sint32 *index); +bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc); void scenario_normalise_name(utf8 *name); #endif diff --git a/src/scenario_list.c b/src/scenario_list.c index fc5ddd41ec..d1329dafa5 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -167,11 +167,15 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) scenario_normalise_name(newEntry->name); // Look up and store information regarding the origins of this scenario. - scenario_source source; - sint32 index; - scenario_get_index_and_source(newEntry->name, &source, &index); - newEntry->source_index = index; - newEntry->source_game = source; + source_desc desc; + if (scenario_get_source_desc(newEntry->name, &desc)) { + newEntry->source_index = desc.index; + newEntry->source_game = desc.source; + newEntry->category = desc.category; + } else { + newEntry->source_index = -1; + newEntry->source_game = SCENARIO_SOURCE_OTHER; + } // Translate scenario name and details utf8 filenameWithoutExtension[MAX_PATH]; @@ -235,7 +239,11 @@ static int scenario_list_sort_by_index(const void *a, const void *b) const scenario_index_entry *entryB = (const scenario_index_entry*)b; if (entryA->source_game == SCENARIO_SOURCE_OTHER && entryB->source_game == SCENARIO_SOURCE_OTHER) { - return scenario_list_sort_by_name(a, b); + if (entryA->category == entryB->category) { + return scenario_list_sort_by_name(a, b); + } else { + return entryA->category - entryB->category; + } } return entryA->source_index - entryB->source_index; } diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 116ec3cc48..faacb06d34 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -15,183 +15,188 @@ const scenario_alias ScenarioAliases[] = { { "Paradise Pier 2", "Big Pier 2" }, }; +typedef struct { + const utf8 *title; + const uint8 category; +} scenario_title_desc; + // RCT -const utf8 * const ScenarioTitlesRCT1[] = { - "Forest Frontiers", - "Dynamite Dunes", - "Leafy Lake", - "Diamond Heights", - "Evergreen Gardens", - "Bumbly Beach", - "Trinity Islands", - "Katie's Dreamland", - "Pokey Park", - "White Water Park", - "Millennium Mines", - "Karts & Coasters", - "Mel's World", - "Mystic Mountain", - "Pacific Pyramids", - "Crumbly Woods", - "Paradise Pier", - "Lightning Peaks", - "Ivory Towers", - "Rainbow Valley", - "Thunder Rock", - "Mega Park", +const scenario_title_desc ScenarioTitlesRCT1[] = { + { "Forest Frontiers", SCENARIO_CATEGORY_BEGINNER }, + { "Dynamite Dunes", SCENARIO_CATEGORY_BEGINNER }, + { "Leafy Lake", SCENARIO_CATEGORY_BEGINNER }, + { "Diamond Heights", SCENARIO_CATEGORY_BEGINNER }, + { "Evergreen Gardens", SCENARIO_CATEGORY_BEGINNER }, + { "Bumbly Beach", SCENARIO_CATEGORY_BEGINNER }, + { "Trinity Islands", SCENARIO_CATEGORY_CHALLENGING }, + { "Katie's Dreamland", SCENARIO_CATEGORY_CHALLENGING }, + { "Pokey Park", SCENARIO_CATEGORY_CHALLENGING }, + { "White Water Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Millennium Mines", SCENARIO_CATEGORY_CHALLENGING }, + { "Karts & Coasters", SCENARIO_CATEGORY_CHALLENGING }, + { "Mel's World", SCENARIO_CATEGORY_CHALLENGING }, + { "Mystic Mountain", SCENARIO_CATEGORY_CHALLENGING }, + { "Pacific Pyramids", SCENARIO_CATEGORY_CHALLENGING }, + { "Crumbly Woods", SCENARIO_CATEGORY_CHALLENGING }, + { "Paradise Pier", SCENARIO_CATEGORY_CHALLENGING }, + { "Lightning Peaks", SCENARIO_CATEGORY_EXPERT }, + { "Ivory Towers", SCENARIO_CATEGORY_EXPERT }, + { "Rainbow Valley", SCENARIO_CATEGORY_EXPERT }, + { "Thunder Rock", SCENARIO_CATEGORY_EXPERT }, + { "Mega Park", SCENARIO_CATEGORY_OTHER }, }; // RCT: Added Attractions -const utf8 * const ScenarioTitlesRCT1AA[] = { - "Whispering Cliffs", - "Three Monkeys Park", - "Canary Mines", - "Barony Bridge", - "Funtopia", - "Haunted Harbor", - "Fun Fortress", - "Future World", - "Gentle Glen", - "Jolly Jungle", - "Hydro Hills", - "Sprightly Park", - "Magic Quarters", - "Fruit Farm", - "Butterfly Dam", - "Coaster Canyon", - "Thunderstorm Park", - "Harmonic Hills", - "Roman Village", - "Swamp Cove", - "Adrenaline Heights", - "Utopia", - "Rotting Heights", - "Fiasco Forest", - "Pickle Park", - "Giggle Downs", - "Mineral Park", - "Coaster Crazy", - "Urban Park", - "Geoffrey Gardens", +const scenario_title_desc ScenarioTitlesRCT1AA[] = { + { "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER }, + { "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER }, + { "Canary Mines", SCENARIO_CATEGORY_BEGINNER }, + { "Barony Bridge", SCENARIO_CATEGORY_BEGINNER }, + { "Funtopia", SCENARIO_CATEGORY_BEGINNER }, + { "Haunted Harbor", SCENARIO_CATEGORY_BEGINNER }, + { "Fun Fortress", SCENARIO_CATEGORY_BEGINNER }, + { "Future World", SCENARIO_CATEGORY_BEGINNER }, + { "Gentle Glen", SCENARIO_CATEGORY_BEGINNER }, + { "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING }, + { "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING }, + { "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING }, + { "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING }, + { "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING }, + { "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING }, + { "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING }, + { "Roman Village", SCENARIO_CATEGORY_CHALLENGING }, + { "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING }, + { "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING }, + { "Utopia", SCENARIO_CATEGORY_CHALLENGING }, + { "Rotting Heights", SCENARIO_CATEGORY_EXPERT }, + { "Fiasco Forest", SCENARIO_CATEGORY_EXPERT }, + { "Pickle Park", SCENARIO_CATEGORY_EXPERT }, + { "Giggle Downs", SCENARIO_CATEGORY_EXPERT }, + { "Mineral Park", SCENARIO_CATEGORY_EXPERT }, + { "Coaster Crazy", SCENARIO_CATEGORY_EXPERT }, + { "Urban Park", SCENARIO_CATEGORY_EXPERT }, + { "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT }, }; // RCT: Loopy Landscapes -const utf8 * const ScenarioTitlesRCT1LL[] = { - "Iceberg Islands", - "Volcania", - "Arid Heights", - "Razor Rocks", - "Crater Lake", - "Vertigo Views", - "Paradise Pier 2", - "Dragon's Cove", - "Good Knight Park", - "Wacky Warren", - "Grand Glacier", - "Crazy Craters", - "Dusty Desert", - "Woodworm Park", - "Icarus Park", - "Sunny Swamps", - "Frightmare Hills", - "Thunder Rocks", - "Octagon Park", - "Pleasure Island", - "Icicle Worlds", - "Tiny Towers", - "Southern Sands", - "Nevermore Park", - "Pacifica", - "Urban Jungle", - "Terror Town", - "Megaworld Park", - "Venus Ponds", - "Micro Park", +const scenario_title_desc ScenarioTitlesRCT1LL[] = { + { "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER }, + { "Volcania", SCENARIO_CATEGORY_BEGINNER }, + { "Arid Heights", SCENARIO_CATEGORY_BEGINNER }, + { "Razor Rocks", SCENARIO_CATEGORY_BEGINNER }, + { "Crater Lake", SCENARIO_CATEGORY_BEGINNER }, + { "Vertigo Views", SCENARIO_CATEGORY_BEGINNER }, + { "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING }, + { "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING }, + { "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING }, + { "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING }, + { "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING }, + { "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING }, + { "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Icarus Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING }, + { "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING }, + { "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING }, + { "Octagon Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING }, + { "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING }, + { "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, + { "Southern Sands", SCENARIO_CATEGORY_CHALLENGING }, + { "Nevermore Park", SCENARIO_CATEGORY_CHALLENGING }, + { "Pacifica", SCENARIO_CATEGORY_CHALLENGING }, + { "Urban Jungle", SCENARIO_CATEGORY_EXPERT }, + { "Terror Town", SCENARIO_CATEGORY_EXPERT }, + { "Megaworld Park", SCENARIO_CATEGORY_EXPERT }, + { "Venus Ponds", SCENARIO_CATEGORY_EXPERT }, + { "Micro Park", SCENARIO_CATEGORY_EXPERT }, }; // RCT2 -const utf8 * const ScenarioTitlesRCT2[] = { - "Crazy Castle", - "Electric Fields", - "Factory Capers", - "Amity Airfield", - "Botany Breakers", - "Bumbly Bazaar", - "Dusty Greens", - "Fungus Woods", - "Gravity Gardens", - "Infernal Views", - "Alpine Adventures", - "Extreme Heights", - "Ghost Town", - "Lucky Lake", - "Rainbow Summit", +const scenario_title_desc ScenarioTitlesRCT2[] = { + { "Crazy Castle", SCENARIO_CATEGORY_BEGINNER }, + { "Electric Fields", SCENARIO_CATEGORY_BEGINNER }, + { "Factory Capers", SCENARIO_CATEGORY_BEGINNER }, + { "Amity Airfield", SCENARIO_CATEGORY_CHALLENGING }, + { "Botany Breakers", SCENARIO_CATEGORY_CHALLENGING }, + { "Bumbly Bazaar", SCENARIO_CATEGORY_CHALLENGING }, + { "Dusty Greens", SCENARIO_CATEGORY_CHALLENGING }, + { "Fungus Woods", SCENARIO_CATEGORY_CHALLENGING }, + { "Gravity Gardens", SCENARIO_CATEGORY_CHALLENGING }, + { "Infernal Views", SCENARIO_CATEGORY_CHALLENGING }, + { "Alpine Adventures", SCENARIO_CATEGORY_EXPERT }, + { "Extreme Heights", SCENARIO_CATEGORY_EXPERT }, + { "Ghost Town", SCENARIO_CATEGORY_EXPERT }, + { "Lucky Lake", SCENARIO_CATEGORY_EXPERT }, + { "Rainbow Summit", SCENARIO_CATEGORY_EXPERT }, }; // RCT2: Wacky Worlds -const utf8 * const ScenarioTitlesRCT2WW[] = { - "Africa - Victoria Falls", - "Asia - Great Wall of China Tourism Enhancement", - "North America - Grand Canyon", - "South America - Rio Carnival", - "Africa - African Diamond Mine", - "Asia - Maharaja Palace", - "Australasia - Ayers Rock", - "Europe - European Cultural Festival", - "North America - Rollercoaster Heaven", - "South America - Inca Lost City", - "Africa - Oasis", - "Antarctic - Ecological Salvage", - "Asia - Japanese Coastal Reclaim", - "Australasia - Fun at the Beach", - "Europe - Renovation", - "N. America - Extreme Hawaiian Island", - "South America - Rain Forest Plateau", +const scenario_title_desc ScenarioTitlesRCT2WW[] = { + { "Africa - Victoria Falls", SCENARIO_CATEGORY_BEGINNER }, + { "Asia - Great Wall of China Tourism Enhancement", SCENARIO_CATEGORY_BEGINNER }, + { "North America - Grand Canyon", SCENARIO_CATEGORY_BEGINNER }, + { "South America - Rio Carnival", SCENARIO_CATEGORY_BEGINNER }, + { "Africa - African Diamond Mine", SCENARIO_CATEGORY_CHALLENGING }, + { "Asia - Maharaja Palace", SCENARIO_CATEGORY_CHALLENGING }, + { "Australasia - Ayers Rock", SCENARIO_CATEGORY_CHALLENGING }, + { "Europe - European Cultural Festival", SCENARIO_CATEGORY_CHALLENGING }, + { "North America - Rollercoaster Heaven", SCENARIO_CATEGORY_CHALLENGING }, + { "South America - Inca Lost City", SCENARIO_CATEGORY_CHALLENGING }, + { "Africa - Oasis", SCENARIO_CATEGORY_EXPERT }, + { "Antarctic - Ecological Salvage", SCENARIO_CATEGORY_EXPERT }, + { "Asia - Japanese Coastal Reclaim", SCENARIO_CATEGORY_EXPERT }, + { "Australasia - Fun at the Beach", SCENARIO_CATEGORY_EXPERT }, + { "Europe - Renovation", SCENARIO_CATEGORY_EXPERT }, + { "N. America - Extreme Hawaiian Island", SCENARIO_CATEGORY_EXPERT }, + { "South America - Rain Forest Plateau", SCENARIO_CATEGORY_EXPERT }, }; // RCT2: Time Twister -const utf8 * const ScenarioTitlesRCT2TT[] = { - "Dark Age - Robin Hood", - "Prehistoric - After the Asteroid", - "Roaring Twenties - Prison Island", - "Rock 'n' Roll - Flower Power", - "Dark Age - Castle", - "Future - First Encounters", - "Mythological - Animatronic Film Set", - "Prehistoric - Jurassic Safari", - "Roaring Twenties - Schneider Cup", - "Future - Future World", - "Mythological - Cradle of Civilisation", - "Prehistoric - Stone Age", - "Roaring Twenties - Skyscrapers", - "Rock 'n' Roll - Rock 'n' Roll", +const scenario_title_desc ScenarioTitlesRCT2TT[] = { + { "Dark Age - Robin Hood", SCENARIO_CATEGORY_BEGINNER }, + { "Prehistoric - After the Asteroid", SCENARIO_CATEGORY_BEGINNER }, + { "Roaring Twenties - Prison Island", SCENARIO_CATEGORY_BEGINNER }, + { "Rock 'n' Roll - Flower Power", SCENARIO_CATEGORY_BEGINNER }, + { "Dark Age - Castle", SCENARIO_CATEGORY_CHALLENGING }, + { "Future - First Encounters", SCENARIO_CATEGORY_CHALLENGING }, + { "Mythological - Animatronic Film Set", SCENARIO_CATEGORY_CHALLENGING }, + { "Prehistoric - Jurassic Safari", SCENARIO_CATEGORY_CHALLENGING }, + { "Roaring Twenties - Schneider Cup", SCENARIO_CATEGORY_CHALLENGING }, + { "Future - Future World", SCENARIO_CATEGORY_EXPERT }, + { "Mythological - Cradle of Civilisation", SCENARIO_CATEGORY_EXPERT }, + { "Prehistoric - Stone Age", SCENARIO_CATEGORY_EXPERT }, + { "Roaring Twenties - Skyscrapers", SCENARIO_CATEGORY_EXPERT }, + { "Rock 'n' Roll - Rock 'n' Roll", SCENARIO_CATEGORY_EXPERT }, }; // Real parks -const utf8 * const ScenarioTitlesRealParks[] = { - "Alton Towers", - "Heide-Park", - "Blackpool Pleasure Beach", - "Six Flags Belgium", - "Six Flags Great Adventure", - "Six Flags Holland", - "Six Flags Magic Mountain", - "Six Flags over Texas", +const scenario_title_desc ScenarioTitlesRealParks[] = { + { "Alton Towers", SCENARIO_CATEGORY_REAL }, + { "Heide-Park", SCENARIO_CATEGORY_REAL }, + { "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, + { "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, + { "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL }, + { "Six Flags Holland", SCENARIO_CATEGORY_REAL }, + { "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL }, + { "Six Flags over Texas", SCENARIO_CATEGORY_REAL }, }; // Other parks -const utf8 * const ScenarioTitlesRCT2BuildYourOwnParks[] = { - "Build your own Six Flags Belgium", - "Build your own Six Flags Great Adventure", - "Build your own Six Flags Holland", - "Build your own Six Flags Magic Mountain", - "Build your own Six Flags Park", - "Build your own Six Flags over Texas", +const scenario_title_desc ScenarioTitlesRCT2BuildYourOwnParks[] = { + { "Build your own Six Flags Belgium", SCENARIO_CATEGORY_OTHER }, + { "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_OTHER }, + { "Build your own Six Flags Holland", SCENARIO_CATEGORY_OTHER }, + { "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_OTHER }, + { "Build your own Six Flags Park", SCENARIO_CATEGORY_OTHER }, + { "Build your own Six Flags over Texas", SCENARIO_CATEGORY_OTHER }, }; const struct { int count; - const utf8 * const * titles; + const scenario_title_desc * const titles; } ScenarioTitlesBySource[] = { { countof(ScenarioTitlesRCT1), ScenarioTitlesRCT1 }, { countof(ScenarioTitlesRCT1AA), ScenarioTitlesRCT1AA }, @@ -202,22 +207,27 @@ const struct { { countof(ScenarioTitlesRealParks), ScenarioTitlesRealParks }, }; -bool scenario_get_index_and_source(const utf8 *name, scenario_source *source, sint32 *index) +bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) { + assert(outDesc != NULL); + sint32 currentIndex = 0; for (int i = 0; i < countof(ScenarioTitlesBySource); i++) { for (int j = 0; j < ScenarioTitlesBySource[i].count; j++) { - if (_strcmpi(name, ScenarioTitlesBySource[i].titles[j]) == 0) { - *source = (scenario_source)i; - *index = currentIndex; + const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; + if (_strcmpi(name, desc->title) == 0) { + outDesc->source = i; + outDesc->index = currentIndex; + outDesc->category = desc->category; return true; } currentIndex++; } } - *source = SCENARIO_SOURCE_OTHER; - *index = -1; + outDesc->source = SCENARIO_SOURCE_OTHER; + outDesc->index = -1; + outDesc->category = SCENARIO_CATEGORY_OTHER; return false; } From be6f7321d0c9714ac65e0cb341488ec4e94a884e Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 13:32:11 +0000 Subject: [PATCH 54/90] place custom real parks in real parks for source mode --- src/scenario_list.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scenario_list.c b/src/scenario_list.c index d1329dafa5..dce12b9c00 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -174,7 +174,11 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) newEntry->category = desc.category; } else { newEntry->source_index = -1; - newEntry->source_game = SCENARIO_SOURCE_OTHER; + if (newEntry->category == SCENARIO_CATEGORY_REAL) { + newEntry->source_game = SCENARIO_SOURCE_REAL; + } else { + newEntry->source_game = SCENARIO_SOURCE_OTHER; + } } // Translate scenario name and details From f2c5ce32f229f53b5190e4a9046ce6f3e9327016 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 13:46:23 +0000 Subject: [PATCH 55/90] improve options window for scenario options --- src/windows/options.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/windows/options.c b/src/windows/options.c index 650e6e07ee..213f7306e1 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -165,7 +165,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { }; #define WW 310 -#define WH 300 +#define WH 302 #define MAIN_OPTIONS_WIDGETS \ { WWT_FRAME, 0, 0, WW-1, 0, WH-1, STR_NONE, STR_NONE }, \ @@ -256,9 +256,9 @@ static rct_widget window_options_controls_and_interface_widgets[] = { { WWT_CHECKBOX, 2, 155, 299, 229, 240, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_NONE }, // Recent messages { WWT_CHECKBOX, 2, 10, 299, 254, 265, STR_SELECT_BY_TRACK_TYPE, STR_SELECT_BY_TRACK_TYPE_TIP }, // Select by track type - { WWT_DROPDOWN, 2, 155, 299, 267, 278, STR_NONE, STR_NONE }, // Scenario select mode - { WWT_DROPDOWN_BUTTON, 2, 288, 298, 268, 277, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_CHECKBOX, 2, 10, 299, 281, 292, STR_OPTIONS_SCENARIO_UNLOCKING, STR_NONE }, // Unlocking of scenarios + { WWT_DROPDOWN, 2, 155, 299, 269, 280, STR_NONE, STR_NONE }, // Scenario select mode + { WWT_DROPDOWN_BUTTON, 2, 288, 298, 270, 279, STR_DROPDOWN_GLYPH, STR_NONE }, + { WWT_CHECKBOX, 2, 18, 299, 284, 295, STR_OPTIONS_SCENARIO_UNLOCKING, STR_NONE }, // Unlocking of scenarios { WIDGETS_END }, }; @@ -654,7 +654,7 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) case WIDX_SCENARIO_UNLOCKING: gConfigGeneral.scenario_unlocking_enabled ^= 1; config_save_default(); - window_invalidate_by_class(WC_SCENARIO_SELECT); + window_close_by_class(WC_SCENARIO_SELECT); break; } break; @@ -1364,6 +1364,12 @@ static void window_options_invalidate(rct_window *w) widget_set_checkbox_value(w, WIDX_SELECT_BY_TRACK_TYPE, gConfigInterface.select_by_track_type); widget_set_checkbox_value(w, WIDX_SCENARIO_UNLOCKING, gConfigGeneral.scenario_unlocking_enabled); + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { + w->disabled_widgets &= ~(1ULL << WIDX_SCENARIO_UNLOCKING); + } else { + w->disabled_widgets |= (1ULL << WIDX_SCENARIO_UNLOCKING); + } + window_options_controls_and_interface_widgets[WIDX_THEMES].type = WWT_DROPDOWN; window_options_controls_and_interface_widgets[WIDX_THEMES_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_options_controls_and_interface_widgets[WIDX_THEMES_BUTTON].type = WWT_DROPDOWN_BUTTON; @@ -1431,6 +1437,15 @@ static void window_options_invalidate(rct_window *w) window_options_twitch_widgets[WIDX_NEWS_CHECKBOX].type = WWT_CHECKBOX; break; } + + // Automatically adjust window height to fit widgets + int y = 0; + for (widget = &w->widgets[WIDX_PAGE_START]; widget->type != WWT_LAST; widget++) { + y = max(y, widget->bottom); + } + w->height = y + 6; + w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; } static void window_options_update(rct_window *w) From 82b05950ff8847bdfd7b2d54445333e9e86737b2 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 16:30:18 +0000 Subject: [PATCH 56/90] add RCT1 title sequence --- data/title/rct1/script.txt | 98 ++++++++++ data/title/rct1aa/script.txt | 187 +++++++++++++++++++ data/title/rct1aall/script.txt | 233 ++++++++++++++++++++++++ src/config.c | 32 +++- src/interface/title_sequences.c | 11 +- src/scenario.h | 108 +++++++++++ src/scenario_sources.c | 311 +++++++++++++++++--------------- src/title.c | 39 ++++ src/title.h | 3 +- src/windows/options.c | 7 +- 10 files changed, 877 insertions(+), 152 deletions(-) create mode 100644 data/title/rct1/script.txt create mode 100644 data/title/rct1aa/script.txt create mode 100644 data/title/rct1aall/script.txt diff --git a/data/title/rct1/script.txt b/data/title/rct1/script.txt new file mode 100644 index 0000000000..6d9ea69198 --- /dev/null +++ b/data/title/rct1/script.txt @@ -0,0 +1,98 @@ +# RollerCoaster Tycoon 1 Title Sequence + +############################## +# RollerCoaster Tycoon 1 # +############################## +# SC_DIAMOND_HEIGHTS +LOADRCT1 3 +ROTATE 2 +LOCATION 47, 99 +WAIT 15 +ROTATE 2 +LOCATION 90, 48 +WAIT 15 +ROTATE 1 +LOCATION 86, 43 +WAIT 15 +ROTATE 3 +LOCATION 57, 50 +WAIT 15 +ROTATE 2 +LOCATION 86, 64 +WAIT 15 + +# SC_KATIES_DREAMLAND +LOADRCT1 7 +LOCATION 48, 44 +WAIT 15 +LOCATION 64, 41 +WAIT 15 + +# SC_POKEY_PARK, +LOADRCT1 8 +ROTATE 2 +LOCATION 56, 64 +WAIT 15 + +# SC_WHITE_WATER_PARK +LOADRCT1 9 +ROTATE 3 +LOCATION 96, 88 +WAIT 15 +LOCATION 84, 95 +WAIT 15 + +# SC_MILLENNIUM_MINES +LOADRCT1 10 +ROTATE 1 +ROTATE 1 +LOCATION 64, 37 +WAIT 15 + +# SC_KARTS_COASTERS +LOADRCT1 11 +LOCATION 84, 56 +WAIT 15 +LOCATION 34, 36 +WAIT 15 +LOCATION 33, 65 +WAIT 15 + +# SC_MELS_WORLD +LOADRCT1 12 +ROTATE 3 +LOCATION 50, 50 +WAIT 15 +LOCATION 35, 39 +WAIT 15 +ROTATE 3 +LOCATION 62, 39 +WAIT 15 + +# SC_CRUMBLY_WOODS +LOADRCT1 15 +ROTATE 3 +LOCATION 57, 94 +WAIT 15 +LOCATION 44, 84 +WAIT 15 +ROTATE 1 +LOCATION 76, 59 +WAIT 15 +LOCATION 76, 48 +WAIT 15 + +# SC_LIGHTNING_PEAKS +LOADRCT1 17 +LOCATION 80, 49 +WAIT 15 +LOCATION 60, 62 +WAIT 15 + +# SC_IVORY_TOWERS +LOADRCT1 18 +ROTATE 3 +LOCATION 50, 77 +WAIT 15 + +RESTART diff --git a/data/title/rct1aa/script.txt b/data/title/rct1aa/script.txt new file mode 100644 index 0000000000..a3dd850a27 --- /dev/null +++ b/data/title/rct1aa/script.txt @@ -0,0 +1,187 @@ +# RollerCoaster Tycoon 1 Title Sequence + +############################## +# Added Attractions # +############################## +# SC_HAUNTED_HARBOR +LOADRCT1 45 +LOCATION 62, 53 +WAIT 11 +ROTATE 3 +LOCATION 78, 45 +WAIT 16 + +# SC_CANARY_MINES +LOADRCT1 42 +LOCATION 52, 28 +WAIT 15 + +# SC_GENTLE_GLEN +LOADRCT1 48 +LOCATION 68, 45 +WAIT 11 + +# SC_FUNTOPIA +LOADRCT1 44 +LOCATION 69, 93 +WAIT 17 + +# SC_SPRIGHTLY_PARK +LOADRCT1 51 +ROTATE 3 +LOCATION 97, 72 +WAIT 12 +ROTATE 2 +LOCATION 74, 71 +WAIT 12 +ROTATE 2 +LOCATION 67, 90 +WAIT 12 + +# SC_GIGGLE_DOWNS +LOADRCT1 65 +LOCATION 94, 64 +WAIT 10 + +# SC_SWAMP_COVE +LOADRCT1 59 +LOCATION 96, 22 +WAIT 10 +ROTATE 3 +LOCATION 90, 29 +WAIT 10 + +# SC_FRUIT_FARM +LOADRCT1 53 +LOCATION 47, 52 +WAIT 12 + +# SC_FUTURE_WORLD +LOADRCT1 47 +LOCATION 67, 59 +WAIT 19 + +# SC_THREE_MONKEYS_PARK +LOADRCT1 41 +ROTATE 2 +LOCATION 72, 61 +WAIT 8 +ROTATE 2 +LOCATION 68, 70 +WAIT 8 +LOCATION 58, 56 +WAIT 8 +ROTATE 1 +LOCATION 44, 70 +WAIT 8 +ROTATE 3 +LOCATION 43, 90 +WAIT 10 + +# SC_ROMAN_VILLAGE +LOADRCT1 58 +LOCATION 49, 46 +WAIT 15 + +# SC_ADRENALINE_HEIGHTS +LOADRCT1 60 +ROTATE 3 +LOCATION 38, 57 +WAIT 15 + +############################## +# RollerCoaster Tycoon 1 # +############################## +# SC_DIAMOND_HEIGHTS +LOADRCT1 3 +ROTATE 2 +LOCATION 47, 99 +WAIT 15 +ROTATE 2 +LOCATION 90, 48 +WAIT 15 +ROTATE 1 +LOCATION 86, 43 +WAIT 15 +ROTATE 3 +LOCATION 57, 50 +WAIT 15 +ROTATE 2 +LOCATION 86, 64 +WAIT 15 + +# SC_KATIES_DREAMLAND +LOADRCT1 7 +LOCATION 48, 44 +WAIT 15 +LOCATION 64, 41 +WAIT 15 + +# SC_POKEY_PARK, +LOADRCT1 8 +ROTATE 2 +LOCATION 56, 64 +WAIT 15 + +# SC_WHITE_WATER_PARK +LOADRCT1 9 +ROTATE 3 +LOCATION 96, 88 +WAIT 15 +LOCATION 84, 95 +WAIT 15 + +# SC_MILLENNIUM_MINES +LOADRCT1 10 +ROTATE 1 +ROTATE 1 +LOCATION 64, 37 +WAIT 15 + +# SC_KARTS_COASTERS +LOADRCT1 11 +LOCATION 84, 56 +WAIT 15 +LOCATION 34, 36 +WAIT 15 +LOCATION 33, 65 +WAIT 15 + +# SC_MELS_WORLD +LOADRCT1 12 +ROTATE 3 +LOCATION 50, 50 +WAIT 15 +LOCATION 35, 39 +WAIT 15 +ROTATE 3 +LOCATION 62, 39 +WAIT 15 + +# SC_CRUMBLY_WOODS +LOADRCT1 15 +ROTATE 3 +LOCATION 57, 94 +WAIT 15 +LOCATION 44, 84 +WAIT 15 +ROTATE 1 +LOCATION 76, 59 +WAIT 15 +LOCATION 76, 48 +WAIT 15 + +# SC_LIGHTNING_PEAKS +LOADRCT1 17 +LOCATION 80, 49 +WAIT 15 +LOCATION 60, 62 +WAIT 15 + +# SC_IVORY_TOWERS +LOADRCT1 18 +ROTATE 3 +LOCATION 50, 77 +WAIT 15 + +RESTART diff --git a/data/title/rct1aall/script.txt b/data/title/rct1aall/script.txt new file mode 100644 index 0000000000..63a64545c7 --- /dev/null +++ b/data/title/rct1aall/script.txt @@ -0,0 +1,233 @@ +# RollerCoaster Tycoon 1 Title Sequence + +############################## +# Added Attractions (part 1) # +############################## +# SC_HAUNTED_HARBOR +LOADRCT1 45 +LOCATION 62, 53 +WAIT 11 +ROTATE 3 +LOCATION 78, 45 +WAIT 16 + +# SC_CANARY_MINES +LOADRCT1 42 +LOCATION 52, 28 +WAIT 15 + +# SC_GENTLE_GLEN +LOADRCT1 48 +LOCATION 68, 45 +WAIT 11 + +# SC_FUNTOPIA +LOADRCT1 44 +LOCATION 69, 93 +WAIT 17 + +############################## +# Loopy Landscapes # +############################## +# SC_FRIGHTMARE_HILLS +LOADRCT1 86 +LOCATION 46, 47 +WAIT 5 + +# SC_GOOD_KNIGHT_PARK +LOADRCT1 30 +ROTATE 2 +LOCATION 60, 62 +WAIT 5 + +# SC_ICEBERG_ISLANDS +LOADRCT1 22 +ROTATE 3 +LOCATION 36, 52 +WAIT 4 + +# SC_SOUTHERN_SANDS +LOADRCT1 91 +ROTATE 2 +LOCATION 51, 47 +WAIT 4 + +# SC_SUNNY_SWAMPS +LOADRCT1 85 +ROTATE 3 +LOCATION 77, 82 +WAIT 4 + +# SC_VERTIGO_VIEWS +LOADRCT1 27 +LOCATION 22, 56 +WAIT 3 + +# SC_WACKY_WARREN +LOADRCT1 31 +ROTATE 3 +LOCATION 72, 80 +WAIT 4 + +############################## +# Added Attractions (part 2) # +############################## +# SC_SPRIGHTLY_PARK +LOADRCT1 51 +ROTATE 3 +LOCATION 97, 72 +WAIT 12 +ROTATE 2 +LOCATION 74, 71 +WAIT 12 +ROTATE 2 +LOCATION 67, 90 +WAIT 12 + +# SC_GIGGLE_DOWNS +LOADRCT1 65 +LOCATION 94, 64 +WAIT 10 + +# SC_SWAMP_COVE +LOADRCT1 59 +LOCATION 96, 22 +WAIT 10 +ROTATE 3 +LOCATION 90, 29 +WAIT 10 + +# SC_FRUIT_FARM +LOADRCT1 53 +LOCATION 47, 52 +WAIT 12 + +# SC_FUTURE_WORLD +LOADRCT1 47 +LOCATION 67, 59 +WAIT 19 + +# SC_THREE_MONKEYS_PARK +LOADRCT1 41 +ROTATE 2 +LOCATION 72, 61 +WAIT 8 +ROTATE 2 +LOCATION 68, 70 +WAIT 8 +LOCATION 58, 56 +WAIT 8 +ROTATE 1 +LOCATION 44, 70 +WAIT 8 +ROTATE 3 +LOCATION 43, 90 +WAIT 10 + +# SC_ROMAN_VILLAGE +LOADRCT1 58 +LOCATION 49, 46 +WAIT 15 + +# SC_ADRENALINE_HEIGHTS +LOADRCT1 60 +ROTATE 3 +LOCATION 38, 57 +WAIT 15 + +############################## +# RollerCoaster Tycoon 1 # +############################## +# SC_DIAMOND_HEIGHTS +LOADRCT1 3 +ROTATE 2 +LOCATION 47, 99 +WAIT 15 +ROTATE 2 +LOCATION 90, 48 +WAIT 15 +ROTATE 1 +LOCATION 86, 43 +WAIT 15 +ROTATE 3 +LOCATION 57, 50 +WAIT 15 +ROTATE 2 +LOCATION 86, 64 +WAIT 15 + +# SC_KATIES_DREAMLAND +LOADRCT1 7 +LOCATION 48, 44 +WAIT 15 +LOCATION 64, 41 +WAIT 15 + +# SC_POKEY_PARK, +LOADRCT1 8 +ROTATE 2 +LOCATION 56, 64 +WAIT 15 + +# SC_WHITE_WATER_PARK +LOADRCT1 9 +ROTATE 3 +LOCATION 96, 88 +WAIT 15 +LOCATION 84, 95 +WAIT 15 + +# SC_MILLENNIUM_MINES +LOADRCT1 10 +ROTATE 1 +ROTATE 1 +LOCATION 64, 37 +WAIT 15 + +# SC_KARTS_COASTERS +LOADRCT1 11 +LOCATION 84, 56 +WAIT 15 +LOCATION 34, 36 +WAIT 15 +LOCATION 33, 65 +WAIT 15 + +# SC_MELS_WORLD +LOADRCT1 12 +ROTATE 3 +LOCATION 50, 50 +WAIT 15 +LOCATION 35, 39 +WAIT 15 +ROTATE 3 +LOCATION 62, 39 +WAIT 15 + +# SC_CRUMBLY_WOODS +LOADRCT1 15 +ROTATE 3 +LOCATION 57, 94 +WAIT 15 +LOCATION 44, 84 +WAIT 15 +ROTATE 1 +LOCATION 76, 59 +WAIT 15 +LOCATION 76, 48 +WAIT 15 + +# SC_LIGHTNING_PEAKS +LOADRCT1 17 +LOCATION 80, 49 +WAIT 15 +LOCATION 60, 62 +WAIT 15 + +# SC_IVORY_TOWERS +LOADRCT1 18 +ROTATE 3 +LOCATION 50, 77 +WAIT 15 + +RESTART diff --git a/src/config.c b/src/config.c index ed5dcdd3bc..b7eb07921c 100644 --- a/src/config.c +++ b/src/config.c @@ -1407,11 +1407,23 @@ void title_sequences_set_default() platform_get_openrct_data_path(dataPath); - // Load OpenRCT2 title sequence + // RCT1 title sequence + sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1", sep); + title_sequence_open(path, language_get_string(5305)); + + // RCT1 (AA) title sequence + sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1aa", sep); + title_sequence_open(path, language_get_string(5306)); + + // RCT1 (AA + LL) title sequence + sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1aall", sep); + title_sequence_open(path, language_get_string(5307)); + + // RCT2 title sequence sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct2", sep); title_sequence_open(path, language_get_string(5308)); - // Load OpenRCT2 title sequence + // OpenRCT2 title sequence sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "openrct2", sep); title_sequence_open(path, language_get_string(5309)); } @@ -1432,12 +1444,21 @@ void title_sequences_load_presets() platform_enumerate_directories_end(dirEnumHandle); // Check which title sequence is the current one - if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT2") == 0) { + if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT1") == 0) { gCurrentTitleSequence = 0; } - else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*OPENRCT2") == 0) { + else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT1AA") == 0) { gCurrentTitleSequence = 1; } + else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT1AALL") == 0) { + gCurrentTitleSequence = 2; + } + else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT2") == 0) { + gCurrentTitleSequence = 3; + } + else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*OPENRCT2") == 0) { + gCurrentTitleSequence = 4; + } else { for (i = TITLE_SEQUENCE_DEFAULT_PRESETS; i < gConfigTitleSequences.num_presets; i++) { if (_stricmp(gConfigInterface.current_title_sequence_preset, gConfigTitleSequences.presets[i].name) == 0) { @@ -1567,6 +1588,9 @@ static void title_sequence_open(const char *path, const char *customName) command.command = TITLE_SCRIPT_END; } else if (_stricmp(token, "LOADMM") == 0) { command.command = TITLE_SCRIPT_LOADMM; + } else if (_stricmp(token, "LOADRCT1") == 0) { + command.command = TITLE_SCRIPT_LOADRCT1; + command.saveIndex = atoi(part1) & 0xFF; } } if (command.command != 0xFF) { diff --git a/src/interface/title_sequences.c b/src/interface/title_sequences.c index 5d3b05cbb3..af66f7e731 100644 --- a/src/interface/title_sequences.c +++ b/src/interface/title_sequences.c @@ -63,9 +63,18 @@ void title_sequence_change_preset(int preset) if (preset >= 0 && preset < gConfigTitleSequences.num_presets) { switch (preset) { case 0: - gConfigInterface.current_title_sequence_preset = "*RCT2"; + gConfigInterface.current_title_sequence_preset = "*RCT1"; break; case 1: + gConfigInterface.current_title_sequence_preset = "*RCT1AA"; + break; + case 2: + gConfigInterface.current_title_sequence_preset = "*RCT1AALL"; + break; + case 3: + gConfigInterface.current_title_sequence_preset = "*RCT2"; + break; + case 4: gConfigInterface.current_title_sequence_preset = "*OPENRCT2"; break; default: diff --git a/src/scenario.h b/src/scenario.h index a113f78460..339e4b088f 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -447,6 +447,7 @@ typedef struct { } scenario_index_entry; typedef struct { + const utf8 *title; uint8 source; sint32 index; uint8 category; @@ -485,6 +486,113 @@ void scenario_success_submit_name(const char *name); void scenario_autosave_check(); bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc); +bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc); void scenario_normalise_name(utf8 *name); +// RCT1 scenario index map +enum { + SC_UNIDENTIFIED = 255, + + // RCT + SC_FOREST_FRONTIERS = 0, + SC_DYNAMITE_DUNES, + SC_LEAFY_LAKES, + SC_DIAMOND_HEIGHTS, + SC_EVERGREEN_GARDENS, + SC_BUMBLY_BEACH, + SC_TRINITY_ISLANDS, + SC_KATIES_DREAMLAND, + SC_POKEY_PARK, + SC_WHITE_WATER_PARK, + SC_MILLENNIUM_MINES, + SC_KARTS_COASTERS, + SC_MELS_WORLD, + SC_MYSTIC_MOUNTAIN, + SC_PACIFIC_PYRAMIDS, + SC_CRUMBLY_WOODS, + SC_PARADISE_PIER, + SC_LIGHTNING_PEAKS, + SC_IVORY_TOWERS, + SC_RAINBOW_VALLEY, + SC_THUNDER_ROCK, + SC_MEGA_PARK, + + // Loopy Landscapes + SC_ICEBERG_ISLANDS, + SC_VOLCANIA, + SC_ARID_HEIGHTS, + SC_RAZOR_ROCKS, + SC_CRATER_LAKE, + SC_VERTIGO_VIEWS, + SC_PARADISE_PIER_2, + SC_DRAGONS_COVE, + SC_GOOD_KNIGHT_PARK, + SC_WACKY_WARREN, + + // Special + ALTON_TOWERS, + FORT_ANACHRONISM, + + // Added Attractions + SC_WHISPERING_CLIFFS = 40, + SC_THREE_MONKEYS_PARK, + SC_CANARY_MINES, + SC_BARONY_BRIDGE, + SC_FUNTOPIA, + SC_HAUNTED_HARBOR, + SC_FUN_FORTRESS, + SC_FUTURE_WORLD, + SC_GENTLE_GLEN, + SC_JOLLY_JUNGLE, + SC_HYDRO_HILLS, + SC_SPRIGHTLY_PARK, + SC_MAGIC_QUARTERS, + SC_FRUIT_FARM, + SC_BUTTERFLY_DAM, + SC_COASTER_CANYON, + SC_THUNDERSTORM_PARK, + SC_HARMONIC_HILLS, + SC_ROMAN_VILLAGE, + SC_SWAMP_COVE, + SC_ADRENALINE_HEIGHTS, + SC_UTOPIA, + SC_ROTTING_HEIGHTS, + SC_FIASCO_FOREST, + SC_PICKLE_PARK, + SC_GIGGLE_DOWNS, + SC_MINERAL_PARK, + SC_COASTER_CRAZY, + SC_URBAN_PARK, + SC_GEOFFREY_GARDENS, + + // Special + SC_HEIDE_PARK, + SC_PCPLAYER, + SC_PCGW, + SC_GAMEPLAY, + SC_BLACKPOOL_PLEASURE_BEACH, + + // Loopy Landscapes + SC_GRAND_GLACIER = 80, + SC_CRAZY_CRATERS, + SC_DUSTY_DESERT, + SC_WOODWORM_PARK, + SC_ICARUS_PARK, + SC_SUNNY_SWAMPS, + SC_FRIGHTMARE_HILLS, + SC_THUNDER_ROCKS, + SC_OCTAGON_PARK, + SC_PLEASURE_ISLAND, + SC_ICICLE_WORLDS, + SC_SOUTHERN_SANDS, + SC_TINY_TOWERS, + SC_NEVERMORE_PARK, + SC_PACIFICA, + SC_URBAN_JUNGLE, + SC_TERROR_TOWN, + SC_MEGAWORLD_PARK, + SC_VENUS_PONDS, + SC_MICRO_PARK, +}; + #endif diff --git a/src/scenario_sources.c b/src/scenario_sources.c index faacb06d34..f6f17083ed 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -16,182 +16,183 @@ const scenario_alias ScenarioAliases[] = { }; typedef struct { + const uint8 id; const utf8 *title; const uint8 category; } scenario_title_desc; // RCT const scenario_title_desc ScenarioTitlesRCT1[] = { - { "Forest Frontiers", SCENARIO_CATEGORY_BEGINNER }, - { "Dynamite Dunes", SCENARIO_CATEGORY_BEGINNER }, - { "Leafy Lake", SCENARIO_CATEGORY_BEGINNER }, - { "Diamond Heights", SCENARIO_CATEGORY_BEGINNER }, - { "Evergreen Gardens", SCENARIO_CATEGORY_BEGINNER }, - { "Bumbly Beach", SCENARIO_CATEGORY_BEGINNER }, - { "Trinity Islands", SCENARIO_CATEGORY_CHALLENGING }, - { "Katie's Dreamland", SCENARIO_CATEGORY_CHALLENGING }, - { "Pokey Park", SCENARIO_CATEGORY_CHALLENGING }, - { "White Water Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Millennium Mines", SCENARIO_CATEGORY_CHALLENGING }, - { "Karts & Coasters", SCENARIO_CATEGORY_CHALLENGING }, - { "Mel's World", SCENARIO_CATEGORY_CHALLENGING }, - { "Mystic Mountain", SCENARIO_CATEGORY_CHALLENGING }, - { "Pacific Pyramids", SCENARIO_CATEGORY_CHALLENGING }, - { "Crumbly Woods", SCENARIO_CATEGORY_CHALLENGING }, - { "Paradise Pier", SCENARIO_CATEGORY_CHALLENGING }, - { "Lightning Peaks", SCENARIO_CATEGORY_EXPERT }, - { "Ivory Towers", SCENARIO_CATEGORY_EXPERT }, - { "Rainbow Valley", SCENARIO_CATEGORY_EXPERT }, - { "Thunder Rock", SCENARIO_CATEGORY_EXPERT }, - { "Mega Park", SCENARIO_CATEGORY_OTHER }, + { SC_FOREST_FRONTIERS, "Forest Frontiers", SCENARIO_CATEGORY_BEGINNER }, + { SC_DYNAMITE_DUNES, "Dynamite Dunes", SCENARIO_CATEGORY_BEGINNER }, + { SC_LEAFY_LAKES, "Leafy Lake", SCENARIO_CATEGORY_BEGINNER }, + { SC_DIAMOND_HEIGHTS, "Diamond Heights", SCENARIO_CATEGORY_BEGINNER }, + { SC_EVERGREEN_GARDENS, "Evergreen Gardens", SCENARIO_CATEGORY_BEGINNER }, + { SC_BUMBLY_BEACH, "Bumbly Beach", SCENARIO_CATEGORY_BEGINNER }, + { SC_TRINITY_ISLANDS, "Trinity Islands", SCENARIO_CATEGORY_CHALLENGING }, + { SC_KATIES_DREAMLAND, "Katie's Dreamland", SCENARIO_CATEGORY_CHALLENGING }, + { SC_POKEY_PARK, "Pokey Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_WHITE_WATER_PARK, "White Water Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_MILLENNIUM_MINES, "Millennium Mines", SCENARIO_CATEGORY_CHALLENGING }, + { SC_KARTS_COASTERS, "Karts & Coasters", SCENARIO_CATEGORY_CHALLENGING }, + { SC_MELS_WORLD, "Mel's World", SCENARIO_CATEGORY_CHALLENGING }, + { SC_MYSTIC_MOUNTAIN, "Mystic Mountain", SCENARIO_CATEGORY_CHALLENGING }, + { SC_PACIFIC_PYRAMIDS, "Pacific Pyramids", SCENARIO_CATEGORY_CHALLENGING }, + { SC_CRUMBLY_WOODS, "Crumbly Woods", SCENARIO_CATEGORY_CHALLENGING }, + { SC_PARADISE_PIER, "Paradise Pier", SCENARIO_CATEGORY_CHALLENGING }, + { SC_LIGHTNING_PEAKS, "Lightning Peaks", SCENARIO_CATEGORY_EXPERT }, + { SC_IVORY_TOWERS, "Ivory Towers", SCENARIO_CATEGORY_EXPERT }, + { SC_RAINBOW_VALLEY, "Rainbow Valley", SCENARIO_CATEGORY_EXPERT }, + { SC_THUNDER_ROCK, "Thunder Rock", SCENARIO_CATEGORY_EXPERT }, + { SC_MEGA_PARK, "Mega Park", SCENARIO_CATEGORY_OTHER }, }; // RCT: Added Attractions const scenario_title_desc ScenarioTitlesRCT1AA[] = { - { "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER }, - { "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER }, - { "Canary Mines", SCENARIO_CATEGORY_BEGINNER }, - { "Barony Bridge", SCENARIO_CATEGORY_BEGINNER }, - { "Funtopia", SCENARIO_CATEGORY_BEGINNER }, - { "Haunted Harbor", SCENARIO_CATEGORY_BEGINNER }, - { "Fun Fortress", SCENARIO_CATEGORY_BEGINNER }, - { "Future World", SCENARIO_CATEGORY_BEGINNER }, - { "Gentle Glen", SCENARIO_CATEGORY_BEGINNER }, - { "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING }, - { "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING }, - { "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING }, - { "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING }, - { "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING }, - { "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING }, - { "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING }, - { "Roman Village", SCENARIO_CATEGORY_CHALLENGING }, - { "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING }, - { "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING }, - { "Utopia", SCENARIO_CATEGORY_CHALLENGING }, - { "Rotting Heights", SCENARIO_CATEGORY_EXPERT }, - { "Fiasco Forest", SCENARIO_CATEGORY_EXPERT }, - { "Pickle Park", SCENARIO_CATEGORY_EXPERT }, - { "Giggle Downs", SCENARIO_CATEGORY_EXPERT }, - { "Mineral Park", SCENARIO_CATEGORY_EXPERT }, - { "Coaster Crazy", SCENARIO_CATEGORY_EXPERT }, - { "Urban Park", SCENARIO_CATEGORY_EXPERT }, - { "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT }, + { SC_WHISPERING_CLIFFS, "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER }, + { SC_THREE_MONKEYS_PARK, "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER }, + { SC_CANARY_MINES, "Canary Mines", SCENARIO_CATEGORY_BEGINNER }, + { SC_BARONY_BRIDGE, "Barony Bridge", SCENARIO_CATEGORY_BEGINNER }, + { SC_FUNTOPIA, "Funtopia", SCENARIO_CATEGORY_BEGINNER }, + { SC_HAUNTED_HARBOR, "Haunted Harbor", SCENARIO_CATEGORY_BEGINNER }, + { SC_FUN_FORTRESS, "Fun Fortress", SCENARIO_CATEGORY_BEGINNER }, + { SC_FUTURE_WORLD, "Future World", SCENARIO_CATEGORY_BEGINNER }, + { SC_GENTLE_GLEN, "Gentle Glen", SCENARIO_CATEGORY_BEGINNER }, + { SC_JOLLY_JUNGLE, "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING }, + { SC_HYDRO_HILLS, "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING }, + { SC_SPRIGHTLY_PARK, "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_MAGIC_QUARTERS, "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING }, + { SC_FRUIT_FARM, "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING }, + { SC_BUTTERFLY_DAM, "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING }, + { SC_COASTER_CANYON, "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING }, + { SC_THUNDERSTORM_PARK, "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_HARMONIC_HILLS, "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING }, + { SC_ROMAN_VILLAGE, "Roman Village", SCENARIO_CATEGORY_CHALLENGING }, + { SC_SWAMP_COVE, "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING }, + { SC_ADRENALINE_HEIGHTS, "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UTOPIA, "Utopia", SCENARIO_CATEGORY_CHALLENGING }, + { SC_ROTTING_HEIGHTS, "Rotting Heights", SCENARIO_CATEGORY_EXPERT }, + { SC_FIASCO_FOREST, "Fiasco Forest", SCENARIO_CATEGORY_EXPERT }, + { SC_PICKLE_PARK, "Pickle Park", SCENARIO_CATEGORY_EXPERT }, + { SC_GIGGLE_DOWNS, "Giggle Downs", SCENARIO_CATEGORY_EXPERT }, + { SC_MINERAL_PARK, "Mineral Park", SCENARIO_CATEGORY_EXPERT }, + { SC_COASTER_CRAZY, "Coaster Crazy", SCENARIO_CATEGORY_EXPERT }, + { SC_URBAN_PARK, "Urban Park", SCENARIO_CATEGORY_EXPERT }, + { SC_GEOFFREY_GARDENS, "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT }, }; // RCT: Loopy Landscapes const scenario_title_desc ScenarioTitlesRCT1LL[] = { - { "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER }, - { "Volcania", SCENARIO_CATEGORY_BEGINNER }, - { "Arid Heights", SCENARIO_CATEGORY_BEGINNER }, - { "Razor Rocks", SCENARIO_CATEGORY_BEGINNER }, - { "Crater Lake", SCENARIO_CATEGORY_BEGINNER }, - { "Vertigo Views", SCENARIO_CATEGORY_BEGINNER }, - { "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING }, - { "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING }, - { "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING }, - { "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING }, - { "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING }, - { "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING }, - { "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Icarus Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING }, - { "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING }, - { "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING }, - { "Octagon Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING }, - { "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING }, - { "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, - { "Southern Sands", SCENARIO_CATEGORY_CHALLENGING }, - { "Nevermore Park", SCENARIO_CATEGORY_CHALLENGING }, - { "Pacifica", SCENARIO_CATEGORY_CHALLENGING }, - { "Urban Jungle", SCENARIO_CATEGORY_EXPERT }, - { "Terror Town", SCENARIO_CATEGORY_EXPERT }, - { "Megaworld Park", SCENARIO_CATEGORY_EXPERT }, - { "Venus Ponds", SCENARIO_CATEGORY_EXPERT }, - { "Micro Park", SCENARIO_CATEGORY_EXPERT }, + { SC_ICEBERG_ISLANDS, "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER }, + { SC_VOLCANIA, "Volcania", SCENARIO_CATEGORY_BEGINNER }, + { SC_ARID_HEIGHTS, "Arid Heights", SCENARIO_CATEGORY_BEGINNER }, + { SC_RAZOR_ROCKS, "Razor Rocks", SCENARIO_CATEGORY_BEGINNER }, + { SC_CRATER_LAKE, "Crater Lake", SCENARIO_CATEGORY_BEGINNER }, + { SC_VERTIGO_VIEWS, "Vertigo Views", SCENARIO_CATEGORY_BEGINNER }, + { SC_PARADISE_PIER_2, "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING }, + { SC_DRAGONS_COVE, "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING }, + { SC_GOOD_KNIGHT_PARK, "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_WACKY_WARREN, "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING }, + { SC_GRAND_GLACIER, "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING }, + { SC_CRAZY_CRATERS, "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING }, + { SC_DUSTY_DESERT, "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING }, + { SC_WOODWORM_PARK, "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_ICARUS_PARK, "Icarus Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_SUNNY_SWAMPS, "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING }, + { SC_FRIGHTMARE_HILLS, "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING }, + { SC_THUNDER_ROCKS, "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING }, + { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING }, + { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING }, + { SC_SOUTHERN_SANDS, "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, + { SC_TINY_TOWERS, "Southern Sands", SCENARIO_CATEGORY_CHALLENGING }, + { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_CHALLENGING }, + { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_CHALLENGING }, + { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT }, + { SC_TERROR_TOWN, "Terror Town", SCENARIO_CATEGORY_EXPERT }, + { SC_MEGAWORLD_PARK, "Megaworld Park", SCENARIO_CATEGORY_EXPERT }, + { SC_VENUS_PONDS, "Venus Ponds", SCENARIO_CATEGORY_EXPERT }, + { SC_MICRO_PARK, "Micro Park", SCENARIO_CATEGORY_EXPERT }, }; // RCT2 const scenario_title_desc ScenarioTitlesRCT2[] = { - { "Crazy Castle", SCENARIO_CATEGORY_BEGINNER }, - { "Electric Fields", SCENARIO_CATEGORY_BEGINNER }, - { "Factory Capers", SCENARIO_CATEGORY_BEGINNER }, - { "Amity Airfield", SCENARIO_CATEGORY_CHALLENGING }, - { "Botany Breakers", SCENARIO_CATEGORY_CHALLENGING }, - { "Bumbly Bazaar", SCENARIO_CATEGORY_CHALLENGING }, - { "Dusty Greens", SCENARIO_CATEGORY_CHALLENGING }, - { "Fungus Woods", SCENARIO_CATEGORY_CHALLENGING }, - { "Gravity Gardens", SCENARIO_CATEGORY_CHALLENGING }, - { "Infernal Views", SCENARIO_CATEGORY_CHALLENGING }, - { "Alpine Adventures", SCENARIO_CATEGORY_EXPERT }, - { "Extreme Heights", SCENARIO_CATEGORY_EXPERT }, - { "Ghost Town", SCENARIO_CATEGORY_EXPERT }, - { "Lucky Lake", SCENARIO_CATEGORY_EXPERT }, - { "Rainbow Summit", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Crazy Castle", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Electric Fields", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Factory Capers", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Amity Airfield", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Botany Breakers", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Bumbly Bazaar", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Dusty Greens", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Fungus Woods", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Gravity Gardens", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Infernal Views", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Alpine Adventures", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Extreme Heights", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Ghost Town", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Lucky Lake", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Rainbow Summit", SCENARIO_CATEGORY_EXPERT }, }; // RCT2: Wacky Worlds const scenario_title_desc ScenarioTitlesRCT2WW[] = { - { "Africa - Victoria Falls", SCENARIO_CATEGORY_BEGINNER }, - { "Asia - Great Wall of China Tourism Enhancement", SCENARIO_CATEGORY_BEGINNER }, - { "North America - Grand Canyon", SCENARIO_CATEGORY_BEGINNER }, - { "South America - Rio Carnival", SCENARIO_CATEGORY_BEGINNER }, - { "Africa - African Diamond Mine", SCENARIO_CATEGORY_CHALLENGING }, - { "Asia - Maharaja Palace", SCENARIO_CATEGORY_CHALLENGING }, - { "Australasia - Ayers Rock", SCENARIO_CATEGORY_CHALLENGING }, - { "Europe - European Cultural Festival", SCENARIO_CATEGORY_CHALLENGING }, - { "North America - Rollercoaster Heaven", SCENARIO_CATEGORY_CHALLENGING }, - { "South America - Inca Lost City", SCENARIO_CATEGORY_CHALLENGING }, - { "Africa - Oasis", SCENARIO_CATEGORY_EXPERT }, - { "Antarctic - Ecological Salvage", SCENARIO_CATEGORY_EXPERT }, - { "Asia - Japanese Coastal Reclaim", SCENARIO_CATEGORY_EXPERT }, - { "Australasia - Fun at the Beach", SCENARIO_CATEGORY_EXPERT }, - { "Europe - Renovation", SCENARIO_CATEGORY_EXPERT }, - { "N. America - Extreme Hawaiian Island", SCENARIO_CATEGORY_EXPERT }, - { "South America - Rain Forest Plateau", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Africa - Victoria Falls", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Asia - Great Wall of China Tourism Enhancement", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "North America - Grand Canyon", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "South America - Rio Carnival", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Africa - African Diamond Mine", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Asia - Maharaja Palace", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Australasia - Ayers Rock", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Europe - European Cultural Festival", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "North America - Rollercoaster Heaven", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "South America - Inca Lost City", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Africa - Oasis", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Antarctic - Ecological Salvage", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Asia - Japanese Coastal Reclaim", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Australasia - Fun at the Beach", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Europe - Renovation", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "N. America - Extreme Hawaiian Island", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "South America - Rain Forest Plateau", SCENARIO_CATEGORY_EXPERT }, }; // RCT2: Time Twister const scenario_title_desc ScenarioTitlesRCT2TT[] = { - { "Dark Age - Robin Hood", SCENARIO_CATEGORY_BEGINNER }, - { "Prehistoric - After the Asteroid", SCENARIO_CATEGORY_BEGINNER }, - { "Roaring Twenties - Prison Island", SCENARIO_CATEGORY_BEGINNER }, - { "Rock 'n' Roll - Flower Power", SCENARIO_CATEGORY_BEGINNER }, - { "Dark Age - Castle", SCENARIO_CATEGORY_CHALLENGING }, - { "Future - First Encounters", SCENARIO_CATEGORY_CHALLENGING }, - { "Mythological - Animatronic Film Set", SCENARIO_CATEGORY_CHALLENGING }, - { "Prehistoric - Jurassic Safari", SCENARIO_CATEGORY_CHALLENGING }, - { "Roaring Twenties - Schneider Cup", SCENARIO_CATEGORY_CHALLENGING }, - { "Future - Future World", SCENARIO_CATEGORY_EXPERT }, - { "Mythological - Cradle of Civilisation", SCENARIO_CATEGORY_EXPERT }, - { "Prehistoric - Stone Age", SCENARIO_CATEGORY_EXPERT }, - { "Roaring Twenties - Skyscrapers", SCENARIO_CATEGORY_EXPERT }, - { "Rock 'n' Roll - Rock 'n' Roll", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Dark Age - Robin Hood", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Prehistoric - After the Asteroid", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Roaring Twenties - Prison Island", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Rock 'n' Roll - Flower Power", SCENARIO_CATEGORY_BEGINNER }, + { SC_UNIDENTIFIED, "Dark Age - Castle", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Future - First Encounters", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Mythological - Animatronic Film Set", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Prehistoric - Jurassic Safari", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Roaring Twenties - Schneider Cup", SCENARIO_CATEGORY_CHALLENGING }, + { SC_UNIDENTIFIED, "Future - Future World", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Mythological - Cradle of Civilisation", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Prehistoric - Stone Age", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Roaring Twenties - Skyscrapers", SCENARIO_CATEGORY_EXPERT }, + { SC_UNIDENTIFIED, "Rock 'n' Roll - Rock 'n' Roll", SCENARIO_CATEGORY_EXPERT }, }; // Real parks const scenario_title_desc ScenarioTitlesRealParks[] = { - { "Alton Towers", SCENARIO_CATEGORY_REAL }, - { "Heide-Park", SCENARIO_CATEGORY_REAL }, - { "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, - { "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, - { "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL }, - { "Six Flags Holland", SCENARIO_CATEGORY_REAL }, - { "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL }, - { "Six Flags over Texas", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Alton Towers", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Heide-Park", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags over Texas", SCENARIO_CATEGORY_REAL }, }; // Other parks const scenario_title_desc ScenarioTitlesRCT2BuildYourOwnParks[] = { - { "Build your own Six Flags Belgium", SCENARIO_CATEGORY_OTHER }, - { "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_OTHER }, - { "Build your own Six Flags Holland", SCENARIO_CATEGORY_OTHER }, - { "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_OTHER }, - { "Build your own Six Flags Park", SCENARIO_CATEGORY_OTHER }, - { "Build your own Six Flags over Texas", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_OTHER }, + { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_OTHER }, }; const struct { @@ -216,6 +217,32 @@ bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) for (int j = 0; j < ScenarioTitlesBySource[i].count; j++) { const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; if (_strcmpi(name, desc->title) == 0) { + outDesc->title = desc->title; + outDesc->source = i; + outDesc->index = currentIndex; + outDesc->category = desc->category; + return true; + } + currentIndex++; + } + } + + outDesc->source = SCENARIO_SOURCE_OTHER; + outDesc->index = -1; + outDesc->category = SCENARIO_CATEGORY_OTHER; + return false; +} + +bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc) +{ + assert(outDesc != NULL); + + sint32 currentIndex = 0; + for (int i = 0; i < countof(ScenarioTitlesBySource); i++) { + for (int j = 0; j < ScenarioTitlesBySource[i].count; j++) { + const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; + if (id == desc->id) { + outDesc->title = desc->title; outDesc->source = i; outDesc->index = currentIndex; outDesc->category = desc->category; diff --git a/src/title.c b/src/title.c index 33d6007ffe..9a982c8b58 100644 --- a/src/title.c +++ b/src/title.c @@ -64,6 +64,7 @@ rct_xy16 _titleScriptCurrentCentralPosition = { -1, -1 }; #define ZOOM(d) TITLE_SCRIPT_ZOOM, d #define RESTART() TITLE_SCRIPT_RESTART #define LOAD(i) TITLE_SCRIPT_LOAD, i +#define LOADRCT1(i) TITLE_SCRIPT_LOADRCT1, i static const uint8 _magicMountainScript[] = { LOADMM(), @@ -422,6 +423,38 @@ static void title_do_next_script_opcode() } } break; + case TITLE_SCRIPT_LOADRCT1: + script_operand = (*_currentScript++); + + source_desc sourceDesc; + if (!scenario_get_source_desc_by_id(script_operand, &sourceDesc) || sourceDesc.index == -1) { + log_fatal("Invalid scenario id."); + exit(-1); + } + + const utf8 *path = NULL; + for (int i = 0; i < gScenarioListCount; i++) { + if (gScenarioList[i].source_index == sourceDesc.index) { + path = gScenarioList[i].path; + break; + } + } + + if (path == NULL || !title_load_park(path)) { + script_opcode = *_currentScript; + while (script_opcode != TITLE_SCRIPT_LOADRCT1 && script_opcode != TITLE_SCRIPT_RESTART && script_opcode != TITLE_SCRIPT_END) { + title_skip_opcode(); + script_opcode = *_currentScript; + } + if (script_opcode == TITLE_SCRIPT_RESTART) { + title_sequence_change_preset(4); + title_refresh_sequence(); + config_save_default(); + return; + } + } + gTitleScriptSave = 0xFF; + break; } window_invalidate_by_class(WC_TITLE_EDITOR); } @@ -688,6 +721,9 @@ bool title_refresh_sequence() hasInvalidSave = true; hasLoad = true; } + else if (title->commands[i].command == TITLE_SCRIPT_LOADRCT1) { + hasLoad = true; + } else if (title->commands[i].command == TITLE_SCRIPT_LOADMM) { hasLoad = true; } @@ -711,6 +747,9 @@ bool title_refresh_sequence() for (int i = 0; i < title->num_commands; i++) { *scriptPtr++ = title->commands[i].command; switch (title->commands[i].command) { + case TITLE_SCRIPT_LOADRCT1: + *scriptPtr++ = title->commands[i].saveIndex; + break; case TITLE_SCRIPT_LOAD: src = title->saves[title->commands[i].saveIndex]; do { diff --git a/src/title.h b/src/title.h index 924bb738eb..88270393ee 100644 --- a/src/title.h +++ b/src/title.h @@ -34,7 +34,8 @@ enum { TITLE_SCRIPT_END, TITLE_SCRIPT_SPEED, TITLE_SCRIPT_LOOP, - TITLE_SCRIPT_ENDLOOP + TITLE_SCRIPT_ENDLOOP, + TITLE_SCRIPT_LOADRCT1, }; extern sint32 gTitleScriptCommand; diff --git a/src/windows/options.c b/src/windows/options.c index 213f7306e1..40b19f12c1 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -996,15 +996,14 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* gDropdownItemsArgs[i] = (uint32)&gConfigTitleSequences.presets[i].name; } - window_dropdown_show_text_custom_width( + window_dropdown_show_text( w->x + widget->left, w->y + widget->top, widget->bottom - widget->top + 1, w->colours[1], DROPDOWN_FLAG_STAY_OPEN, - num_items, - widget->right - widget->left - 3 - ); + num_items + ); dropdown_set_checked(gCurrentPreviewTitleSequence, true); break; From 868da8e4502615f744a76b8cb192d597e7e90b94 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 17:15:48 +0000 Subject: [PATCH 57/90] fix title sequence issue --- src/title.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/title.c b/src/title.c index 9a982c8b58..31a46b5fa2 100644 --- a/src/title.c +++ b/src/title.c @@ -299,10 +299,7 @@ static void title_do_next_script_opcode() uint8 script_opcode, script_operand; rct_window* w; gTitleScriptCommand++; - if (gTitleScriptCommand <= 1 || *(_currentScript - 1) != TITLE_SCRIPT_END) - script_opcode = *_currentScript++; - else - script_opcode = *_currentScript; + script_opcode = *_currentScript++; if (gTitleScriptSkipTo != -1) { if (gTitleScriptSkipTo == gTitleScriptCommand) { gTitleScriptSkipTo = -1; From 51141a905712a1929a1c7bbc2d14115414350471 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 18:37:34 +0000 Subject: [PATCH 58/90] refactor translation of scenarios --- src/scenario_list.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/scenario_list.c b/src/scenario_list.c index dce12b9c00..2efe09d81b 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -39,6 +39,7 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp); static void scenario_list_sort(); static int scenario_list_sort_by_name(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); +static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry); static bool scenario_scores_load(); static void scenario_scores_legacy_get_path(utf8 *outPath); @@ -181,31 +182,34 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) } } - // Translate scenario name and details + scenario_translate(newEntry, &s6Info.entry); +} + +static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry) +{ utf8 filenameWithoutExtension[MAX_PATH]; - safe_strncpy(filenameWithoutExtension, filename, sizeof(filenameWithoutExtension)); + safe_strncpy(filenameWithoutExtension, scenarioEntry->path, sizeof(filenameWithoutExtension)); path_remove_extension(filenameWithoutExtension); rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(filename, localisedStringIds)) { + if (language_get_localised_scenario_strings(filenameWithoutExtension, localisedStringIds)) { if (localisedStringIds[0] != (rct_string_id)STR_NONE) { - safe_strncpy(newEntry->name, language_get_string(localisedStringIds[0]), 64); + safe_strncpy(scenarioEntry->name, language_get_string(localisedStringIds[0]), 64); } if (localisedStringIds[2] != (rct_string_id)STR_NONE) { - safe_strncpy(newEntry->details, language_get_string(localisedStringIds[2]), 256); + safe_strncpy(scenarioEntry->details, language_get_string(localisedStringIds[2]), 256); } } else { // Checks for a scenario string object (possibly for localisation) - if ((s6Info.entry.flags & 0xFF) != 255) { - if (object_get_scenario_text(&s6Info.entry)) { + if ((stexObjectEntry->flags & 0xFF) != 255) { + if (object_get_scenario_text((rct_object_entry*)stexObjectEntry)) { rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); - format_string(newEntry->name, stex_entry->scenario_name, NULL); - format_string(newEntry->details, stex_entry->details, NULL); + format_string(scenarioEntry->name, stex_entry->scenario_name, NULL); + format_string(scenarioEntry->details, stex_entry->details, NULL); object_free_scenario_text(); } } } - } void scenario_list_dispose() From 3ad31135239b5df331d37f7288d22ad459bbceb9 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 18:38:04 +0000 Subject: [PATCH 59/90] add alias for 'Cradle of Civilisation' --- src/scenario_sources.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/scenario_sources.c b/src/scenario_sources.c index f6f17083ed..08d5a0f89d 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -7,12 +7,13 @@ typedef struct { } scenario_alias; const scenario_alias ScenarioAliases[] = { - { "Katie's Dreamland", "Katie's World" }, - { "Pokey Park", "Dinky Park" }, - { "White Water Park", "Aqua Park" }, - { "Mystic Mountain", "Mothball Mountain" }, - { "Paradise Pier", "Big Pier" }, - { "Paradise Pier 2", "Big Pier 2" }, + { "Katie's Dreamland", "Katie's World" }, + { "Pokey Park", "Dinky Park" }, + { "White Water Park", "Aqua Park" }, + { "Mystic Mountain", "Mothball Mountain" }, + { "Paradise Pier", "Big Pier" }, + { "Paradise Pier 2", "Big Pier 2" }, + { "Mythological - Cradle of Civilisation", "Mythological - Cradle of Civilization" }, }; typedef struct { From 9d8898213821e37560feb628c5527b546ea1fc75 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 19:02:22 +0000 Subject: [PATCH 60/90] fix mistake in scenario sources array --- src/scenario_sources.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 08d5a0f89d..7ad8858213 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -105,8 +105,8 @@ const scenario_title_desc ScenarioTitlesRCT1LL[] = { { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING }, { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING }, { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING }, - { SC_SOUTHERN_SANDS, "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, - { SC_TINY_TOWERS, "Southern Sands", SCENARIO_CATEGORY_CHALLENGING }, + { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, + { SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_CHALLENGING }, { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_CHALLENGING }, { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_CHALLENGING }, { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT }, From 8f5a9cfade82bf99f7e1323806d916f98cc7ee1c Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 20:46:13 +0000 Subject: [PATCH 61/90] fix issue caused by not copying filename string --- src/scenario.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scenario.c b/src/scenario.c index 46c627731f..3c52ad321f 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -403,7 +403,7 @@ void scenario_success() } else { scenario_highscore_free(scenario->highscore); } - scenario->highscore->fileName = (utf8*)path_get_filename(scenario->path); + scenario->highscore->fileName = _strdup(path_get_filename(scenario->path)); scenario->highscore->name = NULL; scenario->highscore->company_value = companyValue; From aeda8d68f97a25e7c1ee1c2e9e30f70670ee3201 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 20:46:39 +0000 Subject: [PATCH 62/90] add logic for unlocking mega park and making it invisible --- src/scenario.h | 2 ++ src/scenario_list.c | 2 ++ src/scenario_sources.c | 6 +++++ src/windows/title_scenarioselect.c | 40 ++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/src/scenario.h b/src/scenario.h index 339e4b088f..41d3ffa3b4 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -434,6 +434,7 @@ typedef struct { uint8 category; uint8 source_game; sint16 source_index; + uint16 sc_id; // Objective uint8 objective_type; @@ -448,6 +449,7 @@ typedef struct { typedef struct { const utf8 *title; + uint8 id; uint8 source; sint32 index; uint8 category; diff --git a/src/scenario_list.c b/src/scenario_list.c index 2efe09d81b..3604a3d806 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -170,10 +170,12 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) // Look up and store information regarding the origins of this scenario. source_desc desc; if (scenario_get_source_desc(newEntry->name, &desc)) { + newEntry->sc_id = desc.id; newEntry->source_index = desc.index; newEntry->source_game = desc.source; newEntry->category = desc.category; } else { + newEntry->sc_id = SC_UNIDENTIFIED; newEntry->source_index = -1; if (newEntry->category == SCENARIO_CATEGORY_REAL) { newEntry->source_game = SCENARIO_SOURCE_REAL; diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 7ad8858213..90fddcd7e8 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -219,6 +219,7 @@ bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; if (_strcmpi(name, desc->title) == 0) { outDesc->title = desc->title; + outDesc->id = desc->id; outDesc->source = i; outDesc->index = currentIndex; outDesc->category = desc->category; @@ -228,6 +229,8 @@ bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) } } + outDesc->title = NULL; + outDesc->id = SC_UNIDENTIFIED; outDesc->source = SCENARIO_SOURCE_OTHER; outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; @@ -244,6 +247,7 @@ bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc) const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j]; if (id == desc->id) { outDesc->title = desc->title; + outDesc->id = desc->id; outDesc->source = i; outDesc->index = currentIndex; outDesc->category = desc->category; @@ -253,6 +257,8 @@ bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc) } } + outDesc->title = NULL; + outDesc->id = SC_UNIDENTIFIED; outDesc->source = SCENARIO_SOURCE_OTHER; outDesc->index = -1; outDesc->category = SCENARIO_CATEGORY_OTHER; diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 1b6e706acf..373c2d58ff 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -506,6 +506,11 @@ static void initialise_list_items(rct_window *w) int length = 0; _listItems = malloc(capacity * sizeof(sc_list_item)); + // Mega park unlock + const uint32 rct1RequiredCompletedScenarios = (1 << SC_MEGA_PARK) - 1; + uint32 rct1CompletedScenarios = 0; + int megaParkListItemIndex = -1; + int numUnlocks = INITIAL_NUM_UNLOCKED_SCENARIOS; uint8 currentHeading = UINT8_MAX; for (int i = 0; i < gScenarioListCount; i++) { @@ -555,6 +560,16 @@ static void initialise_list_items(rct_window *w) listItem->scenario.is_locked = numUnlocks <= 0; if (scenario->highscore == NULL) { numUnlocks--; + } else { + // Mark RCT1 scenario as completed + if (scenario->sc_id < SC_MEGA_PARK) { + rct1CompletedScenarios |= 1 << scenario->sc_id; + } + } + + // If scenario is Mega Park, keep a reference to it + if (scenario->sc_id == SC_MEGA_PARK) { + megaParkListItemIndex = length - 1; } } else { listItem->scenario.is_locked = false; @@ -564,6 +579,31 @@ static void initialise_list_items(rct_window *w) length++; _listItems = realloc(_listItems, length * sizeof(sc_list_item)); _listItems[length - 1].type = LIST_ITEM_TYPE_END; + + // Mega park handling + if (megaParkListItemIndex != -1) { + bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios; + _listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked; +#ifdef HIDE_MEGA_PARK + if (megaParkLocked) { + // Remove mega park + int remainingItems = length - megaParkListItemIndex - 1; + memmove(&_listItems[megaParkListItemIndex], &_listItems[megaParkListItemIndex + 1], remainingItems); + + // Remove empty headings + int i = 0; + for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { + if (listItem->type == LIST_ITEM_TYPE_HEADING && (listItem + 1)->type != LIST_ITEM_TYPE_SCENARIO) { + remainingItems = length - i - 1; + memmove(&_listItems[i], &_listItems[i + 1], remainingItems); + listItem--; + } else { + i++; + } + } + } +#endif + } } static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario) From d147f516db9f35ff99e7698253720ccc6c817bed Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 1 Jan 2016 22:43:57 +0000 Subject: [PATCH 63/90] fix default selected tab on scenario select --- src/windows/title_scenarioselect.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 373c2d58ff..156133e8e6 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -86,7 +86,7 @@ static rct_widget window_scenarioselect_widgets[] = { { WIDGETS_END }, }; -static void window_scenarioselect_init_tabs(); +static void window_scenarioselect_init_tabs(rct_window *w); static void window_scenarioselect_close(rct_window *w); static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex); @@ -168,9 +168,8 @@ void window_scenarioselect_open() window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5) | (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8); - window_scenarioselect_init_tabs(); - window->selected_tab = 0; + window_scenarioselect_init_tabs(window); initialise_list_items(window); window_init_scroll_widgets(window); @@ -182,22 +181,27 @@ void window_scenarioselect_open() * * rct2: 0x00677C8A */ -static void window_scenarioselect_init_tabs() +static void window_scenarioselect_init_tabs(rct_window *w) { - int show_pages = 0; + int showPages = 0; for (int i = 0; i < gScenarioListCount; i++) { scenario_index_entry *scenario = &gScenarioList[i]; - if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { - show_pages |= 1 << scenario->source_game; - } else { - show_pages |= 1 << scenario->category; - } + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { + showPages |= 1 << scenario->source_game; + } else { + showPages |= 1 << scenario->category; } + } + + int firstPage = bitscanforward(showPages); + if (firstPage != -1) { + w->selected_tab = firstPage; + } int x = 3; for (int i = 0; i < 8; i++) { - rct_widget* widget = &window_scenarioselect_widgets[i + 4]; - if (!(show_pages & (1 << i))) { + rct_widget* widget = &w->widgets[i + 4]; + if (!(showPages & (1 << i))) { widget->type = WWT_EMPTY; continue; } From 4c6dbd07025457d807dedb457a482794b4c29729 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sat, 2 Jan 2016 18:24:41 +0100 Subject: [PATCH 64/90] Add entries for RCT1/AA/LL scenarios --- data/language/english_uk.txt | 442 +++++++++++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index abd1a8ea03..a7fb98c133 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3971,6 +3971,448 @@ STR_5629 :Difficulty level STR_5630 :Enable unlocking of scenarios STR_5631 :{GREY}{STRINGID} +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Starting from scratch, build a theme park around a large lake + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Several islands form the basis for this new park + + +STR_SCNR :Katie's Dreamland +STR_PARK :Katie's Dreamland +STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :A small, cramped amusement park which requires major expansion + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :A park with some excellent water-based rides requires expansion + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park + + +STR_SCNR :Crumbly Woods +STR_PARK :Crumbly Woods +STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Convert this sleepy town's pier into a thriving attraction + + +STR_SCNR :Lightning Peaks +STR_PARK :Lightning Peaks +STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers - Use the available land to attract a new thrill-seeking clientele + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :A well-established park, which has a few problems + + +STR_SCNR :Rainbow Valley +STR_PARK :Rainbow Valley +STR_DTLS :Rainbow Valley's local authority won't allow any landscape changes or large tree removal, but you must develop the area into a large theme park + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists - Use the available space to build rides to attract more people + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Just for fun! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Develop the seaside cliffs into a thriving amusement park + + +STR_SCNR :Three Monkeys Park +STR_PARK :Three Monkeys Park +STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster + + +STR_SCNR :Canary Mines +STR_PARK :Canary Mines +STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its minature railway and a pair of vertical drop roller coasters + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :An old redundant bridge is yours to develop into an amusement park + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Covering land both sides of a highway, this park has several rides already operating + + +STR_SCNR :Haunted Harbor +STR_PARK :Haunted Harbor +STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :This castle is all yours to turn into a theme park + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape + + +STR_SCNR :Gentle Glen +STR_PARK :Gentle Glen +STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes + + +STR_SCNR :Jolly Jungle +STR_PARK :Jolly Jungle +STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :A series of stepped lakes form the basis for this new park + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :This elderly park has many historical rides but is badly in debt + + +STR_SCNR :Magic Quarters +STR_PARK :Magic Quarters +STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park + + +STR_SCNR :Fruit Farm +STR_PARK :Fruit Farm +STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park + + +STR_SCNR :Butterfly Dam +STR_PARK :Butterfly Dam +STR_DTLS :The area around a dam is available for you to develop into an amusement park + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :A vast canyon is yours to turn into a theme park + + +STR_SCNR :Thunderstorm Park +STR_PARK :Thunderstorm Park +STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover + + +STR_SCNR :Harmonic Hills +STR_PARK :Harmonic Hills +STR_DTLS :The local authority won't allow you to build above tree height in this park + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +STR_SCNR :Swamp Cove +STR_PARK :Swamp Cove +STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centerpiece + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +STR_SCNR :Utopia Park +STR_PARK :Utopia Park +STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +STR_SCNR :Fiasco Forest +STR_PARK :Fiasco Forest +STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around + + +STR_SCNR :Pickle Park +STR_PARK :Pickle Park +STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +STR_SCNR :Coaster Crazy +STR_PARK :Coaster Crazy +STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park + + +STR_SCNR :Urban Park +STR_PARK :Urban Park +STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +STR_SCNR :Arid Heights +STR_PARK :Arid Heights +STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +STR_SCNR :Vertigo Views +STR_PARK :Vertigo Views +STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit + + +STR_SCNR :Paradise Pier 2 +STR_PARK :Paradise Pier 2 +STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +STR_SCNR :Good Knight Park +STR_PARK :Good Knight Park +STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +STR_SCNR :Crazy Craters +STR_PARK :Crazy Craters +STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +STR_SCNR :Sunny Swamps +STR_PARK :Sunny Swamps +STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +STR_SCNR :Thunder Rocks +STR_PARK :Thunder Rocks +STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into as an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +STR_SCNR :Venus Ponds +STR_PARK :Venus Ponds +STR_DTLS :On a far-away planet this area of land needs turning into a theme park + + +STR_SCNR :Micro Park +STR_PARK :Micro Park +STR_DTLS :Try to create the world's smallest profitable park + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : + ##################### # Rides/attractions # ##################### From 5a4ad66a8076f53b4fbc509c327554fe311bb365 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 17:41:53 +0000 Subject: [PATCH 65/90] fix order of Southern Sands and Tiny Towers --- src/scenario_sources.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 90fddcd7e8..9e5ced6c12 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -105,8 +105,8 @@ const scenario_title_desc ScenarioTitlesRCT1LL[] = { { SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING }, { SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING }, { SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING }, - { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, { SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_CHALLENGING }, + { SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING }, { SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_CHALLENGING }, { SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_CHALLENGING }, { SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT }, From 212b8bfa105f1fd5c807a795372f2f729873b220 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 17:57:02 +0000 Subject: [PATCH 66/90] translate scenarios by raw normalised name --- src/scenario.c | 9 ++++----- src/scenario_list.c | 7 +------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/scenario.c b/src/scenario.c index 3c52ad321f..7dd400aa0c 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -268,13 +268,12 @@ void scenario_begin() safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name, 64); { - // Get filename - utf8 filename[MAX_PATH]; - safe_strncpy(filename, _scenarioFileName, sizeof(filename)); - path_remove_extension(filename); + utf8 normalisedName[64]; + safe_strncpy(normalisedName, s6Info->name, sizeof(normalisedName)); + scenario_normalise_name(normalisedName); rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(filename, localisedStringIds)) { + if (language_get_localised_scenario_strings(normalisedName, localisedStringIds)) { if (localisedStringIds[0] != (rct_string_id)STR_NONE) { safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(localisedStringIds[0]), 32); } diff --git a/src/scenario_list.c b/src/scenario_list.c index 3604a3d806..1a403da647 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -71,7 +71,6 @@ void scenario_load_list() scenario_list_sort(); scenario_scores_load(); - utf8 scoresPath[MAX_PATH]; scenario_scores_legacy_get_path(scoresPath); scenario_scores_legacy_load(scoresPath); @@ -189,12 +188,8 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry) { - utf8 filenameWithoutExtension[MAX_PATH]; - safe_strncpy(filenameWithoutExtension, scenarioEntry->path, sizeof(filenameWithoutExtension)); - path_remove_extension(filenameWithoutExtension); - rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(filenameWithoutExtension, localisedStringIds)) { + if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds)) { if (localisedStringIds[0] != (rct_string_id)STR_NONE) { safe_strncpy(scenarioEntry->name, language_get_string(localisedStringIds[0]), 64); } From 2f00a285039a3b6817b32ca9ac82b0813035d2fb Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 18:16:52 +0000 Subject: [PATCH 67/90] add Geoffrey Gardens mistake alias --- src/scenario_sources.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 9e5ced6c12..2e5b0f45c0 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -7,6 +7,7 @@ typedef struct { } scenario_alias; const scenario_alias ScenarioAliases[] = { + // UK - US differences: { "Katie's Dreamland", "Katie's World" }, { "Pokey Park", "Dinky Park" }, { "White Water Park", "Aqua Park" }, @@ -14,6 +15,9 @@ const scenario_alias ScenarioAliases[] = { { "Paradise Pier", "Big Pier" }, { "Paradise Pier 2", "Big Pier 2" }, { "Mythological - Cradle of Civilisation", "Mythological - Cradle of Civilization" }, + + // RCT1 pack by RCTScenarioLover has a mistake: + { "Geoffrey Gardens", "Geoffery Gardens" }, }; typedef struct { From a4e919b02345cb40ff742fd7b15fe7bc976cb777 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 18:37:31 +0000 Subject: [PATCH 68/90] fix scenario sorting for real and other parks --- src/scenario_list.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/scenario_list.c b/src/scenario_list.c index 1a403da647..bfede50777 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -232,10 +232,22 @@ static int scenario_list_sort_by_name(const void *a, const void *b) const scenario_index_entry *entryA = (const scenario_index_entry*)a; const scenario_index_entry *entryB = (const scenario_index_entry*)b; - if (entryA->source_game != entryB->source_game) { - return entryA->source_game - entryB->source_game; + // Order by category + if (entryA->category != entryB->category) { + return entryA->category - entryB->category; + } + + // Then by source game / name + switch (entryA->category) { + default: + if (entryA->source_game != entryB->source_game) { + return entryA->source_game - entryB->source_game; + } + return strcmp(entryA->name, entryB->name); + case SCENARIO_CATEGORY_REAL: + case SCENARIO_CATEGORY_OTHER: + return strcmp(entryA->name, entryB->name); } - return strcmp(entryA->name, entryB->name); } static int scenario_list_sort_by_index(const void *a, const void *b) @@ -243,14 +255,37 @@ static int scenario_list_sort_by_index(const void *a, const void *b) const scenario_index_entry *entryA = (const scenario_index_entry*)a; const scenario_index_entry *entryB = (const scenario_index_entry*)b; - if (entryA->source_game == SCENARIO_SOURCE_OTHER && entryB->source_game == SCENARIO_SOURCE_OTHER) { + // Order by source game + if (entryA->source_game != entryB->source_game) { + return entryA->source_game - entryB->source_game; + } + + // Then by index / category / name + uint8 sourceGame = entryA->source_game; + switch (sourceGame) { + default: + if (entryA->source_index == -1 && entryB->source_index == -1) { + if (entryA->category == entryB->category) { + return scenario_list_sort_by_name(a, b); + } else { + return entryA->category - entryB->category; + } + } else if (entryA->source_index == -1) { + return 1; + } else if (entryB->source_index == -1) { + return -1; + } else { + return entryA->source_index - entryB->source_index; + } + case SCENARIO_SOURCE_REAL: + return scenario_list_sort_by_name(a, b); + case SCENARIO_SOURCE_OTHER: if (entryA->category == entryB->category) { return scenario_list_sort_by_name(a, b); } else { return entryA->category - entryB->category; } } - return entryA->source_index - entryB->source_index; } scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename) From ededc82cba842432f501f70c6db34aafe8209daa Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 20:40:24 +0000 Subject: [PATCH 69/90] add DLC and Build your own scenario classification --- data/language/english_uk.txt | 3 +- src/localisation/string_ids.h | 3 ++ src/scenario.c | 11 ++++++ src/scenario.h | 11 +++++- src/scenario_list.c | 30 +++++++++------- src/scenario_sources.c | 37 ++++++++++++-------- src/windows/editor_objective_options.c | 6 ++-- src/windows/title_scenarioselect.c | 47 +++++++++++++++++++------- 8 files changed, 103 insertions(+), 45 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index a7fb98c133..b275753414 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3969,7 +3969,8 @@ STR_5627 :Group scenario list by: STR_5628 :Source game STR_5629 :Difficulty level STR_5630 :Enable unlocking of scenarios -STR_5631 :{GREY}{STRINGID} +STR_5631 :Original DLC Parks +STR_5632 :Build your own... ############# # Scenarios # diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index e62e622dc0..fe5d9012e6 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2254,6 +2254,9 @@ enum { STR_OPTIONS_SCENARIO_DIFFICULTY = 5629, STR_OPTIONS_SCENARIO_UNLOCKING = 5630, + STR_DLC_PARKS = 5631, + STR_BUILD_YOUR_OWN_PARKS = 5632, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 }; diff --git a/src/scenario.c b/src/scenario.c index 7dd400aa0c..52973e9491 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -45,6 +45,17 @@ #include "world/sprite.h" #include "world/water.h" +const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT] = { + STR_BEGINNER_PARKS, + STR_CHALLENGING_PARKS, + STR_EXPERT_PARKS, + STR_REAL_PARKS, + STR_OTHER_PARKS, + + STR_DLC_PARKS, + STR_BUILD_YOUR_OWN_PARKS, +}; + static char _scenarioPath[MAX_PATH]; static const char *_scenarioFileName = ""; diff --git a/src/scenario.h b/src/scenario.h index 41d3ffa3b4..c8a4b8bfa6 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -398,11 +398,18 @@ enum { #define S6_MAGIC_NUMBER 0x00031144 enum { + // RCT2 categories (keep order) SCENARIO_CATEGORY_BEGINNER, SCENARIO_CATEGORY_CHALLENGING, SCENARIO_CATEGORY_EXPERT, SCENARIO_CATEGORY_REAL, - SCENARIO_CATEGORY_OTHER + SCENARIO_CATEGORY_OTHER, + + // OpenRCT2 categories + SCENARIO_CATEGORY_DLC, + SCENARIO_CATEGORY_BUILD_YOUR_OWN, + + SCENARIO_CATEGORY_COUNT }; enum { @@ -455,6 +462,8 @@ typedef struct { uint8 category; } source_desc; +extern const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT]; + // Scenario list extern int gScenarioListCount; extern int gScenarioListCapacity; diff --git a/src/scenario_list.c b/src/scenario_list.c index bfede50777..d5041788ed 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -37,7 +37,7 @@ scenario_highscore_entry *gScenarioHighscoreList = NULL; static void scenario_list_include(const utf8 *directory); static void scenario_list_add(const utf8 *path, uint64 timestamp); static void scenario_list_sort(); -static int scenario_list_sort_by_name(const void *a, const void *b); +static int scenario_list_sort_by_category(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry); @@ -222,19 +222,29 @@ static void scenario_list_sort() compareFunc = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN ? scenario_list_sort_by_index : - scenario_list_sort_by_name; + scenario_list_sort_by_category; qsort(gScenarioList, gScenarioListCount, sizeof(scenario_index_entry), compareFunc); } -static int scenario_list_sort_by_name(const void *a, const void *b) +static int scenario_list_category_compare(int categoryA, int categoryB) +{ + if (categoryA == categoryB) return 0; + if (categoryA == SCENARIO_CATEGORY_DLC) return -1; + if (categoryB == SCENARIO_CATEGORY_DLC) return 1; + if (categoryA == SCENARIO_CATEGORY_BUILD_YOUR_OWN) return -1; + if (categoryB == SCENARIO_CATEGORY_BUILD_YOUR_OWN) return 1; + return sgn(categoryA - categoryB); +} + +static int scenario_list_sort_by_category(const void *a, const void *b) { const scenario_index_entry *entryA = (const scenario_index_entry*)a; const scenario_index_entry *entryB = (const scenario_index_entry*)b; // Order by category if (entryA->category != entryB->category) { - return entryA->category - entryB->category; + return scenario_list_category_compare(entryA->category, entryB->category); } // Then by source game / name @@ -266,9 +276,9 @@ static int scenario_list_sort_by_index(const void *a, const void *b) default: if (entryA->source_index == -1 && entryB->source_index == -1) { if (entryA->category == entryB->category) { - return scenario_list_sort_by_name(a, b); + return scenario_list_sort_by_category(a, b); } else { - return entryA->category - entryB->category; + return scenario_list_category_compare(entryA->category, entryB->category); } } else if (entryA->source_index == -1) { return 1; @@ -278,13 +288,7 @@ static int scenario_list_sort_by_index(const void *a, const void *b) return entryA->source_index - entryB->source_index; } case SCENARIO_SOURCE_REAL: - return scenario_list_sort_by_name(a, b); - case SCENARIO_SOURCE_OTHER: - if (entryA->category == entryB->category) { - return scenario_list_sort_by_name(a, b); - } else { - return entryA->category - entryB->category; - } + return scenario_list_sort_by_category(a, b); } } diff --git a/src/scenario_sources.c b/src/scenario_sources.c index 2e5b0f45c0..1ca3c957cb 100644 --- a/src/scenario_sources.c +++ b/src/scenario_sources.c @@ -191,26 +191,35 @@ const scenario_title_desc ScenarioTitlesRealParks[] = { }; // Other parks -const scenario_title_desc ScenarioTitlesRCT2BuildYourOwnParks[] = { - { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_OTHER }, - { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_OTHER }, - { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_OTHER }, - { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_OTHER }, - { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_OTHER }, - { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_OTHER }, +const scenario_title_desc ScenarioTitlesOtherParks[] = { + { SC_UNIDENTIFIED, "Fort Anachronism", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "PC Player", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "PC Gaming World", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "gameplay", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Competition Land 1", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Competition Land 2", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, }; +#define DEFINE_SCENARIO_TITLE_DESC_GROUP(x) { countof(x), x } const struct { int count; const scenario_title_desc * const titles; } ScenarioTitlesBySource[] = { - { countof(ScenarioTitlesRCT1), ScenarioTitlesRCT1 }, - { countof(ScenarioTitlesRCT1AA), ScenarioTitlesRCT1AA }, - { countof(ScenarioTitlesRCT1LL), ScenarioTitlesRCT1LL }, - { countof(ScenarioTitlesRCT2), ScenarioTitlesRCT2 }, - { countof(ScenarioTitlesRCT2WW), ScenarioTitlesRCT2WW }, - { countof(ScenarioTitlesRCT2TT), ScenarioTitlesRCT2TT }, - { countof(ScenarioTitlesRealParks), ScenarioTitlesRealParks }, + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1AA), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1LL), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2WW), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2TT), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRealParks), + DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesOtherParks), }; bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc) diff --git a/src/windows/editor_objective_options.c b/src/windows/editor_objective_options.c index 04bdad6fd1..aa7861c59e 100644 --- a/src/windows/editor_objective_options.c +++ b/src/windows/editor_objective_options.c @@ -534,9 +534,9 @@ static void window_editor_objective_options_show_category_dropdown(rct_window *w dropdownWidget = &w->widgets[WIDX_CATEGORY]; - for (i = 0; i < 5; i++) { + for (i = SCENARIO_CATEGORY_BEGINNER; i <= SCENARIO_CATEGORY_OTHER; i++) { gDropdownItemsFormat[i] = 1142; - gDropdownItemsArgs[i] = STR_BEGINNER_PARKS + i; + gDropdownItemsArgs[i] = ScenarioCategoryStringIds[i]; } window_dropdown_show_text_custom_width( w->x + dropdownWidget->left, @@ -1036,7 +1036,7 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi // Scenario category value x = w->x + w->widgets[WIDX_CATEGORY].left + 1; y = w->y + w->widgets[WIDX_CATEGORY].top; - stringId = STR_BEGINNER_PARKS + s6Info->category; + stringId = ScenarioCategoryStringIds[s6Info->category]; gfx_draw_string_left(dpi, 1193, &stringId, 0, x, y); } diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 156133e8e6..fc8fdbd184 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -189,7 +189,11 @@ static void window_scenarioselect_init_tabs(rct_window *w) if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { showPages |= 1 << scenario->source_game; } else { - showPages |= 1 << scenario->category; + int category = scenario->category; + if (category > SCENARIO_CATEGORY_OTHER) { + category = SCENARIO_CATEGORY_OTHER; + } + showPages |= 1 << category; } } @@ -358,7 +362,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1 + i; } else { // old-style - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_BEGINNER_PARKS + i; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = ScenarioCategoryStringIds[i]; } gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 87, format, 10); } @@ -415,7 +419,6 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * int highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193; int unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191; - int disabled_format = 5619; bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN; @@ -528,14 +531,25 @@ static void initialise_list_items(rct_window *w) // Category heading rct_string_id headingStringId = STR_NONE; if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { - if (w->selected_tab != 6 && currentHeading != scenario->category) { + if (w->selected_tab != SCENARIO_SOURCE_REAL && currentHeading != scenario->category) { currentHeading = scenario->category; - headingStringId = STR_BEGINNER_PARKS + currentHeading; + headingStringId = ScenarioCategoryStringIds[currentHeading]; } } else { - if (w->selected_tab < 3 && currentHeading != scenario->source_game) { - currentHeading = scenario->source_game; - headingStringId = STR_SCENARIO_CATEGORY_RCT1 + currentHeading; + if (w->selected_tab <= SCENARIO_CATEGORY_EXPERT) { + if (currentHeading != scenario->source_game) { + currentHeading = scenario->source_game; + headingStringId = STR_SCENARIO_CATEGORY_RCT1 + currentHeading; + } + } else if (w->selected_tab == SCENARIO_CATEGORY_OTHER) { + int category = scenario->category; + if (category <= SCENARIO_CATEGORY_REAL) { + category = SCENARIO_CATEGORY_OTHER; + } + if (currentHeading != category) { + currentHeading = category; + headingStringId = ScenarioCategoryStringIds[category]; + } } } if (headingStringId != (rct_string_id)STR_NONE) { @@ -612,12 +626,19 @@ static void initialise_list_items(rct_window *w) static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario) { - if ((gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN && scenario->source_game != w->selected_tab) || - (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY && scenario->category != w->selected_tab) - ) { - return false; + if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) { + if (scenario->source_game != w->selected_tab) { + return false; + } + } else { + int category = scenario->category; + if (category > SCENARIO_CATEGORY_OTHER) { + category = SCENARIO_CATEGORY_OTHER; + } + if (category != w->selected_tab) { + return false; + } } - return true; } From 9eacd3532b76bcbef3a743126667ce8800aa1e7f Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 21:13:24 +0000 Subject: [PATCH 70/90] use correct window variable for highlighted scenario --- src/interface/window.h | 2 +- src/windows/title_scenarioselect.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/interface/window.h b/src/interface/window.h index 14caac8e53..c3fddca24b 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -277,7 +277,7 @@ typedef struct rct_window { uint16 ride_colour; rct_research_item* research_item; rct_object_entry* object_entry; - rct_scenario_basic* scenario; + scenario_index_entry* highlighted_scenario; }; uint8 var_498[0x14]; sint16 selected_tab; // 0x4AC diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index fc8fdbd184..c61a98c455 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -174,7 +174,7 @@ void window_scenarioselect_open() window_init_scroll_widgets(window); window->viewport_focus_coordinates.var_480 = -1; - window->highlighted_item = 0; + window->highlighted_scenario = NULL; } /** @@ -233,7 +233,7 @@ static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_w { if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB8) { w->selected_tab = widgetIndex - 4; - w->highlighted_item = 0; + w->highlighted_scenario = NULL; initialise_list_items(w); window_invalidate(w); window_event_resize_call(w); @@ -308,8 +308,8 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex } } - if (w->highlighted_item != (uint32)selected) { - w->highlighted_item = (uint32)selected; + if (w->highlighted_scenario != selected) { + w->highlighted_scenario = selected; window_invalidate(w); } } @@ -368,9 +368,10 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) } // Return if no scenario highlighted - scenario = (scenario_index_entry*)w->highlighted_item; - if (scenario == NULL) + scenario = w->highlighted_scenario; + if (scenario == NULL) { return; + } // Scenario path if (gConfigGeneral.debugging_tools) { @@ -440,7 +441,7 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * case LIST_ITEM_TYPE_SCENARIO:; // Draw hover highlight scenario_index_entry *scenario = listItem->scenario.scenario; - bool isHighlighted = w->highlighted_item == (uint32)scenario; + bool isHighlighted = w->highlighted_scenario == scenario; if (isHighlighted) { gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); } From 9b833e5f93c30371ed03a1062981b7a0184bd914 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 22:41:35 +0000 Subject: [PATCH 71/90] shorten path for scenario select debug --- src/drawing/drawing.h | 1 + src/drawing/string.c | 42 ++++++++++++++++++++++++-- src/windows/loadsave.c | 47 ++++-------------------------- src/windows/title_scenarioselect.c | 7 +++-- 4 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 0cd56e2cfb..81bbf2bd8f 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -149,6 +149,7 @@ int string_get_height_raw(char *buffer); void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int y, int width, int colour, rct_string_id format, void *args, int ticks); void gfx_draw_string_with_y_offsets(rct_drawpixelinfo *dpi, const utf8 *text, int colour, int x, int y, const sint8 *yOffsets, bool forceSpriteFont); int gfx_clip_string(char* buffer, int width); +void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availableWidth); bool ttf_initialise(); void ttf_dispose(); diff --git a/src/drawing/string.c b/src/drawing/string.c index f12f0af0e0..7cfaf346df 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -21,9 +21,10 @@ #include "../addresses.h" #include "../interface/colour.h" #include "../localisation/localisation.h" -#include "../sprites.h" -#include "../world/map.h" #include "../platform/platform.h" +#include "../sprites.h" +#include "../util/util.h" +#include "../world/map.h" #include "drawing.h" static int ttf_get_string_width(const utf8 *text); @@ -1355,3 +1356,40 @@ void gfx_draw_string_with_y_offsets(rct_drawpixelinfo *dpi, const utf8 *text, in gLastDrawStringX = info.x; gLastDrawStringY = info.y; } + +void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availableWidth) +{ + int length = strlen(path); + + // Return full string if it fits + if (gfx_get_string_width((char*)path) <= availableWidth) { + safe_strncpy(buffer, path, bufferSize); + return; + } + + // Count path separators + int path_separators = 0; + for (int x = 0; x < length; x++) { + if (path[x] == platform_get_path_separator()) { + path_separators++; + } + } + + // TODO: Replace with unicode ellipsis when supported + safe_strncpy(buffer, "...", bufferSize); + + // Abreviate beginning with xth separator + int begin = -1; + for (int x = 0; x < path_separators; x++){ + do { + begin++; + } while (path[begin] != platform_get_path_separator()); + + safe_strncpy(buffer + 3, path + begin, bufferSize - 3); + if (gfx_get_string_width(buffer) <= availableWidth) { + return; + } + } + + safe_strncpy(buffer, path, bufferSize); +} diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index 0a665ef22a..42842a8723 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -144,8 +144,6 @@ static void window_loadsave_sort_list(int index, int endIndex); static int has_extension(char *path, char *extension); -static void shorten_path(char* path, char* buffer, int available_width); - static rct_window *window_overwrite_prompt_open(const char *name, const char *path); rct_window *window_loadsave_open(int type, char *defaultName) @@ -296,8 +294,9 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) } case WIDX_BROWSE: safe_strncpy(path, _directory, MAX_PATH); - if (_type & LOADSAVETYPE_SAVE) - strcat(path, (char*)RCT2_ADDRESS_SCENARIO_NAME); + if (_type & LOADSAVETYPE_SAVE) { + strcat(path, _defaultName); + } memset(filter, '\0', MAX_PATH); safe_strncpy(filter, "*", MAX_PATH); @@ -470,8 +469,9 @@ static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); - if (_shortenedDirectory[0] == '\0') - shorten_path(_directory, _shortenedDirectory, w->width - 8); + if (_shortenedDirectory[0] == '\0') { + shorten_path(_shortenedDirectory, sizeof(_shortenedDirectory), _directory, w->width - 8); + } utf8 buffer[256]; @@ -500,41 +500,6 @@ static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi) gfx_draw_string_centred_clipped(dpi, STR_DATE, &id, 1, w->x + 4 + (w->width - 8) * 3 / 4, w->y + 50, (w->width - 8) / 2); } -static void shorten_path(char* path, char* buffer, int available_width){ - int length = strlen(path); - - // Return full string if it fits - if (gfx_get_string_width(path) <= available_width){ - strcpy(buffer, path); - return; - } - - // Count path separators - int path_separators = 0; - for (int x = 0; x < length; x++) - if (path[x] == platform_get_path_separator()) - path_separators++; - - // TODO: Replace with unicode ellipsis when supported - strcpy(buffer, "..."); - - // Abreviate beginning with xth separator - - int begin = -1; - for (int x = 0; x < path_separators; x++){ - do { - begin++; - } while (path[begin] != platform_get_path_separator()); - - strcpy(buffer + 3, path + begin); - if (gfx_get_string_width(buffer) <= available_width) - return; - } - - strcpy(buffer, path); - return; -} - static void window_loadsave_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { int i, y; diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index c61a98c455..d94e7414fc 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -375,8 +375,11 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) // Scenario path if (gConfigGeneral.debugging_tools) { - const utf8 *path = scenario->path; - gfx_draw_string_left(dpi, 1170, (void*)&path, w->colours[1], w->x + 3, w->y + w->height - 3 - 11); + utf8 path[MAX_PATH]; + shorten_path(path, sizeof(path), scenario->path, w->width - 6); + + const utf8 *pathPtr = path; + gfx_draw_string_left(dpi, 1170, (void*)&pathPtr, w->colours[1], w->x + 3, w->y + w->height - 3 - 11); } // Scenario name From d2653e304d6c0139b073e2cd7306b91366015faf Mon Sep 17 00:00:00 2001 From: LRFLEW Date: Sat, 2 Jan 2016 16:13:07 -0600 Subject: [PATCH 72/90] Added scenario_sources.c to Xcode --- OpenRCT2.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 1e0b1c12fa..9c5496a6af 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D41B74721C2125E50080A7B9 /* Assets.xcassets */; }; D435325F1C3472E500BA219B /* libpng.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D435325E1C3472E500BA219B /* libpng.dylib */; }; D43532601C34730200BA219B /* libpng.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D435325E1C3472E500BA219B /* libpng.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + D46105CE1C38828D00DB1EE3 /* scenario_sources.c in Sources */ = {isa = PBXBuildFile; fileRef = D46105CD1C38828D00DB1EE3 /* scenario_sources.c */; }; D4ABAB061C2F812B0080CAD9 /* news_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4ABAB051C2F812B0080CAD9 /* news_options.c */; }; D4D4DF141C34697B0048BE43 /* image_io.c in Sources */ = {isa = PBXBuildFile; fileRef = D4D4DF121C34697B0048BE43 /* image_io.c */; }; D4EC47DF1C26342F0024B507 /* addresses.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46D61C26342F0024B507 /* addresses.c */; }; @@ -219,6 +220,7 @@ D41B741C1C210A7A0080A7B9 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; D41B74721C2125E50080A7B9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = distribution/osx/Assets.xcassets; sourceTree = SOURCE_ROOT; }; D435325E1C3472E500BA219B /* libpng.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libpng.dylib; sourceTree = ""; }; + D46105CD1C38828D00DB1EE3 /* scenario_sources.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scenario_sources.c; path = src/scenario_sources.c; sourceTree = ""; }; D4895D321C23EFDD000CD788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = distribution/osx/Info.plist; sourceTree = SOURCE_ROOT; }; D497D0781C20FD52002BF46A /* OpenRCT2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenRCT2.app; sourceTree = BUILT_PRODUCTS_DIR; }; D4ABAB051C2F812B0080CAD9 /* news_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = news_options.c; sourceTree = ""; }; @@ -626,6 +628,7 @@ D4EC47591C26342F0024B507 /* rct2.c */, D4EC475A1C26342F0024B507 /* rct2.h */, D4EC476D1C26342F0024B507 /* scenario_list.c */, + D46105CD1C38828D00DB1EE3 /* scenario_sources.c */, D4EC476E1C26342F0024B507 /* scenario.c */, D4EC476F1C26342F0024B507 /* scenario.h */, D4EC47701C26342F0024B507 /* sprites.h */, @@ -1450,6 +1453,7 @@ D4EC482D1C26342F0024B507 /* util.c in Sources */, D4EC47EA1C26342F0024B507 /* line.c in Sources */, D4EC48271C26342F0024B507 /* vehicle.c in Sources */, + D46105CE1C38828D00DB1EE3 /* scenario_sources.c in Sources */, D4EC48281C26342F0024B507 /* scenario_list.c in Sources */, D4EC48581C26342F0024B507 /* scenery.c in Sources */, D4EC48061C26342F0024B507 /* LanguagePack.cpp in Sources */, From 9d5e798b7aa7e75e66e3bfff1887332bff280ba4 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 2 Jan 2016 23:26:41 +0000 Subject: [PATCH 73/90] update changelog --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 10572450f9..dc24bc75c6 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -6,6 +6,7 @@ - Feature: Update alternative font selection mechanism for all platforms. - Feature: Allow enabling / disabling of different notifications. - Feature: Improved tile inspector. +- Feature: Integrate RCT1 style scenario select with optional unlock progression. - Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug) - Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day From 5a17d6d2ece8f4eac2173492b3826d2efd37e033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 3 Jan 2016 01:20:32 +0100 Subject: [PATCH 74/90] Limit travis jobs Leave all passing jobs commented out for future reference in hopes they will be tested with large changes or when doing changes to CMakeLists --- .travis.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index ada6a796a8..7fa2eb782b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,16 +16,20 @@ cache: apt: true env: - - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" - - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++" - - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" - - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=OFF -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + - OPENRCT2_CMAKE_OPTS="-DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + - OPENRCT2_CMAKE_OPTS="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++" - OPENRCT2_CMAKE_OPTS="-DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows - - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows - - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows - - OPENRCT2_CMAKE_OPTS="-DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows - TARGET=docker32 - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON" TARGET=docker32 + # Following entries used to be included in testing, but they only proved useful while changing things in CMake setup. + # They are meant to be used when there are changes to CMakeLists.txt + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++" + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=OFF -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows + # - OPENRCT2_CMAKE_OPTS="-DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows sudo: required dist: trusty From 99e0d999b277eb87219fc500eb16a413876406fc Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sun, 3 Jan 2016 01:48:52 +0000 Subject: [PATCH 75/90] add timestamp to highscores.dat --- src/platform/platform.h | 2 ++ src/platform/posix.c | 19 +++++++++++++++++++ src/platform/windows.c | 13 +++++++++++++ src/rct2.h | 5 +++++ src/scenario.c | 1 + src/scenario.h | 1 + src/scenario_list.c | 3 +++ 7 files changed, 44 insertions(+) diff --git a/src/platform/platform.h b/src/platform/platform.h index c9e3eb23ad..026e6df020 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -166,6 +166,8 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer); bool platform_check_steam_overlay_attached(); +datetime64 platform_get_datetime_now_utc(); + // BSD and OS X has MAP_ANON instead of MAP_ANONYMOUS #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON diff --git a/src/platform/posix.c b/src/platform/posix.c index 36d9844c15..b331c49b34 100644 --- a/src/platform/posix.c +++ b/src/platform/posix.c @@ -753,4 +753,23 @@ uint8 platform_get_locale_temperature_format(){ return TEMPERATURE_FORMAT_C; } +datetime64 platform_get_datetime_now_utc() +{ + const datetime64 epochAsTicks = 621355968000000000; + + // Get current time + time_t rawtime; + time(&rawtime); + + // Convert to UTC epoch + struct tm *utcTM = gmtime(&rawtime); + time_t utcEpoch = mktime(utcTM); + + // Epoch starts from: 1970-01-01T00:00:00Z + // Convert to ticks from 0001-01-01T00:00:00Z + uint64 utcEpochTicks = (uint64)utcEpoch * 10000000ULL; + datetime64 utcNow = epochAsTicks + utcEpochTicks; + return utcNow; +} + #endif diff --git a/src/platform/windows.c b/src/platform/windows.c index d1443b762a..87a1d9df81 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -935,4 +935,17 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) #endif } +datetime64 platform_get_datetime_now_utc() +{ + // Get file time + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + uint64 fileTime64 = ((uint64)fileTime.dwHighDateTime << 32ULL) | ((uint64)fileTime.dwLowDateTime); + + // File time starts from: 1601-01-01T00:00:00Z + // Convert to start from: 0001-01-01T00:00:00Z + datetime64 utcNow = fileTime64 - 504911232000000000ULL; + return utcNow; +} + #endif diff --git a/src/rct2.h b/src/rct2.h index 8885921a74..07bc633de7 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -115,6 +115,11 @@ typedef utf16* utf16string; #define OPENRCT2_MASTER_SERVER_URL "https://servers.openrct2.website" +// Time (represented as number of 100-nanosecond intervals since 0001-01-01T00:00:00Z) +typedef uint64 datetime64; + +#define DATETIME64_MIN ((datetime64)0) + // Represent fixed point numbers. dp = decimal point typedef uint8 fixed8_1dp; typedef uint8 fixed8_2dp; diff --git a/src/scenario.c b/src/scenario.c index 52973e9491..c7bcdcafb0 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -416,6 +416,7 @@ void scenario_success() scenario->highscore->fileName = _strdup(path_get_filename(scenario->path)); scenario->highscore->name = NULL; scenario->highscore->company_value = companyValue; + scenario->highscore->timestamp = platform_get_datetime_now_utc(); // Allow name entry RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_SCENARIO_COMPLETE_NAME_INPUT; diff --git a/src/scenario.h b/src/scenario.h index c8a4b8bfa6..6368292d79 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -431,6 +431,7 @@ typedef struct { utf8 *fileName; utf8 *name; money32 company_value; + datetime64 timestamp; } scenario_highscore_entry; typedef struct { diff --git a/src/scenario_list.c b/src/scenario_list.c index d5041788ed..d62c906946 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -385,6 +385,7 @@ static bool scenario_scores_legacy_load(const utf8 *path) highscore->fileName = _strdup(scBasic.path); highscore->name = _strdup(scBasic.completed_by); highscore->company_value = (money32)scBasic.company_value; + highscore->timestamp = DATETIME64_MIN; highscoresDirty = true; } @@ -431,6 +432,7 @@ static bool scenario_scores_load() highscore->fileName = io_read_string(file); highscore->name = io_read_string(file); SDL_RWread(file, &highscore->company_value, sizeof(highscore->company_value), 1); + SDL_RWread(file, &highscore->timestamp, sizeof(highscore->timestamp), 1); // Attach highscore to correct scenario entry scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_filename(highscore->fileName); @@ -467,6 +469,7 @@ bool scenario_scores_save() io_write_string(file, highscore->fileName); io_write_string(file, highscore->name); SDL_RWwrite(file, &highscore->company_value, sizeof(highscore->company_value), 1); + SDL_RWwrite(file, &highscore->timestamp, sizeof(highscore->timestamp), 1); } SDL_RWclose(file); From b45ca38d52ec82e031d0c1ef68fdd5f84ce7ffae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 3 Jan 2016 21:41:21 +0100 Subject: [PATCH 76/90] UTC epoch time for POSIX --- src/platform/posix.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/platform/posix.c b/src/platform/posix.c index b331c49b34..fe656a3d5b 100644 --- a/src/platform/posix.c +++ b/src/platform/posix.c @@ -36,6 +36,7 @@ #include #include #include +#include #include // The name of the mutex used to prevent multiple instances of the game from running @@ -757,17 +758,14 @@ datetime64 platform_get_datetime_now_utc() { const datetime64 epochAsTicks = 621355968000000000; - // Get current time - time_t rawtime; - time(&rawtime); + struct timeval tv; + gettimeofday(&tv, NULL); - // Convert to UTC epoch - struct tm *utcTM = gmtime(&rawtime); - time_t utcEpoch = mktime(utcTM); + uint64 utcEpoch = tv.tv_sec; // Epoch starts from: 1970-01-01T00:00:00Z // Convert to ticks from 0001-01-01T00:00:00Z - uint64 utcEpochTicks = (uint64)utcEpoch * 10000000ULL; + uint64 utcEpochTicks = (uint64)tv.tv_sec * 10000000ULL + tv.tv_usec * 10; datetime64 utcNow = epochAsTicks + utcEpochTicks; return utcNow; } From b94cd7499d673360d936704241b322a74894c02b Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sun, 3 Jan 2016 21:06:10 +0000 Subject: [PATCH 77/90] add config for hide mega park and set locking as default --- src/config.c | 3 ++- src/config.h | 1 + src/windows/title_scenarioselect.c | 4 +--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config.c b/src/config.c index b7eb07921c..8ff2ccced9 100644 --- a/src/config.c +++ b/src/config.c @@ -204,7 +204,8 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, trap_cursor), "trap_cursor", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, auto_open_shops), "auto_open_shops", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, scenario_select_mode), "scenario_select_mode", CONFIG_VALUE_TYPE_UINT8, SCENARIO_SELECT_MODE_ORIGIN, NULL }, - { offsetof(general_configuration, scenario_unlocking_enabled), "scenario_unlocking_enabled", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(general_configuration, scenario_unlocking_enabled), "scenario_unlocking_enabled", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(general_configuration, scenario_hide_mega_park), "scenario_hide_mega_park", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, }; diff --git a/src/config.h b/src/config.h index daa64f9e2b..ced0402a6a 100644 --- a/src/config.h +++ b/src/config.h @@ -179,6 +179,7 @@ typedef struct { uint8 auto_open_shops; uint8 scenario_select_mode; uint8 scenario_unlocking_enabled; + uint8 scenario_hide_mega_park; } general_configuration; typedef struct { diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index d94e7414fc..20e358ceed 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -606,8 +606,7 @@ static void initialise_list_items(rct_window *w) if (megaParkListItemIndex != -1) { bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios; _listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked; -#ifdef HIDE_MEGA_PARK - if (megaParkLocked) { + if (megaParkLocked && gConfigGeneral.scenario_hide_mega_park) { // Remove mega park int remainingItems = length - megaParkListItemIndex - 1; memmove(&_listItems[megaParkListItemIndex], &_listItems[megaParkListItemIndex + 1], remainingItems); @@ -624,7 +623,6 @@ static void initialise_list_items(rct_window *w) } } } -#endif } } From e4052b332febf559babd0ba70c85313860366e01 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 4 Jan 2016 04:00:18 +0000 Subject: [PATCH 78/90] Merge Localisation/master into OpenRCT2/develop. --- data/language/german.txt | 39 +++++++- data/language/korean.txt | 190 +++++++++++++++++++-------------------- 2 files changed, 131 insertions(+), 98 deletions(-) diff --git a/data/language/german.txt b/data/language/german.txt index b2903cfcc1..5c5f2f5cc9 100644 --- a/data/language/german.txt +++ b/data/language/german.txt @@ -3672,8 +3672,8 @@ STR_5335 :Attraktionseingang STR_5336 :Attraktionsausgang STR_5337 :Parkeingang STR_5338 :Elementtyp -STR_5339 :Basishöhe -STR_5340 :Lichte Höhe +STR_5339 :{SMALLFONT}{BLACK}Basishöhe +STR_5340 :{SMALLFONT}{BLACK}Lichte Höhe STR_5341 :Kennzeichen STR_5342 :Eine Kachel auf der Karte auswählen STR_5343 :Personal automatisch platzieren @@ -3898,7 +3898,7 @@ STR_5561 :Sprache konnte nicht geladen werden STR_5562 :WARNUNG! STR_5563 :Diese Funktion ist derzeit instabil und mit erhöhter Vorsicht zu verwenden. STR_5564 :Fehlerhaftes Element einf. -STR_5565 :{SMALLFONT}{BLACK}Fügt ein fehlerhaftes Kartenelement auf der Kachel ein, dadurch werden alle Elemente darüber versteckt. +STR_5565 :{SMALLFONT}{BLACK}Fügt ein fehlerhaftes Kartenelement auf{NEWLINE}der Kachel ein, dadurch werden alle Elemente darüber versteckt. STR_5566 :Passwort: STR_5567 :Veröffentlichen STR_5568 :Passwort benötigt @@ -3919,6 +3919,39 @@ STR_5582 :Mauszeiger im Fenster fangen STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} STR_5584 :SI STR_5585 :{SMALLFONT}{BLACK}Hebt Beschränkungen von Attraktionen auf, um Dinge wie {VELOCITY} schnelle Lifthügel zu erlauben +STR_5586 :Läden und Stände automatisch öffnen +STR_5587 :{SMALLFONT}{BLACK}Wenn aktiviert, werden Läden und Stände nach dem Bauen automatisch geöffnet +STR_5588 :{SMALLFONT}{BLACK}Mit anderen Spielern spielen +STR_5589 :Benachrichtigungseinstellungen +STR_5590 :Parkauszeichnungen +STR_5591 :Marketingkampage wurde beendet +STR_5592 :Parkwarnungen +STR_5593 :Parkbewertungswarnungen +STR_5594 :Attraktion ist ausgefallen +STR_5595 :Attraktion ist verunglückt +STR_5596 :Attraktionswarnungen +STR_5597 :Attraktion / Szenerie erforscht +STR_5598 :Besucherwarnungen +STR_5599 :Besucher hat sich verirrt +STR_5600 :Besucher hat den Park verlassen +STR_5601 :Besucher steht für eine Attraktion schlange +STR_5602 :Besucher ist auf einer Attraktion +STR_5603 :Besucher hat eine Attraktion verlassen +STR_5604 :Besucher hat einen Gegenstand gekauft +STR_5605 :Besucher hat eine Einrichtung benutzt +STR_5606 :Besucher ist gestorben +STR_5607 :{SMALLFONT}{BLACK}Erzwingt das Löschen des{NEWLINE}ausgewählten Elements +STR_5608 :BH +STR_5609 :LH +STR_5610 :{SMALLFONT}{BLACK}Entfernt das ausgewählte Kartenelement. Das Löschen wird erzwungen und dadurch kein Geld verwendet/gutgeschrieben. Mit Vorsicht zu verwenden. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}Flag für Ghost-Element +STR_5613 :D +STR_5614 :{SMALLFONT}{BLACK}Flag für defektes Element +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Flag für letztes Element der Kachel +STR_5617 :{SMALLFONT}{BLACK}Ausgewähltes Element nach oben bewegen +STR_5618 :{SMALLFONT}{BLACK}Ausgewähltes Element nach unten bewegen ####################### # Bahnen/Attraktionen # diff --git a/data/language/korean.txt b/data/language/korean.txt index 18e4cb45ed..a7ad6c4891 100644 --- a/data/language/korean.txt +++ b/data/language/korean.txt @@ -45,7 +45,7 @@ STR_0040 :모션 시뮬레이터 STR_0041 :3D 영화관 STR_0042 :톱 스핀 STR_0043 :스페이스 링 -STR_0044 :리버스 프리폴 코스터 +STR_0044 :역방향 자유낙하 코스터 STR_0045 :리프트 STR_0046 :버티컬 드롭 롤러코스터 STR_0047 :현금 지급기 @@ -93,7 +93,7 @@ STR_0088 :인버티트 임펄스 코스터 STR_0089 :미니 롤러코스터 STR_0090 :마인 라이드 STR_0091 :알 수 없는 놀이기구 (59) -STR_0092 :LIM 런치드 롤러코스터 +STR_0092 :LIM 발진 롤러코스터 STR_0093 : STR_0094 : STR_0095 : @@ -528,7 +528,7 @@ STR_0523 :정해진 트랙을 따라 천천히 움직이는 놀이기구입 STR_0524 :자유낙하 차량은 공기 압축 방식으로 높은 철제 탑을 향해 차량을 쏘아올려 자유낙하하는 차량입니다. STR_0525 :손님들이 반원형으로 휘어있고 꼬여있는 트랙을 따라 이동합니다. STR_0526 :손님들이 높은 곳으로 회전하면서 올라가는 관망대 캐빈에 탑승하는 놀이기구입니다. -STR_0527 :버티컬 루프를 사용할 수 있는 부드러운 철제 트랙의 롤러코스터입니다. +STR_0527 :수직 루프를 사용할 수 있는 부드러운 철제 트랙의 롤러코스터입니다. STR_0528 :손님들이 공기를 넣은 고무 보트를 타고 반원이나 원형의 튜브 트랙을 따라 이동하는 놀이기구입니다. STR_0529 :오래된 기차 선로처럼 보이게 만든 철제 트랙을 따라 움직이는 탄광 열차 테마를 한 롤러코스터 차량입니다. STR_0530 :철제 케이블에 달린 차량이 연속적으로 놀이기구의 한쪽 끝에서 다른쪽 끝을 왕복 운행합니다. @@ -588,7 +588,7 @@ STR_0583 : STR_0584 :탑승객이 스스로 페달을 밟아 이동해야 하는, 특별한 철제 모노레일 트랙 위를 이동하는 자전거입니다 STR_0585 :탑승객은 트랙 밑에 매달린 좌석 한 쌍에 앉아 루프와 트위스트를 급격히 통과합니다 STR_0586 :보트 모양의 차량이 꼬인 커브와 급강하가 가능한 롤러코스터 트랙을 달리며, 강 섹션의 물에서는 물보라를 일으키며 감속합니다 -STR_0587 :아주 짜릿한 공기 압축 방식으로 발진하여 차량이 수직 트랙을 향해 속력을 높인 뒤, 꼭대기에 다다르면 다시 수직으로 하강하며 다른 탑승장에 도착합니다 +STR_0587 :아주 짜릿한 공기 압축 방식으로 발진하여 차량이 수직 트랙을 향해 속력을 높인 뒤, 꼭대기에 다다르면 다시 수직으로 하강하며 다시 탑승장에 도착합니다 STR_0588 :개별적인 차량이 헤이펀 커브와 급강하를 포함한 지그재그 모양의 트랙 아래를 이동합니다 STR_0589 : STR_0590 :탑승객들은 잠수가 가능한 잠수함을 타고 수중 코스를 돕니다 @@ -933,8 +933,8 @@ STR_0927 :여기에 건설할 수 없습니다... STR_0928 :{SMALLFONT}{BLACK}경사를 오르기 위한 체인 리프트 STR_0929 :S자 트랙 (왼쪽) STR_0930 :S자 트랙 (오른쪽) -STR_0931 :버티컬 루프 (왼쪽) -STR_0932 :버티컬 루프 (오른쪽) +STR_0931 :수직 루프 (왼쪽) +STR_0932 :수직 루프 (오른쪽) STR_0933 :땅을 먼저 올리거나 내리세요 STR_0934 :놀이기구 입구가 있습니다 STR_0935 :놀이기구 출구가 있습니다 @@ -1004,14 +1004,14 @@ STR_0998 :탑승장이 너무 많습니다 STR_0999 :탑승장이 필요합니다 STR_1000 :트랙이 완성되지 않았습니다 STR_1001 :트랙이 열차 종류와 맞지 않습니다 -STR_1002 :{POP16}{POP16}{POP16}{STRINGID}(을)를 운행할 수 없습니다... -STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}(을)를 테스트할 수 없습니다... -STR_1004 :{POP16}{POP16}{POP16}{STRINGID}(을)를 닫을 수 없습니다... +STR_1002 :{POP16}{POP16}{POP16}{STRINGID} - 운행할 수 없습니다... +STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID} - 테스트할 수 없습니다... +STR_1004 :{POP16}{POP16}{POP16}{STRINGID} - 닫을 수 없습니다... STR_1005 :{POP16}{POP16}{POP16}{STRINGID}의 건설을 시작할 수 없습니다... STR_1006 :먼저 닫아야 합니다 STR_1007 :차량을 충분히 만들 수 없습니다 -STR_1008 :{SMALLFONT}{BLACK}놀이기구나 시설을 열거나, 닫거나 테스트합니다 -STR_1009 :{SMALLFONT}{BLACK}모든 놀이기구나 시설을 열거나 닫습니다 +STR_1008 :{SMALLFONT}{BLACK}놀이기구/시설을 개장/폐장/테스트합니다 +STR_1009 :{SMALLFONT}{BLACK}모든 놀이기구/시설을 개장/폐장합니다 STR_1010 :{SMALLFONT}{BLACK}공원을 열거나 닫습니다 STR_1011 :모두 닫기 STR_1012 :모두 열기 @@ -1029,7 +1029,7 @@ STR_1023 :1대당 {POP16}{POP16}{POP16}{COMMA16}량의 차량 STR_1024 :1대당 {COMMA16}량의 차량 STR_1025 :1대당 {COMMA16}량의 차량 STR_1026 :탑승장이 너무 깁니다! -STR_1027 :{SMALLFONT}{BLACK}여기로 이동 +STR_1027 :{SMALLFONT}{BLACK}여기로 이동합니다 STR_1028 :지도 끝을 벗어납니다! STR_1029 :일부분만 수면 위로 나오도록 건설할 수 없습니다! STR_1030 :수중에만 건설할 수 있습니다! @@ -1212,13 +1212,13 @@ STR_1206 :{WINDOW_COLOUR_2}출발: STR_1207 :{WINDOW_COLOUR_2}다른 열차가 탑승장에 도착하면 열차를 출발시킴 STR_1208 :{WINDOW_COLOUR_2}다른 보트가 탑승장에 도착하면 보트를 출발시킴 STR_1209 :{SMALLFONT}{BLACK}출발하기 전에 승객을 기다릴지 여부를 선택하세요 -STR_1210 :{SMALLFONT}{BLACK}다른 차량이 같은 탑승장에 도착하면 열차를 출발시킬지 여부를 선택하세요 +STR_1210 :{SMALLFONT}{BLACK}체크하면 다른 차량이 탑승장에 도착하면 열차를 출발시킵니다 STR_1211 :{WINDOW_COLOUR_2}최소 대기 시간: STR_1212 :{WINDOW_COLOUR_2}최대 대기 시간: -STR_1213 :{SMALLFONT}{BLACK}출발하기 전에 최소한으로 기다릴 시간 길이를 선택하세요 -STR_1214 :{SMALLFONT}{BLACK}출발하기 전에 최대한으로 기다릴 시간 길이를 선택하세요 +STR_1213 :{SMALLFONT}{BLACK}출발하기 전에 반드시 기다릴 시간 +STR_1214 :{SMALLFONT}{BLACK}출발하기 전에 최대한 기다릴 시간 STR_1215 :{WINDOW_COLOUR_2}인접한 탑승장과 같이 출발시킴 -STR_1216 :{SMALLFONT}{BLACK}모든 인접한 탑승장과 차량을 동시에 출발시킬지 여부를 선택하세요 +STR_1216 :{SMALLFONT}{BLACK}체크하면 모든 인접한 탑승장의 차량을 동시에 출발시킵니다 STR_1217 :{COMMA16}초 STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} @@ -1434,10 +1434,10 @@ STR_1428 :{WINDOW_COLOUR_2}입장료: STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1430 :무료 STR_1431 :걷는 중 -STR_1432 :{STRINGID}(으)로 향하는 중 -STR_1433 :{STRINGID}(에)서 대기 중 +STR_1432 :목적지 : {STRINGID} +STR_1433 :{STRINGID} 대기 중 STR_1434 :물에 빠짐 -STR_1435 :{STRINGID} 위에 +STR_1435 :{STRINGID} 탑승중 STR_1436 :{STRINGID} 안에 STR_1437 :{STRINGID}에 STR_1438 :앉음 @@ -1446,7 +1446,7 @@ STR_1440 :잔디 깎는 중 STR_1441 :보도 청소 중 STR_1442 :쓰레기통 비우는 중 STR_1443 :정원에 물을 주는 중 -STR_1444 :{STRINGID}(을)를 보는 중 +STR_1444 :{STRINGID} 구경 중 STR_1445 :{STRINGID}의 건설 장면을 보는 중 STR_1446 :풍경을 보는 중 STR_1447 :공원을 떠나는 중 @@ -1713,7 +1713,7 @@ STR_1707 :게임에 직원이 너무 많습니다 STR_1708 :{SMALLFONT}{BLACK}이 직원이 순찰할 영역을 지정합니다 STR_1709 :직원 해고 STR_1710 :예 -STR_1711 :{WINDOW_COLOUR_1}{STRINGID}(을)를 정말 해고하시겠습니까? +STR_1711 :{WINDOW_COLOUR_1}{STRINGID} - 정말 해고하시겠습니까? STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}보도 청소 STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}정원에 물 주기 STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}쓰레기통 비우기 @@ -1892,7 +1892,7 @@ STR_1886 :{STRINGID} 점검 중 STR_1887 :{WINDOW_COLOUR_2}지난 점검 이후 지난 시간: {BLACK}{COMMA16}분 STR_1888 :{WINDOW_COLOUR_2}지난 점검 이후 지난 시간: {BLACK}4시간 이상 STR_1889 :{WINDOW_COLOUR_2}고장률: {MOVE_X}{255}{BLACK}{COMMA16}% -STR_1890 :{SMALLFONT}{BLACK}정비기술자가 이 놀이기구를 얼마나 자주 점검할 지 선택합니다 +STR_1890 :{SMALLFONT}{BLACK}정비기술자가 놀이기구를 얼마나 자주 점검할 지 선택 STR_1891 :공원에 아직 {STRINGID}(이)가 없습니다! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. @@ -1944,12 +1944,12 @@ STR_1936 :{STRINGID} - {STRINGID}(을)를 샀습니다 STR_1937 :{SMALLFONT}{BLACK}이 메시지의 주제에 대한 정보를 보여줍니다 STR_1938 :{SMALLFONT}{BLACK}손님 주변으로 화면을 이동합니다 STR_1939 :{SMALLFONT}{BLACK}직원 주변으로 화면을 이동합니다 -STR_1940 :{SMALLFONT}{BLACK}이 손님의 행복도, 에너지, 배고픔 등의 수치를 보여줍니다 -STR_1941 :{SMALLFONT}{BLACK}이 손님이 이용한 놀이기구를 보여줍니다 -STR_1942 :{SMALLFONT}{BLACK}이 손님의 재정 상황을 보여줍니다 -STR_1943 :{SMALLFONT}{BLACK}손님의 최근 생각을 보여줍니다 -STR_1944 :{SMALLFONT}{BLACK}손님이 가지고 있는 물건을 보여줍니다 -STR_1945 :{SMALLFONT}{BLACK}이 직원이 할 일이나 설정을 보여줍니다 +STR_1940 :{SMALLFONT}{BLACK}행복도/에너지/배고픔 등의 수치를 보여줍니다 +STR_1941 :{SMALLFONT}{BLACK}이용한 놀이기구를 보여줍니다 +STR_1942 :{SMALLFONT}{BLACK}재정 상황을 보여줍니다 +STR_1943 :{SMALLFONT}{BLACK}최근 생각을 보여줍니다 +STR_1944 :{SMALLFONT}{BLACK}가지고 있는 물건을 보여줍니다 +STR_1945 :{SMALLFONT}{BLACK}이 직원의 업무나 역할을 설정합니다 STR_1946 :{SMALLFONT}{BLACK}이 엔터테이너의 복장을 선택합니다 STR_1947 :{SMALLFONT}{BLACK}선택한 직원의 행동 영역을 보여주고 가까운 직원을 거기로 이동시킵니다 STR_1948 :{SMALLFONT}{BLACK}선택한 종류의 직원을 새로 고용합니다 @@ -2214,10 +2214,10 @@ STR_2206 :빈 음료수 통 STR_2207 :빈 주스 컵 STR_2208 :구운 소시지 STR_2209 :빈 사발 -STR_2210 :{SMALLFONT}{BLACK}공원의 미화원 목록을 보여줍니다 -STR_2211 :{SMALLFONT}{BLACK}공원의 정비기술자 목록을 보여줍니다 -STR_2212 :{SMALLFONT}{BLACK}공원의 경비원 목록을 보여줍니다 -STR_2213 :{SMALLFONT}{BLACK}공원의 엔터테이너 목록을 보여줍니다 +STR_2210 :{SMALLFONT}{BLACK}미화원 목록을 보여줍니다 +STR_2211 :{SMALLFONT}{BLACK}정비기술자 목록을 보여줍니다 +STR_2212 :{SMALLFONT}{BLACK}경비원 목록을 보여줍니다 +STR_2213 :{SMALLFONT}{BLACK}엔터테이너 목록을 보여줍니다 STR_2214 :게임 일시정지 중에는 건설할 수 없습니다! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C @@ -2300,15 +2300,15 @@ STR_2292 :{WINDOW_COLOUR_2}Rides been on: STR_2293 :{BLACK} 없음 STR_2294 :{SMALLFONT}{BLACK}땅 표면 모양을 변경합니다 STR_2295 :{SMALLFONT}{BLACK}땅의 벽 모양을 변경합니다 -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 공원 입장료로 썼습니다 -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 {BLACK}{COMMA16} 놀이기구에 썼습니다 -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 {BLACK}{COMMA16} 놀이기구에 썼습니다 -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음식 {BLACK}{COMMA16}종류에 썼습니다 -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음식 {BLACK}{COMMA16}종류에 썼습니다 -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음료수 {BLACK}{COMMA16}종류에 썼습니다 -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음료수 {BLACK}{COMMA16}종류에 썼습니다 -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 기념품 {BLACK}{COMMA16}종류에 썼습니다 -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 기념품 {BLACK}{COMMA16}종류에 썼습니다 +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 공원 입장료로 썼습니다 +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 {BLACK}{COMMA16} 놀이기구에 썼습니다 +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 {BLACK}{COMMA16} 놀이기구에 썼습니다 +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음식 {BLACK}{COMMA16}종류에 썼습니다 +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음식 {BLACK}{COMMA16}종류에 썼습니다 +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음료수 {BLACK}{COMMA16}종류에 썼습니다 +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음료수 {BLACK}{COMMA16}종류에 썼습니다 +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 기념품 {BLACK}{COMMA16}종류에 썼습니다 +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 기념품 {BLACK}{COMMA16}종류에 썼습니다 STR_2305 :트랙 디자인 파일 STR_2306 :트랙 디자인 저장 STR_2307 :{STRINGID} 디자인 선택 @@ -2481,7 +2481,7 @@ STR_2473 :{SMALLFONT}{BLACK}새 스릴있는 놀이기구를 개발합니다 STR_2474 :{SMALLFONT}{BLACK}새 물 놀이기구를 개발합니다 STR_2475 :{SMALLFONT}{BLACK}새 상점/매점을 개발합니다 STR_2476 :{SMALLFONT}{BLACK}새 풍경/테마를 개발합니다 -STR_2477 :{SMALLFONT}{BLACK}이 놀이기구/시설의 운영 모드를 선택합니다 +STR_2477 :{SMALLFONT}{BLACK}이 놀이기구/시설의 운영 모드 선택 STR_2478 :{SMALLFONT}{BLACK}시간에 따른 속력 그래프를 보여줍니다 STR_2479 :{SMALLFONT}{BLACK}시간에 따른 고도 그래프를 보여줍니다 STR_2480 :{SMALLFONT}{BLACK}시간에 따른 수직 가속도 그래프를 보여줍니다 @@ -2810,8 +2810,8 @@ STR_2799 :{SMALLFONT}{BLACK}지정되어 있는 조작 키를 확인하거나 STR_2800 :{WINDOW_COLOUR_2}총 입장료: {BLACK}{COMMA32} STR_2801 :{WINDOW_COLOUR_2}입장료로 벌어들인 수익: {BLACK}{CURRENCY2DP} STR_2802 :지도 -STR_2803 :{SMALLFONT}{BLACK}이 손님들을 지도에 하이라이트하여 표시합니다 -STR_2804 :{SMALLFONT}{BLACK}이 직원들을 지도에 하이라이트하여 표시합니다 +STR_2803 :{SMALLFONT}{BLACK}이 손님들을 지도에 표시합니다 +STR_2804 :{SMALLFONT}{BLACK}이 직원들을 지도에 표시합니다 STR_2805 :{SMALLFONT}{BLACK}공원의 지도를 표시합니다 STR_2806 :{RED}손님들이 공원의 더러운 보도 청소 상태에 대해 불평하고 있습니다{NEWLINE}미화원을 더 고용하거나 미화원의 업무 효율성을 점검하세요 STR_2807 :{RED}손님들이 공원에 널린 쓰레기에 대해 불평하고 있습니다{NEWLINE}미화원을 더 고용하거나 미화원의 업무 효율성을 점검하세요 @@ -3465,7 +3465,7 @@ STR_5125 :모두 파괴 가능 STR_5126 :무작위 타이틀 음악 STR_5127 :{SMALLFONT}{BLACK}땅을 올리거나 내리지 않음 STR_5128 :선택 도구 크기 -STR_5129 :선택 도구 크기를 {COMMA16}에서 {COMMA16} 사이의 값으로 입력하세요 +STR_5129 :{COMMA16}에서 {COMMA16} 사이의 값을 입력하세요 STR_5130 :지도 크기 STR_5131 :지도 크기를 {COMMA16}에서 {COMMA16} 사이의 값으로 입력하세요 STR_5132 :모든 놀이기구 수리 @@ -4230,87 +4230,87 @@ STR_CPTY :차량당 2명의 승객 [NEMT] STR_NAME :인버티드 롤러코스터 -STR_DESC :Riders sit in seats suspended beneath the track as they speed through giant loops, twists, and large swooping drops +STR_DESC :거대한 루프, 트위스트와 급격한 낙하 트랙을 따라 이동하며, 탑승객이 트랙 아래에 매달린 좌석에 앉는 차량 STR_CPTY :차량당 4명의 승객 [PMT1] STR_NAME :탄광 차량 -STR_DESC :Powered mine trains career along a smooth and twisted track layout +STR_DESC :부드럽게 꼬인 트랙 구조를 따라 달리는 탄광 차량 STR_CPTY :차량당 2명 또는 4명의 승객 [PREMT1] -STR_NAME :LIM 런치드 롤러코스터 -STR_DESC :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_NAME :LIM 발진 롤러코스터 +STR_DESC :역에서 선형 유도 모터에 의해 가속되어 꼬여있는 트랙을 빠른 속도로 통과하는 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [PTCT1] STR_NAME :우든 롤러코스터 차량 -STR_DESC :우든 롤러코스터 차량 with padded seats and lap bar restraints +STR_DESC :푹신한 좌석과 무릎 안전바가 있는 나무 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [PTCT2] STR_NAME :우든 롤러코스터 차량 (6인승) -STR_DESC :우든 롤러코스터 차량 with padded seats and lap bar restraints +STR_DESC :푹신한 좌석과 무릎 안전바가 있는 나무 롤러코스터 차량 STR_CPTY :차량당 6명의 승객 [PTCT2R] STR_NAME :우든 롤러코스터 차량 (6인승, 역방향) -STR_DESC :우든 롤러코스터 차량 with padded seats and lap bar restraints, running with the seats facing backwards +STR_DESC :푹신한 좌석과 무릎 안전바가 있고, 뒤쪽을 본 채로 앉아서 달리는 나무 롤러코스터 차량 STR_CPTY :차량당 6명의 승객 [RCKC] STR_NAME :로켓 차량 -STR_DESC :Roller coaster cars themed to look like rockets +STR_DESC :로켓처럼 꾸며져 있는 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [REVCAR] -STR_NAME :리버서 롤러코스터 -STR_DESC :Bogied cars run on wooden tracks, turning around on special reversing sections +STR_NAME :반전 롤러코스터 +STR_DESC :특수한 반전 섹션 위에서 앞뒤가 뒤집히는 나무 트랙 위를 운행하는 불안한 차량 STR_CPTY :차량당 6명의 승객 [REVF1] -STR_NAME :리버스 프리폴 차량 -STR_DESC :Large coaster car for the Reverse Freefall Coaster +STR_NAME :역방향 자유낙하 차량 +STR_DESC :역방향 자유낙하 코스터를 위한 대형 코스터 차량 STR_CPTY :승객 8명 [SBOX] STR_NAME :조립 경주차 경주 레이서 -STR_DESC :Riders ride soap-box car shaped vehicles along a single-rail roller coaster track -STR_CPTY :4 riders per car +STR_DESC :하나의 레일로 이루어진 롤러코스터 트랙을 이동하는 조립 경주차 모양의 차량 +STR_CPTY :차량당 4명의 승객 [SCHT1] STR_NAME :롤러코스터 차량 -STR_DESC :Roller coaster trains with lap bars capable of travelling through vertical loops +STR_DESC :무릎 안전바가 있으며 수직 루프를 돌 수 있는 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [SFRIC1] STR_NAME :우든 사이드 프릭션 차량 -STR_DESC :Basic cars for the Side-Friction Roller Coaster +STR_DESC :사이드 프릭션 롤러코스터를 위한 기본 차량 STR_CPTY :차량당 4명의 승객 [SKYTR] STR_NAME :미니 서스펜디드 플라잉 코스터 -STR_DESC :Passengers ride face-down in a lying position, suspended in a specially designed car from the single-rail track, swinging freely from side to side around corners +STR_DESC :하나의 레일로 이루어진 트랙에 매달린 특수 차량에 얼굴을 아래로 한 자세로 타고 코너를 돌 때마다 이리 저리 자유롭게 흔들리는 차량 STR_CPTY :차량당 승객 1명 [SLCFO] STR_NAME :인버티드 셔틀 코스터 -STR_DESC :Riders sit in pairs facing either forwards or backwards as they loop and twist through tight inversions +STR_DESC :앞쪽이나 뒤쪽을 보고 2명씩 짝지어 앉아 루프와 트위스트와 급격한 전이 트랙을 지나는 차량 STR_CPTY :차량당 4명의 승객 [SLCT] STR_NAME :컴팩트 인버티드 코스터 -STR_DESC :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions +STR_DESC :트랙 밑에 매달린 좌석에 2명씩 짝지어 앉아 루프와 트위스트와 급격한 전이 트랙을 지나는 차량 STR_CPTY :차량당 2명의 승객 [SMC1] STR_NAME :쥐 차량 -STR_DESC :Individual cars shaped like mice +STR_DESC :쥐처럼 생긴 개별 차량 STR_CPTY :차량당 4명의 승객 [SMC2] STR_NAME :탄광 차량 -STR_DESC :Individual cars shaped like wooden mine trucks +STR_DESC :나무 탄광 트럭처럼 생긴 개별 차량 STR_CPTY :차량당 4명의 승객 [SPDRCR] @@ -4321,16 +4321,16 @@ STR_CPTY :차량당 6명의 승객 [STEEP1] STR_NAME :스티플체이스 STR_DESC :Riders ride horse-shaped vehicles which run along a single-rail roller coaster track -STR_CPTY :2 riders per horse +STR_CPTY :차량당 2명의 승객 [STEEP2] STR_NAME :모터바이크 레이스 STR_DESC :Riders ride motorbike-shaped roller coaster vehicles along a single-rail track -STR_CPTY :2 riders per bike +STR_CPTY :자전거당 2명의 승객 [THCAR] STR_NAME :에어 파워드 버티컬 코스터 -STR_DESC :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station +STR_DESC :아주 짜릿한 공기 압축 방식으로 발진하여 차량이 수직 트랙을 향해 속력을 높인 뒤, 꼭대기에 다다르면 다시 수직으로 하강하며 다시 탑승장에 도착합니다 STR_CPTY :차량당 2명의 승객 [TOGST] @@ -4340,12 +4340,12 @@ STR_CPTY :차량당 4명의 승객 [UTCAR] STR_NAME :트위스터 차량 -STR_DESC :Roller coaster cars capable of heartline twists +STR_DESC :하트라인 트위스트에 적합한 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [UTCARR] STR_NAME :트위스터 차량 (역방향) -STR_DESC :Roller coaster cars capable of heartline twists +STR_DESC :하트라인 트위스트에 적합한 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [VEKDV] @@ -4400,7 +4400,7 @@ STR_CPTY :차량당 2명의 승객 [C3D] STR_NAME :3D 영화관 -STR_DESC :Cinema showing 3D films inside a geodesic sphere shaped building +STR_DESC :둥근 구 모양의 건물 안에서 3D 영화를 상영하는 영화관 STR_CPTY :손님 20명 [ENTERP] @@ -4415,8 +4415,8 @@ STR_CPTY :승객 16명 [KART1] STR_NAME :고 카트 -STR_DESC :Self-drive petrol-engined go karts -STR_CPTY :single-seater +STR_DESC :스스로 운전하는 페트롤 엔진의 고 카트 +STR_CPTY :1인승 [MCARPET1] STR_NAME :마법의 양탄자 @@ -4435,7 +4435,7 @@ STR_CPTY :승객 8명 [SWSH1] STR_NAME :바이킹 -STR_DESC :Large swinging pirate ship +STR_DESC :흔들리는 거대한 해적선 STR_CPTY :승객 16명 [SWSH2] @@ -6330,7 +6330,7 @@ STR_NAME :정원 STR_NAME :대형 정원 테마 [SCGHALLO] -STR_NAME :으스스한 테마 +STR_NAME :오싹한 테마 [SCGINDUS] STR_NAME :기계 테마 @@ -6551,7 +6551,7 @@ STR_CPTY :차량당 4명의 승객 [MINECART] STR_NAME :탄광 카트 라이드 -STR_DESC :우든 롤러코스터 차량 with padded seats and lap bar restraints +STR_DESC :푹신한 좌석과 무릎 안전바가 있는 나무 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [OSTRICH] @@ -6616,7 +6616,7 @@ STR_CPTY :차량당 4명의 승객 [TGVTRAIN] STR_NAME :TGV 트레인 롤러코스터 -STR_DESC :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_DESC :역에서 선형 유도 모터에 의해 가속되어 꼬여있는 트랙을 빠른 속도로 통과하는 롤러코스터 차량 STR_CPTY :차량당 4명의 승객 [TIGRTWST] @@ -8575,49 +8575,49 @@ STR_NAME :Wind Sculpted Wall Piece STR_NAME :Wind Sculpted Wall Piece [WBamboPC] -STR_NAME :Bamboo Wall +STR_NAME :대나무 벽 [SCGAFRIC] -STR_NAME : Africa Themeing +STR_NAME :아프리카 테마 [SCGARTIC] -STR_NAME : Antarctic Themeing +STR_NAME :남극 테마 [SCGASIA] -STR_NAME : Asia Themeing +STR_NAME :아시아 테마 [SCGAUSTR] -STR_NAME : Australasian Themeing +STR_NAME :오스트레일리아 테마 [SCGEUROP] -STR_NAME : Europe Themeing +STR_NAME :유럽 테마 [SCGNAMRC] -STR_NAME : North America Themeing +STR_NAME :북아메리카 테마 [SCGSAMER] -STR_NAME : South America Themeing +STR_NAME :남아메리카 테마 [AFRICENT] -STR_NAME :Africa Park Entrance +STR_NAME :아프리카식 공원 입구 [EUROENT] -STR_NAME :European Park Entrance +STR_NAME :유럽식 공원 입구 [ICEENT] -STR_NAME :Ice Park Entrance +STR_NAME :얼음 공원 입구 [JAPENT] -STR_NAME :Japanese Park Entrance +STR_NAME :일본식 공원 입구 [NAENT] -STR_NAME :North America Park Entrance +STR_NAME :북아메리카식 공원 입구 [OZENTRAN] -STR_NAME :Australasian Park Entrance +STR_NAME :오스트레일리아식 공원 입구 [SAMERENT] -STR_NAME :South American Park Entrance +STR_NAME :남아메리카식 공원 입구 ############################################################################### ## Time Twister Objects @@ -8698,8 +8698,8 @@ STR_DESC :Riders lock horns with each other in Triceratops dodgem cars STR_CPTY :차량당 1명의 손님 [BARNSTRM] -STR_NAME :선거 유세 코스터 -STR_DESC :Riders sit in seats suspended beneath the track as they speed through giant loops, twists, and large swooping drops +STR_NAME :곡예 비행기 코스터 +STR_DESC :거대한 루프, 트위스트와 급격한 낙하 트랙을 따라 이동하며, 탑승객이 트랙 아래에 매달린 좌석에 앉는 차량 STR_CPTY :차량당 4명의 승객 [BATTRRAM] From a0bb568889c9c374c344f5adb7ca6766458e146a Mon Sep 17 00:00:00 2001 From: Maximilian Irlinger Date: Mon, 4 Jan 2016 16:22:15 +0100 Subject: [PATCH 79/90] Append timestamp to autosave --- src/game.c | 88 +++++++++++++++++++++++++++++++++++++++++++- src/platform/posix.c | 4 +- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/game.c b/src/game.c index 1ff9d3cddb..7463dc8e5e 100644 --- a/src/game.c +++ b/src/game.c @@ -57,6 +57,9 @@ #include "world/scenery.h" #include "world/sprite.h" #include "world/water.h" +#include + +#define NUMBER_OF_AUTOSAVES_TO_KEEP 9 int gGameSpeed = 1; float gDayNightCycle = 0; @@ -1059,16 +1062,99 @@ void save_game_as() window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, (char*)path_get_filename(gScenarioSavePath)); } +int compare_autosave_file_paths (const void * a, const void * b ) { + return strcmp(*(char **)a, *(char **)b); +} + +void limit_autosave_count(const size_t numberOfFilesToKeep) +{ + int fileEnumHandle = 0; + + size_t autosavesCount = 0; + size_t numAutosavesToDelete = 0; + + file_info fileInfo; + + utf8 filter[MAX_PATH]; + + utf8 **autosaveFiles = NULL; + + size_t i=0; + + platform_get_user_directory(filter, "save"); + strncat(filter, "autosave_*.sv6", sizeof(filter) - strnlen(filter, MAX_PATH) - 1); + + // At first, count how many autosaves there are + fileEnumHandle = platform_enumerate_files_begin(filter); + while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { + autosavesCount++; + } + platform_enumerate_files_end(fileEnumHandle); + + // If there are fewer autosaves than the number of files to keep we don't need to delete anything + if(autosavesCount <= numberOfFilesToKeep) { + return; + } + + autosaveFiles = (utf8**) malloc(sizeof(utf8*) * autosavesCount); + + fileEnumHandle = platform_enumerate_files_begin(filter); + for(i = 0; i < autosavesCount; i++) { + autosaveFiles[i] = (utf8*)malloc(sizeof(utf8) * MAX_PATH); + memset(autosaveFiles[i], 0, sizeof(utf8) * MAX_PATH); + + if(platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { + platform_get_user_directory(autosaveFiles[i], "save"); + strcat(autosaveFiles[i], fileInfo.path); + } + } + platform_enumerate_files_end(fileEnumHandle); + + qsort (autosaveFiles, autosavesCount, sizeof (char*), compare_autosave_file_paths); + + // calculate how many saves we need to delete. + numAutosavesToDelete = autosavesCount - numberOfFilesToKeep; + + i=0; + while (numAutosavesToDelete > 0) { + platform_file_delete(autosaveFiles[i]); + + i++; + numAutosavesToDelete--; + } + + + for(i = 0; i < autosavesCount; i++) { + free(autosaveFiles[i]); + } + + free(autosaveFiles); +} void game_autosave() { utf8 path[MAX_PATH]; utf8 backupPath[MAX_PATH]; + utf8 timeString[21]=""; + + time_t rawtime; + struct tm * timeinfo; + + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); + limit_autosave_count(NUMBER_OF_AUTOSAVES_TO_KEEP); + + snprintf(timeString, 20, "%d-%02d-%02d_%02d-%02d-%02d", 1900+timeinfo->tm_year, 1+timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + + platform_get_user_directory(path, "save"); safe_strncpy(backupPath, path, MAX_PATH); - strcat(path, "autosave.sv6"); + strcat(path, "autosave_"); + strcat(path, timeString); + strcat(path, ".sv6"); + strcat(backupPath, "autosave.sv6.bak"); if (platform_file_exists(path)) { diff --git a/src/platform/posix.c b/src/platform/posix.c index 36d9844c15..c565865f1e 100644 --- a/src/platform/posix.c +++ b/src/platform/posix.c @@ -499,8 +499,8 @@ bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath) bool platform_file_delete(const utf8 *path) { - STUB(); - return 0; + int ret = unlink(path); + return ret == 0; } wchar_t *regular_to_wchar(const char* src) From b29a3b08234c15b2fe4d4c4e8c078df205b52c66 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 4 Jan 2016 17:26:02 +0000 Subject: [PATCH 80/90] fix appveyor --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 081ac5567d..c2beb58a80 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,5 @@ version: 0.0.4.{build} +os: Previous Visual Studio 2015 build_script: - ps: >- .\setenv.ps1 From d371fa603e85a66e8bd9f8bdd0872f13ec14bb34 Mon Sep 17 00:00:00 2001 From: LRFLEW Date: Mon, 4 Jan 2016 11:07:36 -0700 Subject: [PATCH 81/90] Updated OS X shasum to new value --- OpenRCT2.xcodeproj/project.pbxproj | 2 +- scripts/linux/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 9c5496a6af..8b956eb69b 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -1315,7 +1315,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "cachedir=\".cache\"\nliburl=\"https://openrct2.website/files/orctlibs-osx.zip\"\n# keep in sync with version in build.sh\nsha256sum=\"02ebc8e7fd8b9b02b7144721784c5d96202a17398bc8652da163c8c85b66a7db\"\n\n[[ ! -e \"${SRCROOT}/libversion\" || $(head -n 1 \"${SRCROOT}/libversion\") != $sha256sum ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]] || [[ ! -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then\n if [[ ! -d \"${SRCROOT}/$cachedir\" ]]; then mkdir \"${SRCROOT}/$cachedir\"; fi\n if [[ -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then rm \"${SRCROOT}/$cachedir/orctlibs.zip\"; fi\n curl -L -o \"${SRCROOT}/$cachedir/orctlibs.zip\" \"$liburl\"\n if [[ -d \"${SRCROOT}/$cachedir/orctlibs\" ]]; then rm -rf \"${SRCROOT}/$cachedir/orctlibs\"; fi\n mkdir \"${SRCROOT}/$cachedir/orctlibs\"\n unzip -uaq -d \"${SRCROOT}/$cachedir/orctlibs\" \"${SRCROOT}/$cachedir/orctlibs.zip\"\nfi\n\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/lib\" ]]; then\n if [[ -d \"${SRCROOT}/lib\" ]]; then rm -r \"${SRCROOT}/lib\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/local\" \"${SRCROOT}/lib\"\nfi\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/libxc\" ]]; then\n if [[ -d \"${SRCROOT}/libxc\" ]]; then rm -r \"${SRCROOT}/libxc\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/glob\" \"${SRCROOT}/libxc\"\nfi\n\nif [[ $outdated -eq 0 ]]; then\n newsha=$(shasum -a 256 \"${SRCROOT}/$cachedir/orctlibs.zip\" | cut -f1 -d\" \")\n echo $newsha > \"${SRCROOT}/libversion\"\n [[ \"$newsha\" == \"$sha256sum\" ]]\nfi"; + shellScript = "cachedir=\".cache\"\nliburl=\"https://openrct2.website/files/orctlibs-osx.zip\"\n# keep in sync with version in build.sh\nsha256sum=\"6562ce9e1f37f125e3345bfd8b961777800436bf607b30dc7c964e0e6991ad2c\"\n\n[[ ! -e \"${SRCROOT}/libversion\" || $(head -n 1 \"${SRCROOT}/libversion\") != $sha256sum ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]] || [[ ! -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then\n if [[ ! -d \"${SRCROOT}/$cachedir\" ]]; then mkdir \"${SRCROOT}/$cachedir\"; fi\n if [[ -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then rm \"${SRCROOT}/$cachedir/orctlibs.zip\"; fi\n curl -L -o \"${SRCROOT}/$cachedir/orctlibs.zip\" \"$liburl\"\n if [[ -d \"${SRCROOT}/$cachedir/orctlibs\" ]]; then rm -rf \"${SRCROOT}/$cachedir/orctlibs\"; fi\n mkdir \"${SRCROOT}/$cachedir/orctlibs\"\n unzip -uaq -d \"${SRCROOT}/$cachedir/orctlibs\" \"${SRCROOT}/$cachedir/orctlibs.zip\"\nfi\n\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/lib\" ]]; then\n if [[ -d \"${SRCROOT}/lib\" ]]; then rm -r \"${SRCROOT}/lib\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/local\" \"${SRCROOT}/lib\"\nfi\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/libxc\" ]]; then\n if [[ -d \"${SRCROOT}/libxc\" ]]; then rm -r \"${SRCROOT}/libxc\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/glob\" \"${SRCROOT}/libxc\"\nfi\n\nif [[ $outdated -eq 0 ]]; then\n newsha=$(shasum -a 256 \"${SRCROOT}/$cachedir/orctlibs.zip\" | cut -f1 -d\" \")\n echo $newsha > \"${SRCROOT}/libversion\"\n [[ \"$newsha\" == \"$sha256sum\" ]]\nfi"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 8c64ee3283..049059f2fa 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -15,7 +15,7 @@ fi # keep in sync with version in install.sh if [[ $(uname -s) == "Darwin" ]]; then # keep in sync with version in Xcode project - sha256sum=02ebc8e7fd8b9b02b7144721784c5d96202a17398bc8652da163c8c85b66a7db + sha256sum=6562ce9e1f37f125e3345bfd8b961777800436bf607b30dc7c964e0e6991ad2c else sha256sum=31c5e19d9f794bd5f0e75f20c2b4c3c4664d736b0a4d50c8cde14a9a9007b62d fi From 3b4928c041642b63f2240753c6cdc78f2907347c Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 4 Jan 2016 18:26:49 +0000 Subject: [PATCH 82/90] fix windows file enumerate pattern matching --- src/platform/windows.c | 70 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/src/platform/windows.c b/src/platform/windows.c index 87a1d9df81..7069950c18 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -262,6 +262,48 @@ int platform_enumerate_files_begin(const utf8 *pattern) return INVALID_HANDLE; } +/** + * Due to FindFirstFile / FindNextFile searching for DOS names as well, *.doc also matches *.docx which isn't what the pattern + * specified. This will verify if a filename does indeed match the pattern we asked for. + * @remarks Based on algorithm (http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html) + */ +static bool match_wildcard(const wchar_t *fileName, const wchar_t *pattern) +{ + while (*fileName != '\0') { + switch (*pattern) { + case '?': + if (*fileName == '.') { + return false; + } + break; + case '*': + do { + pattern++; + } while (*pattern == '*'); + if (*pattern == '\0') { + return false; + } + while (*fileName != '\0') { + if (match_wildcard(fileName++, pattern)) { + return true; + } + } + return false; + default: + if (toupper(*fileName) != toupper(*pattern)) { + return false; + } + break; + } + pattern++; + fileName++; + } + while (*pattern == '*') { + ++fileName; + } + return *pattern == '\0'; +} + bool platform_enumerate_files_next(int handle, file_info *outFileInfo) { bool result; @@ -270,18 +312,28 @@ bool platform_enumerate_files_next(int handle, file_info *outFileInfo) enumFileInfo = &_enumerateFileInfoList[handle]; - if (enumFileInfo->handle == NULL) { - findFileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data); - if (findFileHandle != INVALID_HANDLE_VALUE) { - enumFileInfo->handle = findFileHandle; - result = true; - } else { - result = false; - } + // Get pattern (just filename part) + const wchar_t *patternWithoutDirectory = wcsrchr(enumFileInfo->pattern, '\\'); + if (patternWithoutDirectory == NULL) { + patternWithoutDirectory = enumFileInfo->pattern; } else { - result = FindNextFileW(enumFileInfo->handle, &enumFileInfo->data); + patternWithoutDirectory++; } + do { + if (enumFileInfo->handle == NULL) { + findFileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data); + if (findFileHandle != INVALID_HANDLE_VALUE) { + enumFileInfo->handle = findFileHandle; + result = true; + } else { + result = false; + } + } else { + result = FindNextFileW(enumFileInfo->handle, &enumFileInfo->data); + } + } while (result && !match_wildcard(enumFileInfo->data.cFileName, patternWithoutDirectory)); + if (result) { outFileInfo->path = enumFileInfo->outFilename = widechar_to_utf8(enumFileInfo->data.cFileName); outFileInfo->size = ((uint64)enumFileInfo->data.nFileSizeHigh << 32ULL) | (uint64)enumFileInfo->data.nFileSizeLow; From 9c4cf14069df44269e5d99f669f1ecb416c3a3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 3 Jan 2016 00:49:08 +0100 Subject: [PATCH 83/90] Game commands hardening --- src/management/marketing.c | 7 ++ src/peep/staff.c | 20 +++++- src/ride/ride.c | 135 +++++++++++++++++++++++++++++++++---- src/ride/track.c | 20 +++++- src/world/map.c | 74 ++++++++++++++++++-- src/world/park.c | 1 + 6 files changed, 236 insertions(+), 21 deletions(-) diff --git a/src/management/marketing.c b/src/management/marketing.c index 7e3a4a16be..55cf24c521 100644 --- a/src/management/marketing.c +++ b/src/management/marketing.c @@ -155,6 +155,13 @@ void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* es int rideOrItem = (*edx >> 8) & 0xFF; int numWeeks = (*ebx >> 8) & 0xFF; + if (type < 0 || type >= countof(AdvertisingCampaignPricePerWeek)) + { + log_warning("Invalid game command, type = %d", type); + *ebx = MONEY32_UNDEFINED; + return; + } + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_MARKETING * 4; if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_MARKETING_CAMPAIGN) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 3048; diff --git a/src/peep/staff.c b/src/peep/staff.c index 7ded0b1528..f1adf05318 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -293,7 +293,13 @@ void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *e RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_WAGES * 4; uint8 order_id = *ebx >> 8; uint16 sprite_id = *edx; - if(*ebx & GAME_COMMAND_FLAG_APPLY){ + if (sprite_id >= MAX_SPRITES) + { + log_warning("Invalid game command, sprite_id = %u", sprite_id); + *ebx = MONEY32_UNDEFINED; + return; + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { rct_peep *peep = &g_sprite_list[sprite_id].peep; if(order_id & 0x80){ // change costume uint8 sprite_type = order_id & ~0x80; @@ -366,7 +372,19 @@ void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int if(*ebx & GAME_COMMAND_FLAG_APPLY){ window_close_by_class(WC_FIRE_PROMPT); uint16 sprite_id = *edx; + if (sprite_id >= MAX_SPRITES) + { + log_warning("Invalid game command, sprite_id = %u", sprite_id); + *ebx = MONEY32_UNDEFINED; + return; + } rct_peep *peep = &g_sprite_list[sprite_id].peep; + if (peep->sprite_identifier != SPRITE_IDENTIFIER_PEEP || peep->type != PEEP_TYPE_STAFF) + { + log_warning("Invalid game command, peep->sprite_identifier = %u, peep->type = %u", peep->sprite_identifier, peep->type); + *ebx = MONEY32_UNDEFINED; + return; + } remove_peep_from_ride(peep); peep_sprite_remove(peep); } diff --git a/src/ride/ride.c b/src/ride/ride.c index 78da7a1230..2229b51c0c 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -2914,7 +2914,15 @@ static bool ride_does_vehicle_colour_exist(uint8 ride_sub_type, vehicle_colour * static int ride_get_unused_preset_vehicle_colour(uint8 ride_type, uint8 ride_sub_type) { + if (ride_sub_type >= 128) + { + return 0; + } rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride_sub_type); + if (rideEntry == (rct_ride_type *)0xFFFFFFFF) + { + return 0; + } vehicle_colour_preset_list *presetList = rideEntry->vehicle_preset_list; if (presetList->count == 255) return 255; @@ -3588,6 +3596,12 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int * uint8 ride_id = *edx & 0xFF; rct_ride* ride = GET_RIDE(ride_id); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command."); + *ebx = MONEY32_UNDEFINED; + return; + } uint8 flags = *ebx & 0xFF; uint8 new_value = (*ebx >> 8) & 0xFF; @@ -4606,6 +4620,11 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying) rct_xy_element trackElement, problematicTrackElement; ride = GET_RIDE(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid ride type for ride %u", rideIndex); + return 0; + } window_close_by_number(WC_RIDE_CONSTRUCTION, rideIndex); @@ -4864,6 +4883,12 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; ride = GET_RIDE(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", rideIndex); + *ebx = MONEY32_UNDEFINED; + return; + } RCT2_GLOBAL(0x00F43484, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32); switch (targetStatus) { @@ -4944,6 +4969,7 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi if (nameChunkOffset < 0) nameChunkOffset = 2; nameChunkOffset *= 12; + nameChunkOffset = min(nameChunkOffset, countof(newName) - 12); RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; @@ -5162,6 +5188,10 @@ static int ride_get_random_colour_preset_index(uint8 ride_type) { const track_colour_preset_list *colourPresets; const track_colour *colours; + if (ride_type >= 128) + { + return 0; + } colourPresets = RCT2_ADDRESS(0x0097D934, track_colour_preset_list*)[ride_type]; @@ -5265,6 +5295,11 @@ money32 ride_create(int type, int subType, int flags, int *outRideIndex, int *ou foundRideEntry: rideEntryIndex = subType; rideIndex = ride_get_empty_slot(); + if (subType >= 128) + { + log_warning("Invalid request for ride type %u", subType); + return MONEY32_UNDEFINED; + } if (rideIndex == -1) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_RIDES; return MONEY32_UNDEFINED; @@ -5287,6 +5322,11 @@ foundRideEntry: ride = GET_RIDE(rideIndex); rideEntry = GET_RIDE_ENTRY(rideEntryIndex); + if (rideEntry == (rct_ride_type *)0xFFFFFFFF) + { + log_warning("Invalid request for ride %u", rideIndex); + return MONEY32_UNDEFINED; + } ride->type = type; ride->subtype = rideEntryIndex; ride_set_colour_preset(ride, *outRideColour & 0xFF); @@ -5596,7 +5636,13 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = 0; - rct_ride *ride = &g_ride_list[ride_id]; + rct_ride *ride = GET_RIDE(ride_id); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", ride_id); + *ebx = MONEY32_UNDEFINED; + return; + } int x = 0, y = 0, z = 0; if(ride->overall_view != (uint16)-1){ x = ((ride->overall_view & 0xFF) * 32) + 16; @@ -5724,25 +5770,61 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in uint8 type = *ebx >> 8; uint8 value = *edx >> 8; int index = *edi; - rct_ride *ride = &g_ride_list[ride_id]; + if (index < 0) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + return; + } + rct_ride *ride = GET_RIDE(ride_id); + if (ride->type == RIDE_TYPE_NULL) { + log_warning("Invalid game command, ride_id = %u", ride_id); + *ebx = MONEY32_UNDEFINED; + return; + } + *ebx = 0; switch(type){ case 0: + if (index >= countof(ride->track_colour_main)) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + break; + } ride->track_colour_main[index] = value; gfx_invalidate_screen(); break; case 1: + if (index >= countof(ride->track_colour_additional)) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + break; + } ride->track_colour_additional[index] = value; gfx_invalidate_screen(); break; case 2: + if (index >= countof(ride->vehicle_colours)) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + break; + } *((uint8*)(&ride->vehicle_colours[index])) = value; ride_update_vehicle_colours(ride_id); break; case 3: + if (index >= countof(ride->vehicle_colours)) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + break; + } *((uint8*)(&ride->vehicle_colours[index]) + 1) = value; ride_update_vehicle_colours(ride_id); break; case 4: + if (index >= countof(ride->track_colour_supports)) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + break; + } ride->track_colour_supports[index] = value; gfx_invalidate_screen(); break; @@ -5761,13 +5843,17 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in gfx_invalidate_screen(); break; case 7: + if (index >= countof(ride->vehicle_colours_extended)) { + log_warning("Invalid game command, index %d out of bounds", index); + *ebx = MONEY32_UNDEFINED; + break; + } ride->vehicle_colours_extended[index] = value; ride_update_vehicle_colours(ride_id); break; } window_invalidate_by_number(WC_RIDE, ride_id); } - *ebx = 0; } /** @@ -5780,21 +5866,28 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es uint8 ride_number; money16 price; rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_type *rideEntry; bool secondary_price; flags = *ebx; ride_number = (*edx & 0xFF); ride = GET_RIDE(ride_number); - ride_type = gRideTypeList[ride->subtype]; + rideEntry = GET_RIDE_ENTRY(ride->subtype); price = *edi; secondary_price = (*edx >> 8); + if (rideEntry == (rct_ride_type *)0xFFFFFFFF) + { + log_warning("Invalid game command for ride %u", ride_number); + *ebx = MONEY32_UNDEFINED; + return; + } + //eax //ebx flags //ecx ecx //edx ride_number - //ebp ride_type + //ebp rideEntry *ebx = 0; // for cost check - changing ride price does not cost anything @@ -5803,7 +5896,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es if (!secondary_price) { shop_item = 0x1F; if (ride->type != RIDE_TYPE_TOILETS) { - shop_item = ride_type->shop_item; + shop_item = rideEntry->shop_item; if (shop_item == 0xFF) { ride->price = price; window_invalidate_by_class(WC_RIDE); @@ -5818,7 +5911,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es } } else { - shop_item = ride_type->shop_item_secondary; + shop_item = rideEntry->shop_item_secondary; if (shop_item == 0xFF) { shop_item = RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8); if ((ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) == 0) { @@ -5835,12 +5928,12 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es } } ride = GET_RIDE(0); - ride_type = gRideTypeList[ride->subtype]; + rideEntry = GET_RIDE_ENTRY(ride->subtype); uint8 count = 0; while (count < 0xFF) { if (ride->type != 0xFF) { if (ride->type != RIDE_TYPE_TOILETS || shop_item != 0x1F) { - if (ride_type->shop_item == shop_item) { + if (rideEntry->shop_item == shop_item) { ride->price = price; window_invalidate_by_number(WC_RIDE, count); } @@ -5850,8 +5943,8 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es window_invalidate_by_number(WC_RIDE, count); } // If the shop item is the same or an on-ride photo - if (ride_type->shop_item_secondary == shop_item || - (ride_type->shop_item_secondary == 0xFF && + if (rideEntry->shop_item_secondary == shop_item || + (rideEntry->shop_item_secondary == 0xFF && (shop_item == 0x3 || shop_item == 0x20 || shop_item == 0x21 || shop_item == 0x22))) { ride->price_secondary = price; @@ -5860,7 +5953,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es } count++; ride++; - ride_type = gRideTypeList[ride->subtype]; + rideEntry = GET_RIDE_ENTRY(ride->subtype); } } } @@ -6749,6 +6842,12 @@ void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int value = (*edx >> 8) & 0xFF; ride = GET_RIDE(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", rideIndex); + *ebx = MONEY32_UNDEFINED; + return; + } RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; @@ -7090,6 +7189,11 @@ void game_command_place_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 station_num, uint8 flags){ rct_ride* ride = GET_RIDE(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalide ride id %u for entrance/exit removal", rideIndex); + return MONEY32_UNDEFINED; + } if (!(flags & GAME_COMMAND_FLAG_GHOST)){ if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ @@ -7110,6 +7214,11 @@ money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 uint8 found = 0; rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32); + if (mapElement == NULL) + { + log_warning("Invalid coordinates for entrance/exit removal x = %d, y = %d", x, y); + return MONEY32_UNDEFINED; + } do{ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE) continue; diff --git a/src/ride/track.c b/src/ride/track.c index 978c71b91e..9a35bdd9c7 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3309,6 +3309,14 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int rideIndex = _edi & 0xFF; } + rct_ride* ride = GET_RIDE(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for track placement, ride id = %d", rideIndex); + *ebx = MONEY32_UNDEFINED; + return; + } + money32 cost = 0; if (!(flags & GAME_COMMAND_FLAG_APPLY)){ RCT2_GLOBAL(0x00F44150, uint8) = 0; @@ -3365,7 +3373,6 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int if (num_circuits == 0) num_circuits = 1; game_do_command(0, GAME_COMMAND_FLAG_APPLY | (num_circuits << 8), 0, rideIndex | (9 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - rct_ride* ride = GET_RIDE(rideIndex); ride->lifecycle_flags |= RIDE_LIFECYCLE_NOT_CUSTOM_DESIGN; @@ -4511,6 +4518,11 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, uint8 found = 0; rct_map_element* mapElement = map_get_first_element_at(originX / 32, originY / 32); + if (mapElement == NULL) + { + log_warning("Invalid coordinates for track removal. x = %d, y = %d", originX, originY); + return MONEY32_UNDEFINED; + } do{ if (mapElement->base_height * 8 != originZ) continue; @@ -4798,6 +4810,12 @@ void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int * } mapElement = map_get_first_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + log_warning("Invalid game command for setting brakes speed. x = %d, y = %d", x, y); + *ebx = MONEY32_UNDEFINED; + return; + } do { if (mapElement->base_height * 8 != z) continue; diff --git a/src/world/map.c b/src/world/map.c index 8962ed1033..d782c40465 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -645,15 +645,18 @@ int map_is_location_owned(int x, int y, int z) { rct_map_element *mapElement; + // This check is to avoid throwing lots of messages in logs. if (x < (256 * 32) && y < (256 * 32)) { mapElement = map_get_surface_element_at(x / 32, y / 32); - if (mapElement->properties.surface.ownership & OWNERSHIP_OWNED) - return 1; - - if (mapElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) { - z /= 8; - if (z < mapElement->base_height || z - 2 > mapElement->base_height) + if (mapElement != NULL) { + if (mapElement->properties.surface.ownership & OWNERSHIP_OWNED) return 1; + + if (mapElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) { + z /= 8; + if (z < mapElement->base_height || z - 2 > mapElement->base_height) + return 1; + } } } @@ -708,6 +711,12 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es money32 cost; rct_scenery_entry *entry = g_smallSceneryEntries[scenery_type]; + if (entry == (rct_scenery_entry *)0xFFFFFFFF) + { + log_warning("Invalid game command for scenery removal, scenery_type = %u", scenery_type); + *ebx = MONEY32_UNDEFINED; + return; + } cost = entry->small_scenery.removal_price * 10; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; @@ -793,6 +802,12 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i bool element_found = false; rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + if (map_element == NULL) + { + log_warning("Invalid game command for scenery removal, x = %d, y = %d", x, y); + *ebx = MONEY32_UNDEFINED; + return; + } do { if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) continue; @@ -2128,6 +2143,11 @@ static money32 smooth_land_tile(int direction, uint8 flags, int x, int y, int ta // Get height of tile rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y); + return MONEY32_UNDEFINED; + } int baseZ = map_get_corner_height(mapElement, direction); // Check if tile is same height as target tile @@ -2200,6 +2220,11 @@ money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop x = mapLeft; y = mapTop; mapElement = map_get_surface_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y); + return MONEY32_UNDEFINED; + } int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; if (slope != 0) { commandType = command == 0xFFFF ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; @@ -3294,12 +3319,25 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in return; } + if (entry_index >= 128) + { + log_warning("Invalid game command for scenery placement, entry_index = %u", entry_index); + *ebx = MONEY32_UNDEFINED; + return; + } + if (!sub_68B044()) { *ebx = MONEY32_UNDEFINED; return; } rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[entry_index]; + if (scenery_entry == (rct_scenery_entry *)0xFFFFFFFF) + { + log_warning("Invalid game command for scenery placement, entry_index = %u", entry_index); + *ebx = MONEY32_UNDEFINED; + return; + } if(scenery_entry->large_scenery.var_11 != 0xFF){ banner_id = create_new_banner(flags); @@ -4284,6 +4322,10 @@ bool map_element_is_underground(rct_map_element *mapElement) rct_map_element *map_get_large_scenery_segment(int x, int y, int z, int direction, int sequence) { rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + return NULL; + } do { if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) continue; @@ -4767,6 +4809,12 @@ void game_command_place_park_entrance(int* eax, int* ebx, int* ecx, int* edx, in void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { static char newName[128]; + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + log_warning("Invalid game command for setting banner name, banner id = %d", *ecx); + *ebx = MONEY32_UNDEFINED; + return; + } rct_banner* banner = &gBanners[*ecx]; int nameChunkIndex = *eax & 0xFFFF; @@ -4776,6 +4824,7 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e if (nameChunkOffset < 0) nameChunkOffset = 2; nameChunkOffset *= 12; + nameChunkOffset = min(nameChunkOffset, countof(newName) - 12); RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; @@ -4811,6 +4860,12 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { static char newName[128]; + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + log_warning("Invalid game command for setting sign name, banner id = %d", *ecx); + *ebx = MONEY32_UNDEFINED; + return; + } rct_banner* banner = &gBanners[*ecx]; int x = banner->x << 5; int y = banner->y << 5; @@ -4822,6 +4877,7 @@ void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi if (nameChunkOffset < 0) nameChunkOffset = 2; nameChunkOffset *= 12; + nameChunkOffset = min(nameChunkOffset, countof(newName) - 12); RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; @@ -4866,6 +4922,12 @@ void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi } void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_SELECTION_OF_OBJECTS; + *ebx = MONEY32_UNDEFINED; + return; + } rct_banner* banner = &gBanners[*ecx]; banner->colour = (uint8)*edx; diff --git a/src/world/park.c b/src/world/park.c index 6512d2a9a4..e17e053359 100644 --- a/src/world/park.c +++ b/src/world/park.c @@ -871,6 +871,7 @@ void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi if (nameChunkOffset < 0) nameChunkOffset = 2; nameChunkOffset *= 12; + nameChunkOffset = min(nameChunkOffset, countof(newName) - 12); RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; From b5069d3809438648b5de2d9e0bd012df0ed4dfd8 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 4 Jan 2016 22:45:51 +0000 Subject: [PATCH 84/90] integrate variable: gInputState --- src/game.c | 4 +-- src/input.c | 56 +++++++++++++++++++++------------------- src/input.h | 15 +++++++++++ src/interface/viewport.c | 3 ++- src/interface/widget.c | 2 +- src/interface/window.h | 13 ---------- src/windows/dropdown.c | 4 +-- src/windows/scenery.c | 4 +-- src/windows/tooltip.c | 3 ++- 9 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/game.c b/src/game.c index 7463dc8e5e..3c343e2428 100644 --- a/src/game.c +++ b/src/game.c @@ -291,8 +291,8 @@ void game_update() RCT2_GLOBAL(0x009E2D74, uint32) = 0; break; } else { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESET || - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_NORMAL + if (gInputState == INPUT_STATE_RESET || + gInputState == INPUT_STATE_NORMAL ) { if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_VIEWPORT_SCROLLING) { RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING; diff --git a/src/input.c b/src/input.c index 2f3ca89b54..0ea15b9fea 100644 --- a/src/input.c +++ b/src/input.c @@ -50,6 +50,8 @@ static rct_windownumber _dragWindowNumber; static int _dragWidgetIndex, _dragScrollIndex; static int _originalWindowWidth, _originalWindowHeight; +uint8 gInputState; + typedef struct { uint32 x, y; uint32 state; //1 = LeftDown 2 = LeftUp 3 = RightDown 4 = RightUp @@ -184,7 +186,7 @@ static rct_mouse_data* get_mouse_input() * rct2: 0x006E957F */ static void input_scroll_drag_begin(int x, int y, rct_window* w, rct_widget* widget, int widgetIndex) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_RIGHT; + gInputState = INPUT_STATE_SCROLL_RIGHT; _dragX = x; _dragY = y; _dragWindowClass = w->classification; @@ -244,7 +246,7 @@ static void input_scroll_right(int x, int y, int state) { if (w == NULL) { platform_show_cursor(); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; return; } @@ -258,7 +260,7 @@ static void input_scroll_right(int x, int y, int state) { input_scroll_drag_continue(x, y, w); break; case 4: - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; platform_show_cursor(); break; } @@ -279,7 +281,7 @@ static void game_handle_input_mouse(int x, int y, int state) widgetIndex = w == NULL ? -1 : window_find_widget_from_point(w, x, y); widget = widgetIndex == -1 ? 0 : &w->widgets[widgetIndex]; - switch (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8)) { + switch (gInputState) { case INPUT_STATE_RESET: window_tooltip_reset(x, y); // fall-through @@ -317,7 +319,7 @@ static void game_handle_input_mouse(int x, int y, int state) case INPUT_STATE_POSITIONING_WINDOW: w = window_find_by_number(_dragWindowClass, _dragWindowNumber); if (w == NULL) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; } else { input_window_position_continue(w, _dragX, _dragY, x, y); @@ -346,13 +348,13 @@ static void game_handle_input_mouse(int x, int y, int state) RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) ); if (!w){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; + gInputState = INPUT_STATE_RESET; break; } if (state == 0){ if (!w->viewport){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; + gInputState = INPUT_STATE_RESET; break; } @@ -371,7 +373,7 @@ static void game_handle_input_mouse(int x, int y, int state) } else if (state == 2){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; + gInputState = INPUT_STATE_RESET; if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break; if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)){ w = window_find_by_number( @@ -399,7 +401,7 @@ static void game_handle_input_mouse(int x, int y, int state) case INPUT_STATE_RESIZING: w = window_find_by_number(_dragWindowClass, _dragWindowNumber); if (w == NULL) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; } else { if (state == 2) @@ -419,7 +421,7 @@ static void game_handle_input_mouse(int x, int y, int state) void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_POSITIONING_WINDOW; + gInputState = INPUT_STATE_POSITIONING_WINDOW; _dragX = x - w->x; _dragY = y - w->y; _dragWindowClass = w->classification; @@ -437,7 +439,7 @@ static void input_window_position_continue(rct_window *w, int wdx, int wdy, int static void input_window_position_end(rct_window *w, int x, int y) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL; + gInputState = INPUT_STATE_NORMAL; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = _dragWindowClass; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber; @@ -447,7 +449,7 @@ static void input_window_position_end(rct_window *w, int x, int y) static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int y) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESIZING; + gInputState = INPUT_STATE_RESIZING; _dragX = x; _dragY = y; _dragWindowClass = w->classification; @@ -477,7 +479,7 @@ static void input_window_resize_continue(rct_window *w, int x, int y) static void input_window_resize_end() { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL; + gInputState = INPUT_STATE_NORMAL; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = _dragWindowClass; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber; @@ -491,7 +493,7 @@ static void input_window_resize_end() static void input_viewport_drag_begin(rct_window *w, int x, int y) { w->flags &= ~WF_SCROLLING_TO_LOCATION; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_RIGHT; + gInputState = INPUT_STATE_VIEWPORT_RIGHT; _dragWindowClass = w->classification; _dragWindowNumber = w->number; RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0; @@ -518,7 +520,7 @@ static void input_viewport_drag_continue() RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16); if (viewport == NULL) { platform_show_cursor(); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; } else if (dx != 0 || dy != 0) { if (!(w->flags & WF_NO_SCROLLING)) { // User dragged a scrollable viewport @@ -544,7 +546,7 @@ static void input_viewport_drag_continue() static void input_viewport_drag_end() { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; platform_show_cursor(); } @@ -558,7 +560,7 @@ static void input_scroll_begin(rct_window *w, int widgetIndex, int x, int y) widget = &w->widgets[widgetIndex]; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_LEFT; + gInputState = INPUT_STATE_SCROLL_LEFT; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = w->classification; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = w->number; @@ -702,7 +704,7 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int static void input_scroll_end() { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; invalidate_scroll(); } @@ -1004,7 +1006,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex) input_window_resize_begin(w, widgetIndex, x, y); break; case WWT_VIEWPORT: - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_LEFT; + gInputState = INPUT_STATE_VIEWPORT_LEFT; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass; @@ -1035,7 +1037,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex) RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex; RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_WIDGET_PRESSED; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_WIDGET_PRESSED; + gInputState = INPUT_STATE_WIDGET_PRESSED; RCT2_GLOBAL(0x009DE528, uint16) = 1; widget_invalidate_by_number(windowClass, windowNumber, widgetIndex); @@ -1185,7 +1187,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi rct_window *cursor_w = window_find_by_number(cursor_w_class, cursor_w_number); if (cursor_w == NULL) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; + gInputState = INPUT_STATE_RESET; return; } @@ -1214,7 +1216,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi return; case 3: case 2: - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 5) { + if (gInputState == INPUT_STATE_DROPDOWN_ACTIVE) { if (w) { int dropdown_index = 0; @@ -1251,7 +1253,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex); } - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 1; + gInputState = INPUT_STATE_NORMAL; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = cursor_w_class; @@ -1263,7 +1265,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi } if (state == 3) return; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 1; + gInputState = INPUT_STATE_NORMAL; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex; @@ -1288,7 +1290,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi } RCT2_GLOBAL(0x9DE528, uint16) = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) != 5){ + if (gInputState != INPUT_STATE_DROPDOWN_ACTIVE){ // Hold down widget and drag outside of area?? if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED){ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE; @@ -1434,7 +1436,7 @@ void game_handle_keyboard_input() // Handle mouse scrolling if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0) if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0) - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 1) + if (gInputState == INPUT_STATE_NORMAL) if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3)) game_handle_edge_scroll(); @@ -1519,7 +1521,7 @@ int get_next_key() * rct2: 0x006ED990 */ void sub_6ED990(char cursor_id){ - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESIZING) + if (gInputState == INPUT_STATE_RESIZING) { cursor_id = CURSOR_DIAGONAL_ARROWS; //resize icon } diff --git a/src/input.h b/src/input.h index e6322a68e8..32f4478717 100644 --- a/src/input.h +++ b/src/input.h @@ -23,6 +23,19 @@ #include "interface/window.h" +enum { + INPUT_STATE_RESET, + INPUT_STATE_NORMAL, + INPUT_STATE_WIDGET_PRESSED, + INPUT_STATE_POSITIONING_WINDOW, + INPUT_STATE_VIEWPORT_RIGHT, + INPUT_STATE_DROPDOWN_ACTIVE, + INPUT_STATE_VIEWPORT_LEFT, + INPUT_STATE_SCROLL_LEFT, + INPUT_STATE_RESIZING, + INPUT_STATE_SCROLL_RIGHT +}; + enum { INPUT_FLAG_WIDGET_PRESSED = (1 << 0), @@ -47,6 +60,8 @@ enum { INPUT_FLAG_VIEWPORT_SCROLLING = (1 << 7) }; +extern uint8 gInputState; + void title_handle_keyboard_input(); void game_handle_input(); void game_handle_keyboard_input(); diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 1de8b79160..0de5641832 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -22,6 +22,7 @@ #include "../config.h" #include "../drawing/drawing.h" #include "../drawing/supports.h" +#include "../input.h" #include "../localisation/localisation.h" #include "../ride/ride_data.h" #include "../ride/track_data.h" @@ -102,7 +103,7 @@ void viewport_init_all() // ? RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1; diff --git a/src/interface/widget.c b/src/interface/widget.c index a07bba487e..97f0333641 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -978,7 +978,7 @@ int widget_is_disabled(rct_window *w, int widgetIndex) int widget_is_pressed(rct_window *w, int widgetIndex) { - int inputState = RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8); + int inputState = gInputState; if (w->pressed_widgets & (1LL << widgetIndex)) return 1; diff --git a/src/interface/window.h b/src/interface/window.h index c3fddca24b..b8a44147a1 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -386,19 +386,6 @@ enum { SCROLL_PART_VSCROLLBAR_THUMB = 10, }; -enum { - INPUT_STATE_RESET = 0, - INPUT_STATE_NORMAL = 1, - INPUT_STATE_WIDGET_PRESSED = 2, - INPUT_STATE_POSITIONING_WINDOW = 3, - INPUT_STATE_VIEWPORT_RIGHT = 4, - INPUT_STATE_DROPDOWN_ACTIVE = 5, - INPUT_STATE_VIEWPORT_LEFT = 6, - INPUT_STATE_SCROLL_LEFT = 7, - INPUT_STATE_RESIZING = 8, - INPUT_STATE_SCROLL_RIGHT = 9 -}; - enum { WC_MAIN_WINDOW = 0, WC_TOP_TOOLBAR = 1, diff --git a/src/windows/dropdown.c b/src/windows/dropdown.c index 655bbde163..4188ff2203 100644 --- a/src/windows/dropdown.c +++ b/src/windows/dropdown.c @@ -204,7 +204,7 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo gDropdownItemsDisabled = 0; gDropdownItemsChecked = 0; gDropdownIsColour = false; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_DROPDOWN_ACTIVE; + gInputState = INPUT_STATE_DROPDOWN_ACTIVE; } /** @@ -274,7 +274,7 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl gDropdownHighlightedIndex = -1; gDropdownItemsDisabled = 0; gDropdownItemsChecked = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_DROPDOWN_ACTIVE; + gInputState = INPUT_STATE_DROPDOWN_ACTIVE; // Copy the following properties until all use of it is decompiled gDropdownHighlightedIndex = gDropdownHighlightedIndex; diff --git a/src/windows/scenery.c b/src/windows/scenery.c index 3c8e57278b..1c2517765a 100644 --- a/src/windows/scenery.c +++ b/src/windows/scenery.c @@ -693,7 +693,7 @@ static void window_scenery_update(rct_window *w) if (widgetIndex >= WIDX_SCENERY_TAB_CONTENT_PANEL) { w->scenery.hover_counter++; if (w->scenery.hover_counter < 8) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) != INPUT_STATE_SCROLL_LEFT) { + if (gInputState != INPUT_STATE_SCROLL_LEFT) { w->min_width = WINDOW_SCENERY_WIDTH; w->max_width = WINDOW_SCENERY_WIDTH; w->min_height = WINDOW_SCENERY_HEIGHT; @@ -713,7 +713,7 @@ static void window_scenery_update(rct_window *w) } } else { w->scenery.hover_counter = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) != INPUT_STATE_SCROLL_LEFT) { + if (gInputState != INPUT_STATE_SCROLL_LEFT) { w->min_width = WINDOW_SCENERY_WIDTH; w->max_width = WINDOW_SCENERY_WIDTH; w->min_height = WINDOW_SCENERY_HEIGHT; diff --git a/src/windows/tooltip.c b/src/windows/tooltip.c index f2bf9b6e7b..fe74464f42 100644 --- a/src/windows/tooltip.c +++ b/src/windows/tooltip.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "../drawing/drawing.h" #include "../localisation/localisation.h" +#include "../input.h" #include "../interface/widget.h" #include "../interface/window.h" @@ -74,7 +75,7 @@ void window_tooltip_reset(int x, int y) RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, uint8) = 255; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 1; + gInputState = INPUT_STATE_NORMAL; RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(1 << 4); } From f0adf906605b9b4956a0e058947c269b5f0ce428 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 4 Jan 2016 22:53:03 +0000 Subject: [PATCH 85/90] integrate variable: gInputFlags --- src/game.c | 18 +++++------ src/input.c | 47 ++++++++++++++-------------- src/input.h | 1 + src/interface/keyboard_shortcut.c | 2 +- src/interface/viewport.c | 2 +- src/interface/viewport_interaction.c | 2 +- src/interface/widget.c | 4 +-- src/interface/window.c | 12 +++---- src/management/news_item.c | 2 +- src/ride/ride.c | 6 ++-- src/title.c | 2 +- src/windows/clear_scenery.c | 2 +- src/windows/dropdown.c | 8 ++--- src/windows/footpath.c | 10 +++--- src/windows/guest.c | 4 +-- src/windows/land_rights.c | 2 +- src/windows/map.c | 8 ++--- src/windows/map_tooltip.c | 2 +- src/windows/maze_construction.c | 4 +-- src/windows/park.c | 16 +++++----- src/windows/ride.c | 10 +++--- src/windows/ride_construction.c | 8 ++--- src/windows/scenery.c | 2 +- src/windows/staff.c | 4 +-- src/windows/staff_list.c | 2 +- src/windows/tooltip.c | 2 +- src/windows/top_toolbar.c | 16 +++++----- src/windows/track_place.c | 4 +-- src/windows/water.c | 2 +- 29 files changed, 103 insertions(+), 101 deletions(-) diff --git a/src/game.c b/src/game.c index 3c343e2428..bab4bbf614 100644 --- a/src/game.c +++ b/src/game.c @@ -294,8 +294,8 @@ void game_update() if (gInputState == INPUT_STATE_RESET || gInputState == INPUT_STATE_NORMAL ) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_VIEWPORT_SCROLLING) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING; + if (gInputFlags & INPUT_FLAG_VIEWPORT_SCROLLING) { + gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING; break; } } else { @@ -313,7 +313,7 @@ void game_update() RCT2_GLOBAL(0x009A8C28, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING; + gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING; // the flickering frequency is reduced by 4, compared to the original // it was done due to inability to reproduce original frequency @@ -773,10 +773,10 @@ int game_load_sv6(SDL_RWops* rw) if (!load_success){ set_load_objects_fail_reason(); - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5){ + if (gInputFlags & INPUT_FLAG_5){ //call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless RCT2_GLOBAL(0x14241BC, uint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5; + gInputFlags &= ~INPUT_FLAG_5; } return 0;//This never gets called @@ -867,10 +867,10 @@ int game_load_network(SDL_RWops* rw) if (!load_success){ set_load_objects_fail_reason(); - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5){ + if (gInputFlags & INPUT_FLAG_5){ //call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless RCT2_GLOBAL(0x14241BC, uint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5; + gInputFlags &= ~INPUT_FLAG_5; } return 0;//This never gets called @@ -1215,8 +1215,8 @@ void game_load_or_quit_no_save_prompt() } else if (RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) == 1) { game_do_command(0, 1, 0, 1, GAME_COMMAND_LOAD_OR_QUIT, 0, 0); tool_cancel(); - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5; + if (gInputFlags & INPUT_FLAG_5) { + gInputFlags &= ~INPUT_FLAG_5; } gGameSpeed = 1; title_load(); diff --git a/src/input.c b/src/input.c index 0ea15b9fea..abbe8e7d7f 100644 --- a/src/input.c +++ b/src/input.c @@ -51,6 +51,7 @@ static int _dragWidgetIndex, _dragScrollIndex; static int _originalWindowWidth, _originalWindowHeight; uint8 gInputState; +uint8 gInputFlags; typedef struct { uint32 x, y; @@ -127,7 +128,7 @@ void game_handle_input() game_handle_input_mouse(x, y, state & 0xFF); } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5) { + if (gInputFlags & INPUT_FLAG_5) { game_handle_input_mouse(x, y, state); } else if (x != 0x80000000) { @@ -360,7 +361,7 @@ static void game_handle_input_mouse(int x, int y, int state) if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) || w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) || - !(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) break; + !(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) break; w = window_find_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), @@ -375,7 +376,7 @@ static void game_handle_input_mouse(int x, int y, int state) gInputState = INPUT_STATE_RESET; if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break; - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)){ + if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE)){ w = window_find_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) @@ -385,7 +386,7 @@ static void game_handle_input_mouse(int x, int y, int state) window_event_tool_up_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y); } else{ - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_4)) + if ((gInputFlags & INPUT_FLAG_4)) break; viewport_interaction_left_click(x, y); @@ -500,7 +501,7 @@ static void input_viewport_drag_begin(rct_window *w, int x, int y) platform_get_cursor_position(&_dragX, &_dragY); platform_hide_cursor(); - // RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_5; + // gInputFlags |= INPUT_FLAG_5; } static void input_viewport_drag_continue() @@ -1011,14 +1012,14 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex) RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) { + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { w = window_find_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) ); if (w != NULL) { window_event_tool_down_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_4; + gInputFlags |= INPUT_FLAG_4; } } break; @@ -1036,7 +1037,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex) RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_WIDGET_PRESSED; + gInputFlags |= INPUT_FLAG_WIDGET_PRESSED; gInputState = INPUT_STATE_WIDGET_PRESSED; RCT2_GLOBAL(0x009DE528, uint16) = 1; @@ -1073,7 +1074,7 @@ void process_mouse_over(int x, int y) switch (window->widgets[widgetId].type){ case WWT_VIEWPORT: - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, int) & INPUT_FLAG_TOOL_ACTIVE) == 0) { + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) { if (viewport_interaction_left_over(x, y)) { sub_6ED990(CURSOR_HAND_POINT); return; @@ -1155,7 +1156,7 @@ void process_mouse_over(int x, int y) */ void process_mouse_tool(int x, int y) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { rct_window* w = window_find_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), @@ -1209,9 +1210,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi window_event_mouse_down_call(w, widgetIndex); } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED) return; + if (gInputFlags & INPUT_FLAG_WIDGET_PRESSED) return; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_WIDGET_PRESSED; + gInputFlags |= INPUT_FLAG_WIDGET_PRESSED; widget_invalidate_by_number(cursor_w_class, cursor_w_number, widgetIndex); return; case 3: @@ -1238,9 +1239,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex) goto dropdown_cleanup; dropdown_index = -1; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_DROPDOWN_STAY_OPEN){ - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_DROPDOWN_MOUSE_UP)){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_MOUSE_UP; + if (gInputFlags & INPUT_FLAG_DROPDOWN_STAY_OPEN){ + if (!(gInputFlags & INPUT_FLAG_DROPDOWN_MOUSE_UP)){ + gInputFlags |= INPUT_FLAG_DROPDOWN_MOUSE_UP; return; } } @@ -1248,8 +1249,8 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi window_close_by_class(WC_DROPDOWN); cursor_w = window_find_by_number(cursor_w_class, cursor_w_number); - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE; + if (gInputFlags & INPUT_FLAG_WIDGET_PRESSED) { + gInputFlags &= ~INPUT_FLAG_WIDGET_PRESSED; widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex); } @@ -1292,8 +1293,8 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi RCT2_GLOBAL(0x9DE528, uint16) = 0; if (gInputState != INPUT_STATE_DROPDOWN_ACTIVE){ // Hold down widget and drag outside of area?? - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE; + if (gInputFlags & INPUT_FLAG_WIDGET_PRESSED){ + gInputFlags &= ~INPUT_FLAG_WIDGET_PRESSED; widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex); } return; @@ -1615,11 +1616,11 @@ void game_handle_edge_scroll() // Scroll viewport if (scrollX != 0) { mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING; + gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING; } if (scrollY != 0) { mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING; + gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING; } } @@ -1684,11 +1685,11 @@ void game_handle_key_scroll() // Scroll viewport if (scrollX != 0) { mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING; + gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING; } if (scrollY != 0) { mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING; + gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING; } } diff --git a/src/input.h b/src/input.h index 32f4478717..19e748c2fe 100644 --- a/src/input.h +++ b/src/input.h @@ -61,6 +61,7 @@ enum { }; extern uint8 gInputState; +extern uint8 gInputFlags; void title_handle_keyboard_input(); void game_handle_input(); diff --git a/src/interface/keyboard_shortcut.c b/src/interface/keyboard_shortcut.c index a10fd4f5c4..7308fac0eb 100644 --- a/src/interface/keyboard_shortcut.c +++ b/src/interface/keyboard_shortcut.c @@ -136,7 +136,7 @@ static void shortcut_cancel_construction_mode() window = window_find_by_class(WC_ERROR); if (window != NULL) window_close(window); - else if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + else if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) tool_cancel(); } diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 0de5641832..ae845bbf01 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -102,7 +102,7 @@ void viewport_init_all() RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_VIEWPORT_PTR_ARRAY, rct_viewport*) = NULL; // ? - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) = 0; + gInputFlags = 0; gInputState = INPUT_STATE_RESET; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index 7734113ede..536ca3a804 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -272,7 +272,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info return info->type; } - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & (INPUT_FLAG_6 | INPUT_FLAG_TOOL_ACTIVE)) != (INPUT_FLAG_6 | INPUT_FLAG_TOOL_ACTIVE)) + if ((gInputFlags & INPUT_FLAG_6) && (gInputFlags && INPUT_FLAG_TOOL_ACTIVE)) if (window_find_by_class(WC_RIDE_CONSTRUCTION) == NULL && window_find_by_class(WC_FOOTPATH) == NULL) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; diff --git a/src/interface/widget.c b/src/interface/widget.c index 97f0333641..6175540dee 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -987,7 +987,7 @@ int widget_is_pressed(rct_window *w, int widgetIndex) return 0; if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) != w->number) return 0; - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED)) + if (!(gInputFlags & INPUT_FLAG_WIDGET_PRESSED)) return 0; if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint32) == widgetIndex) return 1; @@ -1008,7 +1008,7 @@ int widget_is_highlighted(rct_window *w, int widgetIndex) int widget_is_active_tool(rct_window *w, int widgetIndex) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) return 0; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != w->classification) return 0; diff --git a/src/interface/window.c b/src/interface/window.c index a7b3dd483c..449e56d110 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -306,7 +306,7 @@ static void window_all_wheel_input() return; // Check window cursor is over - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5)) { + if (!(gInputFlags & INPUT_FLAG_5)) { w = window_find_from_point(gCursorState.x, gCursorState.y); if (w != NULL) { // Check if main window @@ -1727,7 +1727,7 @@ void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth, */ int tool_set(rct_window *w, int widgetIndex, int tool) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) { + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { if ( w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) && @@ -1740,8 +1740,8 @@ int tool_set(rct_window *w, int widgetIndex, int tool) } } - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_TOOL_ACTIVE; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_TOOL_ACTIVE; + gInputFlags &= ~INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = tool; RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) = w->classification; RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) = w->number; @@ -1757,8 +1757,8 @@ void tool_cancel() { rct_window *w; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_TOOL_ACTIVE; + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { + gInputFlags &= ~INPUT_FLAG_TOOL_ACTIVE; map_invalidate_selection_rect(); map_invalidate_map_selection_tiles(); diff --git a/src/management/news_item.c b/src/management/news_item.c index a855bcbdf2..df7b1de3e9 100644 --- a/src/management/news_item.c +++ b/src/management/news_item.c @@ -379,7 +379,7 @@ void news_item_open_subject(int type, int subject) if (window != NULL) { window_invalidate(window); if (!tool_set(window, 9, 0)) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; window_scenery_open(); } } diff --git a/src/ride/ride.c b/src/ride/ride.c index 2229b51c0c..0fc5fdf956 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -1591,7 +1591,7 @@ static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int sub_6C9627(); if ( _rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT || - !(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) || + !(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) || RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_RIDE_CONSTRUCTION ) { // Replace entrance / exit @@ -1599,7 +1599,7 @@ static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int RCT2_GLOBAL(0x00F44191, uint8) = entranceType; RCT2_GLOBAL(0x00F44192, uint8) = rideIndex; RCT2_GLOBAL(0x00F44193, uint8) = bl; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) { RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState; _rideConstructionState = RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT; @@ -1754,7 +1754,7 @@ int sub_6CC3FB(int rideIndex) w = ride_create_or_find_construction_window(rideIndex); tool_set(w, 23, 12); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; ride = GET_RIDE(_currentRideIndex); diff --git a/src/title.c b/src/title.c index 31a46b5fa2..3d636ef60d 100644 --- a/src/title.c +++ b/src/title.c @@ -538,7 +538,7 @@ void title_update() audio_start_title_music(); } - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~0x80; + gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING; window_map_tooltip_update_visibility(); window_dispatch_update_all(); diff --git a/src/windows/clear_scenery.c b/src/windows/clear_scenery.c index 2bff67b0d9..ebc5251efb 100644 --- a/src/windows/clear_scenery.c +++ b/src/windows/clear_scenery.c @@ -259,7 +259,7 @@ static void window_clear_scenery_paint(rct_window *w, rct_drawpixelinfo *dpi) */ static int window_clear_scenery_should_close() { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) return 1; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TOP_TOOLBAR) return 1; diff --git a/src/windows/dropdown.c b/src/windows/dropdown.c index 4188ff2203..37bc26d370 100644 --- a/src/windows/dropdown.c +++ b/src/windows/dropdown.c @@ -160,9 +160,9 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo memcpy((void*)0x009DEBA4, gDropdownItemsFormat, 40 * 2); memcpy((void*)0x009DEBF4, gDropdownItemsArgs, 40 * 8); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP); + gInputFlags &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP); if (flags & DROPDOWN_FLAG_STAY_OPEN) - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_STAY_OPEN; + gInputFlags |= INPUT_FLAG_DROPDOWN_STAY_OPEN; window_dropdown_close(); _dropdown_num_columns = 1; @@ -230,9 +230,9 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl memcpy((void*)0x009DEBA4, gDropdownItemsFormat, 40 * 2); memcpy((void*)0x009DEBF4, gDropdownItemsArgs, 40 * 8); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP); + gInputFlags &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP); if (flags & DROPDOWN_FLAG_STAY_OPEN) - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_STAY_OPEN; + gInputFlags |= INPUT_FLAG_DROPDOWN_STAY_OPEN; // Close existing dropdown window_dropdown_close(); diff --git a/src/windows/footpath.c b/src/windows/footpath.c index d815f41985..46564f0de5 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -217,7 +217,7 @@ void window_footpath_open() tool_cancel(); RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_LAND; tool_set(window, WIDX_CONSTRUCT_ON_LAND, 17); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0; window_footpath_set_enabled_and_pressed_widgets(); } @@ -263,7 +263,7 @@ static void window_footpath_mouseup(rct_window *w, int widgetIndex) RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2; RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_LAND; tool_set(w, WIDX_CONSTRUCT_ON_LAND, 17); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0; window_footpath_set_enabled_and_pressed_widgets(); break; @@ -278,7 +278,7 @@ static void window_footpath_mouseup(rct_window *w, int widgetIndex) RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2; RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL; tool_set(w, WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL, 12); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0; window_footpath_set_enabled_and_pressed_widgets(); break; @@ -479,14 +479,14 @@ static void window_footpath_update(rct_window *w) // Check tool if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_LAND) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) window_close(w); else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH) window_close(w); else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_CONSTRUCT_ON_LAND) window_close(w); } else if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) window_close(w); else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH) window_close(w); diff --git a/src/windows/guest.c b/src/windows/guest.c index b1b4421c24..cc1782d4c2 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -560,7 +560,7 @@ void window_guest_disable_widgets(rct_window* w){ */ void window_guest_overview_close(rct_window *w) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE){ + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE){ if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS,rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER,rct_windownumber)) tool_cancel(); @@ -653,7 +653,7 @@ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex) * rct2: 0x696AA0 */ void window_guest_set_page(rct_window* w, int page){ - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { if(w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) && w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass)) diff --git a/src/windows/land_rights.c b/src/windows/land_rights.c index d2e375312f..6d5b6723f0 100644 --- a/src/windows/land_rights.c +++ b/src/windows/land_rights.c @@ -237,7 +237,7 @@ static void window_land_rights_paint(rct_window *w, rct_drawpixelinfo *dpi) static int window_land_rights_should_close() { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) return 1; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_PARK_INFORMATION) return 1; diff --git a/src/windows/map.c b/src/windows/map.c index 76921d99ee..ffc74fa61b 100644 --- a/src/windows/map.c +++ b/src/windows/map.c @@ -241,7 +241,7 @@ void window_map_open() static void window_map_close(rct_window *w) { free(RCT2_GLOBAL(RCT2_ADDRESS_MAP_IMAGE_DATA, uint32*)); - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && + if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == w->classification && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16) == w->number) { tool_cancel(); @@ -319,7 +319,7 @@ static void window_map_mouseup(rct_window *w, int widgetIndex) break; RCT2_GLOBAL(0x9E32D2, sint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; show_gridlines(); show_land_rights(); @@ -740,7 +740,7 @@ static void window_map_invalidate(rct_window *w) if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode) { // scenario editor: build park entrance selected, show rotate button if ( - (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && + (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_MAP && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == WIDX_BUILD_PARK_ENTRANCE ) { @@ -752,7 +752,7 @@ static void window_map_invalidate(rct_window *w) // If any tool is active if ( - (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && + (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_MAP ) { // if not in set land rights mode: show the default scenario editor buttons diff --git a/src/windows/map_tooltip.c b/src/windows/map_tooltip.c index 180a3f9709..eb5b2179f1 100644 --- a/src/windows/map_tooltip.c +++ b/src/windows/map_tooltip.c @@ -81,7 +81,7 @@ void window_map_tooltip_update_visibility() cursorX = RCT2_GLOBAL(0x0142406C, sint32); cursorY = RCT2_GLOBAL(0x01424070, sint32); - inputFlags = RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32); + inputFlags = gInputFlags; // Check for cursor movement _cursorHoldDuration++; diff --git a/src/windows/maze_construction.c b/src/windows/maze_construction.c index 7ca6166205..992eea20b0 100644 --- a/src/windows/maze_construction.c +++ b/src/windows/maze_construction.c @@ -194,7 +194,7 @@ static void window_maze_construction_entrance_mouseup(rct_window *w, int widgetI RCT2_GLOBAL(0x00F44191, uint8) = widgetIndex == WIDX_MAZE_ENTRANCE ? 0 : 1; RCT2_GLOBAL(0x00F44192, uint8) = (uint8)w->number; RCT2_GLOBAL(0x00F44193, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; sub_6C9627(); @@ -311,7 +311,7 @@ static void window_maze_construction_update(rct_window *w) case RIDE_CONSTRUCTION_STATE_BACK: case RIDE_CONSTRUCTION_STATE_SELECTED: if ( - (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && + (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_RIDE_CONSTRUCTION ) { tool_cancel(); diff --git a/src/windows/park.c b/src/windows/park.c index d8306d4d74..51ad8cb281 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -612,7 +612,7 @@ void window_park_entrance_open() */ static void window_park_entrance_close(rct_window *w) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); } @@ -1124,14 +1124,14 @@ static void window_park_init_viewport(rct_window *w) void toggle_land_rights_window(rct_window *parkWindow, int widgetIndex) { - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_PARK_INFORMATION && + if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_PARK_INFORMATION && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == WIDX_BUY_LAND_RIGHTS) { tool_cancel(); } else { show_gridlines(); tool_set(parkWindow, widgetIndex, 2); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1; window_land_rights_open(); } @@ -1156,7 +1156,7 @@ void window_park_rating_open() window->viewport_focus_coordinates.y = -1; } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); @@ -1272,7 +1272,7 @@ void window_park_guests_open() window->viewport_focus_coordinates.y = -1; } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); @@ -1630,7 +1630,7 @@ void window_park_objective_open() window->viewport_focus_coordinates.y = -1; } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); @@ -1795,7 +1795,7 @@ void window_park_awards_open() window->viewport_focus_coordinates.y = -1; } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); @@ -1907,7 +1907,7 @@ static void window_park_set_page(rct_window *w, int page) { int listen; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); diff --git a/src/windows/ride.c b/src/windows/ride.c index 13d0eb5666..6c3f2b96b7 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -1219,7 +1219,7 @@ rct_window *window_ride_main_open(int rideIndex) w->ride.var_482 = -1; } - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) { + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) ) { @@ -1266,7 +1266,7 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex) } if ( - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE && + gInputFlags & INPUT_FLAG_TOOL_ACTIVE && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == w->classification && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) == w->number ) { @@ -1345,7 +1345,7 @@ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle) window_invalidate(w); if ( - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE && + gInputFlags & INPUT_FLAG_TOOL_ACTIVE && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == w->classification && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) == w->number ) { @@ -1410,7 +1410,7 @@ static void window_ride_set_page(rct_window *w, int page) { int listen; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); @@ -3747,7 +3747,7 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y) */ static void window_ride_colour_close(rct_window *w) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) return; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != w->classification) diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c index e43d2083ec..f344fe18d6 100644 --- a/src/windows/ride_construction.c +++ b/src/windows/ride_construction.c @@ -1873,7 +1873,7 @@ static void window_ride_construction_entrance_click(rct_window *w) RCT2_GLOBAL(0x00F44191, uint8) = 0; RCT2_GLOBAL(0x00F44192, uint8) = w->number & 0xFF; RCT2_GLOBAL(0x00F44193, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; sub_6C9627(); if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) { RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState; @@ -1897,7 +1897,7 @@ static void window_ride_construction_exit_click(rct_window *w) RCT2_GLOBAL(0x00F44191, uint8) = 1; RCT2_GLOBAL(0x00F44192, uint8) = w->number & 0xFF; RCT2_GLOBAL(0x00F44193, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; sub_6C9627(); if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) { RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState; @@ -1941,7 +1941,7 @@ static void window_ride_construction_update(rct_window *w) case RIDE_CONSTRUCTION_STATE_BACK: case RIDE_CONSTRUCTION_STATE_SELECTED: if ( - (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && + (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_RIDE_CONSTRUCTION ) { tool_cancel(); @@ -3569,7 +3569,7 @@ void ride_construction_tooldown_construct(int screenX, int screenY) w = window_find_by_class(WC_RIDE_CONSTRUCTION); if (w != NULL){ tool_set(w, 23, 12); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= (1 << 6); + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(0x00F44159, uint8) = 0; RCT2_GLOBAL(0x00F4415C, uint8) = 0; } diff --git a/src/windows/scenery.c b/src/windows/scenery.c index 1c2517765a..87331be5ae 100644 --- a/src/windows/scenery.c +++ b/src/windows/scenery.c @@ -490,7 +490,7 @@ bool window_scenery_is_scenery_tool_active() { int toolWindowClassification = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass); int toolWidgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16); - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (toolWindowClassification == WC_TOP_TOOLBAR && toolWidgetIndex == 9) // 9 is WIDX_SCENERY return true; diff --git a/src/windows/staff.c b/src/windows/staff.c index 3da193a083..9bf5e7c81a 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -369,7 +369,7 @@ void window_staff_disable_widgets(rct_window* w) */ void window_staff_overview_close(rct_window *w) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE){ + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE){ if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); @@ -382,7 +382,7 @@ void window_staff_overview_close(rct_window *w) */ void window_staff_set_page(rct_window* w, int page) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) { if(w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) && w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass)) diff --git a/src/windows/staff_list.c b/src/windows/staff_list.c index afd7271fd7..d1c9fc1825 100644 --- a/src/windows/staff_list.c +++ b/src/windows/staff_list.c @@ -181,7 +181,7 @@ void window_staff_list_open() void window_staff_list_cancel_tools(rct_window *w) { int toolWindowClassification = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass); int toolWindowNumber = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber); - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) + if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)) tool_cancel(); } diff --git a/src/windows/tooltip.c b/src/windows/tooltip.c index fe74464f42..e9fecabf44 100644 --- a/src/windows/tooltip.c +++ b/src/windows/tooltip.c @@ -76,7 +76,7 @@ void window_tooltip_reset(int x, int y) RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, uint8) = 255; gInputState = INPUT_STATE_NORMAL; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(1 << 4); + gInputFlags &= ~INPUT_FLAG_4; } uint8* gTooltip_text_buffer = RCT2_ADDRESS(RCT2_ADDRESS_TOOLTIP_TEXT_BUFFER, uint8); diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 390f4501d4..7c2e2b5e1c 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -310,7 +310,7 @@ static void window_top_toolbar_mouseup(rct_window *w, int widgetIndex) break; case WIDX_SCENERY: if (!tool_set(w, WIDX_SCENERY, 0)) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; window_scenery_open(); } break; @@ -3117,12 +3117,12 @@ void toggle_footpath_window() */ void toggle_land_window(rct_window *topToolbar, int widgetIndex) { - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) { + if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_TOP_TOOLBAR && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) { tool_cancel(); } else { show_gridlines(); tool_set(topToolbar, widgetIndex, 18); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1; window_land_open(); } @@ -3134,12 +3134,12 @@ void toggle_land_window(rct_window *topToolbar, int widgetIndex) */ void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex) { - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) { + if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_TOP_TOOLBAR && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) { tool_cancel(); } else { show_gridlines(); tool_set(topToolbar, widgetIndex, 12); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 2; window_clear_scenery_open(); } @@ -3151,12 +3151,12 @@ void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex) */ void toggle_water_window(rct_window *topToolbar, int widgetIndex) { - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) { + if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_TOP_TOOLBAR && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) { tool_cancel(); } else { show_gridlines(); tool_set(topToolbar, widgetIndex, 19); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1; window_water_open(); } @@ -3168,7 +3168,7 @@ void toggle_water_window(rct_window *topToolbar, int widgetIndex) */ bool land_tool_is_active() { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) return false; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TOP_TOOLBAR) return false; diff --git a/src/windows/track_place.c b/src/windows/track_place.c index 8232abba53..4fe5fb149d 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -389,7 +389,7 @@ void window_track_place_open() w->enabled_widgets = 4 | 8 | 0x10 | 0x20; window_init_scroll_widgets(w); tool_set(w, 6, 12); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; window_push_others_right(w); show_gridlines(); _window_track_place_last_cost = MONEY32_UNDEFINED; @@ -449,7 +449,7 @@ static void window_track_place_mouseup(rct_window *w, int widgetIndex) */ static void window_track_place_update(rct_window *w) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TRACK_DESIGN_PLACE) window_close(w); } diff --git a/src/windows/water.c b/src/windows/water.c index 63bc6dc1e5..8a8b98dd08 100644 --- a/src/windows/water.c +++ b/src/windows/water.c @@ -256,7 +256,7 @@ static void window_water_paint(rct_window *w, rct_drawpixelinfo *dpi) */ static int window_water_should_close() { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) + if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) return 1; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TOP_TOOLBAR) return 1; From 0c933234e0b789bc041e196a60ec64660ed6fd24 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 4 Jan 2016 23:21:23 +0000 Subject: [PATCH 86/90] remove all tutorial code --- OpenRCT2.xcodeproj/project.pbxproj | 6 -- openrct2.vcxproj | 2 - openrct2.vcxproj.filters | 6 -- src/game.c | 1 - src/input.c | 43 ++-------- src/input.h | 1 - src/localisation/string_ids.h | 6 -- src/rct2.c | 3 - src/tutorial.c | 132 ----------------------------- src/tutorial.h | 28 ------ src/windows/game_bottom_toolbar.c | 13 --- src/windows/save_prompt.c | 26 ------ src/windows/title_menu.c | 19 +---- 13 files changed, 7 insertions(+), 279 deletions(-) delete mode 100644 src/tutorial.c delete mode 100644 src/tutorial.h diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 8b956eb69b..499f451a07 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -91,7 +91,6 @@ D4EC48281C26342F0024B507 /* scenario_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC476D1C26342F0024B507 /* scenario_list.c */; }; D4EC48291C26342F0024B507 /* scenario.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC476E1C26342F0024B507 /* scenario.c */; }; D4EC482A1C26342F0024B507 /* title.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47711C26342F0024B507 /* title.c */; }; - D4EC482B1C26342F0024B507 /* tutorial.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47731C26342F0024B507 /* tutorial.c */; }; D4EC482C1C26342F0024B507 /* sawyercoding.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47761C26342F0024B507 /* sawyercoding.c */; }; D4EC482D1C26342F0024B507 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47781C26342F0024B507 /* util.c */; }; D4EC482E1C26342F0024B507 /* about.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC477B1C26342F0024B507 /* about.c */; }; @@ -372,8 +371,6 @@ D4EC47701C26342F0024B507 /* sprites.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sprites.h; path = src/sprites.h; sourceTree = ""; }; D4EC47711C26342F0024B507 /* title.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = title.c; path = src/title.c; sourceTree = ""; }; D4EC47721C26342F0024B507 /* title.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = title.h; path = src/title.h; sourceTree = ""; }; - D4EC47731C26342F0024B507 /* tutorial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tutorial.c; path = src/tutorial.c; sourceTree = ""; }; - D4EC47741C26342F0024B507 /* tutorial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tutorial.h; path = src/tutorial.h; sourceTree = ""; }; D4EC47761C26342F0024B507 /* sawyercoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sawyercoding.c; sourceTree = ""; }; D4EC47771C26342F0024B507 /* sawyercoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sawyercoding.h; sourceTree = ""; }; D4EC47781C26342F0024B507 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; @@ -634,8 +631,6 @@ D4EC47701C26342F0024B507 /* sprites.h */, D4EC47711C26342F0024B507 /* title.c */, D4EC47721C26342F0024B507 /* title.h */, - D4EC47731C26342F0024B507 /* tutorial.c */, - D4EC47741C26342F0024B507 /* tutorial.h */, D4163F671C2A044D00B83136 /* version.h */, ); name = Sources; @@ -1385,7 +1380,6 @@ D4EC48231C26342F0024B507 /* station.c in Sources */, D4EC484D1C26342F0024B507 /* new_ride.c in Sources */, D4EC484A1C26342F0024B507 /* music_credits.c in Sources */, - D4EC482B1C26342F0024B507 /* tutorial.c in Sources */, D4EC48241C26342F0024B507 /* track.c in Sources */, D4EC47DF1C26342F0024B507 /* addresses.c in Sources */, D4EC484B1C26342F0024B507 /* network_status.c in Sources */, diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 019cc6419d..2df174a70f 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -119,7 +119,6 @@ - @@ -271,7 +270,6 @@ - diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index 2e1f69fbca..e6239b6394 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -270,9 +270,6 @@ Source - - Source - Source\Localisation @@ -692,9 +689,6 @@ Source - - Source - Source\Localisation diff --git a/src/game.c b/src/game.c index bab4bbf614..90de03c730 100644 --- a/src/game.c +++ b/src/game.c @@ -46,7 +46,6 @@ #include "ride/track.h" #include "scenario.h" #include "title.h" -#include "tutorial.h" #include "util/sawyercoding.h" #include "util/util.h" #include "windows/error.h" diff --git a/src/input.c b/src/input.c index abbe8e7d7f..b8b81fa4e1 100644 --- a/src/input.c +++ b/src/input.c @@ -35,7 +35,6 @@ #include "platform/platform.h" #include "ride/ride_data.h" #include "scenario.h" -#include "tutorial.h" #include "windows/tooltip.h" #include "windows/dropdown.h" #include "world/banner.h" @@ -95,7 +94,6 @@ static void input_scroll_part_update_vthumb(rct_window *w, int widgetIndex, int static void input_scroll_part_update_vtop(rct_window *w, int widgetIndex, int scroll_id); static void input_scroll_part_update_vbottom(rct_window *w, int widgetIndex, int scroll_id); static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y); -static void update_cursor_position(); #pragma region Mouse input @@ -118,7 +116,6 @@ void game_handle_input() window_event_unknown_07_call(w); sub_6EA73F(); - update_cursor_position(); for (;;) { game_get_next_input(&x, &y, &state); @@ -162,8 +159,6 @@ static void game_get_next_input(int *x, int *y, int *state) *x = eax->x; *y = eax->y; *state = eax->state; - - // NOTE this function lacks tutorial logic } /** @@ -1435,11 +1430,10 @@ void game_handle_keyboard_input() if (!gConsoleOpen) { // Handle mouse scrolling - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0) - if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0) - if (gInputState == INPUT_STATE_NORMAL) - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3)) - game_handle_edge_scroll(); + if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0) + if (gInputState == INPUT_STATE_NORMAL) + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3)) + game_handle_edge_scroll(); // Handle modifier keys and key scrolling RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; @@ -1450,8 +1444,7 @@ void game_handle_keyboard_input() RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 2; if (gKeysState[SDL_SCANCODE_LALT] || gKeysState[SDL_SCANCODE_RALT]) RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 4; - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0) - game_handle_key_scroll(); + game_handle_key_scroll(); } } @@ -1481,8 +1474,6 @@ void game_handle_keyboard_input() w = window_find_by_class(WC_CHANGE_KEYBOARD_SHORTCUT); if (w != NULL) { keyboard_shortcut_set(key); - } else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) { - tutorial_stop(); } else { w = window_find_by_class(WC_TEXTINPUT); if (w != NULL) { @@ -1492,10 +1483,6 @@ void game_handle_keyboard_input() } } } - - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) { - game_handle_keyboard_input_for_tutorial(); - } } /** @@ -1692,23 +1679,3 @@ void game_handle_key_scroll() gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING; } } - -/** - * - * rct2: 0x006E8346 - */ -static void update_cursor_position() -{ - switch (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8)) { - case 0: - // RCT2_GLOBAL(0x0142004C, sint32) = RCT2_GLOBAL(0x0142406C, sint32); - // RCT2_GLOBAL(0x01420050, sint32) = RCT2_GLOBAL(0x01424070, sint32); - break; - case 1: - // read tutorial cursor position - break; - case 2: - // write tutorial cursor position - break; - } -} diff --git a/src/input.h b/src/input.h index 19e748c2fe..80f68d829d 100644 --- a/src/input.h +++ b/src/input.h @@ -66,7 +66,6 @@ extern uint8 gInputFlags; void title_handle_keyboard_input(); void game_handle_input(); void game_handle_keyboard_input(); -void game_handle_keyboard_input_for_tutorial(); void store_mouse_input(int state); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index fe5d9012e6..9e24822c28 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1527,8 +1527,6 @@ enum { STR_ENTRANCE_NOT_CONNECTED = 2854, STR_EXIT_NOT_CONNECTED = 2855, - STR_TUTORIAL = 2856, - STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL = 2857, STR_CANT_START_MARKETING_CAMPAIGN = 2858, STR_INFOGRAMES_INTERACTIVE_CREDITS = 2860, @@ -1878,10 +1876,6 @@ enum { STR_INSTALL_NEW_TRACK_DESIGN = 3376, STR_INSTALL_NEW_TRACK_DESIGN_TIP = 3377, - STR_TUTORIAL_BEGINNERS = 3385, - STR_TUTORIAL_CUSTOM_RIDES = 3386, - STR_TUTORIAL_ROLLER_COASTER = 3387, - STR_SAVE_TRACK_SCENERY_UNABLE_TO_SELECT_ADDITIONAL_ITEM_OF_SCENERY = 3389, STR_SAVE_TRACK_SCENERY_TOO_MANY_ITEMS_SELECTED = 3390, diff --git a/src/rct2.c b/src/rct2.c index db15b17542..aa36ae4a30 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -438,9 +438,6 @@ void rct2_update_2() if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) RCT2_GLOBAL(RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO, sint32) += tick2; - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16) = 31; - // TODO: screenshot countdown process network_update(); diff --git a/src/tutorial.c b/src/tutorial.c deleted file mode 100644 index 56c2655872..0000000000 --- a/src/tutorial.c +++ /dev/null @@ -1,132 +0,0 @@ -/***************************************************************************** - * 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 . - *****************************************************************************/ - -#include "addresses.h" -#include "interface/window.h" -#include "localisation/localisation.h" -#include "tutorial.h" -#include "windows/error.h" -#include "windows/tooltip.h" - -static void sub_6EA2AA(rct_window *w, int widgetIndex, int x, int y, int edi); - -/** - * - * rct2: 0x0066ECC1 - */ -void tutorial_start(int type) -{ - strcpy((char*)0x009BC677, "Tutorial not implemented."); - window_error_open(3165, STR_NONE); -} - -/** - * - * rct2: 0x0066EE25 - */ -void tutorial_stop() -{ - // RCT2_CALLPROC_EBPSAFE(0x0066EE25); -} - -void game_handle_keyboard_input_for_tutorial() -{ -#ifdef ENABLE_TUTORIAL - rct_window *w; - - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) { - int eax, ebx, ecx, edx, esi, edi, ebp; - RCT2_CALLFUNC_X(0x0066EEB4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - eax &= 0xFF; - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = eax; - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4) { - window_tooltip_close(); - if ((w = window_get_main()) != NULL) { - RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0); - RCT2_GLOBAL(0x009DEA72, uint16)++; - } - } - } else { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) { - window_tooltip_close(); - if ((w = window_get_main()) != NULL) { - sub_6EA2AA(w, 0, 0, 0, RCT2_GLOBAL(0x009DEA72, uint16)); - RCT2_GLOBAL(0x009DEA72, uint16)++; - } - } - - // Write tutorial input - RCT2_CALLPROC_X(0x0066EEE1, RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8), 0, 0, 0, 0, 0, 0); - } -#endif -} - -static void sub_6EA2AA(rct_window *w, int widgetIndex, int x, int y, int edi) -{ -#ifdef ENABLE_TUTORIAL - RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0); - return; - - rct_window *tooltipWindow; - - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = w->classification; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = w->number; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = widgetIndex; - - rct_string_id stringId = window_event_tooltip_call(w, widgetIndex); - if (stringId == (rct_string_id)STR_NONE) - return; - - tooltipWindow = window_find_by_class(WC_TOOLTIP); - if (tooltipWindow == NULL) - return; - - char *buffer = (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER; - - RCT2_GLOBAL(0x0142006C, uint32) = edi; - format_string(buffer, edi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; - int width = gfx_get_string_width_new_lined(buffer); - width = min(width, 196); - - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; - - int numLines, fontHeight; - gfx_wrap_string(buffer, width + 1, &numLines, &fontHeight); - - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TEXT_HEIGHT, uint16) = numLines; - tooltipWindow->widgets[0].right = width + 3; - tooltipWindow->widgets[0].bottom = ((numLines + 1) * 10) + 4; - - char *tooltipBuffer = (char*)RCT2_ADDRESS_TOOLTIP_TEXT_BUFFER; - memcpy(tooltipBuffer, buffer, 512); - - window_tooltip_open(w, widgetIndex, x, y); -#endif -} - -/** - * - * rct2: 0x0066EE54 - */ -void sub_66EE54() -{ - // RCT2_CALLPROC_EBPSAFE(0x0066EE54); -} diff --git a/src/tutorial.h b/src/tutorial.h deleted file mode 100644 index a3de1993a3..0000000000 --- a/src/tutorial.h +++ /dev/null @@ -1,28 +0,0 @@ -/***************************************************************************** - * 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 . - *****************************************************************************/ - -#ifndef _TUTORIAL_H_ -#define _TUTORIAL_H_ - -void tutorial_start(int type); -void tutorial_stop(); -void sub_66EE54(); - -#endif diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index 5f97e96b05..ed4572e654 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -85,7 +85,6 @@ static void window_game_bottom_toolbar_draw_left_panel(rct_drawpixelinfo *dpi, r static void window_game_bottom_toolbar_draw_park_rating(rct_drawpixelinfo *dpi, rct_window *w, int colour, int x, int y, uint8 factor); static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi, rct_window *w); static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rct_window *w); -static void window_game_bottom_toolbar_draw_tutorial_text(rct_drawpixelinfo *dpi, rct_window *w); /** * @@ -358,8 +357,6 @@ static void window_game_bottom_toolbar_paint(rct_window *w, rct_drawpixelinfo *d if (!news_item_is_queue_empty()) window_game_bottom_toolbar_draw_news_item(dpi, w); - else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8)) - window_game_bottom_toolbar_draw_tutorial_text(dpi, w); } static void window_game_bottom_toolbar_draw_left_panel(rct_drawpixelinfo *dpi, rct_window *w) @@ -599,16 +596,6 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc } } -static void window_game_bottom_toolbar_draw_tutorial_text(rct_drawpixelinfo *dpi, rct_window *w) -{ - int x, y; - - x = (window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].left + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].right) / 2 + w->x; - y = window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].top + w->y + 2; - gfx_draw_string_centred(dpi, STR_TUTORIAL, x, y, 32, 0); - gfx_draw_string_centred(dpi, STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL, x, y + 10, 32, 0); -} - /** * * rct2: 0x0066C6D8 diff --git a/src/windows/save_prompt.c b/src/windows/save_prompt.c index 60058185e7..68f84e85db 100644 --- a/src/windows/save_prompt.c +++ b/src/windows/save_prompt.c @@ -28,7 +28,6 @@ #include "../interface/window.h" #include "../openrct2.h" #include "../sprites.h" -#include "../tutorial.h" enum WINDOW_SAVE_PROMPT_WIDGET_IDX { WIDX_BACKGROUND, @@ -134,19 +133,6 @@ void window_save_prompt_open() * and game_load_or_quit() are not called by the original binary anymore. */ - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) { - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 1) { - sub_66EE54(); - game_load_or_quit_no_save_prompt(); - return; - } - else { - tutorial_stop(); - game_load_or_quit_no_save_prompt(); - return; - } - } - if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, uint16) < 3840) { game_load_or_quit_no_save_prompt(); return; @@ -249,18 +235,6 @@ static void window_save_prompt_mouseup(rct_window *w, int widgetIndex) return; } } - - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) { - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 1) { - sub_66EE54(); - game_load_or_quit_no_save_prompt(); - return; - } else { - tutorial_stop(); - game_load_or_quit_no_save_prompt(); - return; - } - } } static void window_save_prompt_invalidate(rct_window *w) diff --git a/src/windows/title_menu.c b/src/windows/title_menu.c index 1709c74273..42e125a3f0 100644 --- a/src/windows/title_menu.c +++ b/src/windows/title_menu.c @@ -26,7 +26,6 @@ #include "../interface/window.h" #include "../localisation/localisation.h" #include "../sprites.h" -#include "../tutorial.h" #include "dropdown.h" #include "../interface/themes.h" @@ -148,19 +147,7 @@ static void window_title_menu_mouseup(rct_window *w, int widgetIndex) static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - if (widgetIndex == WIDX_SHOW_TUTORIAL) { - gDropdownItemsFormat[0] = STR_TUTORIAL_BEGINNERS; - gDropdownItemsFormat[1] = STR_TUTORIAL_CUSTOM_RIDES; - gDropdownItemsFormat[2] = STR_TUTORIAL_ROLLER_COASTER; - window_dropdown_show_text( - w->x + widget->left, - w->y + widget->top, - widget->bottom - widget->top + 1, - w->colours[0] | 0x80, - DROPDOWN_FLAG_STAY_OPEN, - 3 - ); - } else if (widgetIndex == WIDX_GAME_TOOLS) { + if (widgetIndex == WIDX_GAME_TOOLS) { gDropdownItemsFormat[0] = STR_SCENARIO_EDITOR; gDropdownItemsFormat[1] = STR_CONVERT_SAVED_GAME_TO_SCENARIO; gDropdownItemsFormat[2] = STR_ROLLER_COASTER_DESIGNER; @@ -178,9 +165,7 @@ static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widge static void window_title_menu_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { - if (widgetIndex == WIDX_SHOW_TUTORIAL) { - tutorial_start(dropdownIndex); - } else if (widgetIndex == WIDX_GAME_TOOLS) { + if (widgetIndex == WIDX_GAME_TOOLS) { switch (dropdownIndex) { case 0: editor_load(); From 88c391120afc4167355b03aadbcee5e10a232976 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 5 Jan 2016 00:02:23 +0000 Subject: [PATCH 87/90] integrate tooltip variables --- src/input.c | 90 ++++++++++++++-------------- src/input.h | 12 ++++ src/interface/viewport.c | 2 +- src/interface/window.c | 2 +- src/windows/editor_inventions_list.c | 8 +-- src/windows/game_bottom_toolbar.c | 9 +-- src/windows/title_menu.c | 5 +- src/windows/tooltip.c | 22 +++---- 8 files changed, 82 insertions(+), 68 deletions(-) diff --git a/src/input.c b/src/input.c index b8b81fa4e1..fcb936da18 100644 --- a/src/input.c +++ b/src/input.c @@ -52,6 +52,12 @@ static int _originalWindowWidth, _originalWindowHeight; uint8 gInputState; uint8 gInputFlags; +uint16 gTooltipNotShownTicks; +uint16 gTooltipTimeout; +widget_ref gTooltipWidget; +sint32 gTooltipCursorX; +sint32 gTooltipCursorY; + typedef struct { uint32 x, y; uint32 state; //1 = LeftDown 2 = LeftUp 3 = RightDown 4 = RightUp @@ -436,10 +442,10 @@ static void input_window_position_continue(rct_window *w, int wdx, int wdy, int static void input_window_position_end(rct_window *w, int x, int y) { gInputState = INPUT_STATE_NORMAL; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = _dragWindowClass; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = _dragWidgetIndex; + gTooltipTimeout = 0; + gTooltipWidget.window_classification = _dragWindowClass; + gTooltipWidget.window_number = _dragWindowNumber; + gTooltipWidget.widget_index = _dragWidgetIndex; window_event_moved_call(w, x, y); } @@ -476,10 +482,10 @@ static void input_window_resize_continue(rct_window *w, int x, int y) static void input_window_resize_end() { gInputState = INPUT_STATE_NORMAL; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = _dragWindowClass; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = _dragWidgetIndex; + gTooltipTimeout = 0; + gTooltipWidget.window_classification = _dragWindowClass; + gTooltipWidget.window_number = _dragWindowNumber; + gTooltipWidget.widget_index = _dragWidgetIndex; } #pragma endregion @@ -560,8 +566,8 @@ static void input_scroll_begin(rct_window *w, int widgetIndex, int x, int y) RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = w->classification; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = w->number; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y; + gTooltipCursorX = x; + gTooltipCursorY = y; int eax, ebx, scroll_area, scroll_id; scroll_id = 0; // safety @@ -645,9 +651,7 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int widget_scroll_get_part(w, widget, x, y, &x2, &y2, &scroll_part, &scroll_id); if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){ - int temp_x = x; - x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16); - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x; + gTooltipCursorX = x - gTooltipCursorX; input_scroll_part_update_hthumb(w, widgetIndex, x, scroll_id); return; } @@ -902,9 +906,9 @@ static void input_widget_over(int x, int y, rct_window *w, int widgetIndex) input_update_tooltip(w, widgetIndex, x, y); } - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) = x; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) = y; + gTooltipTimeout = 0; + gTooltipCursorX = x; + gTooltipCursorY = y; } /** @@ -1250,10 +1254,10 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi } gInputState = INPUT_STATE_NORMAL; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = cursor_w_class; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = cursor_w_number; + gTooltipTimeout = 0; + gTooltipWidget.widget_index = cursor_widgetIndex; + gTooltipWidget.window_classification = cursor_w_class; + gTooltipWidget.window_number = cursor_w_number; window_event_dropdown_call(cursor_w, cursor_widgetIndex, dropdown_index); } dropdown_cleanup: @@ -1262,8 +1266,8 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi if (state == 3) return; gInputState = INPUT_STATE_NORMAL; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex; + gTooltipTimeout = 0; + gTooltipWidget.widget_index = cursor_widgetIndex; if (!w) break; @@ -1326,36 +1330,34 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y) { - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) == 255) { - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) < 500 || - (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) == x && - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) == y) - ) { - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16); + if (gTooltipWidget.window_classification == 255) { + if (gTooltipNotShownTicks < 500 || (gTooltipCursorX == x && gTooltipCursorY == y)) { + gTooltipTimeout = RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16); - int bp = 2000; - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) >= 1) - bp = 0; - if (bp > RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16)) { - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16)++; + int time = 2000; + if (gTooltipNotShownTicks >= 1) { + time = 0; + } + if (time > gTooltipTimeout) { + gTooltipNotShownTicks++; return; } window_tooltip_open(w, widgetIndex, x, y); } - } - else { - if (((w != NULL) && - (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification || - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number)) || - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) != widgetIndex - ) { + } else { + if (( + (w != NULL) && + (gTooltipWidget.window_classification != w->classification || gTooltipWidget.window_number != w->number) + ) || + gTooltipWidget.widget_index != widgetIndex + ) { window_tooltip_close(); } - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16); - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) < 8000) - return; - window_close_by_class(WC_TOOLTIP); + gTooltipTimeout += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16); + if (gTooltipTimeout >= 8000) { + window_close_by_class(WC_TOOLTIP); + } } } diff --git a/src/input.h b/src/input.h index 80f68d829d..3caa9d8584 100644 --- a/src/input.h +++ b/src/input.h @@ -60,9 +60,21 @@ enum { INPUT_FLAG_VIEWPORT_SCROLLING = (1 << 7) }; +typedef struct { + rct_windowclass window_classification; + rct_windownumber window_number; + uint8 widget_index; +} widget_ref; + extern uint8 gInputState; extern uint8 gInputFlags; +extern uint16 gTooltipNotShownTicks; +extern uint16 gTooltipTimeout; +extern widget_ref gTooltipWidget; +extern sint32 gTooltipCursorX; +extern sint32 gTooltipCursorY; + void title_handle_keyboard_input(); void game_handle_input(); void game_handle_keyboard_input(); diff --git a/src/interface/viewport.c b/src/interface/viewport.c index ae845bbf01..80f52a9439 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -106,7 +106,7 @@ void viewport_init_all() gInputState = INPUT_STATE_RESET; RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1; + gTooltipNotShownTicks = -1; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) = 0; RCT2_GLOBAL(0x009DEA50, sint16) = -1; textinput_cancel(); diff --git a/src/interface/window.c b/src/interface/window.c index 449e56d110..bb38986147 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -150,7 +150,7 @@ void window_dispatch_update_all() rct_window *w; RCT2_GLOBAL(0x01423604, sint32)++; - //RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16)++; + // gTooltipNotShownTicks++; for (w = RCT2_LAST_WINDOW; w >= g_window_list; w--) window_event_update_call(w); } diff --git a/src/windows/editor_inventions_list.c b/src/windows/editor_inventions_list.c index 5beef00b2e..1afcad62e4 100644 --- a/src/windows/editor_inventions_list.c +++ b/src/windows/editor_inventions_list.c @@ -910,8 +910,8 @@ static void window_editor_inventions_list_drag_open(rct_research_item *researchI window_editor_inventions_list_drag_widgets[0].right = stringWidth; w = window_create( - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) - (stringWidth / 2), - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) - 7, + gTooltipCursorX - (stringWidth / 2), + gTooltipCursorY - 7, stringWidth, 14, &window_editor_inventions_list_drag_events, @@ -920,9 +920,7 @@ static void window_editor_inventions_list_drag_open(rct_research_item *researchI ); w->widgets = window_editor_inventions_list_drag_widgets; w->colours[1] = 2; - input_window_position_begin( - w, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16), RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) - ); + input_window_position_begin(w, 0, gTooltipCursorX, gTooltipCursorY); } /** diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index ed4572e654..1fbe55c2d7 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -20,10 +20,12 @@ #include "../addresses.h" #include "../config.h" -#include "../localisation/date.h" -#include "../localisation/localisation.h" +#include "../input.h" +#include "../interface/themes.h" #include "../interface/widget.h" #include "../interface/window.h" +#include "../localisation/date.h" +#include "../localisation/localisation.h" #include "../management/news_item.h" #include "../peep/peep.h" #include "../peep/staff.h" @@ -31,7 +33,6 @@ #include "../world/climate.h" #include "../world/park.h" #include "../world/sprite.h" -#include "../interface/themes.h" enum WINDOW_GAME_BOTTOM_TOOLBAR_WIDGET_IDX { WIDX_LEFT_OUTSET, @@ -620,7 +621,7 @@ static void window_game_bottom_toolbar_cursor(rct_window *w, int widgetIndex, in case WIDX_GUESTS: case WIDX_PARK_RATING: case WIDX_DATE: - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 2000; + gTooltipTimeout = 2000; break; } } diff --git a/src/windows/title_menu.c b/src/windows/title_menu.c index 42e125a3f0..246128a264 100644 --- a/src/windows/title_menu.c +++ b/src/windows/title_menu.c @@ -22,12 +22,13 @@ #include "../config.h" #include "../editor.h" #include "../game.h" +#include "../input.h" +#include "../interface/themes.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../localisation/localisation.h" #include "../sprites.h" #include "dropdown.h" -#include "../interface/themes.h" enum { WIDX_START_NEW_GAME, @@ -185,7 +186,7 @@ static void window_title_menu_dropdown(rct_window *w, int widgetIndex, int dropd static void window_title_menu_cursor(rct_window *w, int widgetIndex, int x, int y, int *cursorId) { - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, sint16) = 2000; + gTooltipTimeout = 2000; } static void window_title_menu_paint(rct_window *w, rct_drawpixelinfo *dpi) diff --git a/src/windows/tooltip.c b/src/windows/tooltip.c index e9fecabf44..8ba29917ef 100644 --- a/src/windows/tooltip.c +++ b/src/windows/tooltip.c @@ -71,10 +71,10 @@ static rct_window_event_list window_tooltip_events = { void window_tooltip_reset(int x, int y) { - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, uint8) = 255; + gTooltipCursorX = x; + gTooltipCursorY = y; + gTooltipTimeout = 0; + gTooltipWidget.window_classification = 255; gInputState = INPUT_STATE_NORMAL; gInputFlags &= ~INPUT_FLAG_4; } @@ -135,7 +135,7 @@ void window_tooltip_show(rct_string_id id, int x, int y) ); w->widgets = window_tooltip_widgets; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) = 0; + gTooltipNotShownTicks = 0; } /** @@ -154,9 +154,9 @@ void window_tooltip_open(rct_window *widgetWindow, int widgetIndex, int x, int y if (widget->tooltip == 0xFFFF) return; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = widgetWindow->classification; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = widgetWindow->number; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = widgetIndex; + gTooltipWidget.window_classification = widgetWindow->classification; + gTooltipWidget.window_number = widgetWindow->number; + gTooltipWidget.widget_index = widgetIndex; if (window_event_tooltip_call(widgetWindow, widgetIndex) == (rct_string_id)STR_NONE) return; @@ -171,8 +171,8 @@ void window_tooltip_open(rct_window *widgetWindow, int widgetIndex, int x, int y void window_tooltip_close() { window_close_by_class(WC_TOOLTIP); - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = 255; + gTooltipTimeout = 0; + gTooltipWidget.window_classification = 255; RCT2_GLOBAL(0x0142006C, sint32) = -1; RCT2_GLOBAL(0x009DE51E, uint8) = 0; } @@ -193,7 +193,7 @@ static void window_tooltip_onclose(rct_window *w) static void window_tooltip_update(rct_window *w) { if (RCT2_GLOBAL(0x009DE51E, uint8) == 0) - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) = 0; + gTooltipNotShownTicks = 0; } /** From d842708f90fdf4bdc46e6da4ff88a9cde4c5e504 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 5 Jan 2016 00:10:28 +0000 Subject: [PATCH 88/90] refactor drag widget in input.c --- src/input.c | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/input.c b/src/input.c index fcb936da18..e4d39e40a9 100644 --- a/src/input.c +++ b/src/input.c @@ -43,11 +43,12 @@ #include "world/scenery.h" #include "openrct2.h" -static int _dragX, _dragY; -static rct_windowclass _dragWindowClass; -static rct_windownumber _dragWindowNumber; -static int _dragWidgetIndex, _dragScrollIndex; -static int _originalWindowWidth, _originalWindowHeight; +static sint32 _dragX; +static sint32 _dragY; +static widget_ref _dragWidget; +static uint8 _dragScrollIndex; +static sint32 _originalWindowWidth; +static sint32 _originalWindowHeight; uint8 gInputState; uint8 gInputFlags; @@ -191,9 +192,9 @@ static void input_scroll_drag_begin(int x, int y, rct_window* w, rct_widget* wid gInputState = INPUT_STATE_SCROLL_RIGHT; _dragX = x; _dragY = y; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; - _dragWidgetIndex = widgetIndex; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; + _dragWidget.widget_index = widgetIndex; RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0; _dragScrollIndex = window_get_scroll_data_index(w, widgetIndex); @@ -204,8 +205,9 @@ static void input_scroll_drag_begin(int x, int y, rct_window* w, rct_widget* wid * Based on (heavily changed) * rct2: 0x006E9E0E, 0x006E9ED0 */ -static void input_scroll_drag_continue(int x, int y, rct_window* w) { - uint8 widgetIndex = _dragWidgetIndex; +static void input_scroll_drag_continue(int x, int y, rct_window* w) +{ + uint8 widgetIndex = _dragWidget.widget_index; uint8 scrollIndex = _dragScrollIndex; rct_widget* widget = &w->widgets[widgetIndex]; @@ -242,9 +244,9 @@ static void input_scroll_drag_continue(int x, int y, rct_window* w) { */ static void input_scroll_right(int x, int y, int state) { rct_window* w = window_find_by_number( - _dragWindowClass, - _dragWindowNumber - ); + _dragWidget.window_classification, + _dragWidget.window_number + ); if (w == NULL) { platform_show_cursor(); @@ -319,7 +321,7 @@ static void game_handle_input_mouse(int x, int y, int state) input_state_widget_pressed(x, y, state, widgetIndex, w, widget); break; case INPUT_STATE_POSITIONING_WINDOW: - w = window_find_by_number(_dragWindowClass, _dragWindowNumber); + w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number); if (w == NULL) { gInputState = INPUT_STATE_RESET; } @@ -401,7 +403,7 @@ static void game_handle_input_mouse(int x, int y, int state) input_scroll_end(); break; case INPUT_STATE_RESIZING: - w = window_find_by_number(_dragWindowClass, _dragWindowNumber); + w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number); if (w == NULL) { gInputState = INPUT_STATE_RESET; } @@ -426,9 +428,9 @@ void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y) gInputState = INPUT_STATE_POSITIONING_WINDOW; _dragX = x - w->x; _dragY = y - w->y; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; - _dragWidgetIndex = widgetIndex; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; + _dragWidget.widget_index = widgetIndex; } static void input_window_position_continue(rct_window *w, int wdx, int wdy, int x, int y) @@ -443,9 +445,7 @@ static void input_window_position_end(rct_window *w, int x, int y) { gInputState = INPUT_STATE_NORMAL; gTooltipTimeout = 0; - gTooltipWidget.window_classification = _dragWindowClass; - gTooltipWidget.window_number = _dragWindowNumber; - gTooltipWidget.widget_index = _dragWidgetIndex; + gTooltipWidget = _dragWidget; window_event_moved_call(w, x, y); } @@ -454,9 +454,9 @@ static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int gInputState = INPUT_STATE_RESIZING; _dragX = x; _dragY = y; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; - _dragWidgetIndex = widgetIndex; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; + _dragWidget.widget_index = widgetIndex; _originalWindowWidth = w->width; _originalWindowHeight = w->height; } @@ -483,9 +483,7 @@ static void input_window_resize_end() { gInputState = INPUT_STATE_NORMAL; gTooltipTimeout = 0; - gTooltipWidget.window_classification = _dragWindowClass; - gTooltipWidget.window_number = _dragWindowNumber; - gTooltipWidget.widget_index = _dragWidgetIndex; + gTooltipWidget = _dragWidget; } #pragma endregion @@ -496,8 +494,8 @@ static void input_viewport_drag_begin(rct_window *w, int x, int y) { w->flags &= ~WF_SCROLLING_TO_LOCATION; gInputState = INPUT_STATE_VIEWPORT_RIGHT; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0; platform_get_cursor_position(&_dragX, &_dragY); platform_hide_cursor(); @@ -515,7 +513,7 @@ static void input_viewport_drag_continue() dx = newDragX - _dragX; dy = newDragY - _dragY; - w = window_find_by_number(_dragWindowClass, _dragWindowNumber); + w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number); assert(w != NULL); viewport = w->viewport; From 79b7913b78531122574315d2f48f23c67ef85fec Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 5 Jan 2016 04:00:19 +0000 Subject: [PATCH 89/90] Merge Localisation/master into OpenRCT2/develop. --- data/language/chinese_traditional.txt | 26 ++ data/language/english_us.txt | 496 +++++++++++++++++++++++++- data/language/german.txt | 460 +++++++++++++++++++++++- data/language/japanese.txt | 44 +-- data/language/korean.txt | 491 ++++++++++++++++++++++++- 5 files changed, 1477 insertions(+), 40 deletions(-) diff --git a/data/language/chinese_traditional.txt b/data/language/chinese_traditional.txt index aa8fbe1452..8b5d74b464 100644 --- a/data/language/chinese_traditional.txt +++ b/data/language/chinese_traditional.txt @@ -3946,6 +3946,32 @@ STR_5603 :遊客已離開遊樂設施 STR_5604 :遊客已購買物品 STR_5605 :遊客已使用設施 STR_5606 :遊客已死亡 +STR_5607 :{SMALLFONT}{BLACK}強制移除選中的地圖元素. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}移除選中的地圖元素. 使用時請注意. 因為強制移除地圖元素並不會對遊戲中的現金做成影響. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}Ghost flag +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}Broken flag +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag +STR_5617 :{SMALLFONT}{BLACK}將選中的元素移到上面. +STR_5618 :{SMALLFONT}{BLACK}將選中的元素移到下面. +STR_5619 :夢幻遊樂園 +STR_5620 :夢幻遊樂園: 資料片1 +STR_5621 :夢幻遊樂園: 資料片2 +STR_5622 :模擬樂園2 +STR_5623 :瘋狂世界 +STR_5624 :時空歷險 +STR_5625 :{OPENQUOTES}真實的{ENDQUOTES}樂園 +STR_5626 :其他樂園 +STR_5627 :樂園列表的排序方式: +STR_5628 :出處的遊戲 +STR_5629 :困難程度 +STR_5630 :允許劇情解鎖 +STR_5631 :額外下載的官方樂園 +STR_5632 :建設你的.. ##################### diff --git a/data/language/english_us.txt b/data/language/english_us.txt index 25860add99..8ce410de46 100644 --- a/data/language/english_us.txt +++ b/data/language/english_us.txt @@ -3646,8 +3646,8 @@ STR_5302 :Clear loan STR_5303 :Allow building in pause mode STR_5304 :Title Sequence: STR_5305 :RollerCoaster Tycoon 1 -STR_5306 :RollerCoaster Tycoon 1 (AA) -STR_5307 :RollerCoaster Tycoon 1 (AA + LL) +STR_5306 :RollerCoaster Tycoon 1 (CF) +STR_5307 :RollerCoaster Tycoon 1 (CF + LL) STR_5308 :RollerCoaster Tycoon 2 STR_5309 :OpenRCT2 STR_5310 :Random @@ -3679,8 +3679,8 @@ STR_5335 :Ride entrance STR_5336 :Ride exit STR_5337 :Park entrance STR_5338 :Element type -STR_5339 :Base height -STR_5340 :Clearance height +STR_5339 :{SMALLFONT}{BLACK}Base height +STR_5340 :{SMALLFONT}{BLACK}Clearance height STR_5341 :Flags STR_5342 :Choose a map tile STR_5343 :Automatically place staff @@ -3926,6 +3926,494 @@ STR_5582 :Trap mouse cursor in window STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} STR_5584 :SI STR_5585 :{SMALLFONT}{BLACK}Unlocks ride operation limits, allowing for things like {VELOCITY} lift hills +STR_5586 :Automatically open shops and stalls +STR_5587 :{SMALLFONT}{BLACK}When enabled, shops and stalls will be automatically opened after building them +STR_5588 :{SMALLFONT}{BLACK}Play with other players +STR_5589 :Notification Settings +STR_5590 :Park awards +STR_5591 :Marketing campaign has finished +STR_5592 :Park warnings +STR_5593 :Park rating warnings +STR_5594 :Ride has broken down +STR_5595 :Ride has crashed +STR_5596 :Ride warnings +STR_5597 :Ride / scenery researched +STR_5598 :Guest warnings +STR_5599 :Guest is lost +STR_5600 :Guest has left the park +STR_5601 :Guest is queuing for ride +STR_5602 :Guest is on ride +STR_5603 :Guest has left ride +STR_5604 :Guest has bought item +STR_5605 :Guest has used facility +STR_5606 :Guest has died +STR_5607 :{SMALLFONT}{BLACK}Forcefully remove selected map element. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}Ghost flag +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}Broken flag +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag +STR_5617 :{SMALLFONT}{BLACK}Move selected element up. +STR_5618 :{SMALLFONT}{BLACK}Move selected element down. +STR_5619 :RollerCoaster Tycoon +STR_5620 :Corkscrew Follies +STR_5621 :Loopy Landscapes +STR_5622 :RollerCoaster Tycoon 2 +STR_5623 :Wacky Worlds +STR_5624 :Time Twister +STR_5625 :{OPENQUOTES}Real{ENDQUOTES} Parks +STR_5626 :Other Parks +STR_5627 :Group scenario list by: +STR_5628 :Source game +STR_5629 :Difficulty level +STR_5630 :Enable unlocking of scenarios +STR_5631 :Original DLC Parks +STR_5632 :Build your own... + +############# +# Scenarios # +############# + +## RCT Original + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Starting from scratch, build a theme park around a large lake + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Several islands form the basis for this new park + + +STR_SCNR :Katie's World +STR_PARK :Katie's World +STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value + + +STR_SCNR :Dinky Park +STR_PARK :Dinky Park +STR_DTLS :A small, cramped amusement park which requires major expansion + + +STR_SCNR :Aqua Park +STR_PARK :Aqua Park +STR_DTLS :A park with some excellent water-based rides requires expansion + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion + + +STR_SCNR :Mothball Mountain +STR_PARK :Mothball Mountain +STR_DTLS :In the hilly forests of Mothball Mountain, build a theme park from scratch + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park + + +STR_SCNR :Crumbly Woods +STR_PARK :Crumbly Woods +STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular + + +STR_SCNR :Big Pier +STR_PARK :Big Pier +STR_DTLS :Convert this sleepy town's pier into a thriving attraction + + +STR_SCNR :Lightning Peaks +STR_PARK :Lightning Peaks +STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers - Use the available land to attract a new thrill-seeking clientele + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :A well-established park, which has a few problems + + +STR_SCNR :Rainbow Valley +STR_PARK :Rainbow Valley +STR_DTLS :Rainbow Valley's local authority won't allow any landscape changes or large tree removal, but you must develop the area into a large theme park + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists - Use the available space to build rides to attract more people + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Just for fun! + +## Corkscrew Follies + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Develop the seaside cliffs into a thriving amusement park + + +STR_SCNR :Three Monkeys Park +STR_PARK :Three Monkeys Park +STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster + + +STR_SCNR :Canary Mines +STR_PARK :Canary Mines +STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its minature railway and a pair of vertical drop roller coasters + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :An old redundant bridge is yours to develop into an amusement park + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Covering land both sides of a highway, this park has several rides already operating + + +STR_SCNR :Haunted Harbor +STR_PARK :Haunted Harbor +STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :This castle is all yours to turn into a theme park + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape + + +STR_SCNR :Gentle Glen +STR_PARK :Gentle Glen +STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes + + +STR_SCNR :Jolly Jungle +STR_PARK :Jolly Jungle +STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :A series of stepped lakes form the basis for this new park + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :This elderly park has many historical rides but is badly in debt + + +STR_SCNR :Magic Quarters +STR_PARK :Magic Quarters +STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park + + +STR_SCNR :Fruit Farm +STR_PARK :Fruit Farm +STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park + + +STR_SCNR :Butterfly Dam +STR_PARK :Butterfly Dam +STR_DTLS :The area around a dam is available for you to develop into an amusement park + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :A vast canyon is yours to turn into a theme park + + +STR_SCNR :Thunderstorm Park +STR_PARK :Thunderstorm Park +STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover + + +STR_SCNR :Harmonic Hills +STR_PARK :Harmonic Hills +STR_DTLS :The local authority won't allow you to build above tree height in this park + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +STR_SCNR :Swamp Cove +STR_PARK :Swamp Cove +STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centerpiece + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +STR_SCNR :Utopia Park +STR_PARK :Utopia Park +STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +STR_SCNR :Fiasco Forest +STR_PARK :Fiasco Forest +STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around + + +STR_SCNR :Pickle Park +STR_PARK :Pickle Park +STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +STR_SCNR :Coaster Crazy +STR_PARK :Coaster Crazy +STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park + + +STR_SCNR :Urban Park +STR_PARK :Urban Park +STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +STR_SCNR :Arid Heights +STR_PARK :Arid Heights +STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +STR_SCNR :Vertigo Views +STR_PARK :Vertigo Views +STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit + + +STR_SCNR :Big Pier 2 +STR_PARK :Big Pier 2 +STR_DTLS :Big Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +STR_SCNR :Good Knight Park +STR_PARK :Good Knight Park +STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +STR_SCNR :Crazy Craters +STR_PARK :Crazy Craters +STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +STR_SCNR :Sunny Swamps +STR_PARK :Sunny Swamps +STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +STR_SCNR :Thunder Rocks +STR_PARK :Thunder Rocks +STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into as an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +STR_SCNR :Venus Ponds +STR_PARK :Venus Ponds +STR_DTLS :On a far-away planet this area of land needs turning into a theme park + + +STR_SCNR :Micro Park +STR_PARK :Micro Park +STR_DTLS :Try to create the world's smallest profitable park + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : ######### # Rides # diff --git a/data/language/german.txt b/data/language/german.txt index 5c5f2f5cc9..830d2fa09a 100644 --- a/data/language/german.txt +++ b/data/language/german.txt @@ -3278,9 +3278,9 @@ STR_3269 :Landschaftsänderungen verbieten STR_3270 :{SMALLFONT}{BLACK}Jegliche Änderungen an der{NEWLINE}Landschaft verbieten STR_3271 :Hohe Bauten verbieten STR_3272 :{SMALLFONT}{BLACK}Jegliche hohe Bauten verbieten -STR_3273 :Höhere Schwierigkeitsstufe für Parkbewertung +STR_3273 :Höhere Schwierigkeitsgrad für Parkbewertung STR_3274 :{SMALLFONT}{BLACK}Machen Sie die Parkbewertung schwieriger -STR_3275 :Höhere Schwierigkeitsstufe für Besuchergewinnung +STR_3275 :Höhere Schwierigkeitsgrad für Besuchergewinnung STR_3276 :{SMALLFONT}{BLACK}Machen Sie das Anlocken von{NEWLINE}Besuchern schwieriger STR_3277 :{WINDOW_COLOUR_2}Kosten für Landkauf: STR_3278 :{WINDOW_COLOUR_2}Kosten für Erwerb v. Baurechten: @@ -3952,6 +3952,462 @@ STR_5615 :L STR_5616 :{SMALLFONT}{BLACK}Flag für letztes Element der Kachel STR_5617 :{SMALLFONT}{BLACK}Ausgewähltes Element nach oben bewegen STR_5618 :{SMALLFONT}{BLACK}Ausgewähltes Element nach unten bewegen +STR_5619 :RollerCoaster Tycoon +STR_5620 :Added Attractions +STR_5621 :Loopy Landscapes +STR_5622 :RollerCoaster Tycoon 2 +STR_5623 :Wacky Worlds +STR_5624 :Time Twister +STR_5625 :{OPENQUOTES}Reale{ENDQUOTES} Parks +STR_5626 :Sonstige Parks +STR_5627 :Szenarioliste ordnen nach: +STR_5628 :Spielherkunft +STR_5629 :Schwierigkeitsgrad +STR_5630 :Freispielen der Szenarios aktivieren +STR_5631 :Originale DLC Parks +STR_5632 :Bauen Sie Ihren eigenen... + +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Bauen Sie tief im Wald auf einem großen freigelegten Gelände einen erfolgreichen Freizeitpark. + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :Dieser Freizeitpark inmitten der Wüste besitzt nur eine Achterbahn, hat aber genug Platz für Erweiterungen. + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Fangen Sie bei Null an und bauen Sie einen Freizeitpark um einen großen See herum. + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :Diamond Heights ist bereits ein erfolgreicher Freizeitpark mit tollen Attraktionen. Entwickeln Sie ihn weiter und verdoppeln Sie seinen Verkehrswert. + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Wandeln Sie die schönen Evergreen Gardens in einen gut besuchten Freizeitpark um. + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Machen Sie aus dem kleinen Vergnügungspark Bumbly Beach einen florierenden Freizeitpark. + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Mehrere Inseln bilden den Ausgangspunkt für diesen neuen Park. + + +STR_SCNR :Katie's Dreamland +STR_PARK :Katie's Dreamland +STR_DTLS :Ein kleiner Freizeitpark mit wenigen Attraktionen, aber genug Gelände zur Erweiterung. Ihr Ziel ist es, den Verkehrswert des Parks zu verdoppeln. + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :Ein kleiner, eng zusammengedrängter Vergnügungspark, bei dem eine Erweiterung in großem Ausmaß erforderlich ist. + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :Dieser Park mit verschiedenen hervorragenden Wasser-Attraktionen hat einen Ausbau nötig. + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Machen Sie einen Freizeitpark aus dieser weitläufigen, verlassenen Mine, die zur Zeit nur von Touristen besichtigt wird. + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :Ein großer Park, versteckt im Wald gelegen, der nur Gokartbahnen und Holzachterbahnen aufzuweisen hat. + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :Dieser Freizeitpark verfügt über ein paar ausgezeichnete moderne Attraktionen und jede Menge Platz für Erweiterungen. + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :Bauen Sie in den bergigen Wäldern der Mystic Mountains einen neuen Freizeitpark. + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Verwandeln Sie die Touristenattraktion mit ägyptischen Ruinen in einen erfolgreichen Freizeitpark. + + +STR_SCNR :Crumbly Woods +STR_PARK :Crumbly Woods +STR_DTLS :Ein großer Park mit guten, aber ziemlich alten Attraktionen. Ersetzen Sie die alten Attraktionen oder fügen Sie neue hinzu, damit der Park mehr Leute anzieht. + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Verwandeln Sie die Anlegestelle dieser verschlafenen Stadt in einen wohlbekannten und gutgehenden Anziehungspunkt. + + +STR_SCNR :Lightning Peaks +STR_PARK :Lightning Peaks +STR_DTLS :Die herrlichen Berge von Lightning Peaks sind beliebt bei Wanderern und Leuten, die gern interessante Orte besichtigen. Nutzen Sie das zur Verfügung stehende Gelände, um jene Besucher anzulocken, die auf der Suche nach einem aufregenden Kick sind. + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :Ein gut geführter Park, der jedoch ein paar Probleme hat. + + +STR_SCNR :Rainbow Valley +STR_PARK :Rainbow Valley +STR_DTLS :Die örtlichen Behörden von Rainbow Valley werden landschaftliche Veränderungen oder größere Baumrodungen nicht erlauben, aber Sie sollen in dem Gebiet einen großen Freizeitpark entstehen lassen. + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock befindet sich mitten in einer Wüste und zieht viele Touristen an. Bauen Sie auf dem verfügbaren Platz Attraktionen, die noch mehr Leute herlocken. + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Nur zum Spaß! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Lassen Sie in diesen Klippen am Meer einen florierenden Vergnügungspark entstehen. + + +STR_SCNR :Three Monkeys Park +STR_PARK :Three Monkeys Park +STR_DTLS :Mitten in diesem großen, aufstrebenden Park steht eine riesige Dreispur-Achterbahn, in der die Fahrt wie ein Kopf-an-Kopf-Rennen abläuft. + + +STR_SCNR :Canary Mines +STR_PARK :Canary Mines +STR_DTLS :Dieses verlassene Bergwerk bietet mit der Miniatureisenbahn und den Sturzachterbahnen bereits gute Voraussetzungen, eine Touristenattraktion zu werden. + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :Wandeln Sie eine alte, nicht mehr benutzte Brücke in einen attraktiven Park um. + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :In diesem Park zu beiden Seiten einer Autobahn sind bereits verschiedene Attraktionen in Betrieb. + + +STR_SCNR :Haunted Harbor +STR_PARK :Haunted Harbor +STR_DTLS :Die örtlichen Behörden haben zugestimmt, dem kleinen Park an der Küste umliegendes Gelände günstig zu verkaufen, unter der Bedingung, dass bestimmte Attraktionen erhalten werden. + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :Sie können Ihrer Fantasie freien Lauf lassen, damit ein Themenpark aus diesem Schloss entsteht. + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :Dieser futuristische Park bietet auf seinem fremdartigen Gelände viel Platz für neue Attraktionen. + + +STR_SCNR :Gentle Glen +STR_PARK :Gentle Glen +STR_DTLS :Die Bevölkerung in der Umgebung bevorzugt gemäßigte Attraktionen, auf denen man sich erholen kann. Ihre Aufgabe ist es, diesen Ansprüchen gerecht zu werden. + + +STR_SCNR :Jolly Jungle +STR_PARK :Jolly Jungle +STR_DTLS :Ein riesiges Gelände tief im Dschungel wartet darauf, von Ihnen in einen Themenpark umgewandelt zu werden. + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :Eine Reihe terrassenförmig angeordneter Seen sind der Ausgangsort für den neuen Park. + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :Dieser ältere Park besitzt viele historisch interessante Attraktionen, ist aber hoch verschuldet. + + +STR_SCNR :Magic Quarters +STR_PARK :Magic Quarters +STR_DTLS :Ein großes Gelände wurde freigeräumt und teilweise thematisch gestaltet. Sie sollen daraus einen interessante Themenlandschaft machen. + + +STR_SCNR :Fruit Farm +STR_PARK :Fruit Farm +STR_DTLS :Eine gutgehende Obstplantage hat eine Miniatureisenbahn bauen lassen, um die Einnahmen zu steigern. Entwickeln Sie jetzt daraus einen Vergnügungspark mit allem Drum und Dran. + + +STR_SCNR :Butterfly Dam +STR_PARK :Butterfly Dam +STR_DTLS :Das Gebiet rings um einen Damm steht Ihnen zur Verfügung, damit daraus ein Vergnügungspark entsteht. + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :Ein weitläufiger Canyon steht Ihnen zur Verfügung, um in einen Themenpark verwandelt zu werden. + + +STR_SCNR :Thunderstorm Park +STR_PARK :Thunderstorm Park +STR_DTLS :Das Wetter in dieser Gegend ist so feucht, dass bereits eine riesengroße Pyramide gebaut wurde, damit wenigstens einige Attraktionen überdacht sind. + + +STR_SCNR :Harmonic Hills +STR_PARK :Harmonic Hills +STR_DTLS :Die Baubehörde dieser Gegend erlaubt in diesem Park keine Konstruktionen über Baumhöhe. + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Entwickeln Sie diesen römisch gestalteten Park weiter, indem Sie Achterbahnen und andere Attraktionen hinzufügen. + + +STR_SCNR :Swamp Cove +STR_PARK :Swamp Cove +STR_DTLS :Dieser Park, der sich über eine Reihe kleiner Inseln erstreckt, besitzt ein Paar einer großen Achterbahn als Hauptattraktion. + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Bauen Sie einen Park für die Menschen dieser Gegend, die hohe Intensität und Nervenkitzel bevorzugen. + + +STR_SCNR :Utopia Park +STR_PARK :Utopia Park +STR_DTLS :Eine Oase inmitten der Wüste ist sicher eine ungewöhnliche Herausforderung für Planer eines Vergnügungsparks. + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Überwuchert und verfallen. Können Sie diesen einst großartigen Vergnügungspark wieder zum Leben erwecken? + + +STR_SCNR :Fiasco Forest +STR_PARK :Fiasco Forest +STR_DTLS :Hier gibt es fast nur gefährliche und schlecht geplante Attraktionen. Sie haben nur sehr begrenzte finanzielle Mittel und wenig Zeit, die Probleme zu beheben und den Park umzukrempeln. + + +STR_SCNR :Pickle Park +STR_PARK :Pickle Park +STR_DTLS :Die strengen örtlichen Ämter erlauben keinerlei Werbung oder Propaganda. Dieser Park kann also nur durch seinen Ruf zum Erfolg gelangen. + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :Eine vierspurige Bahn mit Renncharakter ist das Herzstück dieses aufstrebenden Parks. + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Verwandeln Sie diesen verlassenen Steinbruch in einen Ort, der Touristen anzieht, die den besonderen Kick suchen. + + +STR_SCNR :Coaster Crazy +STR_PARK :Coaster Crazy +STR_DTLS :Sie haben nur begrenzt Geld, aber jede Menge Zeit, aus diesem Berggelände einen riesigen Achterbahn-Park zu machen. + + +STR_SCNR :Urban Park +STR_PARK :Urban Park +STR_DTLS :Ein winzig kleiner Park hat mit der nahe gelegenen Stadt vereinbart, dass er sich durch die Stadt hindurch ausbreiten darf. + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :Eine große gepflegte Parkanlage soll in einen erfolgreichen Themenpark umgestaltet werden. + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :Eine Anzahl Eisberge bilden die kalte Umgebung dieses anspruchsvollen Parkprojekts. + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :Ein untätiger Vulkan fordert geradezu heraus, an ihm eine Achterbahnanlage zu bauen. + + +STR_SCNR :Arid Heights +STR_PARK :Arid Heights +STR_DTLS :Ohne jegliche finanzielle Einschränkungen sollen Sie diesen Wüstenpark ausbauen und dabei die Besucher bei Laune halten. + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Ihre Aufgabe ist es, zwischen den zerklüfteten Felsen einen Park mit dicht gedrängten Achterbahnen zu bauen. + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :Ein großer See in einem alten Krater ist Ausgangspunkt für diesen Park. + + +STR_SCNR :Vertigo Views +STR_PARK :Vertigo Views +STR_DTLS :Dieser große Park besitzt bereits eine ausgezeichnete Hyper-Achterbahn, aber Ihre Aufgabe ist es, die Erträge beträchtlich zu steigern. + + +STR_SCNR :Paradise Pier 2 +STR_PARK :Paradise Pier 2 +STR_DTLS :Paradise Pier hat sein Netz von Spazierwegen über dem Meer erweitert. Sie sollen den Park erweitern, indem Sie den neu gewonnenen Platz nutzen. + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :Eine Meeresbucht ist der Rahmen für dieses anspruchsvolle Achterbahn-Bauvorhaben. + + +STR_SCNR :Good Knight Park +STR_PARK :Good Knight Park +STR_DTLS :Ein Schloss mit ein paar Achterbahnen soll zu einem großen Vergnügungspark entwickelt werden. + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :Ein Park, dessen Gehwege und Achterbahnen größtenteils unterirdisch angelegt sind. + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :Es steht Ihnen ein Gletschertal zur Verfügung, das in einen Vergnügungspark zu verwandeln ist. + + +STR_SCNR :Crazy Craters +STR_PARK :Crazy Craters +STR_DTLS :In einer weit entfernten Welt, wo man Geld nicht braucht, sollen Sie ein Unterhaltungszentrum bauen, damit die Leute glücklich und zufrieden bleiben. + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Fünf Achterbahnen müssen in diesem Wüstenpark fertiggestellt werden. + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :In diesem historischen Park dürfen nur Attraktionen im altmodischen Stil gebaut werden. + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Verbessern Sie diesen außerirdischen Park, damit höchste Erträge erzielt werden. + + +STR_SCNR :Sunny Swamps +STR_PARK :Sunny Swamps +STR_DTLS :In diesem nach Themen angelegten Park gibt es zwar verschiedene Attraktionen, aber noch viel Platz für Erweiterungen. + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :Ein Gruselpark mit einer Riesenachterbahn als Herzstück. + + +STR_SCNR :Thunder Rocks +STR_PARK :Thunder Rocks +STR_DTLS :Zwei enorme Gesteinsbrocken ragen aus dem Wüstensand, auf denen mit den ersten Bauten für einen Vergnügungspark bereits begonnen wurde. + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In diesem weitläufigen Park sollen Sie zehn große Achterbahnen entwerfen und konstruieren. + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :Diese lange, schmale Insel ist Anreiz genug, eine Auswahl an Achterbahnen zu errichten. + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :Eine Eislandschaft soll in einen florierenden Vergnügungspark verwandelt werden. + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :Ein Park in der Wüste mit ein paar durchdachten Achterbahnen steht Ihnen zur Verfügung und soll erweitert werden. + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In diesem winzigen Park sollten Sie die fünf angefangenen Achterbahnen fertigstellen. + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :Ein großer Park mit einem neuartigen Transportsystem, das durch die Randbereiche führt. + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :Diese große Insel steht zu Ihrer Verfügung, machen Sie einen Vergnügungspark daraus. + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :Ein gigantischer, verlassener Wolkenkratzer ist eine einmalige Gelegenheit für einen Vergnügungsparkbetreiber. + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :Aus diesem Stadtgebiet können Sie einen Vergnügungspark zaubern. + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :Ein ausgedehnter Park, der bereits mit Attraktionen vollgepackt ist, bedarf der Verbesserung. + + +STR_SCNR :Venus Ponds +STR_PARK :Venus Ponds +STR_DTLS :Auf einem weit entfernten Planeten soll dieses Stück Land in einen Vergnügungspark umgewandelt werden. + + +STR_SCNR :Micro Park +STR_PARK :Micro Park +STR_DTLS :Versuchen Sie, den kleinsten Park der Welt anzulegen und dabei möglichst viel Gewinn zu erzielen. + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : ####################### # Bahnen/Attraktionen # diff --git a/data/language/japanese.txt b/data/language/japanese.txt index 2719237d84..7aed535d54 100644 --- a/data/language/japanese.txt +++ b/data/language/japanese.txt @@ -829,12 +829,12 @@ STR_0824 :{BLACK}{CROSS} STR_0825 :Chosen name in use already STR_0826 :Too many names defined STR_0827 :Not enough cash - requires {CURRENCY2DP} -STR_0828 :{SMALLFONT}{BLACK}Close window -STR_0829 :{SMALLFONT}{BLACK}Window title - Drag this to move window -STR_0830 :{SMALLFONT}{BLACK}Zoom view in -STR_0831 :{SMALLFONT}{BLACK}Zoom view out -STR_0832 :{SMALLFONT}{BLACK}Rotate view 90{DEGREE} clockwise -STR_0833 :{SMALLFONT}{BLACK}Pause game +STR_0828 :{SMALLFONT}{BLACK}ウィンドウを閉める +STR_0829 :{SMALLFONT}{BLACK}ウィンドウのタイトル - これをドラッグさせる +STR_0830 :{SMALLFONT}{BLACK}ズームアウト +STR_0831 :{SMALLFONT}{BLACK}ズームイン +STR_0832 :{SMALLFONT}{BLACK}時計回90{DEGREE}りに移動させる +STR_0833 :{SMALLFONT}{BLACK}ゲームをポーズする STR_0834 :{SMALLFONT}{BLACK}Disk and game options STR_0835 :Game initialisation failed STR_0836 :Unable to start game in a minimised state @@ -884,14 +884,14 @@ STR_0878 :高すぎる! STR_0879 :Can't lower land here... STR_0880 :Can't raise land here... STR_0881 :Object in the way -STR_0882 :Load Game -STR_0883 :Save Game -STR_0884 :Load Landscape -STR_0885 :Save Landscape -STR_0886 :Quit Game -STR_0887 :Quit Scenario Editor -STR_0888 :Quit Roller Coaster Designer -STR_0889 :Quit Track Designs Manager +STR_0882 :ゲームを再更新する +STR_0883 :ゲームをセーブする +STR_0884 :景色を再更新する +STR_0885 :景色をセーブする +STR_0886 :ゲームを閉じる +STR_0887 :Scenario Editorを閉じる +STR_0888 :Roller Coaster Designerを閉じる +STR_0889 :Track Designs Managerを閉じる STR_0890 :SCR{COMMA16}.BMP STR_0891 :スクリーンショット STR_0892 :Screenshot saved to disk as '{STRINGID}' @@ -952,9 +952,9 @@ STR_0946 :Cancel STR_0947 :Save this before loading ? STR_0948 :Save this before quitting ? STR_0949 :Save this before quitting ? -STR_0950 :Load Game -STR_0951 :Quit Game -STR_0952 :Quit Game +STR_0950 :ゲームを再更新する +STR_0951 :ゲームを閉じる +STR_0952 :ゲームを閉じる STR_0953 :Load Landscape STR_0954 : STR_0955 :{SMALLFONT}{BLACK}Select seat rotation angle for this track section @@ -1112,11 +1112,11 @@ STR_1106 :Crashing! STR_1107 :Crashed! STR_1108 :Travelling at {VELOCITY} STR_1109 :Swinging -STR_1110 :Rotating -STR_1111 :Rotating +STR_1110 :回転させる +STR_1111 :回転させる STR_1112 :Operating STR_1113 :Showing film -STR_1114 :Rotating +STR_1114 :回転させる STR_1115 :Operating STR_1116 :Operating STR_1117 :Doing circus show @@ -3819,7 +3819,7 @@ STR_5477 :Map rendering STR_5478 :Controls STR_5479 :Toolbar STR_5480 :Show toolbar buttons for: -STR_5481 :Themes +STR_5481 :スタイル STR_5482 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}1 minute STR_5483 :{BLACK}({COMMA16} weeks remaining) STR_5484 :{BLACK}({COMMA16} week remaining) @@ -3850,7 +3850,7 @@ STR_5508 :Allow loading files with incorrect checksums STR_5509 :{SMALLFONT}{BLACK}Allows loading scenarios and saves that have an incorrect checksum, like the scenarios from the demo or damaged saves. STR_5510 :Default sound device STR_5511 :(UNKNOWN) -STR_5512 :Save Game As +STR_5512 :名前を保存 STR_5513 :(Quick) save game STR_5514 :Disable vandalism STR_5515 :{SMALLFONT}{BLACK}Stops guests from vandalising your park when they're angry diff --git a/data/language/korean.txt b/data/language/korean.txt index a7ad6c4891..0baa603c90 100644 --- a/data/language/korean.txt +++ b/data/language/korean.txt @@ -8,7 +8,7 @@ STR_0003 :스탠드업 롤러코스터 STR_0004 :서스펜디드 스윙잉 코스터 STR_0005 :인버티드 롤러코스터 STR_0006 :주니어 롤러코스터 -STR_0007 :미니어처 레일웨이 +STR_0007 :모형 기차 STR_0008 :모노레일 STR_0009 :미니 서스펜디드 롤러코스터 STR_0010 :보트 라이드 @@ -47,7 +47,7 @@ STR_0042 :톱 스핀 STR_0043 :스페이스 링 STR_0044 :역방향 자유낙하 코스터 STR_0045 :리프트 -STR_0046 :버티컬 드롭 롤러코스터 +STR_0046 :수직 낙하 롤러코스터 STR_0047 :현금 지급기 STR_0048 :트위스트 STR_0049 :귀신의 집 @@ -518,7 +518,7 @@ STR_0513 :손님들이 일어선 자세로 탑승하는 루핑 롤러코스 STR_0514 :코너를 돌 때 롤러코스터 트랙 아래에 달린 차량이 흔들리는 열차입니다. STR_0515 :복잡하고 꼬인 트랙 요소를 가진 트랙 아래를 달리는 스틸 롤러코스터 차량입니다. STR_0516 :큰 놀이기구를 탈 용기가 없는 사람들을 위한 얌전한 롤러코스터입니다. -STR_0517 :손님들이 협궤 선로를 따라 달리는 미니어처 열차에 탑승하는 놀이기구입니다. +STR_0517 :손님들이 협궤 선로를 따라 달리는 모형 열차에 탑승하는 놀이기구입니다. STR_0518 :손님들이 모노레일 트랙을 따라 달리는 전기 차량에 탑승하는 놀이기구입니다. STR_0519 :손님들이 단선 트랙 아래에 달려서 코너를 돌 때마다 좌우로 흔들리는 작은 차량에 탑승하는 놀이기구입니다. STR_0520 :손님들이 물 위를 다니는 배를 운전하거나 또는 저을 수 있는 선착장입니다. @@ -2222,7 +2222,7 @@ STR_2214 :게임 일시정지 중에는 건설할 수 없습니다! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F -STR_2218 :{RED}{STRINGID}(놀이기구: {STRINGID})(이)가 {STRINGID}(으)로 아직 돌아오지 않았습니다!{NEWLINE}놀이기구가 멈춰있거나 Check whether it is stuck or has 상점ed +STR_2218 :{RED}{POP16}{POP16}{STRINGID}의 {PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{STRINGID}(이)가 {POP16}{POP16}{POP16}{STRINGID}으로 아직 돌아오지 않았습니다!{NEWLINE}놀이기구가 멈춰있거나 오도가도 못하고 있는지 확인하세요. STR_2219 :{RED}{COMMA16}명의 손님이 {STRINGID} 사고로 사망하였습니다! STR_2220 :{WINDOW_COLOUR_2}공원 등급: {BLACK}{COMMA16} STR_2221 :{SMALLFONT}{BLACK}공원 등급: {COMMA16} @@ -2366,7 +2366,7 @@ STR_2358 :유닛 STR_2359 :실제 값 STR_2360 :{WINDOW_COLOUR_2}해상도: STR_2361 :땅 테두리를 부드럽게 -STR_2362 :{SMALLFONT}{BLACK}땅의 테두리를 부드럽게 보입니다 +STR_2362 :{SMALLFONT}{BLACK}땅의 테두리를 부드럽게 보이게 만듭니다 STR_2363 :땅에 격자선 보이기 STR_2364 :{SMALLFONT}{BLACK}땅에 격자선을 보여줍니다 STR_2365 :은행이 대출을 증가시키는 것을 거절했습니다! @@ -3844,8 +3844,8 @@ STR_5504 :{SMALLFONT}{BLACK}멀티플레이 창을 엽니다 STR_5505 :서버에 접속할 수 없습니다 STR_5506 :손님이 격렬도를 무시하고 탐 STR_5507 :미화원이 기본적으로 잔디를 깎음 -STR_5508 :올바르지 않은 체크합을 가진 파일 불러오기 허용 -STR_5509 :{SMALLFONT}{BLACK}데모에서 저장한 시나리오나 손상된 저장 파일과 같이 올바르지 않은 체크합을 가진 시나리오나 저장 파일을 불러오는 것을 허용합니다. +STR_5508 :올바르지 않은 검사합을 가진 파일 불러오기 허용 +STR_5509 :{SMALLFONT}{BLACK}데모에서 저장한 시나리오나 손상된 저장 파일과 같이 올바르지 않은 검사합을 가진 시나리오나 저장 파일을 불러오는 것을 허용합니다. STR_5510 :기본 사운드 장치 STR_5511 :(알 수 없음) STR_5512 :다른 이름으로 저장 @@ -3943,14 +3943,481 @@ STR_5603 :손님의 놀이기구 하차 STR_5604 :손님의 물건 구입 STR_5605 :손님의 시설 사용 STR_5606 :손님의 사망 +STR_5607 :{SMALLFONT}{BLACK}선택한 맵 요소를 강제로 제거합니다. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}현재 선택한 맵 요소를 제거합니다. 강제로 삭제하기 때문에 돈이 들어오거나 빠지진 않을 것입니다. 주의해서 사용하세요. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}유령 플래그 +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}깨짐 플래그 +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}타일 플래그의 마지막 요소 +STR_5617 :{SMALLFONT}{BLACK}선택한 요소를 위로 이동합니다. +STR_5618 :{SMALLFONT}{BLACK}선택한 요소를 아래로 이동합니다. +STR_5619 :롤러코스터 타이쿤 +STR_5620 :애디드 어트랙션 +STR_5621 :루피 랜드스케이프 +STR_5622 :롤러코스터 타이쿤 2 +STR_5623 :와키 월드 +STR_5624 :타임 트위스터 +STR_5625 :{OPENQUOTES}실제{ENDQUOTES} 공원 +STR_5626 :기타 공원 +STR_5627 :시나리오 목록 분류 방식: +STR_5628 :게임별 +STR_5629 :난이도별 +STR_5630 :시나리오 클리어시 새 시나리오 열기 켜기 +STR_5631 :오리지널 다운로드 콘텐츠 공원 +STR_5632 :직접 만들기... +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :미개척된 숲 +STR_DTLS :깊은 숲 속 넓은 공터에 번창한 놀이공원을 건설하세요. + + +STR_SCNR :Dynamite Dunes +STR_PARK :다이너마이트 모래언덕 +STR_DTLS :사막 한가운데 건설된 이 놀이공원에는 롤러코스터 한 대만이 있지만 확장할 수 있는 곳이 많습니다. + + +STR_SCNR :Leafy Lake +STR_PARK :나뭇잎 호수 +STR_DTLS :처음부터 시작하여 큰 호수 주변에 놀이공원을 건설하세요. + + +STR_SCNR :Diamond Heights +STR_PARK :다이아몬드 언덕 +STR_DTLS :다이아몬드 언덕은 멋진 놀이기구를 통해 이미 성공한 놀이공원입니다. 공원의 가치를 두 배로 늘려 보세요. + + +STR_SCNR :Evergreen Gardens +STR_PARK :상록수 정원 +STR_DTLS :아름다운 상록수 정원을 번창한 놀이공원으로 바꿔보세요. + + +STR_SCNR :Bumbly Beach +STR_PARK :범블리 해변 +STR_DTLS :범블리 해변의 작은 놀이공원을 번창한 놀이공원으로 발전시키세요. + + +STR_SCNR :Trinity Islands +STR_PARK :삼위일체 섬 +STR_DTLS :몇 개의 섬이 이 새로운 공원의 기반입니다. + + +STR_SCNR :Katie's Dreamland +STR_PARK :케이티의 드림랜드 +STR_DTLS :몇 개의 놀이기구와 확장할 공간이 있는 작은 놀이공원으로, 여러분의 목표는 공원 가치를 두 배로 늘리는 것입니다. + + +STR_SCNR :Pokey Park +STR_PARK :비좁은 공원 +STR_DTLS :대대적인 확장을 해야하는 비좁은 놀이공원 + + +STR_SCNR :White Water Park +STR_PARK :맑은 물 공원 +STR_DTLS :훌륭한 물 놀이기구를 몇 개 갖고있지만 확장이 필요한 공원 + + +STR_SCNR :Millennium Mines +STR_PARK :밀레니엄 광산 +STR_DTLS :버려져있는 커다란 탄광을 관광시설에서 놀이공원으로 바꿔보세요. + + +STR_SCNR :Karts & Coasters +STR_PARK :카트 & 코스터 +STR_DTLS :몇 개의 고 카트 트랙과 우든 롤러코스터만이 숲 속에 숨겨져 있는 대형 놀이공원 + + +STR_SCNR :Mel's World +STR_PARK :멜의 세계 +STR_DTLS :이 놀이공원에는 잘 디자인된 현대식 놀이기구가 있지만 아직도 확장해야 할 곳이 많습니다. + + +STR_SCNR :Mystic Mountain +STR_PARK :신비한 산 +STR_DTLS :비밀스런 숲 속 언덕에 처음부터 놀이공원을 건설하세요. + + +STR_SCNR :Pacific Pyramids +STR_PARK :평화로운 피라미드 +STR_DTLS :이집트 유적 관광지를 번창한 놀이공원으로 바꿔 보세요. + + +STR_SCNR :Crumbly Woods +STR_PARK :부서지기 쉬운 숲 +STR_DTLS :잘 디자인되었지만 다소 낡은 놀이기구를 가진 대형 공원입니다. 오래된 놀이기구를 교체하거나 새로운 놀이기구를 추가하여 보다 인기있는 공원을 만들어보세요. + + +STR_SCNR :Paradise Pier +STR_PARK :파라다이스 부두 +STR_DTLS :이 조용한 마을의 부두를 번창한 놀이공원으로 바꿔보세요. + + +STR_SCNR :Lightning Peaks +STR_PARK :번개치는 산꼭대기 +STR_DTLS :번개치는 산꼭대기의 아름다운 산은 경치를 즐기며 산책을 즐기는 사람들에게 인기가 높습니다. 사용 가능한 땅을 이용해서 스릴을 찾는 새로운 고객을 유혹해보세요. + + +STR_SCNR :Ivory Towers +STR_PARK :상아 탑 +STR_DTLS :문제가 몇 가지 있지만 잘 구성된 공원 + + +STR_SCNR :Rainbow Valley +STR_PARK :무지개 계곡 +STR_DTLS :무지개 계곡의 지역 당국은 풍경을 바꾸거나 큰 나무를 제거할 수 없게 했지만, 이 지역을 개발하여 대형 놀이공원으로 바꿔야만 합니다. + + +STR_SCNR :Thunder Rock +STR_PARK :천둥 바위 +STR_DTLS :천둥 바위는 사막 한가운데에서 많은 관광객을 끌어 모으고 있습니다. 사용 가능한 공간을 이용해 놀이기구를 건설해서 더 많은 사람들을 끌어 보세요. + + +STR_SCNR :Mega Park +STR_PARK :대공원 +STR_DTLS :그냥 즐기세요! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :속삭이는 절벽 +STR_DTLS :해변의 절벽을 인기있는 놀이공원으로 발전시키세요. + + +STR_SCNR :Three Monkeys Park +STR_PARK :세 원숭이 공원 +STR_DTLS :개발 중인 이 거대한 공원의 한 가운데에는 동시에 경주하는 거대한 세 쌍둥이 스틸 롤러코스터가 있습니다. + + +STR_SCNR :Canary Mines +STR_PARK :카나리아 광산 +STR_DTLS :이 버려진 탄광은 모형 기차와 수직 낙하 롤러코스터로 이미 관광객의 인기를 끌고 있습니다. + + +STR_SCNR :Barony Bridge +STR_PARK :남작의 다리 +STR_DTLS :필요없는 오래된 다리를 놀이공원으로 개발할 수 있습니다. + + +STR_SCNR :Funtopia +STR_PARK :펀토피아 +STR_DTLS :고속도로 양쪽을 잘 활용한 이 공원은 이미 몇 가지 놀이기구를 운영하고 있습니다. + + +STR_SCNR :Haunted Harbor +STR_PARK :유령 항구 +STR_DTLS :지역 당국은 특정 놀이기구는 파괴할 수 없다는 조건을 걸고 이 작은 해변 공원 근처의 땅을 저렴하게 팔기로 합의했습니다. + + +STR_SCNR :Fun Fortress +STR_PARK :즐거운 요새 +STR_DTLS :이 성은 놀이공원으로 탈바꿈하기 위해 온전히 당신의 소유가 되었습니다. + + +STR_SCNR :Future World +STR_PARK :미래 세계 +STR_DTLS :이 미래지향적인 공원에는 새로운 놀이기구를 그 외계 지형 위에 지을 많은 공간이 있습니다. + + +STR_SCNR :Gentle Glen +STR_PARK :얌전한 골짜기 +STR_DTLS :이 지역의 주민들은 격렬하지 않고 얌전한 놀이기구를 선호하기 때문에 이 공원을 그들의 취향에 맞게 확장하는 것이 여러분의 임무입니다. + + +STR_SCNR :Jolly Jungle +STR_PARK :즐거운 정글 +STR_DTLS :정글 속 깊은 곳에 놀이공원으로 탈바꿈할 수 있는 넓은 대지가 있습니다. + + +STR_SCNR :Hydro Hills +STR_PARK :하이드로 언덕 +STR_DTLS :몇 개의 호수를 기반으로 새로운 공원을 건설할 수 있습니다. + + +STR_SCNR :Sprightly Park +STR_PARK :활기 넘치는 공원 +STR_DTLS :이 오래된 공원에는 아주 역사적인 놀이기구가 많이 있지만 심각한 적자에 시달리고 있습니다. + + +STR_SCNR :Magic Quarters +STR_PARK :매직 쿼터 +STR_DTLS :비어있는 넓은 지역의 일부분을 아름다운 풍경의 테마파크로 개발될 준비가 되었습니다. + + +STR_SCNR :Fruit Farm +STR_PARK :과일 농장 +STR_DTLS :무성한 과일 농장에 모형 기차를 건설해서 수익을 극대화하고 있습니다. 여러분의 임무는 이 농장을 최고의 놀이공원으로 만드는 것입니다. + + +STR_SCNR :Butterfly Dam +STR_PARK :나비 댐 +STR_DTLS :댐 주변 지역을 놀이공원으로 개발할 수 있습니다. + + +STR_SCNR :Coaster Canyon +STR_PARK 코스터 협곡 +STR_DTLS :광대한 협곡을 테마파크로 개발할 수 있습니다. + + +STR_SCNR :Thunderstorm Park +STR_PARK :폭풍우 공원 +STR_DTLS :날씨가 너무 습해서 거대한 피라미드를 짓고 몇몇 놀이기구를 그 밑에 두기로 했습니다. + + +STR_SCNR :Harmonic Hills +STR_PARK :조화로운 언덕 +STR_DTLS :지역 당국은 이 공원에서 나무 높이 이상의 건설을 허용하지 않습니다. + + +STR_SCNR :Roman Village +STR_PARK :로마의 마을 +STR_DTLS :이 로마 스타일의 테마파크에 놀이기구와 롤러코스터를 추가해서 더욱 발전시켜보세요. + + +STR_SCNR :Swamp Cove +STR_PARK :습지 골짜기 +STR_DTLS :몇 개의 작은 섬에 부분 부분 건설된 이 공원에는 이미 중앙에 한 쌍의 거대한 롤러코스터가 있습니다. + + +STR_SCNR :Adrenaline Heights +STR_PARK :아드레날린 언덕 +STR_DTLS :격렬한 스릴을 즐기는 사람들을 위한 공원을 건설하세요. + + +STR_SCNR :Utopia Park +STR_PARK :유토피아 공원 +STR_DTLS :사막 한가운데의 오아시스에 놀이공원을 건설해보세요. + + +STR_SCNR :Rotting Heights +STR_PARK :썩어버린 언덕 +STR_DTLS :지나치게 성장해서 황폐화되어버린 이 곳을 다시 멋진 공원으로 바꿀 수 있습니까? + + +STR_SCNR :Fiasco Forest +STR_PARK :실패한 숲 +STR_DTLS :위험하고 잘못 설계된 놀이기구가 많이 있습니다. 공원을 둘러보고 문제를 수정할 시간과 예산이 매우 부족합니다. + + +STR_SCNR :Pickle Park +STR_PARK :피클 공원 +STR_DTLS :지역 당국에서는 광고나 홍보를 허용하지 않으므로 이 공원은 사람들의 입을 통해서만 알릴 수 있습니다. + + +STR_SCNR :Giggle Downs +STR_PARK :웃기는 구릉 지대 +STR_DTLS :이 넓은 공원의 중앙에는 네 쌍둥이 스티플체이스 놀이기구가 있습니다. + + +STR_SCNR :Mineral Park +STR_PARK :광물 공원 +STR_DTLS :이 버려진 채석장을 스릴을 찾는 사람들을 유혹할만한 장소로 바꿔보세요. + + +STR_SCNR :Coaster Crazy +STR_PARK :미친 코스터 +STR_DTLS :이 산악 지대에 다양한 롤러코스터를 건설해보세요. 예산은 한정되어 있지만 시간은 제한이 없습니다. + + +STR_SCNR :Urban Park +STR_PARK :도시 공원 +STR_DTLS :이 작은 공원은 이 도시뿐만 아니라 근교 도시의 주민들에게까지 인기를 모으고 있습니다. + + +STR_SCNR :Geoffrey Gardens +STR_PARK :제프리의 정원 +STR_DTLS :대규모의 정원 공원을 북적이는 놀이공원으로 바꿔해야 합니다. + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :빙산 섬 +STR_DTLS :빙산이 이 야심찬 놀이공원에 차가운 이미지를 더하고 있습니다. + + +STR_SCNR :Volcania +STR_PARK :볼케이니아 +STR_DTLS :이번 롤러코스터 건설 도전에서는 휴화산이 무대가 됩니다. + + +STR_SCNR :Arid Heights +STR_PARK :건조한 언덕 +STR_DTLS :아무런 재정적 제한 없는 상황에서, 지속적으로 손님들을 행복하게 만들 수 있는 공원을 사막에 건설해보세요. + + +STR_SCNR :Razor Rocks +STR_PARK :날카로운 바위 +STR_DTLS :여러분의 임무는 날카로운 바위 사이에 롤러코스터로 가득한 거대한 공원을 만드는 것입니다. + + +STR_SCNR :Crater Lake +STR_PARK :분화구 호수 +STR_DTLS :이 공원의 부지는 고대 분화구에 만들어진긴 커다란 호수입니다. + + +STR_SCNR :Vertigo Views +STR_PARK :어지러운 풍경 +STR_DTLS :이 거대한 공원에는 이미 훌륭한 하이퍼코스터가 있습니다. 여러분의 임무는 그 매출을 아주 극대화시키는 것입니다. + + +STR_SCNR :Paradise Pier 2 +STR_PARK :파라다이스 부두 2 +STR_DTLS :파라다이스 부두는 바다 위의 산책로를 확장했습니다. 여러분의 임무는 이 새로운 공간을 이용하여 공원을 확장하는 것 입니다. + + +STR_SCNR :Dragon's Cove +STR_PARK :용의 동굴 +STR_DTLS :이번 롤러코스터 건설 도전에서는 해안 동굴이 무대가 됩니다. + + +STR_SCNR :Good Knight Park +STR_PARK :훌륭한 기사 공원 +STR_DTLS :한 쌍의 롤러코스터가 있는 성을 더 큰 놀이공원으로 발전시켜야 합니다. + + +STR_SCNR :Wacky Warren +STR_PARK :괴짜 미로 +STR_DTLS :대부분의 보도와 롤러코스터가 지하에 있는 공원입니다. + + +STR_SCNR :Grand Glacier +STR_PARK :웅장한 빙하 +STR_DTLS :놀이공원으로 만들기 위해 당신에게 빙하가 가득한 계곡이 주어졌습니다. + + +STR_SCNR :Crazy Craters +STR_PARK :미친 분화구 +STR_DTLS :돈이 필요없는 머나먼 세상에서, 여러분은 사람들을 행복하게 해줄 놀이공원을 건설해야 합니다. + + +STR_SCNR :Dusty Desert +STR_PARK :먼지투성이 사막 +STR_DTLS :이 사막 공원에 있는 다섯 대의 롤러코스터를 완성하십시오. + + +STR_SCNR :Woodworm Park +STR_PARK :나무좀벌레 공원 +STR_DTLS :이 역사적인 공원에는 오직 오래된 스타일의 놀이기구만을 건설할 수 있습니다. + + +STR_SCNR :Icarus Park +STR_PARK :이카루스 공원 +STR_DTLS :이 외계 공원을 개발하여 최대한의 매출을 올리세요. + + +STR_SCNR :Sunny Swamps +STR_PARK :맑은 늪지 +STR_DTLS :이 잘 구성된 놀이공원에는 이미 몇 개의 놀이기구가 있지만, 아직 확장할 수 있는 공간은 충분합니다. + + +STR_SCNR :Frightmare Hills +STR_PARK :무시무시한 언덕 +STR_DTLS :거대한 롤러코스터가 공원 가운데에 있는 무시무시한 공원 + + +STR_SCNR :Thunder Rocks +STR_PARK :천둥 바위들 +STR_DTLS :놀이공원의 기초가 될 두 개의 커다란 바위가 사막의 모래 위에 솟아 있습니다. + + +STR_SCNR :Octagon Park +STR_PARK :팔각형 공원 +STR_DTLS :이 거대한 공원에 여러분은 10개의 거대한 롤러코스터를 디자인하고 만들어야 합니다. + + +STR_SCNR :Pleasure Island +STR_PARK :즐거운 섬 +STR_DTLS :길고 가느다란 섬에서 롤러코스터 건설에 도전해보세요. + + +STR_SCNR :Icicle Worlds +STR_PARK :고드름 세상 +STR_DTLS :얼음으로 덮인 땅을 번창하는 놀이공원으로 바꿔보세요. + + +STR_SCNR :Southern Sands +STR_PARK :남부 사막 +STR_DTLS :빈틈없이 세워진 롤러코스터가 있는 사막 공원이 확장을 위해 여러분에게 주어졌습니다. + + +STR_SCNR :Tiny Towers +STR_PARK :조그마한 탑 +STR_DTLS :이 조그마한 공원에 있는 다섯 개의 미완성된 롤러코스터를 모두 완성해야 합니다. + + +STR_SCNR :Nevermore Park +STR_PARK :네버모어 공원 +STR_DTLS :공원 주변에 참신한 운송수단이 설치된 거대한 공원 + + +STR_SCNR :Pacifica +STR_PARK :패시피카 +STR_DTLS :놀이공원으로 개발하기 위해 이 거대한 섬이 여러분에게 주어졌습니다. + + +STR_SCNR :Urban Jungle +STR_PARK :도시의 정글 +STR_DTLS :버려진 거대한 마천루 빌딩은 놀이공원 개발자에게는 독특한 기회일 것입니다. + + +STR_SCNR :Terror Town +STR_PARK :공포스러운 마을 +STR_DTLS :놀이공원으로 개발하기 위해 이 도시 지역이 여러분에게 주어졌습니다. + + +STR_SCNR :Megaworld Park +STR_PARK :대세상 공원 +STR_DTLS :이미 놀이기구로 가득한 거대한 공원을 확장해야 합니다. + + +STR_SCNR :Venus Ponds +STR_PARK :비너스의 연못 +STR_DTLS :멀리 떨어진 행성에 있는 이 지역을 놀이공원으로 바꿔야 합니다. + + +STR_SCNR :Micro Park +STR_PARK :마이크로 공원 +STR_DTLS :세상에서 가장 작지만 수익이 좋은 공원을 만들어보세요. + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :알턴 타워스 +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :하이데 파르크 +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :블랙풀 플레져 비치 +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :역사적인 성채 +STR_DTLS : ############################################################################### ## RCT2 Objects ############################################################################### [AML1] STR_NAME :미국 스타일 증기 기관차 -STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 미니어처 증기 기관차 차량 +STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 STR_CPTY :차량당 6명의 승객 [CLIFT1] @@ -3985,12 +4452,12 @@ STR_CPTY :차량당 4명의 승객 [NRL] STR_NAME :증기 기관차 -STR_DESC :나무 객차와 증기 기관차 모형으로 이루어진 미니어처 증기 기관차 차량 +STR_DESC :나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 STR_CPTY :객차당 6명의 승객 [NRL2] STR_NAME :천장이 있는 증기 기관차 -STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 미니어처 증기 기관차 차량 +STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 STR_CPTY :객차당 6명의 승객 [SMONO] @@ -4040,7 +4507,7 @@ STR_CPTY :승객 32명 [GOLF1] STR_NAME :미니 골프 -STR_DESC :미니어처 골프 게임 +STR_DESC :모형 골프 게임 STR_CPTY : [GTC] @@ -4184,7 +4651,7 @@ STR_DESC :탑승자들이 선 자세로 낙하와 여러 특수 트랙을 즐 STR_CPTY :차량당 4명의 승객 [BMVD] -STR_NAME :버티컬 드롭 롤러코스터 +STR_NAME :수직 낙하 롤러코스터 STR_DESC :자유 낙하의 극한 경험을 선사하기 위해 완전히 수직 경사 트랙을 따라 하강하는 아주 폭이 넓은 차량 STR_CPTY :차량당 6명의 승객 From db76615af0e535e43698d88d869a2e776e1a6d63 Mon Sep 17 00:00:00 2001 From: LRFLEW Date: Tue, 5 Jan 2016 00:17:10 -0700 Subject: [PATCH 90/90] Fixed typo in viewport_interaction.c --- src/interface/viewport_interaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index 536ca3a804..c9f96379a4 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -272,7 +272,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info return info->type; } - if ((gInputFlags & INPUT_FLAG_6) && (gInputFlags && INPUT_FLAG_TOOL_ACTIVE)) + if ((gInputFlags & INPUT_FLAG_6) && (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) if (window_find_by_class(WC_RIDE_CONSTRUCTION) == NULL && window_find_by_class(WC_FOOTPATH) == NULL) return info->type = VIEWPORT_INTERACTION_ITEM_NONE;