mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #3477 from IntelOrca/feature/multiple-trackdesign-locations
Scan track designs from multiple locations and refactor
This commit is contained in:
commit
fc6a589c35
|
@ -7,6 +7,10 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
008BF72A1CDAA5C30019A2AD /* track_design_index.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7261CDAA5C30019A2AD /* track_design_index.c */; };
|
||||
008BF72B1CDAA5C30019A2AD /* track_design_save.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7271CDAA5C30019A2AD /* track_design_save.c */; };
|
||||
008BF72C1CDAA5C30019A2AD /* track_design.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7281CDAA5C30019A2AD /* track_design.c */; };
|
||||
C61FAAE21CD1643A0010C9D8 /* paint_surface.c in Sources */ = {isa = PBXBuildFile; fileRef = C61FAAE01CD1643A0010C9D8 /* paint_surface.c */; };
|
||||
C650B2191CCABBDD00B4D91C /* S4Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2151CCABBDD00B4D91C /* S4Importer.cpp */; };
|
||||
C650B21A1CCABBDD00B4D91C /* tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2171CCABBDD00B4D91C /* tables.cpp */; };
|
||||
C650B21C1CCABC4400B4D91C /* ConvertCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B21B1CCABC4400B4D91C /* ConvertCommand.cpp */; };
|
||||
|
@ -318,6 +322,12 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
008BF7261CDAA5C30019A2AD /* track_design_index.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_design_index.c; sourceTree = "<group>"; };
|
||||
008BF7271CDAA5C30019A2AD /* track_design_save.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_design_save.c; sourceTree = "<group>"; };
|
||||
008BF7281CDAA5C30019A2AD /* track_design.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_design.c; sourceTree = "<group>"; };
|
||||
008BF7291CDAA5C30019A2AD /* track_design.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track_design.h; sourceTree = "<group>"; };
|
||||
C61FAAE01CD1643A0010C9D8 /* paint_surface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = paint_surface.c; sourceTree = "<group>"; };
|
||||
C61FAAE11CD1643A0010C9D8 /* paint_surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = paint_surface.h; sourceTree = "<group>"; };
|
||||
C650B2151CCABBDD00B4D91C /* S4Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S4Importer.cpp; sourceTree = "<group>"; };
|
||||
C650B2161CCABBDD00B4D91C /* S4Importer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S4Importer.h; sourceTree = "<group>"; };
|
||||
C650B2171CCABBDD00B4D91C /* tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tables.cpp; sourceTree = "<group>"; };
|
||||
|
@ -1250,6 +1260,10 @@
|
|||
C686F8F01CDBC3B7009F9BFC /* thrill */,
|
||||
C686F8FC1CDBC3B7009F9BFC /* transport */,
|
||||
C686F9021CDBC3B7009F9BFC /* water */,
|
||||
008BF7261CDAA5C30019A2AD /* track_design_index.c */,
|
||||
008BF7271CDAA5C30019A2AD /* track_design_save.c */,
|
||||
008BF7281CDAA5C30019A2AD /* track_design.c */,
|
||||
008BF7291CDAA5C30019A2AD /* track_design.h */,
|
||||
D442716F1CC81B3200D84D28 /* cable_lift.c */,
|
||||
D44271701CC81B3200D84D28 /* cable_lift.h */,
|
||||
D44271731CC81B3200D84D28 /* ride_data.c */,
|
||||
|
@ -1721,6 +1735,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
008BF72B1CDAA5C30019A2AD /* track_design_save.c in Sources */,
|
||||
D44272491CC81B3200D84D28 /* track.c in Sources */,
|
||||
C686F9201CDBC3B7009F9BFC /* side_friction_roller_coaster.c in Sources */,
|
||||
D44272561CC81B3200D84D28 /* cheats.c in Sources */,
|
||||
|
@ -1799,6 +1814,7 @@
|
|||
C686F9321CDBC3B7009F9BFC /* haunted_house.c in Sources */,
|
||||
D442720A1CC81B3200D84D28 /* drawing_fast.cpp in Sources */,
|
||||
C686F9521CDBC3B7009F9BFC /* river_rapids.c in Sources */,
|
||||
008BF72C1CDAA5C30019A2AD /* track_design.c in Sources */,
|
||||
D44272191CC81B3200D84D28 /* colour.c in Sources */,
|
||||
D442724C1CC81B3200D84D28 /* vehicle.c in Sources */,
|
||||
D44272261CC81B3200D84D28 /* currency.c in Sources */,
|
||||
|
@ -1919,6 +1935,7 @@
|
|||
C686F9501CDBC3B7009F9BFC /* log_flume.c in Sources */,
|
||||
D44272241CC81B3200D84D28 /* intro.c in Sources */,
|
||||
D44272631CC81B3200D84D28 /* game_bottom_toolbar.c in Sources */,
|
||||
008BF72A1CDAA5C30019A2AD /* track_design_index.c in Sources */,
|
||||
D44272091CC81B3200D84D28 /* drawing.c in Sources */,
|
||||
C686F94C1CDBC3B7009F9BFC /* monorail.c in Sources */,
|
||||
D442728E1CC81B3200D84D28 /* title_logo.c in Sources */,
|
||||
|
|
|
@ -3364,7 +3364,7 @@ STR_3353 :New name contains invalid characters
|
|||
STR_3354 :Another file exists with this name, or file is write-protected
|
||||
STR_3355 :File is write-protected or locked
|
||||
STR_3356 :Delete File
|
||||
STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRINGID} ?
|
||||
STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRING} ?
|
||||
STR_3358 :Can't delete track design...
|
||||
STR_3359 :{BLACK}No track designs of this type
|
||||
STR_3360 :Warning!
|
||||
|
@ -4118,6 +4118,8 @@ STR_5809 :{WINDOW_COLOUR_2}Number of information kiosks and other facilities:
|
|||
STR_5810 :Disable train length limit
|
||||
STR_5811 :{SMALLFONT}{BLACK}If checked, you can have up to{NEWLINE}255 cars per train
|
||||
STR_5812 :Show multiplayer window
|
||||
STR_5813 :{OPENQUOTES}{STRING}{ENDQUOTES}
|
||||
STR_5814 :{WINDOW_COLOUR_1}{OPENQUOTES}{STRING}{ENDQUOTES}
|
||||
|
||||
#############
|
||||
# Scenarios #
|
||||
|
|
|
@ -181,6 +181,9 @@
|
|||
<ClCompile Include="src\ride\thrill\twist.c" />
|
||||
<ClCompile Include="src\ride\track.c" />
|
||||
<ClCompile Include="src\ride\track_data.c" />
|
||||
<ClCompile Include="src\ride\track_design.c" />
|
||||
<ClCompile Include="src\ride\track_design_save.c" />
|
||||
<ClCompile Include="src\ride\track_design_index.c" />
|
||||
<ClCompile Include="src\ride\track_paint.c" />
|
||||
<ClCompile Include="src\ride\transport\chairlift.c" />
|
||||
<ClCompile Include="src\ride\transport\lift.c" />
|
||||
|
@ -374,6 +377,7 @@
|
|||
<ClInclude Include="src\ride\station.h" />
|
||||
<ClInclude Include="src\ride\track.h" />
|
||||
<ClInclude Include="src\ride\track_data.h" />
|
||||
<ClInclude Include="src\ride\track_design.h" />
|
||||
<ClInclude Include="src\ride\track_paint.h" />
|
||||
<ClInclude Include="src\ride\vehicle.h" />
|
||||
<ClInclude Include="src\ride\vehicle_paint.h" />
|
||||
|
|
|
@ -242,20 +242,6 @@
|
|||
// 8 x 8 in size.
|
||||
#define RCT2_ADDRESS_CHARACTER_BITMAP 0x00F4393C
|
||||
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_X_MIN 0x00F440F9
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_X_MAX 0x00F440FB
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN 0x00F440FD
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX 0x00F440FF
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MIN 0x00F44101
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX 0x00F44103
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_CACHE 0x00F44105
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE 0x00F44109
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE 0x00F44119
|
||||
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_COST 0x00F4411D
|
||||
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE 0x00F44152
|
||||
|
||||
#define RCT2_ADDRESS_ABOVE_GROUND_FLAGS 0x00F441D4
|
||||
#define RCT2_ADDRESS_TRACK_LIST 0x00F441EC
|
||||
|
||||
|
@ -602,7 +588,19 @@
|
|||
#define RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE 0x00F3EF91
|
||||
|
||||
#define RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS 0x00F3EF9E
|
||||
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_ROTATION 0x00F440AE
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_X_MIN 0x00F440F9
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_X_MAX 0x00F440FB
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN 0x00F440FD
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX 0x00F440FF
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MIN 0x00F44101
|
||||
#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX 0x00F44103
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_CACHE 0x00F44105
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE 0x00F44109
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE 0x00F44119
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_COST 0x00F4411D
|
||||
#define RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE 0x00F44152
|
||||
|
||||
#define RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT 0x0140E9A4
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ static void set_all_land_owned()
|
|||
{
|
||||
int mapSize = gMapSize;
|
||||
|
||||
game_do_command(64, 1, 64, 2, GAME_COMMAND_SET_LAND_OWNERSHIP, (mapSize - 2) * 32, (mapSize - 2) * 32);
|
||||
game_do_command(64, 1, 64, 2, GAME_COMMAND_SET_LAND_OWNERSHIP, (mapSize - 3) * 32, (mapSize - 3) * 32);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ride/ride_ratings.h"
|
||||
#include "ride/vehicle.h"
|
||||
#include "ride/track.h"
|
||||
#include "ride/track_design.h"
|
||||
#include "scenario.h"
|
||||
#include "title.h"
|
||||
#include "util/sawyercoding.h"
|
||||
|
|
|
@ -19,12 +19,13 @@
|
|||
|
||||
#include "../common.h"
|
||||
#include "../drawing/drawing.h"
|
||||
#include "../management/research.h"
|
||||
#include "../peep/peep.h"
|
||||
#include "../ride/ride.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../ride/vehicle.h"
|
||||
#include "../world/park.h"
|
||||
#include "../management/research.h"
|
||||
#include "../scenario.h"
|
||||
#include "../world/park.h"
|
||||
#include "colour.h"
|
||||
|
||||
struct rct_window;
|
||||
|
@ -209,8 +210,8 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint16 var_480;
|
||||
uint16 var_482;
|
||||
uint16 var_484;
|
||||
bool reload_track_designs;
|
||||
} track_list_variables;
|
||||
|
||||
typedef struct {
|
||||
|
@ -627,7 +628,7 @@ void ride_construction_toolupdate_construct(int screenX, int screenY);
|
|||
void ride_construction_tooldown_construct(int screenX, int screenY);
|
||||
|
||||
void window_maze_construction_update_pressed_widgets();
|
||||
void window_track_place_open();
|
||||
void window_track_place_open(const track_design_file_ref *tdFileRef);
|
||||
rct_window *window_new_ride_open();
|
||||
rct_window *window_new_ride_open_research();
|
||||
void window_install_track_open(const char* path);
|
||||
|
@ -651,7 +652,7 @@ void window_research_funding_page_paint(rct_window *w, rct_drawpixelinfo *dpi, i
|
|||
void window_scenery_open();
|
||||
void window_music_credits_open();
|
||||
void window_publisher_credits_open();
|
||||
void window_track_manage_open();
|
||||
void window_track_manage_open(track_design_file_ref *tdFileRef);
|
||||
void window_viewport_open();
|
||||
void window_themes_open();
|
||||
void window_title_editor_open(int tab);
|
||||
|
|
|
@ -1879,10 +1879,13 @@ enum {
|
|||
STR_TRACK_MANAGE_RENAME = 3348,
|
||||
STR_TRACK_MANAGE_DELETE = 3349,
|
||||
|
||||
STR_TRACK_DESIGN_RENAME_TITLE = 3350,
|
||||
STR_TRACK_DESIGN_RENAME_DESC = 3351,
|
||||
STR_CANT_RENAME_TRACK_DESIGN = 3352,
|
||||
STR_NEW_NAME_CONTAINS_INVALID_CHARACTERS = 3353,
|
||||
STR_ANOTHER_FILE_EXISTS_WITH_NAME_OR_FILE_IS_WRITE_PROTECTED = 3354,
|
||||
STR_FILE_IS_WRITE_PROTECTED_OR_LOCKED = 3355,
|
||||
STR_DELETE_FILE = 3356,
|
||||
|
||||
STR_ARE_YOU_SURE_YOU_WANT_TO_PERMANENTLY_DELETE_TRACK = 3357,
|
||||
STR_CANT_DELETE_TRACK_DESIGN = 3358,
|
||||
|
@ -1900,6 +1903,10 @@ enum {
|
|||
STR_INSTALL_NEW_TRACK_DESIGN = 3376,
|
||||
STR_INSTALL_NEW_TRACK_DESIGN_TIP = 3377,
|
||||
|
||||
STR_UNABLE_TO_INSTALL_THIS_TRACK_DESIGN = 3380,
|
||||
STR_SELECT_NEW_NAME_FOR_TRACK_DESIGN = 3383,
|
||||
STR_AN_EXISTING_TRACK_DESIGN_ALREADY_HAS_THIS_NAME = 3384,
|
||||
|
||||
STR_SAVE_TRACK_SCENERY_UNABLE_TO_SELECT_ADDITIONAL_ITEM_OF_SCENERY = 3389,
|
||||
STR_SAVE_TRACK_SCENERY_TOO_MANY_ITEMS_SELECTED = 3390,
|
||||
|
||||
|
@ -2454,6 +2461,9 @@ enum {
|
|||
|
||||
STR_SHORTCUT_SHOW_MULTIPLAYER = 5812,
|
||||
|
||||
STR_TRACK_LIST_NAME_FORMAT = 5813,
|
||||
STR_TRACK_PREVIEW_NAME_FORMAT = 5814,
|
||||
|
||||
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
|
||||
STR_COUNT = 32768
|
||||
};
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
|
||||
#include "addresses.h"
|
||||
#include "config.h"
|
||||
#include "game.h"
|
||||
#include "localisation/localisation.h"
|
||||
#include "object.h"
|
||||
#include "platform/platform.h"
|
||||
#include "ride/track.h"
|
||||
#include "util/sawyercoding.h"
|
||||
#include "game.h"
|
||||
#include "rct1.h"
|
||||
#include "ride/track.h"
|
||||
#include "ride/track_design.h"
|
||||
#include "util/sawyercoding.h"
|
||||
#include "world/entrance.h"
|
||||
#include "world/footpath.h"
|
||||
#include "world/scenery.h"
|
||||
|
@ -336,7 +337,7 @@ void object_list_load()
|
|||
ride_list_item ride_list;
|
||||
ride_list.entry_index = 0xFC;
|
||||
ride_list.type = 0xFC;
|
||||
track_load_list(ride_list);
|
||||
// track_load_list(ride_list);
|
||||
|
||||
object_list_examine();
|
||||
}
|
||||
|
|
|
@ -527,8 +527,8 @@ enum{
|
|||
};
|
||||
|
||||
enum{
|
||||
RCT1_RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE = 2,
|
||||
RCT1_RIDE_MODE_POWERED_LAUNCH = 3,
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "rct1.h"
|
||||
#include "ride/ride.h"
|
||||
#include "ride/track.h"
|
||||
#include "ride/track_design.h"
|
||||
#include "scenario.h"
|
||||
#include "title.h"
|
||||
#include "util/util.h"
|
||||
|
@ -158,9 +159,7 @@ int rct2_init()
|
|||
|
||||
object_list_load();
|
||||
scenario_load_list();
|
||||
|
||||
ride_list_item item = { 253, 0 };
|
||||
track_load_list(item);
|
||||
track_design_index_create();
|
||||
|
||||
font_sprite_initialise_characters();
|
||||
if (!gOpenRCT2Headless) {
|
||||
|
|
172
src/ride/ride.c
172
src/ride/ride.c
|
@ -199,7 +199,7 @@ rct_ride *get_ride(int index)
|
|||
|
||||
rct_ride_entry *get_ride_entry(int index)
|
||||
{
|
||||
if (index < 0 || index >= object_entry_group_counts[0])
|
||||
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE])
|
||||
{
|
||||
log_error("invalid index %d for ride type", index);
|
||||
return NULL;
|
||||
|
@ -207,6 +207,19 @@ rct_ride_entry *get_ride_entry(int index)
|
|||
return gRideTypeList[index];
|
||||
}
|
||||
|
||||
void get_ride_entry_name(char *name, int index)
|
||||
{
|
||||
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE])
|
||||
{
|
||||
log_error("invalid index %d for ride type", index);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *entryName = object_entry_groups[OBJECT_TYPE_RIDE].entries[index].name;
|
||||
memcpy(name, entryName, 8);
|
||||
name[8] = '\0';
|
||||
}
|
||||
|
||||
rct_ride_measurement *get_ride_measurement(int index)
|
||||
{
|
||||
return &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement)[index]);
|
||||
|
@ -5485,10 +5498,17 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
|
|||
|
||||
void ride_set_name(int rideIndex, const char *name)
|
||||
{
|
||||
typedef union name_union {
|
||||
char as_char[4];
|
||||
int as_int;
|
||||
} name_union;
|
||||
|
||||
name_union name_buffer[9];
|
||||
safe_strcpy((char *)name_buffer, name, sizeof(name_buffer));
|
||||
gGameCommandErrorTitle = STR_CANT_RENAME_RIDE_ATTRACTION;
|
||||
game_do_command(1, (rideIndex << 8) | 1, 0, *((int*)(name + 0)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(name + 8)), *((int*)(name + 4)));
|
||||
game_do_command(2, (rideIndex << 8) | 1, 0, *((int*)(name + 12)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(name + 20)), *((int*)(name + 16)));
|
||||
game_do_command(0, (rideIndex << 8) | 1, 0, *((int*)(name + 24)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(name + 32)), *((int*)(name + 28)));
|
||||
game_do_command(1, (rideIndex << 8) | 1, 0, name_buffer[0].as_int, GAME_COMMAND_SET_RIDE_NAME, name_buffer[2].as_int, name_buffer[1].as_int);
|
||||
game_do_command(2, (rideIndex << 8) | 1, 0, name_buffer[3].as_int, GAME_COMMAND_SET_RIDE_NAME, name_buffer[5].as_int, name_buffer[4].as_int);
|
||||
game_do_command(0, (rideIndex << 8) | 1, 0, name_buffer[6].as_int, GAME_COMMAND_SET_RIDE_NAME, name_buffer[8].as_int, name_buffer[7].as_int);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5836,6 +5856,21 @@ bool shop_item_has_common_price(int shopItem)
|
|||
}
|
||||
}
|
||||
|
||||
money32 ride_create_command(int type, int subType, int flags, uint8 *outRideIndex, uint8 *outRideColour)
|
||||
{
|
||||
int eax = 0;
|
||||
int ebx = flags;
|
||||
int ecx = 0;
|
||||
int edx = type | (subType << 8);
|
||||
int esi = 0;
|
||||
int edi = 0;
|
||||
int ebp = 0;
|
||||
money32 cost = game_do_command_p(GAME_COMMAND_CREATE_RIDE, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
*outRideIndex = edi & 0xFF;
|
||||
*outRideColour = eax;
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B3F0F
|
||||
|
@ -7200,14 +7235,14 @@ bool ride_select_forwards_from_back()
|
|||
}
|
||||
}
|
||||
|
||||
money32 ride_remove_track_piece(int x, int y, int z, int direction, int type)
|
||||
money32 ride_remove_track_piece(int x, int y, int z, int direction, int type, uint8 flags)
|
||||
{
|
||||
gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS;
|
||||
if (network_get_mode() == NETWORK_MODE_CLIENT)
|
||||
{
|
||||
game_command_callback = game_command_callback_ride_remove_track_piece;
|
||||
}
|
||||
return game_do_command(x, (GAME_COMMAND_FLAG_APPLY) | ((direction & 3) << 8), y, type, GAME_COMMAND_REMOVE_TRACK, z, 0);
|
||||
return game_do_command(x, flags | ((direction & 3) << 8), y, type, GAME_COMMAND_REMOVE_TRACK, z, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7811,25 +7846,15 @@ void sub_6CB945(int rideIndex)
|
|||
location.x -= TileDirectionDelta[direction].x;
|
||||
location.y -= TileDirectionDelta[direction].y;
|
||||
}
|
||||
mapElement = map_get_first_element_at(location.x / 32, location.y / 32);
|
||||
mapElement = map_get_first_element_at(location.x >> 5, location.y >> 5);
|
||||
|
||||
bool trackFound = false;
|
||||
do {
|
||||
if (mapElement->base_height != location.z)
|
||||
continue;
|
||||
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.track.ride_index != rideIndex)
|
||||
continue;
|
||||
|
||||
// Only allow sequence 0
|
||||
if (mapElement->properties.track.sequence & 0xF)
|
||||
continue;
|
||||
|
||||
if (!(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & (1 << 4)))
|
||||
continue;
|
||||
if (mapElement->base_height != location.z) continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue;
|
||||
if (mapElement->properties.track.ride_index != rideIndex) continue;
|
||||
if ((mapElement->properties.track.sequence & 0x0F) != 0) continue;
|
||||
if (!(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & (1 << 4))) continue;
|
||||
|
||||
trackFound = true;
|
||||
break;
|
||||
|
@ -7850,53 +7875,29 @@ void sub_6CB945(int rideIndex)
|
|||
}
|
||||
}
|
||||
|
||||
if (specialTrack == false)
|
||||
if (specialTrack == false) {
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
const rct_preview_track *trackBlock = get_track_def_from_ride(ride, mapElement->properties.track.type);
|
||||
|
||||
while ((++trackBlock)->index != 0xFF) {
|
||||
rct_xyz16 blockLocation = location;
|
||||
|
||||
switch (direction) {
|
||||
case 0:
|
||||
blockLocation.x += trackBlock->x;
|
||||
blockLocation.y += trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
blockLocation.x += trackBlock->y;
|
||||
blockLocation.y -= trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
blockLocation.x -= trackBlock->x;
|
||||
blockLocation.y -= trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
blockLocation.x -= trackBlock->y;
|
||||
blockLocation.y += trackBlock->x;
|
||||
break;
|
||||
}
|
||||
|
||||
blockLocation.z += trackBlock->z / 8;
|
||||
map_offset_with_rotation(&blockLocation.x, &blockLocation.y, trackBlock->x, trackBlock->y, direction);
|
||||
|
||||
bool trackFound = false;
|
||||
mapElement = map_get_first_element_at(blockLocation.x / 32, blockLocation.y / 32);
|
||||
mapElement = map_get_first_element_at(blockLocation.x >> 5, blockLocation.y >> 5);
|
||||
do {
|
||||
if (blockLocation.z != mapElement->base_height)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (!(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & 0x10))
|
||||
continue;
|
||||
if (blockLocation.z != mapElement->base_height) continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue;
|
||||
if (!(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & (1 << 4))) continue;
|
||||
|
||||
trackFound = true;
|
||||
break;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
if (trackFound == false)
|
||||
if (!trackFound) {
|
||||
break;
|
||||
}
|
||||
|
||||
mapElement->properties.track.sequence &= 0x8F;
|
||||
mapElement->properties.track.sequence |= (stationId << 4);
|
||||
|
@ -7904,8 +7905,7 @@ void sub_6CB945(int rideIndex)
|
|||
}
|
||||
}
|
||||
|
||||
uint16* locationList = RCT2_ADDRESS(0x00F441B0, uint16);
|
||||
|
||||
uint16 *locationList = RCT2_ADDRESS(0x00F441B0, uint16);
|
||||
for (uint8 stationId = 0; stationId < 4; ++stationId) {
|
||||
if (ride->entrances[stationId] != 0xFFFF) {
|
||||
*locationList++ = ride->entrances[stationId];
|
||||
|
@ -7917,11 +7917,9 @@ void sub_6CB945(int rideIndex)
|
|||
ride->exits[stationId] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
*locationList++ = 0xFFFF;
|
||||
|
||||
locationList = RCT2_ADDRESS(0x00F441B0, uint16);
|
||||
|
||||
for (; *locationList != 0xFFFF; locationList++) {
|
||||
uint16* locationList2 = locationList;
|
||||
locationList2++;
|
||||
|
@ -7934,50 +7932,40 @@ void sub_6CB945(int rideIndex)
|
|||
}
|
||||
} while (*locationList2++ != 0xFFFF);
|
||||
|
||||
if (duplicateLocation == true)
|
||||
if (duplicateLocation == true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rct_xy16 location = {
|
||||
.x = (*locationList & 0xFF) * 32,
|
||||
.y = ((*locationList >> 8) & 0xFF) * 32
|
||||
};
|
||||
|
||||
rct_map_element* mapElement = map_get_first_element_at(location.x / 32, location.y / 32);
|
||||
|
||||
rct_map_element *mapElement = map_get_first_element_at(location.x >> 5, location.y >> 5);
|
||||
do {
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.entrance.ride_index != rideIndex)
|
||||
continue;
|
||||
|
||||
// If its a park entrance
|
||||
if (mapElement->properties.entrance.type > ENTRANCE_TYPE_RIDE_EXIT)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE) continue;
|
||||
if (mapElement->properties.entrance.ride_index != rideIndex) continue;
|
||||
if (mapElement->properties.entrance.type > ENTRANCE_TYPE_RIDE_EXIT) continue;
|
||||
|
||||
rct_xy16 nextLocation = location;
|
||||
nextLocation.x += TileDirectionDelta[map_element_get_direction(mapElement)].x;
|
||||
nextLocation.y += TileDirectionDelta[map_element_get_direction(mapElement)].y;
|
||||
|
||||
bool shouldRemove = true;
|
||||
rct_map_element* trackElement = map_get_first_element_at(nextLocation.x / 32, nextLocation.y / 32);
|
||||
rct_map_element *trackElement = map_get_first_element_at(nextLocation.x >> 5, nextLocation.y >> 5);
|
||||
do {
|
||||
if (map_element_get_type(trackElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (trackElement->properties.track.ride_index != rideIndex)
|
||||
continue;
|
||||
|
||||
if (trackElement->base_height != mapElement->base_height)
|
||||
continue;
|
||||
if (map_element_get_type(trackElement) != MAP_ELEMENT_TYPE_TRACK) continue;
|
||||
if (trackElement->properties.track.ride_index != rideIndex) continue;
|
||||
if (trackElement->base_height != mapElement->base_height) continue;
|
||||
|
||||
uint32 edi = trackElement->properties.track.type * 16;
|
||||
edi |= trackElement->properties.track.sequence & 0xF;
|
||||
|
||||
uint8 direction = (map_element_get_direction(mapElement) - map_element_get_direction(trackElement) + 2) & 3;
|
||||
|
||||
if (!(RCT2_GLOBAL(0x0099BA64 + edi, uint32) & (1 << direction)))
|
||||
if (!(RCT2_GLOBAL(0x0099BA64 + edi, uint32) & (1 << direction))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8 stationId = 0;
|
||||
if (trackElement->properties.track.type != TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) {
|
||||
|
@ -7985,15 +7973,14 @@ void sub_6CB945(int rideIndex)
|
|||
}
|
||||
|
||||
if (mapElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_EXIT) {
|
||||
if (ride->exits[stationId] != 0xFFFF)
|
||||
if (ride->exits[stationId] != 0xFFFF) {
|
||||
break;
|
||||
|
||||
}
|
||||
ride->exits[stationId] = (location.x / 32) | ((location.y / 32) << 8);
|
||||
}
|
||||
else {
|
||||
if (ride->entrances[stationId] != 0xFFFF)
|
||||
} else {
|
||||
if (ride->entrances[stationId] != 0xFFFF) {
|
||||
break;
|
||||
|
||||
}
|
||||
ride->entrances[stationId] = (location.x / 32) | ((location.y / 32) << 8);
|
||||
}
|
||||
|
||||
|
@ -8615,3 +8602,14 @@ rct_vehicle *ride_get_broken_vehicle(rct_ride *ride) {
|
|||
|
||||
return vehicle;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D235B
|
||||
*/
|
||||
void ride_delete(uint8 rideIndex)
|
||||
{
|
||||
rct_ride *ride = get_ride(rideIndex);
|
||||
user_string_free(ride->name);
|
||||
ride->type = RIDE_TYPE_NULL;
|
||||
}
|
||||
|
|
|
@ -874,6 +874,7 @@ enum {
|
|||
/** Helper macros until rides are stored in this module. */
|
||||
rct_ride *get_ride(int index);
|
||||
rct_ride_entry *get_ride_entry(int index);
|
||||
void get_ride_entry_name(char *name, int index);
|
||||
rct_ride_measurement *get_ride_measurement(int index);
|
||||
|
||||
/**
|
||||
|
@ -983,6 +984,7 @@ void game_command_callback_ride_remove_track_piece(int eax, int ebx, int ecx, in
|
|||
void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
money32 ride_create_command(int type, int subType, int flags, uint8 *outRideIndex, uint8 *outRideColour);
|
||||
|
||||
void ride_clear_for_construction(int rideIndex);
|
||||
void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, int num_images);
|
||||
|
@ -1030,7 +1032,7 @@ void ride_get_entrance_or_exit_position_from_screen_position(int x, int y, int *
|
|||
bool ride_select_backwards_from_front();
|
||||
bool ride_select_forwards_from_back();
|
||||
|
||||
money32 ride_remove_track_piece(int x, int y, int z, int direction, int type);
|
||||
money32 ride_remove_track_piece(int x, int y, int z, int direction, int type, uint8 flags);
|
||||
|
||||
bool ride_are_all_possible_entrances_and_exits_built(rct_ride *ride);
|
||||
void ride_fix_breakdown(int rideIndex, int reliabilityIncreaseFactor);
|
||||
|
@ -1073,4 +1075,6 @@ void window_ride_construction_do_station_check();
|
|||
void window_ride_construction_do_entrance_exit_check();
|
||||
void game_command_callback_place_ride_entrance_or_exit(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);
|
||||
|
||||
void ride_delete(uint8 rideIndex);
|
||||
|
||||
#endif
|
||||
|
|
3802
src/ride/track.c
3802
src/ride/track.c
File diff suppressed because it is too large
Load Diff
170
src/ride/track.h
170
src/ride/track.h
|
@ -45,64 +45,19 @@ typedef struct {
|
|||
} rct_preview_track;
|
||||
|
||||
/* size 0x0A */
|
||||
typedef struct{
|
||||
typedef struct {
|
||||
sint8 rotation_begin; // 0x00
|
||||
sint8 rotation_end; // 0x01
|
||||
sint16 z_begin; // 0x02
|
||||
sint16 z_end; // 0x04
|
||||
sint16 x; // 0x06
|
||||
sint16 y; // 0x08
|
||||
}rct_track_coordinates;
|
||||
|
||||
/**
|
||||
* Size: 0x04
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
uint32 all;
|
||||
struct {
|
||||
sint8 x;
|
||||
sint8 y;
|
||||
union{
|
||||
uint16 maze_entry;
|
||||
struct{
|
||||
uint8 unk_2;
|
||||
uint8 type;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} rct_maze_element;
|
||||
|
||||
/* Size: 0x02 */
|
||||
typedef struct{
|
||||
uint8 type;
|
||||
uint8 flags;
|
||||
}rct_track_element;
|
||||
|
||||
/* Track Scenery entry size: 0x16 */
|
||||
typedef struct{
|
||||
rct_object_entry scenery_object; // 0x00
|
||||
sint8 x; // 0x10
|
||||
sint8 y; // 0x11
|
||||
sint8 z; // 0x12
|
||||
uint8 flags; // 0x13 direction quadrant tertiary colour
|
||||
uint8 primary_colour; // 0x14
|
||||
uint8 secondary_colour; // 0x15
|
||||
}rct_track_scenery;
|
||||
|
||||
/* Track Entrance entry size: 0x6 */
|
||||
typedef struct{
|
||||
sint8 z;
|
||||
uint8 direction; // 0x01
|
||||
sint16 x; // 0x02
|
||||
sint16 y; // 0x04
|
||||
}rct_track_entrance;
|
||||
} rct_track_coordinates;
|
||||
|
||||
enum{
|
||||
TRACK_ELEMENT_FLAG_CHAIN_LIFT = (1<<7),
|
||||
TRACK_ELEMENT_FLAG_INVERTED = (1<<6),
|
||||
TRACK_ELEMENT_FLAG_TERMINAL_STATION = (1<<3),
|
||||
TRACK_ELEMENT_FLAG_TERMINAL_STATION = 1 << 3,
|
||||
TRACK_ELEMENT_FLAG_INVERTED = 1 << 6,
|
||||
TRACK_ELEMENT_FLAG_CHAIN_LIFT = 1 << 7,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -115,86 +70,8 @@ enum {
|
|||
#define TRACK_ELEMENT_FLAG_COLOUR_MASK 0x30
|
||||
#define TRACK_ELEMENT_FLAG_STATION_NO_MASK 0x02
|
||||
|
||||
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
|
||||
|
||||
#define MAX_STATION_PLATFORM_LENGTH 32
|
||||
|
||||
/**
|
||||
* Track design structure.
|
||||
* size: 0x4E72B
|
||||
*/
|
||||
typedef struct {
|
||||
uint8 type; // 0x00
|
||||
uint8 vehicle_type;
|
||||
union{
|
||||
// After loading the track this is converted to
|
||||
// a cost but before its a flags register
|
||||
money32 cost; // 0x02
|
||||
uint32 flags; // 0x02
|
||||
};
|
||||
union{
|
||||
// After loading the track this is converted to
|
||||
// a flags register
|
||||
uint8 ride_mode; // 0x06
|
||||
uint8 track_flags; // 0x06
|
||||
};
|
||||
uint8 version_and_colour_scheme; // 0x07 0b0000_VVCC
|
||||
rct_vehicle_colour vehicle_colours[32]; // 0x08
|
||||
union{
|
||||
uint8 pad_48;
|
||||
uint8 track_spine_colour_rct1; // 0x48
|
||||
};
|
||||
union{
|
||||
uint8 entrance_style; // 0x49
|
||||
uint8 track_rail_colour_rct1; // 0x49
|
||||
};
|
||||
union{
|
||||
uint8 total_air_time; // 0x4A
|
||||
uint8 track_support_colour_rct1; // 0x4A
|
||||
};
|
||||
uint8 depart_flags; // 0x4B
|
||||
uint8 number_of_trains; // 0x4C
|
||||
uint8 number_of_cars_per_train; // 0x4D
|
||||
uint8 min_waiting_time; // 0x4E
|
||||
uint8 max_waiting_time; // 0x4F
|
||||
uint8 var_50;
|
||||
sint8 max_speed; // 0x51
|
||||
sint8 average_speed; // 0x52
|
||||
uint16 ride_length; // 0x53
|
||||
uint8 max_positive_vertical_g; // 0x55
|
||||
sint8 max_negative_vertical_g; // 0x56
|
||||
uint8 max_lateral_g; // 0x57
|
||||
union {
|
||||
uint8 inversions; // 0x58
|
||||
uint8 holes; // 0x58
|
||||
};
|
||||
uint8 drops; // 0x59
|
||||
uint8 highest_drop_height; // 0x5A
|
||||
uint8 excitement; // 0x5B
|
||||
uint8 intensity; // 0x5C
|
||||
uint8 nausea; // 0x5D
|
||||
money16 upkeep_cost; // 0x5E
|
||||
uint8 track_spine_colour[4]; // 0x60
|
||||
uint8 track_rail_colour[4]; // 0x64
|
||||
uint8 track_support_colour[4]; // 0x68
|
||||
uint32 flags2; // 0x6C
|
||||
rct_object_entry vehicle_object; // 0x70
|
||||
uint8 space_required_x; // 0x80
|
||||
uint8 space_required_y; // 0x81
|
||||
uint8 vehicle_additional_colour[32]; // 0x82
|
||||
uint8 lift_hill_speed_num_circuits; // 0xA2 0bCCCL_LLLL
|
||||
} rct_track_td6;
|
||||
|
||||
typedef struct{
|
||||
rct_track_td6 track_td6;
|
||||
uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3
|
||||
} rct_track_design;
|
||||
|
||||
enum {
|
||||
TRACK_FLAGS2_CONTAINS_LOG_FLUME_REVERSER = (1 << 1),
|
||||
TRACK_FLAGS2_SIX_FLAGS_RIDE_DEPRECATED = (1 << 31) // Not used anymore.
|
||||
};
|
||||
|
||||
enum {
|
||||
TRACK_NONE = 0,
|
||||
|
||||
|
@ -584,38 +461,12 @@ typedef struct {
|
|||
extern const rct_trackdefinition *gFlatRideTrackDefinitions;
|
||||
extern const rct_trackdefinition *gTrackDefinitions;
|
||||
|
||||
extern rct_map_element **gTrackSavedMapElements;
|
||||
|
||||
void track_load_list(ride_list_item item);
|
||||
int sub_67726A(const char *path);
|
||||
rct_track_design *track_get_info(int index, uint8** preview);
|
||||
rct_track_design *temp_track_get_info(char* path, uint8** preview);
|
||||
rct_track_td6* load_track_design(const char *path);
|
||||
int track_rename(const char *text);
|
||||
int track_delete();
|
||||
void track_mirror();
|
||||
void reset_track_list_cache();
|
||||
int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b);
|
||||
int sub_6D01B3(uint8 bl, uint8 rideIndex, int x, int y, int z);
|
||||
int save_track_design(uint8 rideIndex);
|
||||
int install_track(char* source_path, char* dest_name);
|
||||
void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool quotes);
|
||||
void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
void game_command_place_maze_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
|
||||
void track_save_reset_scenery();
|
||||
void track_save_select_nearby_scenery(int rideIndex);
|
||||
void track_save_toggle_map_element(int interactionType, int x, int y, rct_map_element *mapElement);
|
||||
|
||||
const rct_preview_track *get_track_def_from_ride(rct_ride *ride, int trackType);
|
||||
const rct_preview_track *get_track_def_from_ride_index(int rideIndex, int trackType);
|
||||
const rct_track_coordinates *get_track_coord_from_ride(rct_ride *ride, int trackType);
|
||||
|
||||
void game_command_place_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_remove_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_maze_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
|
||||
void track_circuit_iterator_begin(track_circuit_iterator *it, rct_xy_element first);
|
||||
bool track_circuit_iterator_previous(track_circuit_iterator *it);
|
||||
bool track_circuit_iterator_next(track_circuit_iterator *it);
|
||||
|
@ -623,9 +474,10 @@ bool track_circuit_iterator_next(track_circuit_iterator *it);
|
|||
void track_get_back(rct_xy_element *input, rct_xy_element *output);
|
||||
void track_get_front(rct_xy_element *input, rct_xy_element *output);
|
||||
|
||||
bool track_element_is_lift_hill(rct_map_element *trackElement);
|
||||
bool track_element_is_block_start(rct_map_element *trackElement);
|
||||
|
||||
bool track_element_is_covered(int trackElementType);
|
||||
bool track_element_is_station(rct_map_element *trackElement);
|
||||
bool track_element_is_lift_hill(rct_map_element *trackElement);
|
||||
bool track_element_is_cable_lift(rct_map_element *trackElement);
|
||||
void track_element_set_cable_lift(rct_map_element *trackElement);
|
||||
void track_element_clear_cable_lift(rct_map_element *trackElement);
|
||||
|
@ -634,7 +486,9 @@ int track_get_actual_bank(rct_map_element *mapElement, int bank);
|
|||
int track_get_actual_bank_2(int rideType, int trackColour, int bank);
|
||||
int track_get_actual_bank_3(rct_vehicle *vehicle, rct_map_element *mapElement);
|
||||
|
||||
bool track_element_is_station(rct_map_element *trackElement);
|
||||
bool track_element_is_covered(int trackElementType);
|
||||
void game_command_place_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_remove_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_maze_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,216 @@
|
|||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#ifndef _TRACK_DESIGN_H_
|
||||
#define _TRACK_DESIGN_H_
|
||||
|
||||
#include "../common.h"
|
||||
#include "../object.h"
|
||||
#include "../world/map.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
|
||||
|
||||
/* Maze Element entry size: 0x04 */
|
||||
typedef struct {
|
||||
union {
|
||||
uint32 all;
|
||||
struct {
|
||||
sint8 x;
|
||||
sint8 y;
|
||||
union {
|
||||
uint16 maze_entry;
|
||||
struct{
|
||||
uint8 unk_2;
|
||||
uint8 type;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} rct_td6_maze_element;
|
||||
|
||||
/* Track Element entry size: 0x02 */
|
||||
typedef struct {
|
||||
uint8 type; // 0x00
|
||||
uint8 flags; // 0x01
|
||||
} rct_td6_track_element;
|
||||
|
||||
/* Track Entrance entry size: 0x06 */
|
||||
typedef struct {
|
||||
sint8 z; // 0x00
|
||||
uint8 direction; // 0x01
|
||||
sint16 x; // 0x02
|
||||
sint16 y; // 0x04
|
||||
} rct_td6_entrance_element;
|
||||
|
||||
/* Track Scenery entry size: 0x16 */
|
||||
typedef struct {
|
||||
rct_object_entry scenery_object; // 0x00
|
||||
sint8 x; // 0x10
|
||||
sint8 y; // 0x11
|
||||
sint8 z; // 0x12
|
||||
uint8 flags; // 0x13 direction quadrant tertiary colour
|
||||
uint8 primary_colour; // 0x14
|
||||
uint8 secondary_colour; // 0x15
|
||||
} rct_td6_scenery_element;
|
||||
|
||||
/**
|
||||
* Track design structure.
|
||||
* size: 0x4E72B
|
||||
*/
|
||||
typedef struct {
|
||||
uint8 type; // 0x00
|
||||
uint8 vehicle_type;
|
||||
union{
|
||||
// After loading the track this is converted to
|
||||
// a cost but before its a flags register
|
||||
money32 cost; // 0x02
|
||||
uint32 flags; // 0x02
|
||||
};
|
||||
union{
|
||||
// After loading the track this is converted to
|
||||
// a flags register
|
||||
uint8 ride_mode; // 0x06
|
||||
uint8 track_flags; // 0x06
|
||||
};
|
||||
uint8 version_and_colour_scheme; // 0x07 0b0000_VVCC
|
||||
rct_vehicle_colour vehicle_colours[32]; // 0x08
|
||||
union{
|
||||
uint8 pad_48;
|
||||
uint8 track_spine_colour_rct1; // 0x48
|
||||
};
|
||||
union{
|
||||
uint8 entrance_style; // 0x49
|
||||
uint8 track_rail_colour_rct1; // 0x49
|
||||
};
|
||||
union{
|
||||
uint8 total_air_time; // 0x4A
|
||||
uint8 track_support_colour_rct1; // 0x4A
|
||||
};
|
||||
uint8 depart_flags; // 0x4B
|
||||
uint8 number_of_trains; // 0x4C
|
||||
uint8 number_of_cars_per_train; // 0x4D
|
||||
uint8 min_waiting_time; // 0x4E
|
||||
uint8 max_waiting_time; // 0x4F
|
||||
uint8 var_50;
|
||||
sint8 max_speed; // 0x51
|
||||
sint8 average_speed; // 0x52
|
||||
uint16 ride_length; // 0x53
|
||||
uint8 max_positive_vertical_g; // 0x55
|
||||
sint8 max_negative_vertical_g; // 0x56
|
||||
uint8 max_lateral_g; // 0x57
|
||||
union {
|
||||
uint8 inversions; // 0x58
|
||||
uint8 holes; // 0x58
|
||||
};
|
||||
uint8 drops; // 0x59
|
||||
uint8 highest_drop_height; // 0x5A
|
||||
uint8 excitement; // 0x5B
|
||||
uint8 intensity; // 0x5C
|
||||
uint8 nausea; // 0x5D
|
||||
money16 upkeep_cost; // 0x5E
|
||||
uint8 track_spine_colour[4]; // 0x60
|
||||
uint8 track_rail_colour[4]; // 0x64
|
||||
uint8 track_support_colour[4]; // 0x68
|
||||
uint32 flags2; // 0x6C
|
||||
rct_object_entry vehicle_object; // 0x70
|
||||
uint8 space_required_x; // 0x80
|
||||
uint8 space_required_y; // 0x81
|
||||
uint8 vehicle_additional_colour[32]; // 0x82
|
||||
uint8 lift_hill_speed_num_circuits; // 0xA2 0bCCCL_LLLL
|
||||
void *elements; // 0xA3 (data starts here in file)
|
||||
size_t elementsSize;
|
||||
|
||||
rct_td6_maze_element *maze_elements;
|
||||
rct_td6_track_element *track_elements;
|
||||
rct_td6_entrance_element *entrance_elements;
|
||||
rct_td6_scenery_element *scenery_elements;
|
||||
|
||||
utf8 *name;
|
||||
} rct_track_td6;
|
||||
|
||||
typedef struct{
|
||||
rct_track_td6 track_td6;
|
||||
uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3
|
||||
} rct_track_design;
|
||||
|
||||
typedef struct {
|
||||
utf8 *name;
|
||||
utf8 *path;
|
||||
} track_design_file_ref;
|
||||
|
||||
enum {
|
||||
TRACK_FLAGS2_CONTAINS_LOG_FLUME_REVERSER = (1 << 1),
|
||||
TRACK_FLAGS2_SIX_FLAGS_RIDE_DEPRECATED = (1 << 31) // Not used anymore.
|
||||
};
|
||||
|
||||
enum {
|
||||
TDPF_PLACE_SCENERY = 1 << 0,
|
||||
};
|
||||
|
||||
enum {
|
||||
PTD_OPERATION_DRAW_OUTLINES,
|
||||
PTD_OPERATION_1,
|
||||
PTD_OPERATION_2,
|
||||
PTD_OPERATION_GET_PLACE_Z,
|
||||
PTD_OPERATION_4,
|
||||
PTD_OPERATION_GET_COST,
|
||||
PTD_OPERATION_CLEAR_OUTLINES
|
||||
};
|
||||
|
||||
extern rct_track_td6 *gActiveTrackDesign;
|
||||
extern uint8 gTrackDesignPlaceFlags;
|
||||
extern bool gTrackDesignSceneryToggle;
|
||||
extern rct_xyz16 gTrackPreviewMin;
|
||||
extern rct_xyz16 gTrackPreviewMax;
|
||||
extern rct_xyz16 gTrackPreviewOrigin;
|
||||
|
||||
extern uint8 byte_F4414E;
|
||||
extern uint8 byte_9D8150;
|
||||
|
||||
rct_track_td6 *track_design_open(const utf8 *path);
|
||||
void track_design_dispose(rct_track_td6 *td6);
|
||||
|
||||
void track_design_mirror(rct_track_td6 *td6);
|
||||
|
||||
int sub_6D01B3(rct_track_td6 *td6, uint8 bl, uint8 rideIndex, int x, int y, int z);
|
||||
|
||||
void track_design_index_create();
|
||||
size_t track_design_index_get_count_for_ride(uint8 rideType, const char *entry);
|
||||
size_t track_design_index_get_for_ride(track_design_file_ref **tdRefs, uint8 rideType, const char *entry);
|
||||
utf8 *track_design_get_name_from_path(const utf8 *path);
|
||||
bool track_design_index_rename(const utf8 *path, const utf8 *newName);
|
||||
bool track_design_index_delete(const utf8 *path);
|
||||
bool track_design_index_install(const utf8 *srcPath, const utf8 *destPath);
|
||||
|
||||
void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
void game_command_place_maze_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Track design preview
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void track_design_draw_preview(rct_track_td6 *td6, uint8 *pixels);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Track design saving
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void track_design_save_init();
|
||||
void track_design_save_reset_scenery();
|
||||
void track_design_save_select_nearby_scenery(int rideIndex);
|
||||
void track_design_save_toggle_map_element(int interactionType, int x, int y, rct_map_element *mapElement);
|
||||
bool track_design_save(uint8 rideIndex);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,360 @@
|
|||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include "../common.h"
|
||||
#include "../config.h"
|
||||
#include "../game.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../localisation/string_ids.h"
|
||||
#include "../util/util.h"
|
||||
#include "track.h"
|
||||
#include "track_design.h"
|
||||
|
||||
typedef struct {
|
||||
uint8 ride_type;
|
||||
char ride_entry[9];
|
||||
utf8 path[MAX_PATH];
|
||||
} td_index_item;
|
||||
|
||||
static bool track_design_index_read_header(SDL_RWops *file, uint32 *tdidxCount);
|
||||
static void track_design_index_scan();
|
||||
static int track_design_index_item_compare(const void *a, const void *b);
|
||||
static void track_design_index_include(const utf8 *directory);
|
||||
static void track_design_add_file(const utf8 *path);
|
||||
static void track_design_add(const td_index_item *item);
|
||||
static void track_design_index_dispose();
|
||||
static void track_design_index_get_path(utf8 * buffer, size_t bufferLength);
|
||||
|
||||
static const uint32 TrackIndexMagicNumber = 0x58444954;
|
||||
static const uint16 TrackIndexVersion = 0;
|
||||
|
||||
static td_index_item *_tdIndex = NULL;
|
||||
static size_t _tdIndexSize = 0;
|
||||
static size_t _tdIndexCapacity = 0;
|
||||
|
||||
void track_design_index_create()
|
||||
{
|
||||
track_design_index_dispose();
|
||||
|
||||
log_verbose("saving track design index (tracks.idx)");
|
||||
|
||||
utf8 path[MAX_PATH];
|
||||
track_design_index_get_path(path, sizeof(path));
|
||||
|
||||
SDL_RWops *file = SDL_RWFromFile(path, "wb");
|
||||
if (file != NULL) {
|
||||
track_design_index_scan();
|
||||
|
||||
SDL_RWwrite(file, &TrackIndexMagicNumber, sizeof(TrackIndexMagicNumber), 1);
|
||||
SDL_RWwrite(file, &TrackIndexVersion, sizeof(TrackIndexVersion), 1);
|
||||
SDL_RWwrite(file, &_tdIndexSize, sizeof(uint32), 1);
|
||||
SDL_RWwrite(file, _tdIndex, sizeof(td_index_item), _tdIndexSize);
|
||||
SDL_RWclose(file);
|
||||
track_design_index_dispose();
|
||||
}
|
||||
}
|
||||
|
||||
size_t track_design_index_get_count_for_ride(uint8 rideType, const char *entry)
|
||||
{
|
||||
log_verbose("reading track design index (tracks.idx)");
|
||||
|
||||
utf8 path[MAX_PATH];
|
||||
track_design_index_get_path(path, sizeof(path));
|
||||
|
||||
// Return list
|
||||
size_t refsCount = 0;
|
||||
SDL_RWops *file = SDL_RWFromFile(path, "rb");
|
||||
if (file != NULL) {
|
||||
uint32 tdidxCount;
|
||||
if (!track_design_index_read_header(file, &tdidxCount)) {
|
||||
SDL_RWclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < tdidxCount; i++) {
|
||||
td_index_item tdItem;
|
||||
SDL_RWread(file, &tdItem, sizeof(td_index_item), 1);
|
||||
|
||||
if (tdItem.ride_type != rideType) continue;
|
||||
if (entry != NULL && _strcmpi(entry, tdItem.ride_entry) != 0) continue;
|
||||
refsCount++;
|
||||
}
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
|
||||
return refsCount;
|
||||
}
|
||||
|
||||
size_t track_design_index_get_for_ride(track_design_file_ref **tdRefs, uint8 rideType, const char *entry)
|
||||
{
|
||||
log_verbose("reading track design index (tracks.idx)");
|
||||
|
||||
utf8 path[MAX_PATH];
|
||||
track_design_index_get_path(path, sizeof(path));
|
||||
|
||||
// Return list
|
||||
size_t refsCount = 0;
|
||||
size_t refsCapacity = 0;
|
||||
track_design_file_ref *refs = NULL;
|
||||
|
||||
SDL_RWops *file = SDL_RWFromFile(path, "rb");
|
||||
if (file != NULL) {
|
||||
uint32 tdidxCount;
|
||||
if (!track_design_index_read_header(file, &tdidxCount)) {
|
||||
SDL_RWclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < tdidxCount; i++) {
|
||||
td_index_item tdItem;
|
||||
SDL_RWread(file, &tdItem, sizeof(td_index_item), 1);
|
||||
|
||||
if (tdItem.ride_type != rideType) continue;
|
||||
if (entry != NULL && _strcmpi(entry, tdItem.ride_entry) != 0) continue;
|
||||
|
||||
size_t nextIndex = refsCount;
|
||||
if (nextIndex >= refsCapacity) {
|
||||
refsCapacity = max(8, refsCapacity * 2);
|
||||
refs = realloc(refs, refsCapacity * sizeof(track_design_file_ref));
|
||||
if (refs == NULL) {
|
||||
log_fatal("Unable to allocate more memory.");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
refs[nextIndex].name = track_design_get_name_from_path(tdItem.path);
|
||||
refs[nextIndex].path = _strdup(tdItem.path);
|
||||
refsCount++;
|
||||
}
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
|
||||
*tdRefs = realloc(refs, refsCount * sizeof(track_design_file_ref));
|
||||
return refsCount;
|
||||
}
|
||||
|
||||
utf8 *track_design_get_name_from_path(const utf8 *path)
|
||||
{
|
||||
const char *filename = path_get_filename(path);
|
||||
const char *lastDot = strrchr(filename, '.');
|
||||
size_t nameLength;
|
||||
if (lastDot == NULL) {
|
||||
nameLength = strlen(filename);
|
||||
} else {
|
||||
nameLength = (size_t)(lastDot - filename);
|
||||
}
|
||||
return strndup(filename, nameLength);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D3664
|
||||
*/
|
||||
bool track_design_index_rename(const utf8 *path, const utf8 *newName)
|
||||
{
|
||||
if (str_is_null_or_empty(newName)) {
|
||||
gGameCommandErrorText = STR_CANT_RENAME_TRACK_DESIGN;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filename_valid_characters(newName)) {
|
||||
gGameCommandErrorText = STR_NEW_NAME_CONTAINS_INVALID_CHARACTERS;
|
||||
return false;
|
||||
}
|
||||
|
||||
utf8 newPath[MAX_PATH];
|
||||
const char *lastPathSep = strrchr(path, platform_get_path_separator());
|
||||
if (lastPathSep == NULL) {
|
||||
gGameCommandErrorText = STR_CANT_RENAME_TRACK_DESIGN;
|
||||
return false;
|
||||
}
|
||||
size_t directoryLength = (size_t)(lastPathSep - path + 1);
|
||||
memcpy(newPath, path, directoryLength);
|
||||
strcpy(newPath + directoryLength, newName);
|
||||
strcat(newPath, ".td6");
|
||||
|
||||
if (!platform_file_move(path, newPath)) {
|
||||
gGameCommandErrorText = STR_ANOTHER_FILE_EXISTS_WITH_NAME_OR_FILE_IS_WRITE_PROTECTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
track_design_index_create();
|
||||
|
||||
rct_window *trackListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackListWindow != NULL) {
|
||||
trackListWindow->track_list.reload_track_designs = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D3761
|
||||
*/
|
||||
bool track_design_index_delete(const utf8 *path)
|
||||
{
|
||||
if (!platform_file_delete(path)) {
|
||||
gGameCommandErrorText = STR_FILE_IS_WRITE_PROTECTED_OR_LOCKED;
|
||||
return false;
|
||||
}
|
||||
|
||||
track_design_index_create();
|
||||
|
||||
rct_window *trackListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackListWindow != NULL) {
|
||||
trackListWindow->track_list.reload_track_designs = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D40B2
|
||||
*/
|
||||
bool track_design_index_install(const utf8 *srcPath, const utf8 *destPath)
|
||||
{
|
||||
if (!platform_file_copy(srcPath, destPath, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
track_design_index_create();
|
||||
|
||||
rct_window *trackListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackListWindow != NULL) {
|
||||
trackListWindow->track_list.reload_track_designs = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool track_design_index_read_header(SDL_RWops *file, uint32 *tdidxCount)
|
||||
{
|
||||
uint32 tdidxMagicNumber;
|
||||
uint16 tdidxVersion;
|
||||
SDL_RWread(file, &tdidxMagicNumber, sizeof(tdidxMagicNumber), 1);
|
||||
SDL_RWread(file, &tdidxVersion, sizeof(tdidxVersion), 1);
|
||||
SDL_RWread(file, tdidxCount, sizeof(uint32), 1);
|
||||
if (tdidxMagicNumber != TrackIndexMagicNumber) {
|
||||
log_error("invalid track index file");
|
||||
return false;
|
||||
}
|
||||
if (tdidxVersion != TrackIndexVersion) {
|
||||
log_error("unsupported track index file version");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void track_design_index_scan()
|
||||
{
|
||||
utf8 directory[MAX_PATH];
|
||||
|
||||
// Get track directory from RCT2
|
||||
safe_strcpy(directory, gConfigGeneral.game_path, sizeof(directory));
|
||||
safe_strcat_path(directory, "Tracks", sizeof(directory));
|
||||
track_design_index_include(directory);
|
||||
|
||||
// Get track directory from user directory
|
||||
platform_get_user_directory(directory, "track");
|
||||
track_design_index_include(directory);
|
||||
|
||||
// Sort items by ride type then by filename
|
||||
qsort(_tdIndex, _tdIndexSize, sizeof(td_index_item), track_design_index_item_compare);
|
||||
}
|
||||
|
||||
static int track_design_index_item_compare(const void *a, const void *b)
|
||||
{
|
||||
const td_index_item *tdA = (const td_index_item*)a;
|
||||
const td_index_item *tdB = (const td_index_item*)b;
|
||||
|
||||
if (tdA->ride_type != tdB->ride_type) {
|
||||
return tdA->ride_type - tdB->ride_type;
|
||||
}
|
||||
|
||||
const utf8 *tdAName = path_get_filename(tdA->path);
|
||||
const utf8 *tdBName = path_get_filename(tdB->path);
|
||||
return _stricmp(tdAName, tdBName);
|
||||
}
|
||||
|
||||
static void track_design_index_include(const utf8 *directory)
|
||||
{
|
||||
int handle;
|
||||
file_info fileInfo;
|
||||
|
||||
// Scenarios in this directory
|
||||
utf8 pattern[MAX_PATH];
|
||||
safe_strcpy(pattern, directory, sizeof(pattern));
|
||||
safe_strcat_path(pattern, "*.td6", sizeof(pattern));
|
||||
|
||||
handle = platform_enumerate_files_begin(pattern);
|
||||
while (platform_enumerate_files_next(handle, &fileInfo)) {
|
||||
utf8 path[MAX_PATH];
|
||||
safe_strcpy(path, directory, sizeof(pattern));
|
||||
safe_strcat_path(path, fileInfo.path, sizeof(pattern));
|
||||
track_design_add_file(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_strcpy(path, directory, sizeof(pattern));
|
||||
safe_strcat_path(path, subDirectory, sizeof(pattern));
|
||||
track_design_index_include(path);
|
||||
}
|
||||
platform_enumerate_directories_end(handle);
|
||||
}
|
||||
|
||||
static void track_design_add_file(const utf8 *path)
|
||||
{
|
||||
rct_track_td6 *td6 = track_design_open(path);
|
||||
if (td6 != NULL) {
|
||||
td_index_item tdIndexItem = { 0 };
|
||||
safe_strcpy(tdIndexItem.path, path, sizeof(tdIndexItem.path));
|
||||
memcpy(tdIndexItem.ride_entry, td6->vehicle_object.name, 8);
|
||||
tdIndexItem.ride_type = td6->type;
|
||||
track_design_add(&tdIndexItem);
|
||||
track_design_dispose(td6);
|
||||
}
|
||||
}
|
||||
|
||||
static void track_design_add(const td_index_item *item)
|
||||
{
|
||||
size_t nextIndex = _tdIndexSize;
|
||||
if (nextIndex >= _tdIndexCapacity) {
|
||||
_tdIndexCapacity = max(128, _tdIndexCapacity * 2);
|
||||
_tdIndex = realloc(_tdIndex, _tdIndexCapacity * sizeof(td_index_item));
|
||||
if (_tdIndex == NULL) {
|
||||
log_fatal("Unable to allocate more memory.");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
_tdIndex[nextIndex] = *item;
|
||||
_tdIndexSize++;
|
||||
}
|
||||
|
||||
static void track_design_index_dispose()
|
||||
{
|
||||
SafeFree(_tdIndex);
|
||||
_tdIndexSize = 0;
|
||||
_tdIndexCapacity = 0;
|
||||
}
|
||||
|
||||
static void track_design_index_get_path(utf8 * buffer, size_t bufferLength)
|
||||
{
|
||||
platform_get_user_directory(buffer, NULL);
|
||||
safe_strcat(buffer, "tracks.idx", bufferLength);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,7 @@
|
|||
#include "../ride/ride.h"
|
||||
#include "../ride/ride_data.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../scenario.h"
|
||||
#include "../util/util.h"
|
||||
#include "../world/footpath.h"
|
||||
|
@ -1961,7 +1962,7 @@ static void window_editor_object_selection_manage_tracks()
|
|||
RCT2_GLOBAL(0xF44158, uint8) = ride_type;
|
||||
|
||||
ride_list_item item = { ride_type, entry_index };
|
||||
track_load_list(item);
|
||||
// track_load_list(item);
|
||||
window_track_list_open(item);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,14 +17,16 @@
|
|||
#include "../addresses.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../editor.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../interface/themes.h"
|
||||
#include "../interface/widget.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../ride/ride.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../sprites.h"
|
||||
#include "../util/util.h"
|
||||
#include "error.h"
|
||||
#include "../interface/themes.h"
|
||||
|
||||
enum {
|
||||
WIDX_BACKGROUND,
|
||||
|
@ -86,127 +88,71 @@ static rct_window_event_list window_install_track_events = {
|
|||
NULL
|
||||
};
|
||||
|
||||
ride_list_item _window_install_track_item;
|
||||
static rct_track_td6 *_trackDesign;
|
||||
static utf8 *_trackPath;
|
||||
static utf8 *_trackName;
|
||||
static uint8 *_trackDesignPreviewPixels;
|
||||
|
||||
char track_dest_name[MAX_PATH];
|
||||
char track_path[MAX_PATH];
|
||||
static void window_install_track_update_preview();
|
||||
static void window_install_track_design(rct_window *w);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D386D
|
||||
*/
|
||||
void window_install_track_open(const char* path)
|
||||
void window_install_track_open(const utf8 *path)
|
||||
{
|
||||
rct_window *w;
|
||||
int x, y;
|
||||
void *mem;
|
||||
_trackDesign = track_design_open(path);
|
||||
if (_trackDesign == NULL) {
|
||||
window_error_open(3010, STR_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
object_unload_all();
|
||||
if (_trackDesign->type == RIDE_TYPE_NULL){
|
||||
log_error("Failed to load track (ride type null): %s", path);
|
||||
return;
|
||||
}
|
||||
if (!object_load_chunk(0, &_trackDesign->vehicle_object, NULL)){
|
||||
log_error("Failed to load track (vehicle load fail): %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
window_close_by_class(WC_EDITOR_OBJECT_SELECTION);
|
||||
|
||||
window_close_construction_windows();
|
||||
ride_list_item item = {
|
||||
.type = 0xFF,
|
||||
.entry_index = 0
|
||||
};
|
||||
_window_install_track_item = item;
|
||||
|
||||
mem = malloc(1285292);
|
||||
if (mem == NULL)
|
||||
return;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*) = mem;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 0;
|
||||
gTrackDesignSceneryToggle = false;
|
||||
_currentTrackPieceDirection = 2;
|
||||
reset_track_list_cache();
|
||||
|
||||
x = gScreenWidth / 2 - 201;
|
||||
y = max(28, gScreenHeight / 2 - 200);
|
||||
int x = gScreenWidth / 2 - 201;
|
||||
int y = max(28, gScreenHeight / 2 - 200);
|
||||
|
||||
w = window_create(x, y, 402, 400, &window_install_track_events, WC_INSTALL_TRACK, 0);
|
||||
rct_window *w = window_create(x, y, 402, 400, &window_install_track_events, WC_INSTALL_TRACK, 0);
|
||||
w->widgets = window_install_track_widgets;
|
||||
w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY) | (1 << WIDX_INSTALL) | (1 << WIDX_CANCEL);
|
||||
window_init_scroll_widgets(w);
|
||||
w->track_list.var_482 = 0;
|
||||
w->track_list.var_484 = 0;
|
||||
window_push_others_right(w);
|
||||
|
||||
strncpy(track_path, path, MAX_PATH);
|
||||
track_path[MAX_PATH - 1] = '\0';
|
||||
|
||||
char* track_name_pointer = strrchr(track_path, platform_get_path_separator());
|
||||
track_name_pointer++;
|
||||
|
||||
strncpy(track_dest_name, track_name_pointer, MAX_PATH);
|
||||
track_dest_name[MAX_PATH - 1] = '\0';
|
||||
_trackPath = _strdup(path);
|
||||
_trackName = track_design_get_name_from_path(path);
|
||||
_trackDesignPreviewPixels = calloc(4, TRACK_PREVIEW_IMAGE_SIZE);
|
||||
|
||||
window_install_track_update_preview();
|
||||
window_invalidate(w);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CFB82
|
||||
*/
|
||||
static void window_install_track_select(rct_window *w, int index)
|
||||
{
|
||||
utf8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, utf8);
|
||||
rct_track_design *trackDesign;
|
||||
|
||||
w->track_list.var_480 = index;
|
||||
|
||||
audio_play_sound_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && index == 0) {
|
||||
window_close(w);
|
||||
ride_construct_new(_window_install_track_item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (RCT2_GLOBAL(0x00F44153, uint8) != 0)
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 1;
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER))
|
||||
index--;
|
||||
|
||||
trackDesignItem = trackDesignList + (index * 128);
|
||||
RCT2_GLOBAL(0x00F4403C, utf8*) = trackDesignItem;
|
||||
|
||||
window_track_list_format_name(
|
||||
(char*)0x009BC313,
|
||||
trackDesignItem,
|
||||
gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ?
|
||||
0 :
|
||||
FORMAT_WHITE,
|
||||
1);
|
||||
|
||||
char track_path[MAX_PATH] = { 0 };
|
||||
substitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
|
||||
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
window_track_manage_open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!load_track_design(track_path)) {
|
||||
w->track_list.var_480 = 0xFFFF;
|
||||
window_invalidate(w);
|
||||
return;
|
||||
}
|
||||
|
||||
trackDesign = track_get_info(index, NULL);
|
||||
if (trackDesign == NULL) return;
|
||||
if (trackDesign->track_td6.track_flags & 4)
|
||||
window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1);
|
||||
|
||||
window_close(w);
|
||||
window_track_place_open();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D41DC
|
||||
*/
|
||||
static void window_install_track_close(rct_window *w)
|
||||
{
|
||||
free(RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*));
|
||||
SafeFree(_trackPath);
|
||||
SafeFree(_trackName);
|
||||
SafeFree(_trackDesignPreviewPixels);
|
||||
track_design_dispose(_trackDesign);
|
||||
_trackDesign = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,8 +161,6 @@ static void window_install_track_close(rct_window *w)
|
|||
*/
|
||||
static void window_install_track_mouseup(rct_window *w, int widgetIndex)
|
||||
{
|
||||
int result;
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_CLOSE:
|
||||
case WIDX_CANCEL:
|
||||
|
@ -228,24 +172,12 @@ static void window_install_track_mouseup(rct_window *w, int widgetIndex)
|
|||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_TOGGLE_SCENERY:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) ^= 1;
|
||||
reset_track_list_cache();
|
||||
gTrackDesignSceneryToggle = !gTrackDesignSceneryToggle;
|
||||
window_install_track_update_preview();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_INSTALL:
|
||||
result = install_track(track_path, track_dest_name);
|
||||
|
||||
if (result == 1)
|
||||
window_close(w);
|
||||
else if(result == 0){
|
||||
window_error_open(3380, 3382);
|
||||
window_close(w);
|
||||
}
|
||||
else{
|
||||
// Copy the track name into the string buffer.
|
||||
window_track_list_format_name(RCT2_ADDRESS(0x009BC677, char), track_dest_name, 0, 0);
|
||||
window_text_input_open(w, WIDX_INSTALL, 3383, 3384, 3165, 0, 255);
|
||||
}
|
||||
window_install_track_design(w);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -260,17 +192,17 @@ static void window_install_track_invalidate(rct_window *w)
|
|||
colour_scheme_update(w);
|
||||
|
||||
w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0)
|
||||
if (!gTrackDesignSceneryToggle) {
|
||||
w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
|
||||
else
|
||||
} else {
|
||||
w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
|
||||
}
|
||||
|
||||
if (w->track_list.var_482 != 0xFFFF) {
|
||||
w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
|
||||
}
|
||||
else {
|
||||
w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
|
||||
}
|
||||
// if (w->track_list.var_482 != 0xFFFF) {
|
||||
// w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
|
||||
// } else {
|
||||
// w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,36 +211,18 @@ static void window_install_track_invalidate(rct_window *w)
|
|||
*/
|
||||
static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
||||
{
|
||||
rct_widget *widget;
|
||||
rct_track_design *trackDesign = NULL;
|
||||
uint8 *image, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
|
||||
uint16 holes, speed, drops, dropHeight, inversions;
|
||||
fixed32_2dp rating;
|
||||
int x, y, colour, gForces, airTime;
|
||||
rct_g1_element tmpElement, *substituteElement;
|
||||
|
||||
window_draw_widgets(w, dpi);
|
||||
|
||||
if (w->track_list.var_482 == 0xFFFF)
|
||||
return;
|
||||
|
||||
// Track preview
|
||||
widget = &window_install_track_widgets[WIDX_TRACK_PREVIEW];
|
||||
x = w->x + widget->left + 1;
|
||||
y = w->y + widget->top + 1;
|
||||
colour = ColourMapA[w->colours[0]].darkest;
|
||||
rct_widget *widget = &window_install_track_widgets[WIDX_TRACK_PREVIEW];
|
||||
int x = w->x + widget->left + 1;
|
||||
int y = w->y + widget->top + 1;
|
||||
int colour = ColourMapA[w->colours[0]].darkest;
|
||||
gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);
|
||||
|
||||
//call 6d3993 (load track)
|
||||
trackDesign = temp_track_get_info(track_path, &image);
|
||||
if (trackDesign == NULL)
|
||||
return;
|
||||
|
||||
rct_track_td6* track_td6 = &trackDesign->track_td6;
|
||||
|
||||
substituteElement = &g1Elements[0];
|
||||
tmpElement = *substituteElement;
|
||||
substituteElement->offset = image;
|
||||
rct_g1_element *substituteElement = &g1Elements[0];
|
||||
rct_g1_element tmpElement = *substituteElement;
|
||||
substituteElement->offset = _trackDesignPreviewPixels + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
|
||||
substituteElement->width = 370;
|
||||
substituteElement->height = 217;
|
||||
substituteElement->x_offset = 0;
|
||||
|
@ -323,9 +237,10 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
RCT2_GLOBAL(0x00F44153, uint8) = 0;
|
||||
|
||||
// Warnings
|
||||
if (track_td6->track_flags & 1) {
|
||||
rct_track_td6 *td6 = _trackDesign;
|
||||
if (td6->track_flags & 1) {
|
||||
RCT2_GLOBAL(0x00F44153, uint8) = 1;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0) {
|
||||
if (!gTrackDesignSceneryToggle) {
|
||||
// Scenery not available
|
||||
gfx_draw_string_centred_clipped(dpi, STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE, NULL, 0, x, y, 368);
|
||||
y -= 10;
|
||||
|
@ -333,8 +248,7 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
}
|
||||
|
||||
// Track design name
|
||||
window_track_list_format_name((char*)0x009BC677, (char*)0x009E3504, FORMAT_WINDOW_COLOUR_1, 1);
|
||||
gfx_draw_string_centred_clipped(dpi, 3165, NULL, 0, x, y, 368);
|
||||
gfx_draw_string_centred_clipped(dpi, STR_TRACK_PREVIEW_NAME_FORMAT, &_trackName, 0, x, y, 368);
|
||||
|
||||
// Information
|
||||
x = w->x + widget->left + 1;
|
||||
|
@ -342,85 +256,85 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
// 0x006D3CF1 -- 0x006d3d71 missing
|
||||
|
||||
// Stats
|
||||
rating = track_td6->excitement * 10;
|
||||
fixed32_2dp rating = td6->excitement * 10;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
rating = track_td6->intensity * 10;
|
||||
rating = td6->intensity * 10;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
rating = track_td6->nausea * 10;
|
||||
rating = td6->nausea * 10;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_NAUSEA_RATING, &rating, 0, x, y);
|
||||
y += 14;
|
||||
|
||||
if (track_td6->type != RIDE_TYPE_MAZE) {
|
||||
if (track_td6->type == RIDE_TYPE_MINI_GOLF) {
|
||||
if (td6->type != RIDE_TYPE_MAZE) {
|
||||
if (td6->type == RIDE_TYPE_MINI_GOLF) {
|
||||
// Holes
|
||||
holes = track_td6->holes & 0x1F;
|
||||
uint16 holes = td6->holes & 0x1F;
|
||||
gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
else {
|
||||
// Maximum speed
|
||||
speed = ((track_td6->max_speed << 16) * 9) >> 18;
|
||||
uint16 speed = ((td6->max_speed << 16) * 9) >> 18;
|
||||
gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Average speed
|
||||
speed = ((track_td6->average_speed << 16) * 9) >> 18;
|
||||
speed = ((td6->average_speed << 16) * 9) >> 18;
|
||||
gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &speed, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
// Ride length
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 1345;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->ride_length;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = td6->ride_length;
|
||||
gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, 214);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
if (ride_type_has_flag(track_td6->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
|
||||
if (ride_type_has_flag(td6->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
|
||||
// Maximum positive vertical Gs
|
||||
gForces = track_td6->max_positive_vertical_g * 32;
|
||||
int gForces = td6->max_positive_vertical_g * 32;
|
||||
gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Maximum negative verical Gs
|
||||
gForces = track_td6->max_negative_vertical_g * 32;
|
||||
gForces = td6->max_negative_vertical_g * 32;
|
||||
gfx_draw_string_left(dpi, STR_MAX_NEGATIVE_VERTICAL_G, &gForces, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Maximum lateral Gs
|
||||
gForces = track_td6->max_lateral_g * 32;
|
||||
gForces = td6->max_lateral_g * 32;
|
||||
gfx_draw_string_left(dpi, STR_MAX_LATERAL_G, &gForces, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// If .TD6
|
||||
if (track_td6->version_and_colour_scheme / 4 >= 2) {
|
||||
if (track_td6->total_air_time != 0) {
|
||||
if (td6->version_and_colour_scheme / 4 >= 2) {
|
||||
if (td6->total_air_time != 0) {
|
||||
// Total air time
|
||||
airTime = track_td6->total_air_time * 25;
|
||||
int airTime = td6->total_air_time * 25;
|
||||
gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &airTime, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ride_type_has_flag(track_td6->type, RIDE_TYPE_FLAG_HAS_DROPS)) {
|
||||
if (ride_type_has_flag(td6->type, RIDE_TYPE_FLAG_HAS_DROPS)) {
|
||||
// Drops
|
||||
drops = track_td6->drops & 0x3F;
|
||||
uint16 drops = td6->drops & 0x3F;
|
||||
gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Drop height is multiplied by 0.75
|
||||
dropHeight = (track_td6->highest_drop_height + (track_td6->highest_drop_height / 2)) / 2;
|
||||
uint16 dropHeight = (td6->highest_drop_height + (td6->highest_drop_height / 2)) / 2;
|
||||
gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &drops, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
if (track_td6->type != RIDE_TYPE_MINI_GOLF) {
|
||||
inversions = track_td6->inversions & 0x1F;
|
||||
if (td6->type != RIDE_TYPE_MINI_GOLF) {
|
||||
uint16 inversions = td6->inversions & 0x1F;
|
||||
if (inversions != 0) {
|
||||
// Inversions
|
||||
gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, 0, x, y);
|
||||
|
@ -429,16 +343,16 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
}
|
||||
y += 4;
|
||||
|
||||
if (track_td6->space_required_x != 0xFF) {
|
||||
if (td6->space_required_x != 0xFF) {
|
||||
// Space required
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = track_td6->space_required_x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->space_required_y;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = td6->space_required_x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = td6->space_required_y;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
if (track_td6->cost != 0) {
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &track_td6->cost, 0, x, y);
|
||||
if (td6->cost != 0) {
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &td6->cost, 0, x, y);
|
||||
y += 14;
|
||||
}
|
||||
}
|
||||
|
@ -449,17 +363,51 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
*/
|
||||
static void window_install_track_text_input(rct_window *w, int widgetIndex, char *text)
|
||||
{
|
||||
if (text == NULL) {
|
||||
window_close(w);
|
||||
if (widgetIndex != WIDX_INSTALL || str_is_null_or_empty(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (widgetIndex == WIDX_INSTALL) {
|
||||
char* extension_pointer = track_dest_name;
|
||||
while (*extension_pointer++ != '.');
|
||||
--extension_pointer;
|
||||
strcat(text, extension_pointer);
|
||||
strcpy(track_dest_name, text);
|
||||
window_event_mouse_up_call(w, WIDX_INSTALL);
|
||||
free(_trackName);
|
||||
_trackName = _strdup(text);
|
||||
|
||||
window_event_mouse_up_call(w, WIDX_INSTALL);
|
||||
}
|
||||
|
||||
static void window_install_track_update_preview()
|
||||
{
|
||||
track_design_draw_preview(_trackDesign, _trackDesignPreviewPixels);
|
||||
}
|
||||
|
||||
static void window_install_track_design(rct_window *w)
|
||||
{
|
||||
utf8 destPath[MAX_PATH];
|
||||
|
||||
platform_get_user_directory(destPath, "track");
|
||||
if (!platform_ensure_directory_exists(destPath)) {
|
||||
log_error("Unable to create directory '%s'", destPath);
|
||||
window_error_open(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
strcat(destPath, _trackName);
|
||||
strcat(destPath, ".td6");
|
||||
|
||||
if (platform_file_exists(destPath)) {
|
||||
log_info("%s already exists, prompting user for a different track design name", destPath);
|
||||
window_error_open(STR_UNABLE_TO_INSTALL_THIS_TRACK_DESIGN, STR_NONE);
|
||||
window_text_input_raw_open(
|
||||
w,
|
||||
WIDX_INSTALL,
|
||||
STR_SELECT_NEW_NAME_FOR_TRACK_DESIGN,
|
||||
STR_AN_EXISTING_TRACK_DESIGN_ALREADY_HAS_THIS_NAME,
|
||||
_trackName,
|
||||
255
|
||||
);
|
||||
} else {
|
||||
if (track_design_index_install(_trackPath, destPath)) {
|
||||
window_close(w);
|
||||
} else {
|
||||
window_error_open(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "../rct1.h"
|
||||
#include "../ride/ride.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../world/scenery.h"
|
||||
#include "../ride/ride_data.h"
|
||||
|
||||
|
@ -841,15 +842,17 @@ static ride_list_item window_new_ride_scroll_get_ride_list_item_at(rct_window *w
|
|||
|
||||
static int get_num_track_designs(ride_list_item item)
|
||||
{
|
||||
track_load_list(item);
|
||||
|
||||
char *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char);
|
||||
int count = 0;
|
||||
while (*trackDesignList != 0 && trackDesignList < (char*)0x00F635EC) {
|
||||
trackDesignList += 128;
|
||||
count++;
|
||||
char entry[9];
|
||||
const char *entryPtr = NULL;
|
||||
if (item.type < 0x80) {
|
||||
rct_ride_entry *rideEntry = get_ride_entry(item.entry_index);
|
||||
if ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) && !rideTypeShouldLoseSeparateFlag(rideEntry)) {
|
||||
get_ride_entry_name(entry, item.entry_index);
|
||||
entryPtr = entry;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
return track_design_index_get_count_for_ride(item.type, entryPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -942,10 +945,7 @@ static void window_new_ride_select(rct_window *w)
|
|||
#endif
|
||||
|
||||
if (allowTrackDesigns && ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_TRACK)) {
|
||||
track_load_list(item);
|
||||
|
||||
char *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char);
|
||||
if (*trackDesignList != 0) {
|
||||
if (_lastTrackDesignCount > 0) {
|
||||
window_track_list_open(item);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "../ride/ride.h"
|
||||
#include "../ride/ride_data.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../sprites.h"
|
||||
#include "../windows/error.h"
|
||||
#include "../world/map.h"
|
||||
|
@ -4629,7 +4630,8 @@ static void cancel_scenery_selection(){
|
|||
*
|
||||
* rct2: 0x006D27A3
|
||||
*/
|
||||
static void setup_scenery_selection(rct_window* w){
|
||||
static void setup_scenery_selection(rct_window* w)
|
||||
{
|
||||
rct_ride* ride = get_ride(w->number);
|
||||
|
||||
if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1){
|
||||
|
@ -4639,9 +4641,8 @@ static void setup_scenery_selection(rct_window* w){
|
|||
while (tool_set(w, 0, 12));
|
||||
|
||||
RCT2_GLOBAL(0x00F64DE8, uint8) = (uint8)w->number;
|
||||
RCT2_GLOBAL(0x009DA193, uint8) = 0xFF;
|
||||
|
||||
gTrackSavedMapElements[0] = (rct_map_element*)-1;
|
||||
track_design_save_init();
|
||||
gGamePaused |= GAME_PAUSED_SAVING_TRACK;
|
||||
RCT2_GLOBAL(0x009DEA6F, uint8) |= 1;
|
||||
|
||||
|
@ -4662,7 +4663,7 @@ static void setup_scenery_selection(rct_window* w){
|
|||
*/
|
||||
static void window_ride_measurements_design_reset()
|
||||
{
|
||||
track_save_reset_scenery();
|
||||
track_design_save_reset_scenery();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4671,7 +4672,7 @@ static void window_ride_measurements_design_reset()
|
|||
*/
|
||||
static void window_ride_measurements_design_select_nearby_scenery()
|
||||
{
|
||||
track_save_select_nearby_scenery(RCT2_GLOBAL(0x00F64DE8, uint8));
|
||||
track_design_save_select_nearby_scenery(RCT2_GLOBAL(0x00F64DE8, uint8));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4690,7 +4691,7 @@ static void window_ride_measurements_design_cancel()
|
|||
*/
|
||||
static void window_ride_measurements_design_save(rct_window *w)
|
||||
{
|
||||
if (save_track_design((uint8)w->number) == 0) return;
|
||||
if (track_design_save((uint8)w->number) == 0) return;
|
||||
|
||||
window_ride_measurements_design_cancel();
|
||||
}
|
||||
|
@ -4790,7 +4791,7 @@ static void window_ride_measurements_dropdown(rct_window *w, int widgetIndex, in
|
|||
dropdownIndex = gDropdownHighlightedIndex;
|
||||
|
||||
if (dropdownIndex == 0)
|
||||
save_track_design((uint8)w->number);
|
||||
track_design_save((uint8)w->number);
|
||||
else
|
||||
setup_scenery_selection(w);
|
||||
}
|
||||
|
@ -4822,7 +4823,7 @@ static void window_ride_measurements_tooldown(rct_window *w, int widgetIndex, in
|
|||
case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY:
|
||||
case VIEWPORT_INTERACTION_ITEM_WALL:
|
||||
case VIEWPORT_INTERACTION_ITEM_FOOTPATH:
|
||||
track_save_toggle_map_element(interactionType, mapX, mapY, mapElement);
|
||||
track_design_save_toggle_map_element(interactionType, mapX, mapY, mapElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1789,7 +1789,8 @@ static void window_ride_construction_mouseup_demolish(rct_window* w)
|
|||
_currentTrackBeginY,
|
||||
_currentTrackBeginZ,
|
||||
_currentTrackPieceDirection,
|
||||
_currentTrackPieceType
|
||||
_currentTrackPieceType,
|
||||
GAME_COMMAND_FLAG_APPLY
|
||||
);
|
||||
if (cost == MONEY32_UNDEFINED) {
|
||||
sub_6C84CE();
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
#include "../addresses.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../editor.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../interface/themes.h"
|
||||
#include "../interface/widget.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../rct1.h"
|
||||
#include "../ride/ride.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../sprites.h"
|
||||
#include "error.h"
|
||||
#include "../interface/themes.h"
|
||||
#include "../rct1.h"
|
||||
|
||||
enum {
|
||||
WIDX_BACKGROUND,
|
||||
|
@ -52,6 +53,7 @@ static rct_widget window_track_list_widgets[] = {
|
|||
|
||||
static void window_track_list_close(rct_window *w);
|
||||
static void window_track_list_mouseup(rct_window *w, int widgetIndex);
|
||||
static void window_track_list_update(rct_window *w);
|
||||
static void window_track_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height);
|
||||
static void window_track_list_scrollmousedown(rct_window *w, int scrollIndex, int x, int y);
|
||||
static void window_track_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y);
|
||||
|
@ -67,7 +69,7 @@ static rct_window_event_list window_track_list_events = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
window_track_list_update,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -91,31 +93,34 @@ static rct_window_event_list window_track_list_events = {
|
|||
window_track_list_scrollpaint
|
||||
};
|
||||
|
||||
#define TRACK_DESIGN_INDEX_UNLOADED UINT16_MAX
|
||||
|
||||
ride_list_item _window_track_list_item;
|
||||
|
||||
static track_design_file_ref *_trackDesigns = NULL;
|
||||
static size_t _trackDesignsCount = 0;
|
||||
static uint16 _loadedTrackDesignIndex;
|
||||
static rct_track_td6 *_loadedTrackDesign;
|
||||
static uint8 *_trackDesignPreviewPixels;
|
||||
|
||||
static void track_list_load_designs(ride_list_item item);
|
||||
static bool track_list_load_design_for_preview(utf8 *path);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CF1A2
|
||||
*/
|
||||
void window_track_list_open(ride_list_item item)
|
||||
{
|
||||
rct_window *w;
|
||||
int x, y;
|
||||
void *mem;
|
||||
|
||||
window_close_construction_windows();
|
||||
_window_track_list_item = item;
|
||||
track_list_load_designs(item);
|
||||
|
||||
if (RCT2_GLOBAL(0x00F635ED, uint8) & 1)
|
||||
if (RCT2_GLOBAL(0x00F635ED, uint8) & 1) {
|
||||
window_error_open(STR_WARNING, STR_TOO_MANY_TRACK_DESIGNS_OF_THIS_TYPE);
|
||||
}
|
||||
|
||||
mem = malloc(1285292);
|
||||
if (mem == NULL)
|
||||
return;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*) = mem;
|
||||
reset_track_list_cache();
|
||||
|
||||
int x, y;
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
x = gScreenWidth / 2 - 300;
|
||||
y = max(28, gScreenHeight / 2 - 200);
|
||||
|
@ -123,7 +128,7 @@ void window_track_list_open(ride_list_item item)
|
|||
x = 0;
|
||||
y = 29;
|
||||
}
|
||||
w = window_create(
|
||||
rct_window *w = window_create(
|
||||
x,
|
||||
y,
|
||||
600,
|
||||
|
@ -136,92 +141,14 @@ void window_track_list_open(ride_list_item item)
|
|||
w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY) | (1 << WIDX_BACK);
|
||||
window_init_scroll_widgets(w);
|
||||
w->track_list.var_480 = 0xFFFF;
|
||||
w->track_list.var_482 = gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 1;
|
||||
w->track_list.var_484 = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 0;
|
||||
w->track_list.reload_track_designs = false;
|
||||
w->selected_list_item = gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 1;
|
||||
gTrackDesignSceneryToggle = false;
|
||||
window_push_others_right(w);
|
||||
_currentTrackPieceDirection = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CFB82
|
||||
*/
|
||||
static void window_track_list_select(rct_window *w, int index)
|
||||
{
|
||||
utf8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, utf8);
|
||||
rct_track_design *trackDesign;
|
||||
|
||||
w->track_list.var_480 = index;
|
||||
|
||||
audio_play_sound_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && index == 0) {
|
||||
window_close(w);
|
||||
ride_construct_new(_window_track_list_item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (RCT2_GLOBAL(0x00F44153, uint8) != 0)
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 1;
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER))
|
||||
index--;
|
||||
|
||||
trackDesignItem = trackDesignList + (index * 128);
|
||||
RCT2_GLOBAL(0x00F4403C, utf8*) = trackDesignItem;
|
||||
|
||||
window_track_list_format_name(
|
||||
(char*)0x009BC313,
|
||||
trackDesignItem,
|
||||
gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ?
|
||||
0 :
|
||||
FORMAT_WHITE,
|
||||
1);
|
||||
|
||||
char track_path[MAX_PATH] = { 0 };
|
||||
substitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
|
||||
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
window_track_manage_open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!load_track_design(track_path)) {
|
||||
w->track_list.var_480 = 0xFFFF;
|
||||
window_invalidate(w);
|
||||
return;
|
||||
}
|
||||
|
||||
trackDesign = track_get_info(index, NULL);
|
||||
if (trackDesign == NULL) return;
|
||||
if (trackDesign->track_td6.track_flags & 4)
|
||||
window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1);
|
||||
|
||||
window_close(w);
|
||||
window_track_place_open();
|
||||
}
|
||||
|
||||
static int window_track_list_get_list_item_index_from_position(int x, int y)
|
||||
{
|
||||
int index;
|
||||
uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
|
||||
|
||||
index = 0;
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
|
||||
y -= 10;
|
||||
if (y < 0)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
|
||||
for (trackDesignItem = trackDesignList; *trackDesignItem != 0; trackDesignItem += 128) {
|
||||
y -= 10;
|
||||
if (y < 0)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
_trackDesignPreviewPixels = calloc(4, TRACK_PREVIEW_IMAGE_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,7 +157,67 @@ static int window_track_list_get_list_item_index_from_position(int x, int y)
|
|||
*/
|
||||
static void window_track_list_close(rct_window *w)
|
||||
{
|
||||
free(RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*));
|
||||
// Dispose track design and preview
|
||||
track_design_dispose(_loadedTrackDesign);
|
||||
_loadedTrackDesign = NULL;
|
||||
SafeFree(_trackDesignPreviewPixels);
|
||||
|
||||
// Dispose track list
|
||||
for (size_t i = 0; i < _trackDesignsCount; i++) {
|
||||
free(_trackDesigns[i].name);
|
||||
free(_trackDesigns[i].path);
|
||||
}
|
||||
SafeFree(_trackDesigns);
|
||||
_trackDesignsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CFB82
|
||||
*/
|
||||
static void window_track_list_select(rct_window *w, int index)
|
||||
{
|
||||
w->track_list.var_480 = index;
|
||||
|
||||
audio_play_sound_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
|
||||
if (index == 0) {
|
||||
window_close(w);
|
||||
ride_construct_new(_window_track_list_item);
|
||||
return;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
|
||||
if (RCT2_GLOBAL(0x00F44153, uint8) != 0) {
|
||||
gTrackDesignSceneryToggle = true;
|
||||
}
|
||||
|
||||
track_design_file_ref *tdRef = &_trackDesigns[index];
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
window_track_manage_open(tdRef);
|
||||
} else {
|
||||
if (_loadedTrackDesignIndex != TRACK_DESIGN_INDEX_UNLOADED && (_loadedTrackDesign->track_flags & 4)) {
|
||||
window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, STR_NONE);
|
||||
}
|
||||
|
||||
window_track_place_open(tdRef);
|
||||
}
|
||||
}
|
||||
|
||||
static int window_track_list_get_list_item_index_from_position(int x, int y)
|
||||
{
|
||||
int maxItems = _trackDesignsCount;
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
|
||||
// Extra item: custom design
|
||||
maxItems++;
|
||||
}
|
||||
|
||||
int index = y / 10;
|
||||
if (index < 0 || index >= maxItems) {
|
||||
index = -1;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -254,8 +241,8 @@ static void window_track_list_mouseup(rct_window *w, int widgetIndex)
|
|||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_TOGGLE_SCENERY:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) ^= 1;
|
||||
reset_track_list_cache();
|
||||
gTrackDesignSceneryToggle = !gTrackDesignSceneryToggle;
|
||||
_loadedTrackDesignIndex = TRACK_DESIGN_INDEX_UNLOADED;
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_BACK:
|
||||
|
@ -277,11 +264,13 @@ static void window_track_list_mouseup(rct_window *w, int widgetIndex)
|
|||
*/
|
||||
static void window_track_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
|
||||
{
|
||||
uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
|
||||
size_t numItems = _trackDesignsCount;
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
|
||||
// Extra item: custom design
|
||||
numItems++;
|
||||
}
|
||||
|
||||
*height = gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 10;
|
||||
for (trackDesignItem = trackDesignList; *trackDesignItem != 0; trackDesignItem += 128)
|
||||
*height += 10;
|
||||
*height = (int)(numItems * 10);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,14 +279,12 @@ static void window_track_list_scrollgetsize(rct_window *w, int scrollIndex, int
|
|||
*/
|
||||
static void window_track_list_scrollmousedown(rct_window *w, int scrollIndex, int x, int y)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (w->track_list.var_484 & 1)
|
||||
return;
|
||||
|
||||
i = window_track_list_get_list_item_index_from_position(x, y);
|
||||
if (i != -1)
|
||||
window_track_list_select(w, i);
|
||||
if (!(w->track_list.var_484 & 1)) {
|
||||
int i = window_track_list_get_list_item_index_from_position(x, y);
|
||||
if (i != -1) {
|
||||
window_track_list_select(w, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -306,15 +293,12 @@ static void window_track_list_scrollmousedown(rct_window *w, int scrollIndex, in
|
|||
*/
|
||||
static void window_track_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (w->track_list.var_484 & 1)
|
||||
return;
|
||||
|
||||
i = window_track_list_get_list_item_index_from_position(x, y);
|
||||
if (i != -1 && w->track_list.var_482 != i) {
|
||||
w->track_list.var_482 = i;
|
||||
window_invalidate(w);
|
||||
if (!(w->track_list.var_484 & 1)) {
|
||||
int i = window_track_list_get_list_item_index_from_position(x, y);
|
||||
if (i != -1 && w->selected_list_item != i) {
|
||||
w->selected_list_item = i;
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,6 +311,15 @@ static void window_track_list_tooltip(rct_window* w, int widgetIndex, rct_string
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_LIST;
|
||||
}
|
||||
|
||||
static void window_track_list_update(rct_window *w)
|
||||
{
|
||||
if (w->track_list.reload_track_designs) {
|
||||
track_list_load_designs(_window_track_list_item);
|
||||
w->selected_list_item = 0;
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CF2D6
|
||||
|
@ -353,15 +346,16 @@ static void window_track_list_invalidate(rct_window *w)
|
|||
window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP;
|
||||
}
|
||||
|
||||
if ((gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) || w->track_list.var_482 != 0) {
|
||||
if ((gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) || w->selected_list_item != 0) {
|
||||
w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW;
|
||||
w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
|
||||
window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN;
|
||||
window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_FLATBTN;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0)
|
||||
w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
|
||||
else
|
||||
if (gTrackDesignSceneryToggle) {
|
||||
w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
|
||||
} else {
|
||||
w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
|
||||
}
|
||||
} else {
|
||||
w->pressed_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
|
||||
w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
|
||||
|
@ -376,41 +370,43 @@ static void window_track_list_invalidate(rct_window *w)
|
|||
*/
|
||||
static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
||||
{
|
||||
rct_widget *widget;
|
||||
rct_track_design *trackDesign = NULL;
|
||||
uint8 *image;
|
||||
utf8 *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, utf8);
|
||||
uint16 holes, speed, drops, dropHeight, inversions;
|
||||
fixed32_2dp rating;
|
||||
int trackIndex, x, y, colour, gForces, airTime;
|
||||
rct_g1_element tmpElement, *substituteElement;
|
||||
|
||||
window_draw_widgets(w, dpi);
|
||||
|
||||
trackIndex = w->track_list.var_482;
|
||||
int trackIndex = w->selected_list_item;
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
if (*trackDesignList == 0 || trackIndex == -1)
|
||||
if (_trackDesignsCount == 0 || trackIndex == -1) {
|
||||
return;
|
||||
}
|
||||
} else if (trackIndex-- == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Track preview
|
||||
widget = &window_track_list_widgets[WIDX_TRACK_PREVIEW];
|
||||
int x, y, colour;
|
||||
rct_widget *widget = &window_track_list_widgets[WIDX_TRACK_PREVIEW];
|
||||
x = w->x + widget->left + 1;
|
||||
y = w->y + widget->top + 1;
|
||||
colour = ColourMapA[w->colours[0]].darkest;
|
||||
gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);
|
||||
|
||||
trackDesign = track_get_info(trackIndex, &image);
|
||||
if (trackDesign == NULL)
|
||||
if (_loadedTrackDesignIndex != trackIndex) {
|
||||
utf8 *path = _trackDesigns[trackIndex].path;
|
||||
if (track_list_load_design_for_preview(path)) {
|
||||
_loadedTrackDesignIndex = trackIndex;
|
||||
} else {
|
||||
_loadedTrackDesignIndex = TRACK_DESIGN_INDEX_UNLOADED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rct_track_td6 *td6 = _loadedTrackDesign;
|
||||
if (td6 == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
rct_track_td6* track_td6 = &trackDesign->track_td6;
|
||||
|
||||
substituteElement = &g1Elements[0];
|
||||
tmpElement = *substituteElement;
|
||||
substituteElement->offset = image;
|
||||
rct_g1_element *substituteElement = &g1Elements[0];
|
||||
rct_g1_element tmpElement = *substituteElement;
|
||||
substituteElement->offset = _trackDesignPreviewPixels + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
|
||||
substituteElement->width = 370;
|
||||
substituteElement->height = 217;
|
||||
substituteElement->x_offset = 0;
|
||||
|
@ -424,15 +420,15 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
|
||||
RCT2_GLOBAL(0x00F44153, uint8) = 0;
|
||||
// Warnings
|
||||
if ((track_td6->track_flags & 4) && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
|
||||
if ((td6->track_flags & 4) && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
|
||||
// Vehicle design not available
|
||||
gfx_draw_string_centred_clipped(dpi, STR_VEHICLE_DESIGN_UNAVAILABLE, NULL, 0, x, y, 368);
|
||||
y -= 10;
|
||||
}
|
||||
|
||||
if (track_td6->track_flags & 1) {
|
||||
if (td6->track_flags & 1) {
|
||||
RCT2_GLOBAL(0x00F44153, uint8) = 1;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0) {
|
||||
if (!gTrackDesignSceneryToggle) {
|
||||
// Scenery not available
|
||||
gfx_draw_string_centred_clipped(dpi, STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE, NULL, 0, x, y, 368);
|
||||
y -= 10;
|
||||
|
@ -440,92 +436,92 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
}
|
||||
|
||||
// Track design name
|
||||
window_track_list_format_name((char*)0x009BC677, trackDesignList + (trackIndex * 128), FORMAT_WINDOW_COLOUR_1, 1);
|
||||
gfx_draw_string_centred_clipped(dpi, 3165, NULL, 0, x, y, 368);
|
||||
utf8 *trackName = _trackDesigns[trackIndex].name;
|
||||
gfx_draw_string_centred_clipped(dpi, STR_TRACK_PREVIEW_NAME_FORMAT, &trackName, 0, x, y, 368);
|
||||
|
||||
// Information
|
||||
x = w->x + widget->left + 1;
|
||||
y = w->y + widget->bottom + 2;
|
||||
|
||||
// Stats
|
||||
rating = track_td6->excitement * 10;
|
||||
fixed32_2dp rating = td6->excitement * 10;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
rating = track_td6->intensity * 10;
|
||||
rating = td6->intensity * 10;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
rating = track_td6->nausea * 10;
|
||||
rating = td6->nausea * 10;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_NAUSEA_RATING, &rating, 0, x, y);
|
||||
y += 14;
|
||||
|
||||
if (track_td6->type != RIDE_TYPE_MAZE) {
|
||||
if (track_td6->type == RIDE_TYPE_MINI_GOLF) {
|
||||
if (td6->type != RIDE_TYPE_MAZE) {
|
||||
if (td6->type == RIDE_TYPE_MINI_GOLF) {
|
||||
// Holes
|
||||
holes = track_td6->holes & 0x1F;
|
||||
uint16 holes = td6->holes & 0x1F;
|
||||
gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y);
|
||||
y += 10;
|
||||
} else {
|
||||
// Maximum speed
|
||||
speed = ((track_td6->max_speed << 16) * 9) >> 18;
|
||||
uint16 speed = ((td6->max_speed << 16) * 9) >> 18;
|
||||
gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Average speed
|
||||
speed = ((track_td6->average_speed << 16) * 9) >> 18;
|
||||
speed = ((td6->average_speed << 16) * 9) >> 18;
|
||||
gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &speed, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
// Ride length
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 1345;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->ride_length;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = td6->ride_length;
|
||||
gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, 214);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
if (ride_type_has_flag(track_td6->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
|
||||
if (ride_type_has_flag(td6->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) {
|
||||
// Maximum positive vertical Gs
|
||||
gForces = track_td6->max_positive_vertical_g * 32;
|
||||
int gForces = td6->max_positive_vertical_g * 32;
|
||||
gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Maximum negative verical Gs
|
||||
gForces = track_td6->max_negative_vertical_g * 32;
|
||||
gForces = td6->max_negative_vertical_g * 32;
|
||||
gfx_draw_string_left(dpi, STR_MAX_NEGATIVE_VERTICAL_G, &gForces, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Maximum lateral Gs
|
||||
gForces = track_td6->max_lateral_g * 32;
|
||||
gForces = td6->max_lateral_g * 32;
|
||||
gfx_draw_string_left(dpi, STR_MAX_LATERAL_G, &gForces, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// If .TD6
|
||||
if (track_td6->version_and_colour_scheme / 4 >= 2) {
|
||||
if (track_td6->total_air_time != 0) {
|
||||
if (td6->version_and_colour_scheme / 4 >= 2) {
|
||||
if (td6->total_air_time != 0) {
|
||||
// Total air time
|
||||
airTime = track_td6->total_air_time * 25;
|
||||
int airTime = td6->total_air_time * 25;
|
||||
gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &airTime, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ride_type_has_flag(track_td6->type, RIDE_TYPE_FLAG_HAS_DROPS)) {
|
||||
if (ride_type_has_flag(td6->type, RIDE_TYPE_FLAG_HAS_DROPS)) {
|
||||
// Drops
|
||||
drops = track_td6->drops & 0x3F;
|
||||
uint16 drops = td6->drops & 0x3F;
|
||||
gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y);
|
||||
y += 10;
|
||||
|
||||
// Drop height is multiplied by 0.75
|
||||
dropHeight = (track_td6->highest_drop_height + (track_td6->highest_drop_height / 2)) / 2;
|
||||
uint16 dropHeight = (td6->highest_drop_height + (td6->highest_drop_height / 2)) / 2;
|
||||
gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &drops, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
if (track_td6->type != RIDE_TYPE_MINI_GOLF) {
|
||||
inversions = track_td6->inversions & 0x1F;
|
||||
if (td6->type != RIDE_TYPE_MINI_GOLF) {
|
||||
uint16 inversions = td6->inversions & 0x1F;
|
||||
if (inversions != 0) {
|
||||
// Inversions
|
||||
gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, 0, x, y);
|
||||
|
@ -534,16 +530,16 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
}
|
||||
y += 4;
|
||||
|
||||
if (track_td6->space_required_x != 0xFF) {
|
||||
if (td6->space_required_x != 0xFF) {
|
||||
// Space required
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = track_td6->space_required_x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->space_required_y;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = td6->space_required_x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = td6->space_required_y;
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
if (track_td6->cost != 0) {
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &track_td6->cost, 0, x, y);
|
||||
if (td6->cost != 0) {
|
||||
gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &td6->cost, 0, x, y);
|
||||
y += 14;
|
||||
}
|
||||
}
|
||||
|
@ -554,28 +550,23 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
*/
|
||||
static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
|
||||
{
|
||||
rct_string_id stringId, stringId2;
|
||||
int i, x, y, colour;
|
||||
utf8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, utf8);
|
||||
|
||||
colour = ColourMapA[w->colours[0]].mid_light;
|
||||
int colour = ColourMapA[w->colours[0]].mid_light;
|
||||
colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
|
||||
gfx_clear(dpi, colour);
|
||||
|
||||
i = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
trackDesignItem = trackDesignList;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
size_t listIndex = 0;
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
if (*trackDesignItem == 0) {
|
||||
if (_trackDesignsCount == 0) {
|
||||
// No track designs
|
||||
gfx_draw_string_left(dpi, STR_NO_TRACK_DESIGNS_OF_THIS_TYPE, NULL, 0, x, y - 1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Build custom track item
|
||||
if (i == w->track_list.var_482) {
|
||||
rct_string_id stringId;
|
||||
if (listIndex == w->selected_list_item) {
|
||||
// Highlight
|
||||
gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49);
|
||||
stringId = 1193;
|
||||
|
@ -583,15 +574,16 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
|
|||
stringId = 1191;
|
||||
}
|
||||
|
||||
stringId2 = STR_BUILD_CUSTOM_DESIGN;
|
||||
rct_string_id stringId2 = STR_BUILD_CUSTOM_DESIGN;
|
||||
gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
|
||||
y += 10;
|
||||
i++;
|
||||
listIndex++;
|
||||
}
|
||||
|
||||
while (*trackDesignItem != 0) {
|
||||
for (size_t i = 0; i < _trackDesignsCount; i++, listIndex++) {
|
||||
if (y + 10 >= dpi->y && y < dpi->y + dpi->height) {
|
||||
if (i == w->track_list.var_482) {
|
||||
rct_string_id stringId;
|
||||
if (listIndex == w->selected_list_item) {
|
||||
// Highlight
|
||||
gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49);
|
||||
stringId = 1193;
|
||||
|
@ -600,12 +592,38 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
|
|||
}
|
||||
|
||||
// Draw track name
|
||||
window_track_list_format_name((char *)language_get_string(3165), trackDesignItem, 0, 1);
|
||||
stringId2 = 3165;
|
||||
gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = STR_TRACK_LIST_NAME_FORMAT;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, utf8*) = _trackDesigns[i].name;
|
||||
gfx_draw_string_left(dpi, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y - 1);
|
||||
}
|
||||
y += 10;
|
||||
i++;
|
||||
trackDesignItem += 128;
|
||||
}
|
||||
}
|
||||
|
||||
static void track_list_load_designs(ride_list_item item)
|
||||
{
|
||||
char entry[9];
|
||||
const char *entryPtr = NULL;
|
||||
if (item.type < 0x80) {
|
||||
rct_ride_entry *rideEntry = get_ride_entry(item.entry_index);
|
||||
if ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) && !rideTypeShouldLoseSeparateFlag(rideEntry)) {
|
||||
get_ride_entry_name(entry, item.entry_index);
|
||||
entryPtr = entry;
|
||||
}
|
||||
}
|
||||
_trackDesignsCount = track_design_index_get_for_ride(&_trackDesigns, item.type, entryPtr);
|
||||
}
|
||||
|
||||
static bool track_list_load_design_for_preview(utf8 *path)
|
||||
{
|
||||
// Dispose currently loaded track
|
||||
track_design_dispose(_loadedTrackDesign);
|
||||
_loadedTrackDesign = NULL;
|
||||
|
||||
_loadedTrackDesign = track_design_open(path);
|
||||
if (_loadedTrackDesign != NULL) {
|
||||
track_design_draw_preview(_loadedTrackDesign, _trackDesignPreviewPixels);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "../interface/window.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../util/util.h"
|
||||
#include "error.h"
|
||||
|
||||
#pragma region Widgets
|
||||
|
@ -47,10 +49,10 @@ static rct_widget window_track_manage_widgets[] = {
|
|||
|
||||
static rct_widget window_track_delete_prompt_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 249, 0, 73, STR_NONE, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 248, 1, 14, 3356, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CAPTION, 0, 1, 248, 1, 14, STR_DELETE_FILE, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 237, 247, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_DROPDOWN_BUTTON, 0, 10, 119, 54, 65, 3349, STR_NONE },
|
||||
{ WWT_DROPDOWN_BUTTON, 0, 130, 239, 54, 65, 972, STR_NONE },
|
||||
{ WWT_DROPDOWN_BUTTON, 0, 10, 119, 54, 65, STR_TRACK_MANAGE_DELETE, STR_NONE },
|
||||
{ WWT_DROPDOWN_BUTTON, 0, 130, 239, 54, 65, STR_CANCEL, STR_NONE },
|
||||
{ WIDGETS_END }
|
||||
};
|
||||
|
||||
|
@ -134,19 +136,19 @@ static rct_window_event_list window_track_delete_prompt_events = {
|
|||
|
||||
#pragma endregion
|
||||
|
||||
static track_design_file_ref *_trackDesignFileReference;
|
||||
|
||||
static void window_track_delete_prompt_open();
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D348F
|
||||
*/
|
||||
void window_track_manage_open()
|
||||
void window_track_manage_open(track_design_file_ref *tdFileRef)
|
||||
{
|
||||
rct_window *w, *trackDesignListWindow;
|
||||
|
||||
window_close_by_class(WC_MANAGE_TRACK_DESIGN);
|
||||
|
||||
w = window_create_centred(
|
||||
rct_window *w = window_create_centred(
|
||||
250,
|
||||
44,
|
||||
&window_track_manage_events,
|
||||
|
@ -160,9 +162,15 @@ void window_track_manage_open()
|
|||
(1 << WIDX_DELETE);
|
||||
window_init_scroll_widgets(w);
|
||||
|
||||
trackDesignListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackDesignListWindow != NULL)
|
||||
rct_window *trackDesignListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackDesignListWindow != NULL) {
|
||||
trackDesignListWindow->track_list.var_484 |= 1;
|
||||
}
|
||||
|
||||
utf8 *title = (utf8*)language_get_string(3155);
|
||||
format_string(title, STR_TRACK_LIST_NAME_FORMAT, &tdFileRef->name);
|
||||
|
||||
_trackDesignFileReference = tdFileRef;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,8 +180,9 @@ void window_track_manage_open()
|
|||
static void window_track_manage_close(rct_window *w)
|
||||
{
|
||||
rct_window *trackDesignListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackDesignListWindow != NULL)
|
||||
if (trackDesignListWindow != NULL) {
|
||||
trackDesignListWindow->track_list.var_484 &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,24 +191,19 @@ static void window_track_manage_close(rct_window *w)
|
|||
*/
|
||||
static void window_track_manage_mouseup(rct_window *w, int widgetIndex)
|
||||
{
|
||||
char *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char);
|
||||
rct_window *trackDesignListWindow;
|
||||
char *dst, *src;
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_CLOSE:
|
||||
window_close(w);
|
||||
break;
|
||||
case WIDX_RENAME:
|
||||
trackDesignListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
|
||||
if (trackDesignListWindow != NULL) {
|
||||
src = &trackDesignList[trackDesignListWindow->track_list.var_482 * 128];
|
||||
dst = (char*)0x009BC677;
|
||||
while (*src != 0 && *src != '.')
|
||||
*dst++ = *src++;
|
||||
*dst = 0;
|
||||
window_text_input_open(w, widgetIndex, 3350, 3351, 3165, 0, 127);
|
||||
}
|
||||
window_text_input_raw_open(
|
||||
w,
|
||||
widgetIndex,
|
||||
STR_TRACK_DESIGN_RENAME_TITLE,
|
||||
STR_TRACK_DESIGN_RENAME_DESC,
|
||||
_trackDesignFileReference->name,
|
||||
127
|
||||
);
|
||||
break;
|
||||
case WIDX_DELETE:
|
||||
window_track_delete_prompt_open();
|
||||
|
@ -213,10 +217,11 @@ static void window_track_manage_mouseup(rct_window *w, int widgetIndex)
|
|||
*/
|
||||
static void window_track_manage_textinput(rct_window *w, int widgetIndex, char *text)
|
||||
{
|
||||
if (widgetIndex != WIDX_RENAME || text == NULL)
|
||||
if (widgetIndex != WIDX_RENAME || str_is_null_or_empty(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (track_rename(text)) {
|
||||
if (track_design_index_rename(_trackDesignFileReference->path, text)) {
|
||||
window_close_by_class(WC_TRACK_DELETE_PROMPT);
|
||||
window_close(w);
|
||||
} else {
|
||||
|
@ -279,10 +284,11 @@ static void window_track_delete_prompt_mouseup(rct_window *w, int widgetIndex)
|
|||
break;
|
||||
case WIDX_PROMPT_DELETE:
|
||||
window_close(w);
|
||||
if (track_delete())
|
||||
if (track_design_index_delete(_trackDesignFileReference->path)) {
|
||||
window_close_by_class(WC_MANAGE_TRACK_DESIGN);
|
||||
else
|
||||
} else {
|
||||
window_error_open(STR_CANT_DELETE_TRACK_DESIGN, gGameCommandErrorText);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -298,12 +304,15 @@ static void window_track_delete_prompt_invalidate(rct_window *w)
|
|||
*/
|
||||
static void window_track_delete_prompt_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
||||
{
|
||||
rct_string_id stringId;
|
||||
|
||||
window_draw_widgets(w, dpi);
|
||||
|
||||
stringId = 3155;
|
||||
gfx_draw_string_centred_wrapped(
|
||||
dpi, &stringId, w->x + 125, w->y + 28, 246, STR_ARE_YOU_SURE_YOU_WANT_TO_PERMANENTLY_DELETE_TRACK, 0
|
||||
dpi,
|
||||
&_trackDesignFileReference->name,
|
||||
w->x + 125,
|
||||
w->y + 28,
|
||||
246,
|
||||
STR_ARE_YOU_SURE_YOU_WANT_TO_PERMANENTLY_DELETE_TRACK,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,17 +16,19 @@
|
|||
|
||||
#include "../addresses.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../cheats.h"
|
||||
#include "../game.h"
|
||||
#include "../input.h"
|
||||
#include "../interface/themes.h"
|
||||
#include "../interface/viewport.h"
|
||||
#include "../interface/widget.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../sprites.h"
|
||||
#include "../ride/track.h"
|
||||
#include "../ride/track_data.h"
|
||||
#include "../interface/themes.h"
|
||||
#include "../cheats.h"
|
||||
#include "../ride/track_design.h"
|
||||
#include "../sprites.h"
|
||||
#include "../util/util.h"
|
||||
|
||||
#define TRACK_MINI_PREVIEW_WIDTH 168
|
||||
#define TRACK_MINI_PREVIEW_HEIGHT 78
|
||||
|
@ -98,12 +100,27 @@ static uint8 *_window_track_place_mini_preview;
|
|||
static sint16 _window_track_place_last_x;
|
||||
static sint16 _window_track_place_last_y;
|
||||
|
||||
static uint8 _window_track_place_last_was_valid;
|
||||
static uint8 _window_track_place_ride_index;
|
||||
static bool _window_track_place_last_was_valid;
|
||||
static sint16 _window_track_place_last_valid_x;
|
||||
static sint16 _window_track_place_last_valid_y;
|
||||
static sint16 _window_track_place_last_valid_z;
|
||||
static money32 _window_track_place_last_cost;
|
||||
|
||||
static rct_track_td6 *_trackDesign;
|
||||
|
||||
static void window_track_place_clear_provisional();
|
||||
static int window_track_place_get_base_z(int x, int y);
|
||||
static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex);
|
||||
|
||||
static void window_track_place_clear_mini_preview();
|
||||
static void window_track_place_draw_mini_preview(rct_track_td6 *td6);
|
||||
static void window_track_place_draw_mini_preview_track(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max);
|
||||
static void window_track_place_draw_mini_preview_maze(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max);
|
||||
static rct_xy16 draw_mini_preview_get_pixel_position(sint16 x, sint16 y);
|
||||
static bool draw_mini_preview_is_pixel_in_bounds(rct_xy16 pixel);
|
||||
static uint8 *draw_mini_preview_get_pixel_ptr(rct_xy16 pixel);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D182E
|
||||
|
@ -115,265 +132,23 @@ static void window_track_place_clear_mini_preview()
|
|||
|
||||
#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y;
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D1845
|
||||
*/
|
||||
static void window_track_place_draw_mini_preview()
|
||||
{
|
||||
rct_track_td6 *track = RCT2_ADDRESS(0x009D8178, rct_track_td6);
|
||||
uint8 *pixel, colour, bits;
|
||||
int i, rotation, pass, x, y, pixelX, pixelY, originX, originY, minX, minY, maxX, maxY;
|
||||
rct_maze_element *mazeElement;
|
||||
rct_track_element *trackElement;
|
||||
const rct_preview_track *trackBlock;
|
||||
|
||||
window_track_place_clear_mini_preview();
|
||||
|
||||
minX = 0;
|
||||
minY = 0;
|
||||
maxX = 0;
|
||||
maxY = 0;
|
||||
|
||||
// First pass is used to determine the width and height of the image so it can centre it
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
originX = 0;
|
||||
originY = 0;
|
||||
if (pass == 1) {
|
||||
originX -= ((maxX + minX) >> 6) << 5;
|
||||
originY -= ((maxY + minY) >> 6) << 5;
|
||||
}
|
||||
|
||||
if (track->type != RIDE_TYPE_MAZE) {
|
||||
#pragma region Track
|
||||
|
||||
rotation = _currentTrackPieceDirection + get_current_rotation();
|
||||
trackElement = RCT2_ADDRESS(0x009D821B, rct_track_element);
|
||||
|
||||
while (trackElement->type != 255) {
|
||||
int trackType = trackElement->type;
|
||||
if (trackType == 101)
|
||||
trackType = 255;
|
||||
|
||||
// Station track is a lighter colour
|
||||
colour = RCT2_ADDRESS(0x0099BA64, uint8)[trackType * 16] & 0x10 ? 222 : 218;
|
||||
|
||||
// Follow a single track piece shape
|
||||
trackBlock = TrackBlocks[trackType];
|
||||
while (trackBlock->index != 255) {
|
||||
x = originX;
|
||||
y = originY;
|
||||
|
||||
switch (rotation & 3) {
|
||||
case 0:
|
||||
x += trackBlock->x;
|
||||
y += trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
x += trackBlock->y;
|
||||
y -= trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
x -= trackBlock->x;
|
||||
y -= trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
x -= trackBlock->y;
|
||||
y += trackBlock->x;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pass == 0) {
|
||||
minX = min(minX, x);
|
||||
maxX = max(maxX, x);
|
||||
minY = min(minY, y);
|
||||
maxY = max(maxY, y);
|
||||
} else {
|
||||
pixelX = 80 + ((y / 32) - (x / 32)) * 4;
|
||||
pixelY = 38 + ((y / 32) + (x / 32)) * 2;
|
||||
if (pixelX >= 0 && pixelY >= 0 && pixelX <= 160 && pixelY <= 75) {
|
||||
pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX];
|
||||
|
||||
bits = trackBlock->var_08 << (rotation & 3);
|
||||
bits = (bits & 0x0F) | ((bits & 0xF0) >> 4);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (bits & 1) pixel[338 + i] = colour;
|
||||
if (bits & 2) pixel[168 + i] = colour;
|
||||
if (bits & 4) pixel[ 2 + i] = colour;
|
||||
if (bits & 8) pixel[172 + i] = colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
trackBlock++;
|
||||
}
|
||||
|
||||
// Change rotation and next position based on track curvature
|
||||
rotation &= 3;
|
||||
const rct_track_coordinates* track_coordinate = &TrackCoordinates[trackType];
|
||||
|
||||
trackType *= 10;
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
originX += track_coordinate->x;
|
||||
originY += track_coordinate->y;
|
||||
break;
|
||||
case 1:
|
||||
originX += track_coordinate->y;
|
||||
originY -= track_coordinate->x;
|
||||
break;
|
||||
case 2:
|
||||
originX -= track_coordinate->x;
|
||||
originY -= track_coordinate->y;
|
||||
break;
|
||||
case 3:
|
||||
originX -= track_coordinate->y;
|
||||
originY += track_coordinate->x;
|
||||
break;
|
||||
}
|
||||
rotation += track_coordinate->rotation_end - track_coordinate->rotation_begin;
|
||||
rotation &= 3;
|
||||
if (track_coordinate->rotation_end & 4)
|
||||
rotation |= 4;
|
||||
if (!(rotation & 4)) {
|
||||
originX += TileDirectionDelta[rotation].x;
|
||||
originY += TileDirectionDelta[rotation].y;
|
||||
}
|
||||
trackElement++;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
} else {
|
||||
#pragma region Maze
|
||||
|
||||
rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
|
||||
mazeElement = RCT2_ADDRESS(0x009D821B, rct_maze_element);
|
||||
while (mazeElement->all != 0) {
|
||||
x = mazeElement->x * 32;
|
||||
y = mazeElement->y * 32;
|
||||
switch (rotation) {
|
||||
case 1:
|
||||
x = -x;
|
||||
swap(x, y);
|
||||
break;
|
||||
case 2:
|
||||
x = -x;
|
||||
y = -y;
|
||||
break;
|
||||
case 3:
|
||||
x = -x;
|
||||
swap(x, y);
|
||||
break;
|
||||
}
|
||||
x += originX;
|
||||
y += originY;
|
||||
|
||||
// Entrance or exit is a lighter colour
|
||||
colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218;
|
||||
|
||||
if (pass == 0) {
|
||||
minX = min(minX, x);
|
||||
maxX = max(maxX, x);
|
||||
minY = min(minY, y);
|
||||
maxY = max(maxY, y);
|
||||
} else {
|
||||
pixelX = 80 + ((y / 32) - (x / 32)) * 4;
|
||||
pixelY = 38 + ((y / 32) + (x / 32)) * 2;
|
||||
if (pixelX <= 160 && pixelY <= 75) {
|
||||
pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX];
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pixel[338 + i] = colour;
|
||||
pixel[168 + i] = colour;
|
||||
pixel[ 2 + i] = colour;
|
||||
pixel[172 + i] = colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
mazeElement++;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D017F
|
||||
*/
|
||||
static void window_track_place_clear_provisional()
|
||||
{
|
||||
if (_window_track_place_last_was_valid) {
|
||||
sub_6D01B3(
|
||||
6,
|
||||
RCT2_GLOBAL(0x00F440EB, uint8),
|
||||
_window_track_place_last_valid_x,
|
||||
_window_track_place_last_valid_y,
|
||||
_window_track_place_last_valid_z
|
||||
);
|
||||
_window_track_place_last_was_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D17C6
|
||||
*/
|
||||
static int window_track_place_get_base_z(int x, int y)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
int z;
|
||||
|
||||
mapElement = map_get_surface_element_at(x >> 5, y >> 5);
|
||||
z = mapElement->base_height * 8;
|
||||
|
||||
// Increase Z above slope
|
||||
if (mapElement->properties.surface.slope & 0x0F) {
|
||||
z += 16;
|
||||
|
||||
// Increase Z above double slope
|
||||
if (mapElement->properties.surface.slope & 0x10)
|
||||
z += 16;
|
||||
}
|
||||
|
||||
// Increase Z above water
|
||||
if (mapElement->properties.surface.terrain & 0x1F)
|
||||
z = max(z, (mapElement->properties.surface.terrain & 0x1F) << 4);
|
||||
|
||||
return z + sub_6D01B3(3, 0, x, y, z);
|
||||
}
|
||||
|
||||
static void window_track_place_attempt_placement(int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex)
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
money32 result;
|
||||
|
||||
edx = esi = ebp = 0;
|
||||
eax = x;
|
||||
ebx = bl;
|
||||
ecx = y;
|
||||
edi = z;
|
||||
result = game_do_command_p(GAME_COMMAND_PLACE_TRACK_DESIGN, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
|
||||
if (cost != NULL) *cost = result;
|
||||
if (rideIndex != NULL) *rideIndex = edi & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CFCA0
|
||||
*/
|
||||
void window_track_place_open()
|
||||
void window_track_place_open(const track_design_file_ref *tdFileRef)
|
||||
{
|
||||
rct_window *w;
|
||||
rct_track_td6 *td6 = track_design_open(tdFileRef->path);
|
||||
if (td6 == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
window_close_construction_windows();
|
||||
|
||||
_window_track_place_mini_preview = malloc(TRACK_MINI_PREVIEW_SIZE);
|
||||
window_track_place_clear_mini_preview();
|
||||
|
||||
w = window_create(
|
||||
rct_window *w = window_create(
|
||||
0,
|
||||
29,
|
||||
200,
|
||||
|
@ -392,7 +167,12 @@ void window_track_place_open()
|
|||
_window_track_place_last_cost = MONEY32_UNDEFINED;
|
||||
_window_track_place_last_x = 0xFFFF;
|
||||
_currentTrackPieceDirection = (2 - get_current_rotation()) & 3;
|
||||
window_track_place_draw_mini_preview();
|
||||
window_track_place_draw_mini_preview(td6);
|
||||
|
||||
char *title = (char*)language_get_string(3155);
|
||||
format_string(title, STR_TRACK_LIST_NAME_FORMAT, &td6->name);
|
||||
|
||||
_trackDesign = td6;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -406,7 +186,9 @@ static void window_track_place_close(rct_window *w)
|
|||
map_invalidate_map_selection_tiles();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~6;
|
||||
hide_gridlines();
|
||||
free(_window_track_place_mini_preview);
|
||||
SafeFree(_window_track_place_mini_preview);
|
||||
track_design_dispose(_trackDesign);
|
||||
_trackDesign = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,14 +206,14 @@ static void window_track_place_mouseup(rct_window *w, int widgetIndex)
|
|||
_currentTrackPieceDirection = (_currentTrackPieceDirection + 1) & 3;
|
||||
window_invalidate(w);
|
||||
_window_track_place_last_x = 0xFFFF;
|
||||
window_track_place_draw_mini_preview();
|
||||
window_track_place_draw_mini_preview(_trackDesign);
|
||||
break;
|
||||
case WIDX_MIRROR:
|
||||
track_mirror();
|
||||
track_design_mirror(_trackDesign);
|
||||
_currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3;
|
||||
window_invalidate(w);
|
||||
_window_track_place_last_x = 0xFFFF;
|
||||
window_track_place_draw_mini_preview();
|
||||
window_track_place_draw_mini_preview(_trackDesign);
|
||||
break;
|
||||
case WIDX_SELECT_DIFFERENT_DESIGN:
|
||||
window_close(w);
|
||||
|
@ -474,7 +256,7 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x,
|
|||
|
||||
// Check if tool map position has changed since last update
|
||||
if (mapX == _window_track_place_last_x && mapY == _window_track_place_last_y) {
|
||||
sub_6D01B3(0, 0, mapX, mapY, 0);
|
||||
sub_6D01B3(_trackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -487,13 +269,13 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x,
|
|||
|
||||
// Try increasing Z until a feasible placement is found
|
||||
for (i = 0; i < 7; i++) {
|
||||
window_track_place_attempt_placement(mapX, mapY, mapZ, 105, &cost, &rideIndex);
|
||||
window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 105, &cost, &rideIndex);
|
||||
if (cost != MONEY32_UNDEFINED) {
|
||||
RCT2_GLOBAL(0x00F440EB, uint16) = rideIndex;
|
||||
_window_track_place_ride_index = rideIndex;
|
||||
_window_track_place_last_valid_x = mapX;
|
||||
_window_track_place_last_valid_y = mapY;
|
||||
_window_track_place_last_valid_z = mapZ;
|
||||
_window_track_place_last_was_valid = 1;
|
||||
_window_track_place_last_was_valid = true;
|
||||
break;
|
||||
}
|
||||
mapZ += 8;
|
||||
|
@ -507,7 +289,7 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x,
|
|||
widget_invalidate(w, WIDX_PRICE);
|
||||
}
|
||||
|
||||
sub_6D01B3(0, 0, mapX, mapY, mapZ);
|
||||
sub_6D01B3(_trackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, mapZ);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -533,7 +315,7 @@ static void window_track_place_tooldown(rct_window* w, int widgetIndex, int x, i
|
|||
mapZ = window_track_place_get_base_z(mapX, mapY);
|
||||
for (i = 0; i < 7; i++) {
|
||||
RCT2_GLOBAL(0x009A8C29, uint8) |= 1;
|
||||
window_track_place_attempt_placement(mapX, mapY, mapZ, 1, &cost, &rideIndex);
|
||||
window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 1, &cost, &rideIndex);
|
||||
RCT2_GLOBAL(0x009A8C29, uint8) &= ~1;
|
||||
|
||||
if (cost != MONEY32_UNDEFINED) {
|
||||
|
@ -541,7 +323,7 @@ static void window_track_place_tooldown(rct_window* w, int widgetIndex, int x, i
|
|||
audio_play_sound_at_location(SOUND_PLACE_ITEM, mapX, mapY, mapZ);
|
||||
|
||||
_currentRideIndex = rideIndex;
|
||||
if (RCT2_GLOBAL(0x00F4414E, uint8) & 1) {
|
||||
if (byte_F4414E & 1) {
|
||||
window_ride_main_open(rideIndex);
|
||||
window_close(w);
|
||||
} else {
|
||||
|
@ -578,7 +360,7 @@ static void window_track_place_toolabort(rct_window *w, int widgetIndex)
|
|||
*/
|
||||
static void window_track_place_unknown14(rct_window *w)
|
||||
{
|
||||
window_track_place_draw_mini_preview();
|
||||
window_track_place_draw_mini_preview(_trackDesign);
|
||||
}
|
||||
|
||||
static void window_track_place_invalidate(rct_window *w)
|
||||
|
@ -586,21 +368,85 @@ static void window_track_place_invalidate(rct_window *w)
|
|||
colour_scheme_update(w);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D017F
|
||||
*/
|
||||
static void window_track_place_clear_provisional()
|
||||
{
|
||||
if (_window_track_place_last_was_valid) {
|
||||
sub_6D01B3(
|
||||
_trackDesign,
|
||||
PTD_OPERATION_CLEAR_OUTLINES,
|
||||
_window_track_place_ride_index,
|
||||
_window_track_place_last_valid_x,
|
||||
_window_track_place_last_valid_y,
|
||||
_window_track_place_last_valid_z
|
||||
);
|
||||
_window_track_place_last_was_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D17C6
|
||||
*/
|
||||
static int window_track_place_get_base_z(int x, int y)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
int z;
|
||||
|
||||
mapElement = map_get_surface_element_at(x >> 5, y >> 5);
|
||||
z = mapElement->base_height * 8;
|
||||
|
||||
// Increase Z above slope
|
||||
if (mapElement->properties.surface.slope & 0x0F) {
|
||||
z += 16;
|
||||
|
||||
// Increase Z above double slope
|
||||
if (mapElement->properties.surface.slope & 0x10)
|
||||
z += 16;
|
||||
}
|
||||
|
||||
// Increase Z above water
|
||||
if (mapElement->properties.surface.terrain & 0x1F)
|
||||
z = max(z, (mapElement->properties.surface.terrain & 0x1F) << 4);
|
||||
|
||||
return z + sub_6D01B3(_trackDesign, PTD_OPERATION_GET_PLACE_Z, 0, x, y, z);
|
||||
}
|
||||
|
||||
static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex)
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
money32 result;
|
||||
|
||||
edx = esi = ebp = 0;
|
||||
eax = x;
|
||||
ebx = bl;
|
||||
ecx = y;
|
||||
edi = z;
|
||||
|
||||
gActiveTrackDesign = _trackDesign;
|
||||
result = game_do_command_p(GAME_COMMAND_PLACE_TRACK_DESIGN, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
gActiveTrackDesign = NULL;
|
||||
|
||||
if (cost != NULL) *cost = result;
|
||||
if (rideIndex != NULL) *rideIndex = edi & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CFD9D
|
||||
*/
|
||||
static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
||||
{
|
||||
rct_drawpixelinfo clippedDpi;
|
||||
rct_g1_element tmpElement, *substituteElement;
|
||||
|
||||
window_draw_widgets(w, dpi);
|
||||
|
||||
// Draw mini tile preview
|
||||
rct_drawpixelinfo clippedDpi;
|
||||
if (clip_drawpixelinfo(&clippedDpi, dpi, w->x + 4, w->y + 18, 168, 78)) {
|
||||
substituteElement = &g1Elements[0];
|
||||
tmpElement = *substituteElement;
|
||||
rct_g1_element *substituteElement = &g1Elements[0];
|
||||
rct_g1_element tmpElement = *substituteElement;
|
||||
substituteElement->offset = _window_track_place_mini_preview;
|
||||
substituteElement->width = TRACK_MINI_PREVIEW_WIDTH;
|
||||
substituteElement->height = TRACK_MINI_PREVIEW_HEIGHT;
|
||||
|
@ -612,7 +458,151 @@ static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
|||
}
|
||||
|
||||
// Price
|
||||
if (_window_track_place_last_cost != MONEY32_UNDEFINED)
|
||||
if (!(gParkFlags & PARK_FLAGS_NO_MONEY))
|
||||
gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, 0, &_window_track_place_last_cost);
|
||||
if (_window_track_place_last_cost != MONEY32_UNDEFINED && !(gParkFlags & PARK_FLAGS_NO_MONEY)) {
|
||||
gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, 0, &_window_track_place_last_cost);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D1845
|
||||
*/
|
||||
static void window_track_place_draw_mini_preview(rct_track_td6 *td6)
|
||||
{
|
||||
window_track_place_clear_mini_preview();
|
||||
|
||||
// First pass is used to determine the width and height of the image so it can centre it
|
||||
rct_xy16 min = { 0, 0 };
|
||||
rct_xy16 max = { 0, 0 };
|
||||
for (int pass = 0; pass < 2; pass++) {
|
||||
rct_xy16 origin = { 0, 0 };
|
||||
if (pass == 1) {
|
||||
origin.x -= ((max.x + min.x) >> 6) << 5;
|
||||
origin.y -= ((max.y + min.y) >> 6) << 5;
|
||||
}
|
||||
|
||||
if (td6->type == RIDE_TYPE_MAZE) {
|
||||
window_track_place_draw_mini_preview_maze(td6, pass, origin, &min, &max);
|
||||
} else {
|
||||
window_track_place_draw_mini_preview_track(td6, pass, origin, &min, &max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void window_track_place_draw_mini_preview_track(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max)
|
||||
{
|
||||
uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
|
||||
rct_td6_track_element *trackElement = td6->track_elements;
|
||||
while (trackElement->type != 255) {
|
||||
int trackType = trackElement->type;
|
||||
if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) {
|
||||
trackType = 255;
|
||||
}
|
||||
|
||||
// Follow a single track piece shape
|
||||
const rct_preview_track *trackBlock = TrackBlocks[trackType];
|
||||
while (trackBlock->index != 255) {
|
||||
sint16 x = origin.x;
|
||||
sint16 y = origin.y;
|
||||
map_offset_with_rotation(&x, &y, trackBlock->x, trackBlock->y, rotation);
|
||||
|
||||
if (pass == 0) {
|
||||
min->x = min(min->x, x);
|
||||
max->x = max(max->x, x);
|
||||
min->y = min(min->y, y);
|
||||
max->y = max(max->y, y);
|
||||
} else {
|
||||
rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y);
|
||||
if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) {
|
||||
uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition);
|
||||
|
||||
uint8 bits = trackBlock->var_08 << (rotation & 3);
|
||||
bits = (bits & 0x0F) | ((bits & 0xF0) >> 4);
|
||||
|
||||
// Station track is a lighter colour
|
||||
uint8 colour = RCT2_ADDRESS(0x0099BA64, uint8)[trackType * 16] & 0x10 ? 222 : 218;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (bits & 1) pixel[338 + i] = colour;
|
||||
if (bits & 2) pixel[168 + i] = colour;
|
||||
if (bits & 4) pixel[ 2 + i] = colour;
|
||||
if (bits & 8) pixel[172 + i] = colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
trackBlock++;
|
||||
}
|
||||
|
||||
// Change rotation and next position based on track curvature
|
||||
rotation &= 3;
|
||||
const rct_track_coordinates* track_coordinate = &TrackCoordinates[trackType];
|
||||
|
||||
trackType *= 10;
|
||||
map_offset_with_rotation(&origin.x, &origin.y, track_coordinate->x, track_coordinate->y, rotation);
|
||||
rotation += track_coordinate->rotation_end - track_coordinate->rotation_begin;
|
||||
rotation &= 3;
|
||||
if (track_coordinate->rotation_end & 4) {
|
||||
rotation |= 4;
|
||||
}
|
||||
if (!(rotation & 4)) {
|
||||
origin.x += TileDirectionDelta[rotation].x;
|
||||
origin.y += TileDirectionDelta[rotation].y;
|
||||
}
|
||||
trackElement++;
|
||||
}
|
||||
}
|
||||
|
||||
static void window_track_place_draw_mini_preview_maze(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max)
|
||||
{
|
||||
uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
|
||||
rct_td6_maze_element *mazeElement = td6->maze_elements;
|
||||
while (mazeElement->all != 0) {
|
||||
sint16 x = mazeElement->x * 32;
|
||||
sint16 y = mazeElement->y * 32;
|
||||
rotate_map_coordinates(&x, &y, rotation);
|
||||
|
||||
x += origin.x;
|
||||
y += origin.y;
|
||||
|
||||
if (pass == 0) {
|
||||
min->x = min(min->x, x);
|
||||
max->x = max(max->x, x);
|
||||
min->y = min(min->y, y);
|
||||
max->y = max(max->y, y);
|
||||
} else {
|
||||
rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y);
|
||||
if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) {
|
||||
uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition);
|
||||
|
||||
// Entrance or exit is a lighter colour
|
||||
uint8 colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
pixel[338 + i] = colour;
|
||||
pixel[168 + i] = colour;
|
||||
pixel[ 2 + i] = colour;
|
||||
pixel[172 + i] = colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
mazeElement++;
|
||||
}
|
||||
}
|
||||
|
||||
static rct_xy16 draw_mini_preview_get_pixel_position(sint16 x, sint16 y)
|
||||
{
|
||||
return (rct_xy16) {
|
||||
80 + ((y / 32) - (x / 32)) * 4,
|
||||
38 + ((y / 32) + (x / 32)) * 2
|
||||
};
|
||||
}
|
||||
|
||||
static bool draw_mini_preview_is_pixel_in_bounds(rct_xy16 pixel)
|
||||
{
|
||||
return pixel.x >= 0 && pixel.y >= 0 && pixel.x <= 160 && pixel.y <= 75;
|
||||
}
|
||||
|
||||
static uint8 *draw_mini_preview_get_pixel_ptr(rct_xy16 pixel)
|
||||
{
|
||||
return &_window_track_place_mini_preview[pixel.y * TRACK_MINI_PREVIEW_WIDTH + pixel.x];
|
||||
}
|
||||
|
|
|
@ -1820,16 +1820,7 @@ money32 map_set_land_ownership(uint8 flags, sint16 x1, sint16 y1, sint16 x2, sin
|
|||
y1 = clamp(0, y1, gMapSizeUnits);
|
||||
x2 = min(x2, gMapSizeUnits);
|
||||
y2 = min(y2, gMapSizeUnits);
|
||||
for (sint16 y = y1; y <= y2; y += 32) {
|
||||
for (sint16 x = x1; x <= x2; x += 32) {
|
||||
if (x > gMapSizeUnits)
|
||||
continue;
|
||||
if (y > gMapSizeUnits)
|
||||
continue;
|
||||
|
||||
map_buy_land_rights(x, y, x2, y2, 6, flags | (newOwnership << 8));
|
||||
}
|
||||
}
|
||||
map_buy_land_rights(x1, y1, x2, y2, 6, flags | (newOwnership << 8));
|
||||
|
||||
if (!(RCT2_GLOBAL(0x9E2E28, uint8) & 1)) {
|
||||
return 0;
|
||||
|
@ -2925,8 +2916,8 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi
|
|||
gCommandPosition.x += 16;
|
||||
gCommandPosition.y += 16;
|
||||
if(game_is_not_paused() || gCheatsBuildInPauseMode){
|
||||
if(sub_68B044()){
|
||||
if(RCT2_GLOBAL(0x009D8150, uint8) & 1 || (x <= gMapSizeMaxXY && y <= gMapSizeMaxXY)){
|
||||
if (sub_68B044()) {
|
||||
if ((byte_9D8150 & 1) || (x <= gMapSizeMaxXY && y <= gMapSizeMaxXY)) {
|
||||
rct_scenery_entry* scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks[scenery_type];
|
||||
if(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE || !(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG9)){
|
||||
if(scenery_entry->small_scenery.flags & (SMALL_SCENERY_FLAG9 | SMALL_SCENERY_FLAG24 | SMALL_SCENERY_FLAG25)){
|
||||
|
@ -5494,3 +5485,25 @@ rct_map_element *map_get_track_element_at_with_direction_from_ride(int x, int y,
|
|||
|
||||
return NULL;
|
||||
};
|
||||
|
||||
void map_offset_with_rotation(sint16 *x, sint16 *y, sint16 offsetX, sint16 offsetY, uint8 rotation)
|
||||
{
|
||||
switch (rotation & 3) {
|
||||
case MAP_ELEMENT_DIRECTION_WEST:
|
||||
*x += offsetX;
|
||||
*y += offsetY;
|
||||
break;
|
||||
case MAP_ELEMENT_DIRECTION_NORTH:
|
||||
*x += offsetY;
|
||||
*y -= offsetX;
|
||||
break;
|
||||
case MAP_ELEMENT_DIRECTION_EAST:
|
||||
*x -= offsetX;
|
||||
*y -= offsetY;
|
||||
break;
|
||||
case MAP_ELEMENT_DIRECTION_SOUTH:
|
||||
*x -= offsetY;
|
||||
*y += offsetX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -425,6 +425,8 @@ bool map_large_scenery_get_origin(
|
|||
int *outX, int *outY, int *outZ, rct_map_element** outElement
|
||||
);
|
||||
|
||||
void map_offset_with_rotation(sint16 *x, sint16 *y, sint16 offsetX, sint16 offsetY, uint8 rotation);
|
||||
|
||||
rct_map_element *map_get_track_element_at(int x, int y, int z);
|
||||
rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int trackType);
|
||||
rct_map_element *map_get_track_element_at_of_type_seq(int x, int y, int z, int trackType, int sequence);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "../common.h"
|
||||
#include "../object.h"
|
||||
#include "../world/map.h"
|
||||
|
||||
typedef struct {
|
||||
uint32 flags; // 0x06
|
||||
|
|
Loading…
Reference in New Issue