diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 18045882fd..ac0f802b66 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -271,6 +271,7 @@ + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index 867348d741..9b8fd741cb 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -591,8 +591,8 @@ Source\Windows - + @@ -905,6 +905,7 @@ Source\Core + Resource Files diff --git a/src/core/List.hpp b/src/core/List.hpp index f8e6cc5d25..87d17e4648 100644 --- a/src/core/List.hpp +++ b/src/core/List.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "../common.h" @@ -89,4 +90,17 @@ public: Guard::ArgumentInRange(index, (size_t)0, this->size() - 1); return std::vector::operator[](index); } + + size_t IndexOf(std::function predicate) + { + for (size_t i = 0; i < this->size(); i++) + { + T item = std::vector::operator[](i); + if (predicate(item)) + { + return i; + } + } + return SIZE_MAX; + } }; diff --git a/src/core/Path.cpp b/src/core/Path.cpp index 514f53ddeb..639d5618ee 100644 --- a/src/core/Path.cpp +++ b/src/core/Path.cpp @@ -33,6 +33,29 @@ namespace Path return buffer; } + const utf8 * GetFileName(const utf8 * path) + { + const utf8 * lastPathSeperator = nullptr; + for (const utf8 * ch = path; *ch != '\0'; ch++) + { + if (*ch == platform_get_path_separator()) + { + lastPathSeperator = ch; + } +#ifdef _WINDOWS_ + // Windows also allows forward slashes in paths + else if (*ch == '/') + { + lastPathSeperator = ch; + } +#endif + } + + return lastPathSeperator == nullptr ? + path : + lastPathSeperator + 1; + } + utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path) { const utf8 * lastDot = nullptr; diff --git a/src/core/Path.hpp b/src/core/Path.hpp index b3aa163f72..a74079bf53 100644 --- a/src/core/Path.hpp +++ b/src/core/Path.hpp @@ -9,6 +9,7 @@ namespace Path { utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path); + const utf8 * GetFileName(const utf8 * path); utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path); utf8 * GetAbsolute(utf8 * buffer, size_t bufferSize, const utf8 * relativePath); bool Equals(const utf8 * a, const utf8 * b); diff --git a/src/rct1.c b/src/rct1.c index 60b1cc9eeb..d0d76be0e9 100644 --- a/src/rct1.c +++ b/src/rct1.c @@ -2149,58 +2149,6 @@ static int rct1_get_sc_number(const char *path) } } -bool rct1_load_saved_game(const char *path) -{ - rct1_s4 *s4; - - s4 = malloc(sizeof(rct1_s4)); - if (!rct1_read_sv4(path, s4)) { - free(s4); - return false; - } - rct1_import_s4_properly(s4); - - free(s4); - - game_load_init(); - return true; -} - -bool rct1_load_scenario(const char *path) -{ - rct1_s4 *s4; - - s4 = malloc(sizeof(rct1_s4)); - if (!rct1_read_sc4(path, s4)) { - free(s4); - return false; - } - rct1_import_s4_properly(s4); - - int scNumber = rct1_get_sc_number(path); - if (scNumber != -1) { - rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - - source_desc sourceDesc; - if (scenario_get_source_desc_by_id(scNumber, &sourceDesc)) { - rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(sourceDesc.title, localisedStringIds)) { - if (localisedStringIds[0] != STR_NONE) { - safe_strcpy(s6Info->name, language_get_string(localisedStringIds[0]), 64); - } - if (localisedStringIds[2] != STR_NONE) { - safe_strcpy(s6Info->details, language_get_string(localisedStringIds[2]), 256); - } - } - } - } - - free(s4); - - scenario_begin(); - return true; -} - static void rct1_import_map_elements(rct1_s4 *s4) { memcpy(gMapElements, s4->map_elements, 0xC000 * sizeof(rct_map_element)); diff --git a/src/rct1/S4Importer.cpp b/src/rct1/S4Importer.cpp index fd2257627f..2efecc2a2a 100644 --- a/src/rct1/S4Importer.cpp +++ b/src/rct1/S4Importer.cpp @@ -1,60 +1,72 @@ #include -#include "../common.h" +#include "S4Importer.h" + +#include "../core/Exception.hpp" #include "../core/List.hpp" +#include "../core/Path.hpp" +#include "../core/String.hpp" #include "../core/Util.hpp" #include "import.h" + extern "C" { + #include "../audio/audio.h" + #include "../game.h" + #include "../interface/window.h" + #include "../localisation/date.h" + #include "../localisation/localisation.h" + #include "../management/finance.h" + #include "../object.h" + #include "../peep/staff.h" #include "../rct1.h" #include "../util/sawyercoding.h" + #include "../util/util.h" + #include "../world/footpath.h" + #include "../world/map_animation.h" + #include "../world/park.h" } -/** - * Class to import RollerCoaster Tycoon 1 scenarios (*.SC4) and saved games (*.SV4). - */ -class S4Importer +void S4Importer::LoadSavedGame(const utf8 * path) { -public: + if (!rct1_read_sv4(path, &_s4)) { + throw Exception("Unable to load SV4."); + } + _s4Path = path; +} -private: - rct1_s4 _s4; - uint8 _gameVersion; +void S4Importer::LoadScenario(const utf8 * path) +{ + if (!rct1_read_sc4(path, &_s4)) { + throw Exception("Unable to load SC4."); + } + _s4Path = path; +} - // Lists of dynamic object entries - List _rideEntries; - List _smallSceneryEntries; - List _largeSceneryEntries; - List _wallEntries; - List _sceneryGroupEntries; +void S4Importer::Import() +{ + Initialise(); - // Lookup tables for converting from RCT1 hard coded types to the new dynamic object entries - uint8 _rideTypeToRideEntryMap[96]; - uint8 _vehicleTypeToRideEntryMap[96]; - uint8 _smallSceneryTypeToEntryMap[96]; - uint8 _largeSceneryTypeToEntryMap[96]; - uint8 _wallSceneryTypeToEntryMap[96]; - uint8 _sceneryThemeTypeToEntryMap[24]; + CreateAvailableObjectMappings(); + LoadObjects(); - void Initialise(); + ImportRides(); + ImportRideMeasurements(); + ImportMapElements(); + ImportMapAnimations(); + ImportPeepSpawns(); + ImportFinance(); + ImportResearch(); + ImportParkName(); - /** - * Scans the map and research list for all the object types used and builds lists and - * lookup tables for converting from hard coded RCT1 object types to dynamic object entries. - */ - void CreateAvailableObjectMappings(); - void AddAvailableEntriesFromResearchList(); - void AddAvailableEntriesFromMap(); - void AddAvailableEntriesFromRides(); + RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = _s4.park_flags; + RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_ANTI_CHEAT_DEPRECATED; - void AddEntryForRideType(uint8 rideType); - void AddEntryForVehicleType(uint8 rideType, uint8 vehicleType); - void AddEntryForSmallScenery(uint8 smallSceneryType); - void AddEntriesForSceneryTheme(uint8 sceneryThemeType); - - const rct1_research_item * GetResearchList(size_t * count); -}; + ImportScenarioNameDetails(); + ImportScenarioObjective(); + ImportSavedView(); +} void S4Importer::Initialise() { @@ -64,8 +76,33 @@ void S4Importer::Initialise() Memory::Set(_vehicleTypeToRideEntryMap, 255, sizeof(_vehicleTypeToRideEntryMap)); Memory::Set(_smallSceneryTypeToEntryMap, 255, sizeof(_smallSceneryTypeToEntryMap)); Memory::Set(_largeSceneryTypeToEntryMap, 255, sizeof(_largeSceneryTypeToEntryMap)); - Memory::Set(_wallSceneryTypeToEntryMap, 255, sizeof(_wallSceneryTypeToEntryMap)); + Memory::Set(_wallTypeToEntryMap, 255, sizeof(_wallTypeToEntryMap)); Memory::Set(_sceneryThemeTypeToEntryMap, 255, sizeof(_sceneryThemeTypeToEntryMap)); + + uint16 mapSize = _s4.map_size == 0 ? 128 : _s4.map_size; + + // Do map initialisation, same kind of stuff done when loading scenario editor + audio_pause_sounds(); + audio_unpause_sounds(); + object_unload_all(); + map_init(mapSize); + banner_init(); + reset_park_entrances(); + user_string_clear_all(); + reset_sprite_list(); + ride_init_all(); + window_guest_list_init_vars_a(); + staff_reset_modes(); + park_init(); + finance_init(); + date_reset(); + window_guest_list_init_vars_b(); + window_staff_list_init_vars(); + RCT2_GLOBAL(0x0141F570, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_SHOW_REAL_GUEST_NAMES; + window_new_ride_init_vars(); + RCT2_GLOBAL(0x0141F571, uint8) = 4; + news_item_init_queue(); } void S4Importer::CreateAvailableObjectMappings() @@ -142,6 +179,12 @@ void S4Importer::AddAvailableEntriesFromMap() case MAP_ELEMENT_TYPE_SCENERY: AddEntryForSmallScenery(mapElement->properties.scenery.type); break; + case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE: + AddEntryForLargeScenery(mapElement->properties.scenerymultiple.type & MAP_ELEMENT_LARGE_TYPE_MASK); + break; + case MAP_ELEMENT_TYPE_FENCE: + AddEntryForWall(mapElement->properties.fence.type); + break; } if (map_element_is_last_for_tile(mapElement++)) @@ -166,7 +209,7 @@ void S4Importer::AddEntryForRideType(uint8 rideType) { if (_rideTypeToRideEntryMap[rideType] == 255) { - const char * entryName = RCT1::Tables::GetRideTypeObject(rideType); + const char * entryName = RCT1::GetRideTypeObject(rideType); _rideEntries.Add(entryName); _rideTypeToRideEntryMap[rideType] = (uint8)_rideEntries.GetCount(); } @@ -176,7 +219,7 @@ void S4Importer::AddEntryForVehicleType(uint8 rideType, uint8 vehicleType) { if (_vehicleTypeToRideEntryMap[rideType] == 255) { - const char * entryName = RCT1::Tables::GetVehicleObject(vehicleType); + const char * entryName = RCT1::GetVehicleObject(vehicleType); uint8 rideEntryIndex = (uint8)_rideEntries.GetCount(); _vehicleTypeToRideEntryMap[vehicleType] = rideEntryIndex; @@ -191,15 +234,35 @@ void S4Importer::AddEntryForSmallScenery(uint8 smallSceneryType) { if (_smallSceneryTypeToEntryMap[smallSceneryType] == 255) { - const char * entryName = RCT1::Tables::GetSmallSceneryObject(smallSceneryType); + const char * entryName = RCT1::GetSmallSceneryObject(smallSceneryType); _smallSceneryEntries.Add(entryName); - _smallSceneryTypeToEntryMap[smallSceneryType] = (uint8)_rideEntries.GetCount(); + _smallSceneryTypeToEntryMap[smallSceneryType] = (uint8)_smallSceneryEntries.GetCount(); + } +} + +void S4Importer::AddEntryForLargeScenery(uint8 largeSceneryType) +{ + if (_largeSceneryTypeToEntryMap[largeSceneryType] == 255) + { + const char * entryName = RCT1::GetLargeSceneryObject(largeSceneryType); + _largeSceneryEntries.Add(entryName); + _largeSceneryTypeToEntryMap[largeSceneryType] = (uint8)_largeSceneryEntries.GetCount(); + } +} + +void S4Importer::AddEntryForWall(uint8 wallType) +{ + if (_wallTypeToEntryMap[wallType] == 255) + { + const char * entryName = RCT1::GetWallObject(wallType); + _wallEntries.Add(entryName); + _wallTypeToEntryMap[wallType] = (uint8)_wallEntries.GetCount(); } } void S4Importer::AddEntriesForSceneryTheme(uint8 sceneryThemeType) { - const char * entryName = RCT1::Tables::GetSceneryGroupObject(sceneryThemeType); + const char * entryName = RCT1::GetSceneryGroupObject(sceneryThemeType); _sceneryThemeTypeToEntryMap[sceneryThemeType] = (uint8)_sceneryGroupEntries.GetCount(); _sceneryGroupEntries.Add(entryName); @@ -207,6 +270,920 @@ void S4Importer::AddEntriesForSceneryTheme(uint8 sceneryThemeType) // TODO add entries for all scenery items belonging to scenery group } +void S4Importer::ImportRides() +{ + for (int i = 0; i < MAX_RIDES; i++) + { + if (_s4.rides[i].type != RIDE_TYPE_NULL) + { + ImportRide(get_ride(i), &_s4.rides[i]); + } + } +} + +void S4Importer::ImportRide(rct_ride * dst, rct1_ride * src) +{ + memset(dst, 0, sizeof(rct_ride)); + + dst->type = RCT1::GetRideType(src->type); + dst->subtype = _vehicleTypeToRideEntryMap[src->vehicle_type]; + + rct_ride_entry * rideEntry = get_ride_entry(dst->subtype); + + // Ride name + dst->name = 0; + if (is_user_string_id(src->name)) + { + const char * rideName = GetUserString(src->name); + if (rideName[0] != 0) + { + rct_string_id rideNameStringId = user_string_allocate(4, rideName); + if (rideNameStringId != 0) + { + dst->name = rideNameStringId; + } + } + } + if (dst->name == 0) + { + dst->name = 1; + + uint16 * args = (uint16*)&dst->name_arguments; + args[0] = 2 + dst->type; + args[1] = src->name_argument_number; + } + + // We can't convert vehicles yet so just close the ride + dst->status = RIDE_STATUS_CLOSED; + + // Flags + if (src->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) dst->lifecycle_flags |= RIDE_LIFECYCLE_ON_RIDE_PHOTO; + if (src->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) dst->lifecycle_flags |= RIDE_LIFECYCLE_MUSIC; + if (src->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) dst->lifecycle_flags |= RIDE_LIFECYCLE_INDESTRUCTIBLE; + if (src->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) dst->lifecycle_flags |= RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK; + + // Station + dst->overall_view = src->overall_view; + for (int i = 0; i < 4; i++) + { + dst->station_starts[i] = src->station_starts[i]; + dst->station_heights[i] = src->station_height[i] / 2; + dst->station_length[i] = src->station_length[i]; + dst->station_depart[i] = src->station_light[i]; + + // Use src->station_depart[i] when we import with guests and vehicles intact + dst->train_at_station[i] = 0xFF; + + dst->entrances[i] = src->entrance[i]; + dst->exits[i] = src->exit[i]; + dst->queue_time[i] = src->queue_time[i]; + dst->last_peep_in_queue[i] = 0xFFFF; + } + dst->num_stations = src->num_stations; + + for (int i = 0; i < 32; i++) + { + dst->vehicles[i] = SPRITE_INDEX_NULL; + } + dst->num_vehicles = src->num_trains; + dst->num_cars_per_train = src->num_cars_per_train + rideEntry->zero_cars; + dst->proposed_num_vehicles = src->num_trains; + dst->max_trains = 32; + dst->proposed_num_cars_per_train = src->num_cars_per_train + rideEntry->zero_cars; + + // Operation + dst->depart_flags = src->depart_flags; + dst->min_waiting_time = src->min_waiting_time; + dst->max_waiting_time = src->max_waiting_time; + dst->operation_option = src->operation_option; + dst->num_circuits = 1; + dst->min_max_cars_per_train = (rideEntry->min_cars_in_train << 4) | rideEntry->max_cars_in_train; + + // RCT1 used 5mph / 8 km/h for every lift hill + dst->lift_hill_speed = 5; + + if (_gameVersion == FILE_VERSION_RCT1) + { + // Original RCT had no music settings, take default style + dst->music = RCT2_ADDRESS(0x0097D4F4, uint8)[dst->type * 8]; + } + else + { + dst->music = src->music; + } + + if (src->operating_mode == RCT1_RIDE_MODE_POWERED_LAUNCH) + { + // Launched rides never passed through the station in RCT1. + dst->mode = RIDE_MODE_POWERED_LAUNCH; + } + else + { + dst->mode = src->operating_mode; + } + + // Colours + dst->colour_scheme_type = src->colour_scheme; + if (_gameVersion == FILE_VERSION_RCT1) + { + dst->track_colour_main[0] = RCT1::GetColour(src->track_primary_colour); + dst->track_colour_additional[0] = RCT1::GetColour(src->track_secondary_colour); + dst->track_colour_supports[0] = RCT1::GetColour(src->track_support_colour); + } + else + { + for (int i = 0; i < 4; i++) + { + dst->track_colour_main[i] = RCT1::GetColour(src->track_colour_main[i]); + dst->track_colour_additional[i] = RCT1::GetColour(src->track_colour_additional[i]); + dst->track_colour_supports[i] = RCT1::GetColour(src->track_colour_supports[i]); + } + // Entrance styles were introduced with AA. They correspond directly with those in RCT2. + dst->entrance_style = src->entrance_style; + } + + if (_gameVersion < FILE_VERSION_RCT1_LL && dst->type == RIDE_TYPE_MERRY_GO_ROUND) + { + // The merry-go-round in pre-LL versions was always yellow with red + dst->vehicle_colours[0].body_colour = COLOUR_YELLOW; + dst->vehicle_colours[0].trim_colour = COLOUR_BRIGHT_RED; + } + else + { + for (int i = 0; i < 12; i++) + { + dst->vehicle_colours[i].body_colour = RCT1::GetColour(src->vehicle_colours[i].body); + dst->vehicle_colours[i].trim_colour = RCT1::GetColour(src->vehicle_colours[i].trim); + } + } + + // Fix other Z + // dst->start_drop_height /= 2; + // dst->highest_drop_height = 1; + // if (dst->cur_test_track_z != 255) + // { + // dst->cur_test_track_z /= 2; + // } + // dst->chairlift_bullwheel_z[0] /= 2; + // dst->chairlift_bullwheel_z[1] /= 2; + + // Maintenance + dst->build_date = src->build_date; + dst->inspection_interval = src->inspection_interval; + dst->last_inspection = src->last_inspection; + dst->reliability = src->reliability; + dst->unreliability_factor = src->unreliability_factor; + dst->breakdown_reason = src->breakdown_reason; + + // Finance + dst->upkeep_cost = src->upkeep_cost; + dst->price = src->price; + dst->income_per_hour = src->income_per_hour; + + dst->value = src->value; + dst->satisfaction = 255; + dst->satisfaction_time_out = 0; + dst->satisfaction_next = 0; + dst->popularity = src->popularity; + dst->popularity_next = src->popularity_next; + dst->popularity_time_out = src->popularity_time_out; + + dst->music_tune_id = 255; + dst->measurement_index = 255; + dst->excitement = (ride_rating)-1; +} + +void S4Importer::ImportRideMeasurements() +{ + for (int i = 0; i < MAX_RIDE_MEASUREMENTS; i++) + { + rct_ride_measurement * dst = get_ride_measurement(i); + rct_ride_measurement * src = &_s4.ride_measurements[i]; + ImportRideMeasurement(dst, src); + } +} + +void S4Importer::ImportRideMeasurement(rct_ride_measurement * dst, rct_ride_measurement * src) +{ + // Not yet supported + // *dst = *src; + // for (int i = 0; i < RIDE_MEASUREMENT_MAX_ITEMS; i++) + // { + // dst->altitude[i] /= 2; + // } +} + +void S4Importer::ImportPeepSpawns() +{ + for (int i = 0; i < 2; i++) + { + gPeepSpawns[i] = _s4.peep_spawn[i]; + } +} + +void S4Importer::ImportMapAnimations() +{ + // This is sketchy, ideally we should try to re-create them + rct_map_animation * s4Animations = (rct_map_animation*)_s4.map_animations; + for (int i = 0; i < 1000; i++) + { + gAnimatedObjects[i] = s4Animations[i]; + gAnimatedObjects[i].baseZ /= 2; + } + RCT2_GLOBAL(0x0138B580, uint16) = _s4.num_map_animations; +} + +void S4Importer::ImportFinance() +{ + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, uint32) = ENCRYPT_MONEY(_s4.cash); + RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) = _s4.park_entrance_fee; +} + +void S4Importer::LoadObjects() +{ + LoadObjects(OBJECT_TYPE_RIDE, _rideEntries); + LoadObjects(OBJECT_TYPE_SMALL_SCENERY, _smallSceneryEntries); + LoadObjects(OBJECT_TYPE_LARGE_SCENERY, _largeSceneryEntries); + LoadObjects(OBJECT_TYPE_WALLS, _wallEntries); + LoadObjects(OBJECT_TYPE_SCENERY_SETS, _sceneryGroupEntries); + LoadObjects(OBJECT_TYPE_PATHS, List({ + "TARMAC ", + "TARMACB ", + "PATHSPCE", + "PATHDIRT", + "ROAD ", + "PATHCRZY", + "PATHASH " + })); + LoadObjects(OBJECT_TYPE_PATH_BITS, List({ + "LAMP1 ", + "LAMP2 ", + "LITTER1 ", + "BENCH1 ", + "JUMPFNT1", + "LAMP3 ", + "LAMP4 ", + "JUMPSNW1" + })); + LoadObjects(OBJECT_TYPE_BANNERS, List({ + "BN1 ", + "BN2 ", + "BN3 ", + "BN4 ", + "BN5 ", + "BN6 ", + "BN7 ", + "BN8 ", + "BN9 " + })); + LoadObjects(OBJECT_TYPE_PARK_ENTRANCE, List({ "PKENT1 " })); + LoadObjects(OBJECT_TYPE_WATER, List({ "WTRCYAN " })); +} + +void S4Importer::LoadObjects(uint8 objectType, List entries) +{ + for (const char * objectName : entries) + { + rct_object_entry entry; + entry.flags = 0x00008000 + objectType; + Memory::Copy(entry.name, objectName, 8); + entry.checksum = 0; + + if (!object_load_chunk(objectType, &entry, NULL)) + { + log_error("Failed to load %s.", objectName); + throw Exception("Failed to load object."); + } + } +} + +void S4Importer::ImportMapElements() +{ + memcpy(gMapElements, _s4.map_elements, 0xC000 * sizeof(rct_map_element)); + ClearExtraTileEntries(); + FixColours(); + FixZ(); + FixPaths(); + FixWalls(); + FixBanners(); + FixTerrain(); + FixEntrancePositions(); + FixMapElementEntryTypes(); +} + +void S4Importer::ImportResearch() +{ + // All available objects must be loaded before this method is called as it + // requires them to correctly insert objects into the research list + + research_reset_items(); + + size_t researchListCount; + const rct1_research_item * researchList = GetResearchList(&researchListCount); + + // Initialise the "seen" tables + Memory::Set(_researchRideEntryUsed, 0, sizeof(_researchRideEntryUsed)); + Memory::Set(_researchRideTypeUsed, 0, sizeof(_researchRideTypeUsed)); + + // The first six scenery groups are always available + for (int i = 0; i < 6; i++) + { + research_insert_scenery_group_entry(i, true); + } + + bool researched = true; + for (size_t i = 0; i < researchListCount; i++) + { + const rct1_research_item * researchItem = &researchList[i]; + if (researchItem->item == RCT1_RESEARCH_END_AVAILABLE) + { + researched = false; + } + else if (researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE || + researchItem->item == RCT1_RESEARCH_END) + { + break; + } + + switch (researchItem->category) { + case RCT1_RESEARCH_CATEGORY_THEME: + { + uint8 rct1SceneryTheme = researchItem->item; + uint8 sceneryGroupEntryIndex = _sceneryThemeTypeToEntryMap[rct1SceneryTheme]; + research_insert_scenery_group_entry(sceneryGroupEntryIndex, researched); + break; + } + case RCT1_RESEARCH_CATEGORY_RIDE: + { + uint8 rct1RideType = researchItem->item; + uint8 rideEntryIndex = rct1RideType; + rct_ride_entry *rideEntry = get_ride_entry(rideEntryIndex); + + // Add all vehicles for this ride type that are researched or before this research item + uint32 numVehicles = 0; + for (size_t j = 0; j < researchListCount; j++) + { + const rct1_research_item *researchItem2 = &researchList[j]; + if (researchItem2->item == RCT1_RESEARCH_END_AVAILABLE) + { + break; + } + + if (researchItem->category == RCT1_RESEARCH_CATEGORY_VEHICLE && + researchItem->related_ride == rct1RideType) + { + // Only add the vehicles that were listed before this ride, otherwise we might + // change the research order + if (j < i) + { + InsertResearchVehicle(researchItem, researched); + } + numVehicles++; + } + } + + if (numVehicles == 0) + { + // No vehicles found so just add the default for this ride + if (!_researchRideEntryUsed[rideEntryIndex]) + { + _researchRideEntryUsed[rideEntryIndex] = true; + research_insert_ride_entry(rideEntryIndex, researched); + } + } + break; + } + case RCT1_RESEARCH_CATEGORY_VEHICLE: + // Only add vehicle if the related ride has been seen, this to make sure that vehicles + // are researched only after the ride has been researched + if (_researchRideTypeUsed[researchItem->related_ride]) + { + InsertResearchVehicle(researchItem, researched); + } + break; + case RCT1_RESEARCH_CATEGORY_SPECIAL: + // Not supported + break; + } + } + + research_remove_non_separate_vehicle_types(); +} + +void S4Importer::InsertResearchVehicle(const rct1_research_item * researchItem, bool researched) +{ + uint8 rct1RideType = researchItem->related_ride; + uint8 vehicle = researchItem->item; + + uint8 rideEntryIndex = _vehicleTypeToRideEntryMap[vehicle]; + if (!_researchRideEntryUsed[rideEntryIndex]) + { + _researchRideEntryUsed[rideEntryIndex] = true; + research_insert_ride_entry(rideEntryIndex, researched); + } +} + +void S4Importer::ImportParkName() +{ + const char * parkName = _s4.scenario_name; + if (is_user_string_id((rct_string_id)_s4.park_name_string_index)) + { + const char * userString = GetUserString(_s4.park_name_string_index); + if (userString[0] != '\0') + { + parkName = userString; + } + } + + rct_string_id stringId = user_string_allocate(4, parkName); + if (stringId != 0) + { + RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id) = stringId; + RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32) = 0; + } +} + +void S4Importer::ImportScenarioNameDetails() +{ + rct_s6_info * s6Info = (rct_s6_info*)0x0141F570; + + String::Set(s6Info->name, sizeof(s6Info->name), _s4.scenario_name); + String::Set(s6Info->details, sizeof(s6Info->details), ""); + + int scNumber = GetSCNumber(); + if (scNumber != -1) + { + source_desc sourceDesc; + if (scenario_get_source_desc_by_id(scNumber, &sourceDesc)) + { + rct_string_id localisedStringIds[3]; + if (language_get_localised_scenario_strings(sourceDesc.title, localisedStringIds)) + { + if (localisedStringIds[0] != STR_NONE) + { + String::Set(s6Info->name, sizeof(s6Info->name), language_get_string(localisedStringIds[0])); + } + if (localisedStringIds[2] != STR_NONE) + { + String::Set(s6Info->details, sizeof(s6Info->details), language_get_string(localisedStringIds[2])); + } + } + } + } +} + +void S4Importer::ImportScenarioObjective() +{ + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) = _s4.scenario_objective_type; + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8) = _s4.scenario_objective_years; + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_CURRENCY, uint32) = _s4.scenario_objective_currency; + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, uint16) = _s4.scenario_objective_num_guests; +} + +void S4Importer::ImportSavedView() +{ + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, uint16) = _s4.view_x; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, uint16) = _s4.view_y; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint8) = _s4.view_zoom; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION + 1, uint8) = _s4.view_rotation; +} + +void S4Importer::ClearExtraTileEntries() +{ + // Reset the map tile pointers + for (int i = 0; i < 0x10000; i++) + { + gMapElementTilePointers[i] = (rct_map_element *)-1; + } + + // Get the first free map element + rct_map_element * nextFreeMapElement = gMapElements; + for (int i = 0; i < 128 * 128; i++) + { + do { } while (!map_element_is_last_for_tile(nextFreeMapElement++)); + } + + rct_map_element * mapElement = gMapElements; + rct_map_element * * tilePointer = gMapElementTilePointers; + + // 128 rows of map data from RCT1 map + for (int x = 0; x < 128; x++) + { + // Assign the first half of this row + for (int y = 0; y < 128; y++) + { + *tilePointer++ = mapElement; + do { } while (!map_element_is_last_for_tile(mapElement++)); + } + + // Fill the rest of the row with blank tiles + for (int y = 0; y < 128; y++) + { + nextFreeMapElement->type = MAP_ELEMENT_TYPE_SURFACE; + nextFreeMapElement->flags = MAP_ELEMENT_FLAG_LAST_TILE; + nextFreeMapElement->base_height = 2; + nextFreeMapElement->clearance_height = 0; + nextFreeMapElement->properties.surface.slope = 0; + nextFreeMapElement->properties.surface.terrain = 0; + nextFreeMapElement->properties.surface.grass_length = GRASS_LENGTH_CLEAR_0; + nextFreeMapElement->properties.surface.ownership = 0; + *tilePointer++ = nextFreeMapElement++; + } + } + + // 128 extra rows left to fill with blank tiles + for (int y = 0; y < 128 * 256; y++) + { + nextFreeMapElement->type = MAP_ELEMENT_TYPE_SURFACE; + nextFreeMapElement->flags = MAP_ELEMENT_FLAG_LAST_TILE; + nextFreeMapElement->base_height = 2; + nextFreeMapElement->clearance_height = 0; + nextFreeMapElement->properties.surface.slope = 0; + nextFreeMapElement->properties.surface.terrain = 0; + nextFreeMapElement->properties.surface.grass_length = GRASS_LENGTH_CLEAR_0; + nextFreeMapElement->properties.surface.ownership = 0; + *tilePointer++ = nextFreeMapElement++; + } + + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*) = nextFreeMapElement; +} + +void S4Importer::FixColours() +{ + colour_t colour; + + // The following code would be worth doing if we were able to import sprites + // for (int i = 0; i < MAX_SPRITES; i++) + // { + // rct_unk_sprite * sprite = &(g_sprite_list[i].unknown); + // switch (sprite->sprite_identifier) { + // case SPRITE_IDENTIFIER_PEEP: + // { + // rct_peep * peep = (rct_peep*)sprite; + // peep->tshirt_colour = RCT1ColourConversionTable[peep->tshirt_colour]; + // peep->trousers_colour = RCT1ColourConversionTable[peep->trousers_colour]; + // peep->balloon_colour = RCT1ColourConversionTable[peep->balloon_colour]; + // peep->umbrella_colour = RCT1ColourConversionTable[peep->umbrella_colour]; + // peep->hat_colour = RCT1ColourConversionTable[peep->hat_colour]; + // break; + // } + // case SPRITE_IDENTIFIER_MISC: + // { + // rct_balloon * balloon = (rct_balloon*)sprite; + // balloon->colour = RCT1ColourConversionTable[balloon->colour]; + // balloon->var_2D = RCT1ColourConversionTable[balloon->var_2D]; + // break; + // } + // } + // } + + rct_map_element * mapElement = gMapElements; + while (mapElement < RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*)) + { + if (mapElement->base_height != 255) + { + switch (map_element_get_type(mapElement)) { + case MAP_ELEMENT_TYPE_SCENERY: + colour = RCT1::GetColour(mapElement->properties.scenery.colour_1 & 0x1F); + mapElement->properties.scenery.colour_1 &= 0xE0; + mapElement->properties.scenery.colour_1 |= colour; + + // Copied from [rct2: 0x006A2956] + switch (mapElement->properties.scenery.type) { + case 157: // TGE1 (Geometric Sculpture) + case 162: // TGE2 (Geometric Sculpture) + case 168: // TGE3 (Geometric Sculpture) + case 170: // TGE4 (Geometric Sculpture) + case 171: // TGE5 (Geometric Sculpture) + mapElement->properties.scenery.colour_2 = COLOUR_WHITE; + break; + } + break; + case MAP_ELEMENT_TYPE_FENCE: + colour = ((mapElement->type & 0xC0) >> 3) | + ((mapElement->properties.fence.type & 0xE0) >> 5); + colour = RCT1::GetColour(colour); + + mapElement->type &= 0x3F; + mapElement->properties.fence.type &= 0x1F; + mapElement->type |= (colour & 0x18) << 3; + mapElement->properties.fence.type |= (colour & 7) << 5; + break; + case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE: + colour = RCT1::GetColour(mapElement->properties.scenerymultiple.colour[0] & 0x1F); + mapElement->properties.scenerymultiple.colour[0] &= 0xE0; + mapElement->properties.scenerymultiple.colour[0] |= colour; + + colour = RCT1::GetColour(mapElement->properties.scenerymultiple.colour[1] & 0x1F); + mapElement->properties.scenerymultiple.colour[1] &= 0xE0; + mapElement->properties.scenerymultiple.colour[1] |= colour; + break; + } + } + mapElement++; + } +} + +void S4Importer::FixZ() +{ + // The following code would be useful if we imported sprites + // for (int i = 0; i < MAX_SPRITES; i++) + // { + // rct_unk_sprite * sprite = &(g_sprite_list[i].unknown); + // if (sprite->sprite_identifier == SPRITE_IDENTIFIER_PEEP) { + // rct_peep * peep = (rct_peep*)sprite; + // peep->next_z /= 2; + // RCT2_GLOBAL((int)peep + 0xCE, uint8) /= 2; + // } + // } + + rct_map_element * mapElement = gMapElements; + while (mapElement < RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*)) + { + if (mapElement->base_height != 255) + { + mapElement->base_height /= 2; + mapElement->clearance_height /= 2; + } + mapElement++; + } + RCT2_GLOBAL(0x01359208, uint16) = 7; +} + +// rct2: 0x0098BC9F +static const uint8 RCT1PathTypeConversionTable[96] = +{ + 0x80 | 0, 0x80 | 1, 0x80 | 2, 0x80 | 3, + 0x80 | 0, 0x80 | 1, 0x80 | 2, 0x80 | 3, + 0x80 | 0, 0x80 | 1, 0x80 | 2, 0x80 | 3, + 0x80 | 0, 0x80 | 1, 0x80 | 2, 0x80 | 3, + 0, 0, 0, 0, + 2, 2, 2, 2, + 1, 1, 1, 1, + 0, 0, 0, 0, + 3, 3, 3, 3, + 6, 6, 6, 6, + 0, 0, 0, 0, + 0, 0, 0, 0, + 5, 5, 5, 5, + 5, 5, 5, 5, + 5, 5, 5, 5, + 5, 5, 5, 5, + 4, 4, 4, 4, + 4, 4, 4, 4, + 4, 4, 4, 4, + 4, 4, 4, 4, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +// rct2: 0x0098BCFF +static const uint8 RCT1PathAdditionConversionTable[15] = +{ + 0, + 1, 2, 3, 4, 5, 6, 7, + 0x80 | 1, 0x80 | 2, 0x80 | 3, 0x80 | 4, 0x80 | 6, 0x80 | 7, + 8, +}; + +void S4Importer::FixPaths() +{ + rct_map_element * mapElement = gMapElements; + while (mapElement < RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*)) + { + switch (map_element_get_type(mapElement)) { + case MAP_ELEMENT_TYPE_PATH: + { + // Type + int pathType = ((mapElement->properties.path.type & 0xF0) >> 2) | (mapElement->type & 3); + int secondaryType = (mapElement->flags & 0x60) >> 5; + pathType = RCT1PathTypeConversionTable[pathType * 4 + secondaryType]; + + mapElement->type &= 0xFC; + mapElement->flags &= ~0x60; + mapElement->properties.path.type &= 0x0F; + footpath_scenery_set_is_ghost(mapElement, false); + if (pathType & 0x80) + { + mapElement->type |= 1; + } + mapElement->properties.path.type |= pathType << 4; + + // Additions + int additions = RCT1PathAdditionConversionTable[footpath_element_get_path_scenery(mapElement)]; + if (footpath_element_path_scenery_is_ghost(mapElement)) + { + footpath_scenery_set_is_ghost(mapElement, false); + mapElement->flags |= MAP_ELEMENT_FLAG_BROKEN; + } + else + { + mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN; + } + + footpath_element_set_path_scenery(mapElement, additions); + break; + } + case MAP_ELEMENT_TYPE_ENTRANCE: + if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) + { + int pathType = mapElement->properties.entrance.path_type; + mapElement->properties.entrance.path_type = RCT1PathTypeConversionTable[pathType * 4] & 0x7F; + } + break; + } + mapElement++; + } +} + +void S4Importer::FixWalls() +{ + for (int x = 0; x < 128; x++) + { + for (int y = 0; y < 128; y++) + { + rct_map_element * mapElement = map_get_first_element_at(x, y); + do + { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_FENCE) + { + rct_map_element originalMapElement = *mapElement; + map_element_remove(mapElement); + + uint8 var_05 = originalMapElement.properties.fence.item[0]; + uint16 var_06 = originalMapElement.properties.fence.item[1] | + (originalMapElement.properties.fence.item[2] << 8); + + for (int edge = 0; edge < 4; edge++) + { + int typeA = (var_05 >> (edge * 2)) & 3; + int typeB = (var_06 >> (edge * 4)) & 0x0F; + if (typeB != 0x0F) + { + int type = typeA | (typeB << 2); + int colourA = ((originalMapElement.type & 0xC0) >> 3) | + (originalMapElement.properties.fence.type >> 5); + int colourB = 0; + int colourC = 0; + ConvertWall(&type, &colourA, &colourB, &colourC); + map_place_fence(type, x * 32, y * 32, 0, edge, colourA, colourB, colourC, 169); + } + } + break; + } + } + while (!map_element_is_last_for_tile(mapElement++)); + } + } +} + +void S4Importer::ConvertWall(int * type, int * colourA, int * colourB, int * colourC) +{ + switch (*type) { + case 12: // creepy gate + *colourA = 24; + break; + case 26: // white wooden fence + *type = 12; + *colourA = 2; + break; + case 27: // red wooden fence + *type = 12; + *colourA = 25; + break; + case 50: // plate glass + *colourA = 24; + break; + case 13: + *colourB = *colourA; + *colourA = 24; + break; + case 11: // tall castle wall with grey gate + case 22: // brick wall with gate + *colourB = 2; + break; + case 35: // wood post fence + case 42: // tall grey castle wall + case 43: // wooden fence with snow + case 44: + case 45: + case 46: + *colourA = 1; + break; + } +} + +void S4Importer::FixBanners() +{ + for (int x = 0; x < 128; x++) + { + for (int y = 0; y < 128; y++) + { + rct_map_element * mapElement = map_get_first_element_at(x, y); + do + { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_BANNER) + { + uint8 index = mapElement->properties.banner.index; + rct_banner * src = &_s4.banners[index]; + rct_banner * dst = &gBanners[index]; + ImportBanner(dst, src); + } + } + while (!map_element_is_last_for_tile(mapElement++)); + } + } +} + +void S4Importer::ImportBanner(rct_banner * dst, rct_banner * src) +{ + *dst = *src; + dst->colour = RCT1::GetColour(src->colour); + + dst->string_idx = 778; + if (is_user_string_id(src->string_idx)) + { + const char * bannerText = GetUserString(src->string_idx); + if (!String::IsNullOrEmpty(bannerText)) + { + rct_string_id bannerTextStringId = user_string_allocate(128, bannerText); + if (bannerTextStringId != 0) + { + dst->string_idx = bannerTextStringId; + } + } + } +} + +void S4Importer::FixTerrain() +{ + map_element_iterator it; + map_element_iterator_begin(&it); + while (map_element_iterator_next(&it)) + { + rct_map_element * element = it.element; + if (map_element_get_type(element) == MAP_ELEMENT_TYPE_SURFACE) + { + map_element_set_terrain(element, RCT1::GetTerrain(map_element_get_terrain(element))); + map_element_set_terrain_edge(element, RCT1::GetTerrainEdge(map_element_get_terrain_edge(element))); + } + } +} + +void S4Importer::FixEntrancePositions() +{ + for (int i = 0; i < 4; i++) + { + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] = 0x8000; + } + + uint8 entranceIndex = 0; + + map_element_iterator it; + map_element_iterator_begin(&it); + while (map_element_iterator_next(&it) && entranceIndex < 4) + { + rct_map_element * element = it.element; + + if (map_element_get_type(element) != MAP_ELEMENT_TYPE_ENTRANCE) continue; + if (element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE) continue; + if ((element->properties.entrance.index & 0x0F) != 0) continue; + + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[entranceIndex] = it.x * 32; + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, uint16)[entranceIndex] = it.y * 32; + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, uint16)[entranceIndex] = element->base_height * 8; + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[entranceIndex] = element->type & 3; + entranceIndex++; + } +} + +void S4Importer::FixMapElementEntryTypes() +{ + map_element_iterator it; + map_element_iterator_begin(&it); + while (map_element_iterator_next(&it)) + { + rct_map_element * mapElement = it.element; + switch (map_element_get_type(mapElement)) { + case MAP_ELEMENT_TYPE_SCENERY: + mapElement->properties.scenery.type = _smallSceneryTypeToEntryMap[mapElement->properties.scenery.type]; + break; + case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE: + { + uint8 type = mapElement->properties.scenerymultiple.type & MAP_ELEMENT_LARGE_TYPE_MASK; + mapElement->properties.scenerymultiple.type &= ~MAP_ELEMENT_LARGE_TYPE_MASK; + mapElement->properties.scenerymultiple.type |= _largeSceneryTypeToEntryMap[type]; + break; + } + case MAP_ELEMENT_TYPE_FENCE: + mapElement->properties.fence.type = _wallTypeToEntryMap[mapElement->properties.fence.type]; + break; + } + } +} + const rct1_research_item * S4Importer::GetResearchList(size_t * count) { // Loopy Landscapes stores research items in a different place @@ -222,3 +1199,90 @@ const rct1_research_item * S4Importer::GetResearchList(size_t * count) } } +int S4Importer::GetSCNumber() +{ + const utf8 * fileName = Path::GetFileName(_s4Path); + if (tolower(fileName[0]) == 's' && tolower(fileName[1]) == 'c') { + constexpr size_t maxDigits = 7; + utf8 digitBuffer[maxDigits + 1]; + utf8 * dst = digitBuffer; + const utf8 * src = fileName + 2; + for (int i = 0; i < maxDigits && *src != '.'; i++) + { + *dst++ = *src++; + } + *dst++ = 0; + + if (digitBuffer[0] == '0' && digitBuffer[1] == '\0') + { + return 0; + } + else + { + int digits = atoi(digitBuffer); + return digits == 0 ? -1 : digits; + } + } + else + { + return -1; + } +} + +const char * S4Importer::GetUserString(rct_string_id stringId) +{ + return _s4.string_table[(stringId - 0x8000) % 1024]; +} + +///////////////////////////////////////// +// C -> C++ transfer +///////////////////////////////////////// +extern "C" +bool rct1_load_saved_game(const utf8 * path) +{ + bool result; + + auto s4Importer = new S4Importer(); + try + { + s4Importer->LoadSavedGame(path); + s4Importer->Import(); + result = true; + } + catch (Exception ex) + { + result = false; + } + delete s4Importer; + + if (result) + { + game_load_init(); + } + return result; +} + +extern "C" +bool rct1_load_scenario(const utf8 * path) +{ + bool result; + + auto s4Importer = new S4Importer(); + try + { + s4Importer->LoadSavedGame(path); + s4Importer->Import(); + result = true; + } + catch (Exception ex) + { + result = false; + } + delete s4Importer; + + if (result) + { + scenario_begin(); + } + return result; +} diff --git a/src/rct1/S4Importer.h b/src/rct1/S4Importer.h new file mode 100644 index 0000000000..de040a684b --- /dev/null +++ b/src/rct1/S4Importer.h @@ -0,0 +1,96 @@ +#pragma once + +#include "../common.h" +#include "../core/List.hpp" + +extern "C" +{ + #include "../rct1.h" +} + +/** + * Class to import RollerCoaster Tycoon 1 scenarios (*.SC4) and saved games (*.SV4). + */ +class S4Importer +{ +public: + void LoadSavedGame(const utf8 * path); + void LoadScenario(const utf8 * path); + void Import(); + +private: + const utf8 * _s4Path; + rct1_s4 _s4; + uint8 _gameVersion; + + // Lists of dynamic object entries + List _rideEntries; + List _smallSceneryEntries; + List _largeSceneryEntries; + List _wallEntries; + List _sceneryGroupEntries; + + // Lookup tables for converting from RCT1 hard coded types to the new dynamic object entries + uint8 _rideTypeToRideEntryMap[96]; + uint8 _vehicleTypeToRideEntryMap[96]; + uint8 _smallSceneryTypeToEntryMap[96]; + uint8 _largeSceneryTypeToEntryMap[96]; + uint8 _wallTypeToEntryMap[96]; + uint8 _sceneryThemeTypeToEntryMap[24]; + + // Research + uint8 _researchRideEntryUsed[128]; + uint8 _researchRideTypeUsed[128]; + + void Initialise(); + + /** + * Scans the map and research list for all the object types used and builds lists and + * lookup tables for converting from hard coded RCT1 object types to dynamic object entries. + */ + void CreateAvailableObjectMappings(); + void AddAvailableEntriesFromResearchList(); + void AddAvailableEntriesFromMap(); + void AddAvailableEntriesFromRides(); + + void AddEntryForRideType(uint8 rideType); + void AddEntryForVehicleType(uint8 rideType, uint8 vehicleType); + void AddEntryForSmallScenery(uint8 smallSceneryType); + void AddEntryForLargeScenery(uint8 largeSceneryType); + void AddEntryForWall(uint8 wallType); + void AddEntriesForSceneryTheme(uint8 sceneryThemeType); + + void LoadObjects(); + void LoadObjects(uint8 objectType, List entries); + + void ImportMapElements(); + void ImportRides(); + void ImportRide(rct_ride * dst, rct1_ride * src); + void ImportRideMeasurements(); + void ImportRideMeasurement(rct_ride_measurement * dst, rct_ride_measurement * src); + void ImportPeepSpawns(); + void ImportMapAnimations(); + void ImportFinance(); + void ImportResearch(); + void InsertResearchVehicle(const rct1_research_item * researchItem, bool researched); + void ImportParkName(); + void ImportScenarioNameDetails(); + void ImportScenarioObjective(); + void ImportSavedView(); + + void ClearExtraTileEntries(); + void FixColours(); + void FixZ(); + void FixPaths(); + void FixWalls(); + void ConvertWall(int * type, int * colourA, int * colourB, int * colourC); + void FixBanners(); + void ImportBanner(rct_banner * dst, rct_banner * src); + void FixTerrain(); + void FixEntrancePositions(); + void FixMapElementEntryTypes(); + + const rct1_research_item * GetResearchList(size_t * count); + int GetSCNumber(); + const char * GetUserString(rct_string_id stringId); +}; diff --git a/src/rct1/import.h b/src/rct1/import.h index dd878fc8f4..53635c4272 100644 --- a/src/rct1/import.h +++ b/src/rct1/import.h @@ -2,13 +2,15 @@ namespace RCT1 { - namespace Tables - { - const char * GetRideTypeObject(uint8 rideType); - const char * GetVehicleObject(uint8 vehicleType); - const char * GetSmallSceneryObject(uint8 smallSceneryType); - const char * GetLargeSceneryObject(uint8 largeSceneryType); - const char * GetWallObject(uint8 wallType); - const char * GetSceneryGroupObject(uint8 sceneryGroupType); - } + colour_t GetColour(colour_t colour); + uint8 GetTerrain(uint8 terrain); + uint8 GetTerrainEdge(uint8 terrainEdge); + + uint8 GetRideType(uint8 rideType); + const char * GetRideTypeObject(uint8 rideType); + const char * GetVehicleObject(uint8 vehicleType); + const char * GetSmallSceneryObject(uint8 smallSceneryType); + const char * GetLargeSceneryObject(uint8 largeSceneryType); + const char * GetWallObject(uint8 wallType); + const char * GetSceneryGroupObject(uint8 sceneryGroupType); } diff --git a/src/rct1/tables.cpp b/src/rct1/tables.cpp index bb7670f657..ece3ed95da 100644 --- a/src/rct1/tables.cpp +++ b/src/rct1/tables.cpp @@ -2,6 +2,7 @@ #include "../common.h" #include "../core/List.hpp" +#include "../interface/colour.h" #include "../ride/ride.h" #include "import.h" @@ -9,824 +10,909 @@ namespace RCT1 { const char * DefaultParkEntranceObject = "PKENT1 "; - namespace Tables + colour_t GetColour(colour_t colour) { - uint8 GetRideType(uint8 rideType) + static const uint8 map[] = { - static uint8 map[] = - { - RIDE_TYPE_WOODEN_ROLLER_COASTER, - RIDE_TYPE_STAND_UP_ROLLER_COASTER, - RIDE_TYPE_SUSPENDED_SWINGING_COASTER, - RIDE_TYPE_INVERTED_ROLLER_COASTER, - RIDE_TYPE_JUNIOR_ROLLER_COASTER, - RIDE_TYPE_MINIATURE_RAILWAY, - RIDE_TYPE_MONORAIL, - RIDE_TYPE_MINI_SUSPENDED_COASTER, - RIDE_TYPE_BOAT_RIDE, - RIDE_TYPE_WOODEN_WILD_MOUSE, - RIDE_TYPE_STEEPLECHASE, - RIDE_TYPE_CAR_RIDE, - RIDE_TYPE_LAUNCHED_FREEFALL, - RIDE_TYPE_BOBSLEIGH_COASTER, - RIDE_TYPE_OBSERVATION_TOWER, - RIDE_TYPE_LOOPING_ROLLER_COASTER, - RIDE_TYPE_DINGHY_SLIDE, - RIDE_TYPE_MINE_TRAIN_COASTER, - RIDE_TYPE_CHAIRLIFT, - RIDE_TYPE_CORKSCREW_ROLLER_COASTER, - RIDE_TYPE_MAZE, - RIDE_TYPE_SPIRAL_SLIDE, - RIDE_TYPE_GO_KARTS, - RIDE_TYPE_LOG_FLUME, - RIDE_TYPE_RIVER_RAPIDS, - RIDE_TYPE_DODGEMS, - RIDE_TYPE_PIRATE_SHIP, - RIDE_TYPE_SWINGING_INVERTER_SHIP, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_DRINK_STALL, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_SHOP, - RIDE_TYPE_MERRY_GO_ROUND, - RIDE_TYPE_SHOP, - RIDE_TYPE_INFORMATION_KIOSK, - RIDE_TYPE_TOILETS, - RIDE_TYPE_FERRIS_WHEEL, - RIDE_TYPE_MOTION_SIMULATOR, - RIDE_TYPE_3D_CINEMA, - RIDE_TYPE_TOP_SPIN, - RIDE_TYPE_SPACE_RINGS, - RIDE_TYPE_REVERSE_FREEFALL_COASTER, - RIDE_TYPE_SHOP, - RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_TWIST, - RIDE_TYPE_HAUNTED_HOUSE, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_CIRCUS_SHOW, - RIDE_TYPE_GHOST_TRAIN, - RIDE_TYPE_TWISTER_ROLLER_COASTER, - RIDE_TYPE_WOODEN_ROLLER_COASTER, - RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER, - RIDE_TYPE_WILD_MOUSE, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_SHOP, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_VIRGINIA_REEL, - RIDE_TYPE_SPLASH_BOATS, - RIDE_TYPE_MINI_HELICOPTERS, - RIDE_TYPE_LAY_DOWN_ROLLER_COASTER, - RIDE_TYPE_SUSPENDED_MONORAIL, - RIDE_TYPE_NULL, - RIDE_TYPE_REVERSER_ROLLER_COASTER, - RIDE_TYPE_HEARTLINE_TWISTER_COASTER, - RIDE_TYPE_MINI_GOLF, - RIDE_TYPE_NULL, - RIDE_TYPE_ROTO_DROP, - RIDE_TYPE_FLYING_SAUCERS, - RIDE_TYPE_CROOKED_HOUSE, - RIDE_TYPE_MONORAIL_CYCLES, - RIDE_TYPE_COMPACT_INVERTED_COASTER, - RIDE_TYPE_WATER_COASTER, - RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER, - RIDE_TYPE_INVERTED_HAIRPIN_COASTER, - RIDE_TYPE_BOAT_RIDE, - RIDE_TYPE_SHOP, - RIDE_TYPE_RIVER_RAFTS, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_ENTERPRISE, - RIDE_TYPE_DRINK_STALL, - RIDE_TYPE_FOOD_STALL, - RIDE_TYPE_DRINK_STALL - }; - return map[rideType]; - } + COLOUR_BLACK, + COLOUR_GREY, + COLOUR_WHITE, + COLOUR_LIGHT_PURPLE, + COLOUR_BRIGHT_PURPLE, + COLOUR_DARK_BLUE, + COLOUR_LIGHT_BLUE, + COLOUR_TEAL, + COLOUR_SATURATED_GREEN, + COLOUR_DARK_GREEN, + COLOUR_MOSS_GREEN, + COLOUR_BRIGHT_GREEN, + COLOUR_OLIVE_GREEN, + COLOUR_DARK_OLIVE_GREEN, + COLOUR_YELLOW, + COLOUR_DARK_YELLOW, + COLOUR_LIGHT_ORANGE, + COLOUR_DARK_ORANGE, + COLOUR_LIGHT_BROWN, + COLOUR_SATURATED_BROWN, + COLOUR_DARK_BROWN, + COLOUR_SALMON_PINK, + COLOUR_BORDEAUX_RED, + COLOUR_SATURATED_RED, + COLOUR_BRIGHT_RED, + COLOUR_BRIGHT_PINK, + COLOUR_LIGHT_PINK, + COLOUR_DARK_PINK, + COLOUR_DARK_PURPLE, + COLOUR_AQUAMARINE, + COLOUR_BRIGHT_YELLOW, + COLOUR_ICY_BLUE + }; + return map[colour]; + } - const char * GetRideTypeObject(uint8 rideType) + uint8 GetTerrain(uint8 terrain) + { + static const uint8 map[] = { - static const char * map[] = - { - "PTCT1 ", - "TOGST ", - "ARRSW1 ", - "NEMT ", - "ZLDB ", - "NRL ", - "MONO2 ", - "BATFL ", - "RBOAT ", - "WMOUSE ", - "STEEP1 ", - "SPCAR ", - "SSC1 ", - "BOB1 ", - "OBS1 ", - "SCHT1 ", - "DING1 ", - "AMT1 ", - "CLIFT1 ", - "ARRT1 ", - "HMAZE ", - "HSKELT ", - "KART1 ", - "LFB1 ", - "RAPBOAT ", - "DODG1 ", - "SWSH1 ", - "SWSH2 ", - "ICECR1 ", - "CHPSH ", - "DRNKS ", - "CNDYF ", - "BURGB ", - "MGR1 ", - "BALLN ", - "INFOK ", - "TLT1 ", - "FWH1 ", - "SIMPOD ", - "C3D ", - "TOPSP1 ", - "SRINGS ", - "REVF1 ", - "SOUVS ", - "BMVD ", - "PIZZS ", - "TWIST1 ", - "HHBUILD ", - "POPCS ", - "CIRCUS1 ", - "GTC ", - "BMSD ", - "MFT ", - "SFRIC1 ", - "SMC1 ", - "HOTDS ", - "SQDST ", - "HATST ", - "TOFFS ", - "VREEL ", - "SPBOAT ", - "MONBK ", - "BMAIR ", - "SMONO ", - " ", - "REVCAR ", - "UTCAR ", - "GOLF1 ", - " ", - "GDROP1 ", - "FSAUC ", - "CHBUILD ", - "HELICAR ", - "SLCT ", - "CSTBOAT ", - "THCAR ", - "IVMC1 ", - "JSKI ", - "TSHRT ", - "RFTBOAT ", - "DOUGH ", - "ENTERP ", - "COFFS ", - "CHCKS ", - "LEMST ", - }; - return map[rideType]; - } + TERRAIN_GRASS, + TERRAIN_SAND, + TERRAIN_DIRT, + TERRAIN_ROCK, + TERRAIN_MARTIAN, + TERRAIN_CHECKERBOARD, + TERRAIN_GRASS_CLUMPS, + TERRAIN_DIRT, // Originally TERRAIN_ROOF_BROWN + TERRAIN_ICE, + TERRAIN_DIRT, // Originally TERRAIN_ROOF_LOG + TERRAIN_DIRT, // Originally TERRAIN_ROOF_IRON + TERRAIN_ROCK, // Originally TERRAIN_ROOF_GREY + TERRAIN_GRID_RED, + TERRAIN_GRID_YELLOW, + TERRAIN_GRID_BLUE, + TERRAIN_GRID_GREEN + }; + return map[terrain]; + } - const char * GetVehicleObject(uint8 vehicleType) + uint8 GetTerrainEdge(uint8 terrainEdge) + { + static const uint8 map[] = { - static const char * map[] = - { - "PTCT1 ", // RCT1_VEHICLE_TYPE_STEEL_ROLLER_COASTER_TRAIN - "TOGST ", // RCT1_VEHICLE_TYPE_STEEL_ROLLER_COASTER_TRAIN_BACKWARDS - "ARRSW1 ", // RCT1_VEHICLE_TYPE_WOODEN_ROLLER_COASTER_TRAIN - "NEMT ", // RCT1_VEHICLE_TYPE_INVERTED_COASTER_TRAIN (Not in RCT2) - "ZLDB ", // RCT1_VEHICLE_TYPE_SUSPENDED_SWINGING_CARS - "NRL ", // RCT1_VEHICLE_TYPE_LADYBIRD_CARS - "MONO2 ", // RCT1_VEHICLE_TYPE_STANDUP_ROLLER_COASTER_CARS - "BATFL ", // RCT1_VEHICLE_TYPE_SPINNING_CARS - "RBOAT ", // RCT1_VEHICLE_TYPE_SINGLE_PERSON_SWINGING_CHAIRS - "WMOUSE ", // RCT1_VEHICLE_TYPE_SWANS_PEDAL_BOATS - "STEEP1 ", // RCT1_VEHICLE_TYPE_LARGE_MONORAIL_TRAIN - "SPCAR ", // RCT1_VEHICLE_TYPE_CANOES - "SSC1 ", // RCT1_VEHICLE_TYPE_ROWING_BOATS - "BOB1 ", // RCT1_VEHICLE_TYPE_STEAM_TRAIN - "OBS1 ", // RCT1_VEHICLE_TYPE_WOODEN_MOUSE_CARS - "SCHT1 ", // RCT1_VEHICLE_TYPE_BUMPER_BOATS - "DING1 ", // RCT1_VEHICLE_TYPE_WOODEN_ROLLER_COASTER_TRAIN_BACKWARDS - "AMT1 ", // RCT1_VEHICLE_TYPE_ROCKET_CARS - "CLIFT1 ", // RCT1_VEHICLE_TYPE_HORSES // Steeplechase - "ARRT1 ", // RCT1_VEHICLE_TYPE_SPORTSCARS - "HMAZE ", // RCT1_VEHICLE_TYPE_LYING_DOWN_SWINGING_CARS (Inverted single-rail) - "HSKELT ", // RCT1_VEHICLE_TYPE_WOODEN_MINE_CARS - "KART1 ", // RCT1_VEHICLE_TYPE_SUSPENDED_SWINGING_AIRPLANE_CARS - "LFB1 ", // RCT1_VEHICLE_TYPE_SMALL_MONORAIL_CARS - "RAPBOAT ", // RCT1_VEHICLE_TYPE_WATER_TRICYCLES - "DODG1 ", // RCT1_VEHICLE_TYPE_LAUNCHED_FREEFALL_CAR - "SWSH1 ", // RCT1_VEHICLE_TYPE_BOBSLEIGH_CARS - "SWSH2 ", // RCT1_VEHICLE_TYPE_DINGHIES - "ICECR1 ", // RCT1_VEHICLE_TYPE_ROTATING_CABIN - "CHPSH ", // RCT1_VEHICLE_TYPE_MINE_TRAIN - "DRNKS ", // RCT1_VEHICLE_TYPE_CHAIRLIFT_CARS - "CNDYF ", // RCT1_VEHICLE_TYPE_CORKSCREW_ROLLER_COASTER_TRAIN - "BURGB ", // RCT1_VEHICLE_TYPE_MOTORBIKES - "MGR1 ", // RCT1_VEHICLE_TYPE_RACING_CARS - "BALLN ", // RCT1_VEHICLE_TYPE_TRUCKS - "INFOK ", // RCT1_VEHICLE_TYPE_GO_KARTS - "TLT1 ", // RCT1_VEHICLE_TYPE_RAPIDS_BOATS - "FWH1 ", // RCT1_VEHICLE_TYPE_LOG_FLUME_BOATS - "SIMPOD ", // RCT1_VEHICLE_TYPE_DODGEMS - "C3D ", // RCT1_VEHICLE_TYPE_SWINGING_SHIP - "TOPSP1 ", // RCT1_VEHICLE_TYPE_SWINGING_INVERTER_SHIP - "SRINGS ", // RCT1_VEHICLE_TYPE_MERRY_GO_ROUND - "REVF1 ", // RCT1_VEHICLE_TYPE_FERRIS_WHEEL - "SOUVS ", // RCT1_VEHICLE_TYPE_SIMULATOR_POD - "BMVD ", // RCT1_VEHICLE_TYPE_CINEMA_BUILDING - "PIZZS ", // RCT1_VEHICLE_TYPE_TOPSPIN_CAR - "TWIST1 ", // RCT1_VEHICLE_TYPE_SPACE_RINGS - "HHBUILD ", // RCT1_VEHICLE_TYPE_REVERSE_FREEFALL_ROLLER_COASTER_CAR - "POPCS ", // RCT1_VEHICLE_TYPE_VERTICAL_ROLLER_COASTER_CARS - "CIRCUS1 ", // RCT1_VEHICLE_TYPE_CAT_CARS - "GTC ", // RCT1_VEHICLE_TYPE_TWIST_ARMS_AND_CARS - "BMSD ", // RCT1_VEHICLE_TYPE_HAUNTED_HOUSE_BUILDING - "MFT ", // RCT1_VEHICLE_TYPE_LOG_CARS - "SFRIC1 ", // RCT1_VEHICLE_TYPE_CIRCUS_TENT - "SMC1 ", // RCT1_VEHICLE_TYPE_GHOST_TRAIN_CARS - "HOTDS ", // RCT1_VEHICLE_TYPE_STEEL_TWISTER_ROLLER_COASTER_TRAIN - "SQDST ", // RCT1_VEHICLE_TYPE_WOODEN_TWISTER_ROLLER_COASTER_TRAIN - "HATST ", // RCT1_VEHICLE_TYPE_WOODEN_SIDE_FRICTION_CARS - "TOFFS ", // RCT1_VEHICLE_TYPE_VINTAGE_CARS - "VREEL ", // RCT1_VEHICLE_TYPE_STEAM_TRAIN_COVERED_CARS - "SPBOAT ", // RCT1_VEHICLE_TYPE_STAND_UP_STEEL_TWISTER_ROLLER_COASTER_TRAIN - "MONBK ", // RCT1_VEHICLE_TYPE_FLOORLESS_STEEL_TWISTER_ROLLER_COASTER_TRAIN - "BMAIR ", // RCT1_VEHICLE_TYPE_STEEL_MOUSE_CARS - "SMONO ", // RCT1_VEHICLE_TYPE_CHAIRLIFT_CARS_ALTERNATIVE - " ", // RCT1_VEHICLE_TYPE_SUSPENDED_MONORAIL_TRAIN - "REVCAR ", // RCT1_VEHICLE_TYPE_HELICOPTER_CARS - "UTCAR ", // RCT1_VEHICLE_TYPE_VIRGINIA_REEL_TUBS - "GOLF1 ", // RCT1_VEHICLE_TYPE_REVERSER_CARS - " ", // RCT1_VEHICLE_TYPE_GOLFERS - "GDROP1 ", // RCT1_VEHICLE_TYPE_RIVER_RIDE_BOATS - "FSAUC ", // RCT1_VEHICLE_TYPE_FLYING_ROLLER_COASTER_TRAIN - "CHBUILD ", // RCT1_VEHICLE_TYPE_NON_LOOPING_STEEL_TWISTER_ROLLER_COASTER_TRAIN - "HELICAR ", // RCT1_VEHICLE_TYPE_HEARTLINE_TWISTER_CARS - "SLCT ", // RCT1_VEHICLE_TYPE_HEARTLINE_TWISTER_CARS_REVERSED - "CSTBOAT ", // RCT1_VEHICLE_TYPE_RESERVED - "THCAR ", // RCT1_VEHICLE_TYPE_ROTODROP_CAR - "IVMC1 ", // RCT1_VEHICLE_TYPE_FLYING_SAUCERS - "JSKI ", // RCT1_VEHICLE_TYPE_CROOKED_HOUSE_BUILDING - "TSHRT ", // RCT1_VEHICLE_TYPE_BICYCLES - "RFTBOAT ", // RCT1_VEHICLE_TYPE_HYPERCOASTER_TRAIN - "DOUGH ", // RCT1_VEHICLE_TYPE_4_ACROSS_INVERTED_COASTER_TRAIN - "ENTERP ", // RCT1_VEHICLE_TYPE_WATER_COASTER_BOATS - "COFFS ", // RCT1_VEHICLE_TYPE_FACEOFF_CARS - "CHCKS ", // RCT1_VEHICLE_TYPE_JET_SKIS - "LEMST ", // RCT1_VEHICLE_TYPE_RAFT_BOATS - "WMSPIN ", // RCT1_VEHICLE_TYPE_AMERICAN_STYLE_STEAM_TRAIN - "SWANS ", // RCT1_VEHICLE_TYPE_AIR_POWERED_COASTER_TRAIN - "MONO1 ", // RCT1_VEHICLE_TYPE_SUSPENDED_WILD_MOUSE_CARS (Inverted Hairpin in RCT2) - "CBOAT ", // RCT1_VEHICLE_TYPE_ENTERPRISE_WHEEL - }; - return map[vehicleType]; - } + TERRAIN_EDGE_ROCK, + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_BRICK + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_IRON + TERRAIN_EDGE_WOOD_RED, + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_GREY + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_YELLOW + TERRAIN_EDGE_WOOD_BLACK, + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_RED + TERRAIN_EDGE_ICE, + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_PURPLE + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_GREEN + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_STONE_BROWN + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_STONE_GREY + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_SKYSCRAPER_A + TERRAIN_EDGE_ROCK, // Originally TERRAIN_EDGE_SKYSCRAPER_B + TERRAIN_EDGE_ROCK // Unused + }; + return map[terrainEdge]; + } - const char * GetSmallSceneryObject(uint8 smallSceneryType) + uint8 GetRideType(uint8 rideType) + { + static uint8 map[] = { - static const char * map[] = - { - "TL0 ", - "TL1 ", - "TL2 ", - "TL3 ", - "TM0 ", - "TM1 ", - "TM2 ", - "TM3 ", - "TS0 ", - "TS1 ", - "TS2 ", - "TS3 ", - "TS4 ", - "TS5 ", - "TS6 ", - "TIC ", - "TLC ", - "TMC ", - "TMP ", - "TITC ", - "TGHC ", - "TAC ", - "TGHC2 ", - "TCJ ", - "TMBJ ", - "TCF ", - "TCL ", - "TRF ", - "TRF2 ", - "TEL ", - "TAP ", - "TSP ", - "TMZP ", - "TCRP ", - "TBP ", - "TLP ", - "TWP ", - "TAS ", - "TMG ", - "TWW ", - "TSB ", - "TVL ", - "TCT ", - "TEF ", - "TAL ", - "TSQ ", - "THT ", - "TCB ", - "TDM ", - "TSD ", - "TGS ", - "TUS ", - "TH1 ", - "TBC ", - "TH2 ", - "TPM ", - "TSC ", - "TG1 ", - "TWF ", - "TSH0 ", - "TSH1 ", - "TSH2 ", - "TSH3 ", - "TSH4 ", - "TSH5 ", - "TG2 ", - "TG3 ", - "TG4 ", - "TG5 ", - "TG6 ", - "TG7 ", - "TG8 ", - "TG9 ", - "TG10 ", - "TG11 ", - "TG12 ", - "TG13 ", - "TG14 ", - "TT1 ", - "TDF ", - "TSH ", - "THRS ", - "TSTD ", - "TRMS ", - "TRWS ", - "TRC ", - "TQF ", - "TES1 ", - "TEN ", - "TERS ", - "TERB ", - "TEP ", - "TST1 ", - "TST2 ", - "TMS1 ", - "TAS1 ", - "TAS2 ", - "TAS3 ", - "TST3 ", - "TST4 ", - "TST5 ", - "TAS4 ", - "TCY ", - "TBW ", - "TBR1 ", - "TBR2 ", - "TML ", - "TMW ", - "TBR3 ", - "TBR4 ", - "TMJ ", - "TBR ", - "TMO1 ", - "TMO2 ", - "TMO3 ", - "TMO4 ", - "TMO5 ", - "TWH1 ", - "TWH2 ", - "TNS ", - "TP1 ", - "TP2 ", - "TK1 ", - "TK2 ", - "TR1 ", - "TR2 ", - "TQ1 ", - "TQ2 ", - "TWN ", - "TCE ", - "TCO ", - "THL ", - "TCC ", - "TB1 ", - "TB2 ", - "TK3 ", - "TK4 ", - "TBN ", - "TBN1 ", - "TDT1 ", - "TDT2 ", - "TDT3 ", - "TMM1 ", - "TMM2 ", - "TMM3 ", - "TGS1 ", - "TGS2 ", - "TGS3 ", - "TGS4 ", - "TDN4 ", - "TDN5 ", - "TJT1 ", - "TJT2 ", - "TJB1 ", - "TTF ", - "TF1 ", - "TF2 ", - "TGE1 ", - "TJT3 ", - "TJT4 ", - "TJP1 ", - "TJB2 ", - "TGE2 ", - "TJT5 ", - "TJB3 ", - "TJB4 ", - "TJT6 ", - "TJP2 ", - "TGE3 ", - "TCK ", - "TGE4 ", - "TGE5 ", - "TG15 ", - "TG16 ", - "TG17 ", - "TG18 ", - "TG19 ", - "TG20 ", - "TG21 ", - "TSM ", - "TIG ", - "TCFS ", - "TRFS ", - "TRF3 ", - "TNSS ", - "TCT1 ", - "TCT2 ", - "TSF1 ", - "TSF2 ", - "TSF3 ", - "TCN ", - "TTG ", - "TSNC ", - "TSNB ", - "TSCP ", - "TCD ", - "TSG ", - "TSK ", - "TGH1 ", - "TGH2 ", - "TSMP ", - "TJF ", - "TLY ", - "TGC1 ", - "TGC2 ", - "TGG ", - "TSPH ", - "TOH1 ", - "TOH2 ", - "TOT1 ", - "TOT2 ", - "TOS ", - "TOT3 ", - "TOT4 ", - "TSC2 ", - "TSP1 ", - "TOH3 ", - "TSP2 ", - "ROMROOF1", - "GEOROOF1", - "TNTROOF1", - "JNGROOF1", - "MINROOF1", - "ROMROOF2", - "GEOROOF2", - "PAGROOF1", - "SPCROOF1", - "ROOF1 ", - "ROOF2 ", - "ROOF3 ", - "ROOF4 ", - "ROOF5 ", - "ROOF6 ", - "ROOF7 ", - "ROOF8 ", - "ROOF9 ", - "ROOF10 ", - "ROOF11 ", - "ROOF12 ", - "ROOF13 ", - "ROOF14 ", - "IGROOF ", - "CORROOF ", - "CORROOF2", - }; - return map[smallSceneryType]; - } + RIDE_TYPE_WOODEN_ROLLER_COASTER, + RIDE_TYPE_STAND_UP_ROLLER_COASTER, + RIDE_TYPE_SUSPENDED_SWINGING_COASTER, + RIDE_TYPE_INVERTED_ROLLER_COASTER, + RIDE_TYPE_JUNIOR_ROLLER_COASTER, + RIDE_TYPE_MINIATURE_RAILWAY, + RIDE_TYPE_MONORAIL, + RIDE_TYPE_MINI_SUSPENDED_COASTER, + RIDE_TYPE_BOAT_RIDE, + RIDE_TYPE_WOODEN_WILD_MOUSE, + RIDE_TYPE_STEEPLECHASE, + RIDE_TYPE_CAR_RIDE, + RIDE_TYPE_LAUNCHED_FREEFALL, + RIDE_TYPE_BOBSLEIGH_COASTER, + RIDE_TYPE_OBSERVATION_TOWER, + RIDE_TYPE_LOOPING_ROLLER_COASTER, + RIDE_TYPE_DINGHY_SLIDE, + RIDE_TYPE_MINE_TRAIN_COASTER, + RIDE_TYPE_CHAIRLIFT, + RIDE_TYPE_CORKSCREW_ROLLER_COASTER, + RIDE_TYPE_MAZE, + RIDE_TYPE_SPIRAL_SLIDE, + RIDE_TYPE_GO_KARTS, + RIDE_TYPE_LOG_FLUME, + RIDE_TYPE_RIVER_RAPIDS, + RIDE_TYPE_DODGEMS, + RIDE_TYPE_PIRATE_SHIP, + RIDE_TYPE_SWINGING_INVERTER_SHIP, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_DRINK_STALL, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_SHOP, + RIDE_TYPE_MERRY_GO_ROUND, + RIDE_TYPE_SHOP, + RIDE_TYPE_INFORMATION_KIOSK, + RIDE_TYPE_TOILETS, + RIDE_TYPE_FERRIS_WHEEL, + RIDE_TYPE_MOTION_SIMULATOR, + RIDE_TYPE_3D_CINEMA, + RIDE_TYPE_TOP_SPIN, + RIDE_TYPE_SPACE_RINGS, + RIDE_TYPE_REVERSE_FREEFALL_COASTER, + RIDE_TYPE_SHOP, + RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_TWIST, + RIDE_TYPE_HAUNTED_HOUSE, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_CIRCUS_SHOW, + RIDE_TYPE_GHOST_TRAIN, + RIDE_TYPE_TWISTER_ROLLER_COASTER, + RIDE_TYPE_WOODEN_ROLLER_COASTER, + RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER, + RIDE_TYPE_WILD_MOUSE, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_SHOP, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_VIRGINIA_REEL, + RIDE_TYPE_SPLASH_BOATS, + RIDE_TYPE_MINI_HELICOPTERS, + RIDE_TYPE_LAY_DOWN_ROLLER_COASTER, + RIDE_TYPE_SUSPENDED_MONORAIL, + RIDE_TYPE_NULL, + RIDE_TYPE_REVERSER_ROLLER_COASTER, + RIDE_TYPE_HEARTLINE_TWISTER_COASTER, + RIDE_TYPE_MINI_GOLF, + RIDE_TYPE_NULL, + RIDE_TYPE_ROTO_DROP, + RIDE_TYPE_FLYING_SAUCERS, + RIDE_TYPE_CROOKED_HOUSE, + RIDE_TYPE_MONORAIL_CYCLES, + RIDE_TYPE_COMPACT_INVERTED_COASTER, + RIDE_TYPE_WATER_COASTER, + RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER, + RIDE_TYPE_INVERTED_HAIRPIN_COASTER, + RIDE_TYPE_BOAT_RIDE, + RIDE_TYPE_SHOP, + RIDE_TYPE_RIVER_RAFTS, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_ENTERPRISE, + RIDE_TYPE_DRINK_STALL, + RIDE_TYPE_FOOD_STALL, + RIDE_TYPE_DRINK_STALL + }; + return map[rideType]; + } - const char * GetLargeSceneryObject(uint8 largeSceneryType) + const char * GetRideTypeObject(uint8 rideType) + { + static const char * map[] = { - static const char * map[] = - { - "SCOL ", - "SHS1 ", - "SSPX ", - "SHS2 ", - "SCLN ", - "SMH1 ", - "SMH2 ", - "SVLC ", - "SPYR ", - "SMN1 ", - "SMB ", - "SSK1 ", - "SDN1 ", - "SDN2 ", - "SDN3 ", - "SIP ", - "STB1 ", - "STB2 ", - "STG1 ", - "STG2 ", - "SCT ", - "SOH1 ", - "SOH2 ", - "SOH3 ", - "SGP ", - "SSR ", - "STH ", - "SAH ", - "SPS ", - "SPG ", - "SOB ", - "SAH2 ", - "SST ", - "SSH ", - "SAH3 ", - "SSIG1 ", - "SSIG2 ", - "SSIG3 ", - "SSIG4 ", - }; - return map[largeSceneryType]; - } + "PTCT1 ", + "TOGST ", + "ARRSW1 ", + "NEMT ", + "ZLDB ", + "NRL ", + "MONO2 ", + "BATFL ", + "RBOAT ", + "WMOUSE ", + "STEEP1 ", + "SPCAR ", + "SSC1 ", + "BOB1 ", + "OBS1 ", + "SCHT1 ", + "DING1 ", + "AMT1 ", + "CLIFT1 ", + "ARRT1 ", + "HMAZE ", + "HSKELT ", + "KART1 ", + "LFB1 ", + "RAPBOAT ", + "DODG1 ", + "SWSH1 ", + "SWSH2 ", + "ICECR1 ", + "CHPSH ", + "DRNKS ", + "CNDYF ", + "BURGB ", + "MGR1 ", + "BALLN ", + "INFOK ", + "TLT1 ", + "FWH1 ", + "SIMPOD ", + "C3D ", + "TOPSP1 ", + "SRINGS ", + "REVF1 ", + "SOUVS ", + "BMVD ", + "PIZZS ", + "TWIST1 ", + "HHBUILD ", + "POPCS ", + "CIRCUS1 ", + "GTC ", + "BMSD ", + "MFT ", + "SFRIC1 ", + "SMC1 ", + "HOTDS ", + "SQDST ", + "HATST ", + "TOFFS ", + "VREEL ", + "SPBOAT ", + "MONBK ", + "BMAIR ", + "SMONO ", + " ", + "REVCAR ", + "UTCAR ", + "GOLF1 ", + " ", + "GDROP1 ", + "FSAUC ", + "CHBUILD ", + "HELICAR ", + "SLCT ", + "CSTBOAT ", + "THCAR ", + "IVMC1 ", + "JSKI ", + "TSHRT ", + "RFTBOAT ", + "DOUGH ", + "ENTERP ", + "COFFS ", + "CHCKS ", + "LEMST ", + }; + return map[rideType]; + } - const char * GetWallObject(uint8 wallType) + const char * GetVehicleObject(uint8 vehicleType) + { + static const char * map[] = { - static const char * map[] = - { - "WMF ", - "WMFG ", - "WRW ", - "WEW ", - "WHG ", - "WHGG ", - "WCW1 ", - "WCW2 ", - "WSW ", - "WSWG ", - "WMW ", - "WALLGL16", - "WFW1 ", - "WFWG ", - "WPW1 ", - "WPW2 ", - "WPF ", - "WPFG ", - "WWTW ", - "WMWW ", - "WSW1 ", - "WSW2 ", - "WGW2 ", - "WBW ", - "WBR1 ", - "WBRG ", - "WALLCFAR", - "WALLPOST", - "WBR2 ", - "WBR3 ", - "WPW3 ", - "WJF ", - "WCH ", - "WCHG ", - "WC1 ", - "WC2 ", - "WC3 ", - "WC4 ", - "WC5 ", - "WC6 ", - "WC7 ", - "WC8 ", - "WC9 ", - "WC10 ", - "WC11 ", - "WC12 ", - "WC13 ", - "WC14 ", - "WC15 ", - "WC16 ", - "WC17 ", - "WC18 ", - "WALLBRDR", - "WALLBR32", - "WALLBR16", - "WALLBR8 ", - "WALLCF8 ", - "WALLCF16", - "WALLCF32", - "WALLBB8 ", - "WALLBB16", - "WALLBB32", - "WALLRS8 ", - "WALLRS16", - "WALLRS32", - "WALLCB8 ", - "WALLCB16", - "WALLCB32", - "WALLGL8 ", - "WALLGL32", - "WALLWD8 ", - "WALLWD16", - "WALLWD32", - "WALLTN32", - "WALLJN32", - "WALLMN32", - "WALLSP32", - "WALLPG32", - "WALLU132", - "WALLU232", - "WALLCZ32", - "WALLCW32", - "WALLCY32", - "WALLCX32", - "WBR1A ", - "WBR2A ", - "WRWA ", - "WWTWA ", - "WALLIG16", - "WALLIG24", - "WALLCO16", - "WALLCFDR", - "WALLCBDR", - "WALLBRWN", - "WALLCFWN", - "WALLCBWN", - }; - return map[wallType]; - } + "PTCT1 ", // RCT1_VEHICLE_TYPE_STEEL_ROLLER_COASTER_TRAIN + "TOGST ", // RCT1_VEHICLE_TYPE_STEEL_ROLLER_COASTER_TRAIN_BACKWARDS + "ARRSW1 ", // RCT1_VEHICLE_TYPE_WOODEN_ROLLER_COASTER_TRAIN + "NEMT ", // RCT1_VEHICLE_TYPE_INVERTED_COASTER_TRAIN (Not in RCT2) + "ZLDB ", // RCT1_VEHICLE_TYPE_SUSPENDED_SWINGING_CARS + "NRL ", // RCT1_VEHICLE_TYPE_LADYBIRD_CARS + "MONO2 ", // RCT1_VEHICLE_TYPE_STANDUP_ROLLER_COASTER_CARS + "BATFL ", // RCT1_VEHICLE_TYPE_SPINNING_CARS + "RBOAT ", // RCT1_VEHICLE_TYPE_SINGLE_PERSON_SWINGING_CHAIRS + "WMOUSE ", // RCT1_VEHICLE_TYPE_SWANS_PEDAL_BOATS + "STEEP1 ", // RCT1_VEHICLE_TYPE_LARGE_MONORAIL_TRAIN + "SPCAR ", // RCT1_VEHICLE_TYPE_CANOES + "SSC1 ", // RCT1_VEHICLE_TYPE_ROWING_BOATS + "BOB1 ", // RCT1_VEHICLE_TYPE_STEAM_TRAIN + "OBS1 ", // RCT1_VEHICLE_TYPE_WOODEN_MOUSE_CARS + "SCHT1 ", // RCT1_VEHICLE_TYPE_BUMPER_BOATS + "DING1 ", // RCT1_VEHICLE_TYPE_WOODEN_ROLLER_COASTER_TRAIN_BACKWARDS + "AMT1 ", // RCT1_VEHICLE_TYPE_ROCKET_CARS + "CLIFT1 ", // RCT1_VEHICLE_TYPE_HORSES // Steeplechase + "ARRT1 ", // RCT1_VEHICLE_TYPE_SPORTSCARS + "HMAZE ", // RCT1_VEHICLE_TYPE_LYING_DOWN_SWINGING_CARS (Inverted single-rail) + "HSKELT ", // RCT1_VEHICLE_TYPE_WOODEN_MINE_CARS + "KART1 ", // RCT1_VEHICLE_TYPE_SUSPENDED_SWINGING_AIRPLANE_CARS + "LFB1 ", // RCT1_VEHICLE_TYPE_SMALL_MONORAIL_CARS + "RAPBOAT ", // RCT1_VEHICLE_TYPE_WATER_TRICYCLES + "DODG1 ", // RCT1_VEHICLE_TYPE_LAUNCHED_FREEFALL_CAR + "SWSH1 ", // RCT1_VEHICLE_TYPE_BOBSLEIGH_CARS + "SWSH2 ", // RCT1_VEHICLE_TYPE_DINGHIES + "ICECR1 ", // RCT1_VEHICLE_TYPE_ROTATING_CABIN + "CHPSH ", // RCT1_VEHICLE_TYPE_MINE_TRAIN + "DRNKS ", // RCT1_VEHICLE_TYPE_CHAIRLIFT_CARS + "CNDYF ", // RCT1_VEHICLE_TYPE_CORKSCREW_ROLLER_COASTER_TRAIN + "BURGB ", // RCT1_VEHICLE_TYPE_MOTORBIKES + "MGR1 ", // RCT1_VEHICLE_TYPE_RACING_CARS + "BALLN ", // RCT1_VEHICLE_TYPE_TRUCKS + "INFOK ", // RCT1_VEHICLE_TYPE_GO_KARTS + "TLT1 ", // RCT1_VEHICLE_TYPE_RAPIDS_BOATS + "FWH1 ", // RCT1_VEHICLE_TYPE_LOG_FLUME_BOATS + "SIMPOD ", // RCT1_VEHICLE_TYPE_DODGEMS + "C3D ", // RCT1_VEHICLE_TYPE_SWINGING_SHIP + "TOPSP1 ", // RCT1_VEHICLE_TYPE_SWINGING_INVERTER_SHIP + "SRINGS ", // RCT1_VEHICLE_TYPE_MERRY_GO_ROUND + "REVF1 ", // RCT1_VEHICLE_TYPE_FERRIS_WHEEL + "SOUVS ", // RCT1_VEHICLE_TYPE_SIMULATOR_POD + "BMVD ", // RCT1_VEHICLE_TYPE_CINEMA_BUILDING + "PIZZS ", // RCT1_VEHICLE_TYPE_TOPSPIN_CAR + "TWIST1 ", // RCT1_VEHICLE_TYPE_SPACE_RINGS + "HHBUILD ", // RCT1_VEHICLE_TYPE_REVERSE_FREEFALL_ROLLER_COASTER_CAR + "POPCS ", // RCT1_VEHICLE_TYPE_VERTICAL_ROLLER_COASTER_CARS + "CIRCUS1 ", // RCT1_VEHICLE_TYPE_CAT_CARS + "GTC ", // RCT1_VEHICLE_TYPE_TWIST_ARMS_AND_CARS + "BMSD ", // RCT1_VEHICLE_TYPE_HAUNTED_HOUSE_BUILDING + "MFT ", // RCT1_VEHICLE_TYPE_LOG_CARS + "SFRIC1 ", // RCT1_VEHICLE_TYPE_CIRCUS_TENT + "SMC1 ", // RCT1_VEHICLE_TYPE_GHOST_TRAIN_CARS + "HOTDS ", // RCT1_VEHICLE_TYPE_STEEL_TWISTER_ROLLER_COASTER_TRAIN + "SQDST ", // RCT1_VEHICLE_TYPE_WOODEN_TWISTER_ROLLER_COASTER_TRAIN + "HATST ", // RCT1_VEHICLE_TYPE_WOODEN_SIDE_FRICTION_CARS + "TOFFS ", // RCT1_VEHICLE_TYPE_VINTAGE_CARS + "VREEL ", // RCT1_VEHICLE_TYPE_STEAM_TRAIN_COVERED_CARS + "SPBOAT ", // RCT1_VEHICLE_TYPE_STAND_UP_STEEL_TWISTER_ROLLER_COASTER_TRAIN + "MONBK ", // RCT1_VEHICLE_TYPE_FLOORLESS_STEEL_TWISTER_ROLLER_COASTER_TRAIN + "BMAIR ", // RCT1_VEHICLE_TYPE_STEEL_MOUSE_CARS + "SMONO ", // RCT1_VEHICLE_TYPE_CHAIRLIFT_CARS_ALTERNATIVE + " ", // RCT1_VEHICLE_TYPE_SUSPENDED_MONORAIL_TRAIN + "REVCAR ", // RCT1_VEHICLE_TYPE_HELICOPTER_CARS + "UTCAR ", // RCT1_VEHICLE_TYPE_VIRGINIA_REEL_TUBS + "GOLF1 ", // RCT1_VEHICLE_TYPE_REVERSER_CARS + " ", // RCT1_VEHICLE_TYPE_GOLFERS + "GDROP1 ", // RCT1_VEHICLE_TYPE_RIVER_RIDE_BOATS + "FSAUC ", // RCT1_VEHICLE_TYPE_FLYING_ROLLER_COASTER_TRAIN + "CHBUILD ", // RCT1_VEHICLE_TYPE_NON_LOOPING_STEEL_TWISTER_ROLLER_COASTER_TRAIN + "HELICAR ", // RCT1_VEHICLE_TYPE_HEARTLINE_TWISTER_CARS + "SLCT ", // RCT1_VEHICLE_TYPE_HEARTLINE_TWISTER_CARS_REVERSED + "CSTBOAT ", // RCT1_VEHICLE_TYPE_RESERVED + "THCAR ", // RCT1_VEHICLE_TYPE_ROTODROP_CAR + "IVMC1 ", // RCT1_VEHICLE_TYPE_FLYING_SAUCERS + "JSKI ", // RCT1_VEHICLE_TYPE_CROOKED_HOUSE_BUILDING + "TSHRT ", // RCT1_VEHICLE_TYPE_BICYCLES + "RFTBOAT ", // RCT1_VEHICLE_TYPE_HYPERCOASTER_TRAIN + "DOUGH ", // RCT1_VEHICLE_TYPE_4_ACROSS_INVERTED_COASTER_TRAIN + "ENTERP ", // RCT1_VEHICLE_TYPE_WATER_COASTER_BOATS + "COFFS ", // RCT1_VEHICLE_TYPE_FACEOFF_CARS + "CHCKS ", // RCT1_VEHICLE_TYPE_JET_SKIS + "LEMST ", // RCT1_VEHICLE_TYPE_RAFT_BOATS + "WMSPIN ", // RCT1_VEHICLE_TYPE_AMERICAN_STYLE_STEAM_TRAIN + "SWANS ", // RCT1_VEHICLE_TYPE_AIR_POWERED_COASTER_TRAIN + "MONO1 ", // RCT1_VEHICLE_TYPE_SUSPENDED_WILD_MOUSE_CARS (Inverted Hairpin in RCT2) + "CBOAT ", // RCT1_VEHICLE_TYPE_ENTERPRISE_WHEEL + }; + return map[vehicleType]; + } - const char * GetSceneryGroupObject(uint8 sceneryGroupType) + const char * GetSmallSceneryObject(uint8 smallSceneryType) + { + static const char * map[] = { - static const char * map[] = - { - " ", // RCT1_SCENERY_THEME_GENERAL - "SCGMINE ", // RCT1_SCENERY_THEME_MINE - "SCGCLASS", // RCT1_SCENERY_THEME_CLASSICAL_ROMAN - "SCGEGYPT", // RCT1_SCENERY_THEME_EGYPTIAN - "SCGMART ", // RCT1_SCENERY_THEME_MARTIAN - "SCGWOND ", // RCT1_SCENERY_THEME_TOYLAND - "SCGJURAS", // RCT1_SCENERY_THEME_JURASSIC - "SCGSPOOK", // RCT1_SCENERY_THEME_GRAVEYARD - "SCGJUNGL", // RCT1_SCENERY_THEME_JUNGLE - "SCGABSTR", // RCT1_SCENERY_THEME_ABSTRACT - "SCGSNOW ", // RCT1_SCENERY_THEME_SNOW_ICE - "SCGMEDIE", // RCT1_SCENERY_THEME_MEDIEVAL - "SCGSPACE", // RCT1_SCENERY_THEME_SPACE - "SCGHALLO", // RCT1_SCENERY_THEME_CREEPY - "SCGURBAN", // RCT1_SCENERY_THEME_URBAN - "SCGORIEN", // RCT1_SCENERY_THEME_PAGODA - }; - return map[sceneryGroupType]; - } + "TL0 ", + "TL1 ", + "TL2 ", + "TL3 ", + "TM0 ", + "TM1 ", + "TM2 ", + "TM3 ", + "TS0 ", + "TS1 ", + "TS2 ", + "TS3 ", + "TS4 ", + "TS5 ", + "TS6 ", + "TIC ", + "TLC ", + "TMC ", + "TMP ", + "TITC ", + "TGHC ", + "TAC ", + "TGHC2 ", + "TCJ ", + "TMBJ ", + "TCF ", + "TCL ", + "TRF ", + "TRF2 ", + "TEL ", + "TAP ", + "TSP ", + "TMZP ", + "TCRP ", + "TBP ", + "TLP ", + "TWP ", + "TAS ", + "TMG ", + "TWW ", + "TSB ", + "TVL ", + "TCT ", + "TEF ", + "TAL ", + "TSQ ", + "THT ", + "TCB ", + "TDM ", + "TSD ", + "TGS ", + "TUS ", + "TH1 ", + "TBC ", + "TH2 ", + "TPM ", + "TSC ", + "TG1 ", + "TWF ", + "TSH0 ", + "TSH1 ", + "TSH2 ", + "TSH3 ", + "TSH4 ", + "TSH5 ", + "TG2 ", + "TG3 ", + "TG4 ", + "TG5 ", + "TG6 ", + "TG7 ", + "TG8 ", + "TG9 ", + "TG10 ", + "TG11 ", + "TG12 ", + "TG13 ", + "TG14 ", + "TT1 ", + "TDF ", + "TSH ", + "THRS ", + "TSTD ", + "TRMS ", + "TRWS ", + "TRC ", + "TQF ", + "TES1 ", + "TEN ", + "TERS ", + "TERB ", + "TEP ", + "TST1 ", + "TST2 ", + "TMS1 ", + "TAS1 ", + "TAS2 ", + "TAS3 ", + "TST3 ", + "TST4 ", + "TST5 ", + "TAS4 ", + "TCY ", + "TBW ", + "TBR1 ", + "TBR2 ", + "TML ", + "TMW ", + "TBR3 ", + "TBR4 ", + "TMJ ", + "TBR ", + "TMO1 ", + "TMO2 ", + "TMO3 ", + "TMO4 ", + "TMO5 ", + "TWH1 ", + "TWH2 ", + "TNS ", + "TP1 ", + "TP2 ", + "TK1 ", + "TK2 ", + "TR1 ", + "TR2 ", + "TQ1 ", + "TQ2 ", + "TWN ", + "TCE ", + "TCO ", + "THL ", + "TCC ", + "TB1 ", + "TB2 ", + "TK3 ", + "TK4 ", + "TBN ", + "TBN1 ", + "TDT1 ", + "TDT2 ", + "TDT3 ", + "TMM1 ", + "TMM2 ", + "TMM3 ", + "TGS1 ", + "TGS2 ", + "TGS3 ", + "TGS4 ", + "TDN4 ", + "TDN5 ", + "TJT1 ", + "TJT2 ", + "TJB1 ", + "TTF ", + "TF1 ", + "TF2 ", + "TGE1 ", + "TJT3 ", + "TJT4 ", + "TJP1 ", + "TJB2 ", + "TGE2 ", + "TJT5 ", + "TJB3 ", + "TJB4 ", + "TJT6 ", + "TJP2 ", + "TGE3 ", + "TCK ", + "TGE4 ", + "TGE5 ", + "TG15 ", + "TG16 ", + "TG17 ", + "TG18 ", + "TG19 ", + "TG20 ", + "TG21 ", + "TSM ", + "TIG ", + "TCFS ", + "TRFS ", + "TRF3 ", + "TNSS ", + "TCT1 ", + "TCT2 ", + "TSF1 ", + "TSF2 ", + "TSF3 ", + "TCN ", + "TTG ", + "TSNC ", + "TSNB ", + "TSCP ", + "TCD ", + "TSG ", + "TSK ", + "TGH1 ", + "TGH2 ", + "TSMP ", + "TJF ", + "TLY ", + "TGC1 ", + "TGC2 ", + "TGG ", + "TSPH ", + "TOH1 ", + "TOH2 ", + "TOT1 ", + "TOT2 ", + "TOS ", + "TOT3 ", + "TOT4 ", + "TSC2 ", + "TSP1 ", + "TOH3 ", + "TSP2 ", + "ROMROOF1", + "GEOROOF1", + "TNTROOF1", + "JNGROOF1", + "MINROOF1", + "ROMROOF2", + "GEOROOF2", + "PAGROOF1", + "SPCROOF1", + "ROOF1 ", + "ROOF2 ", + "ROOF3 ", + "ROOF4 ", + "ROOF5 ", + "ROOF6 ", + "ROOF7 ", + "ROOF8 ", + "ROOF9 ", + "ROOF10 ", + "ROOF11 ", + "ROOF12 ", + "ROOF13 ", + "ROOF14 ", + "IGROOF ", + "CORROOF ", + "CORROOF2", + }; + return map[smallSceneryType]; + } - const char * GetWaterObject(uint8 waterType) + const char * GetLargeSceneryObject(uint8 largeSceneryType) + { + static const char * map[] = { - static const char * map[] = - { - "WTRCYAN ", - "WTRORNG ", - }; - return map[waterType]; - } + "SCOL ", + "SHS1 ", + "SSPX ", + "SHS2 ", + "SCLN ", + "SMH1 ", + "SMH2 ", + "SVLC ", + "SPYR ", + "SMN1 ", + "SMB ", + "SSK1 ", + "SDN1 ", + "SDN2 ", + "SDN3 ", + "SIP ", + "STB1 ", + "STB2 ", + "STG1 ", + "STG2 ", + "SCT ", + "SOH1 ", + "SOH2 ", + "SOH3 ", + "SGP ", + "SSR ", + "STH ", + "SAH ", + "SPS ", + "SPG ", + "SOB ", + "SAH2 ", + "SST ", + "SSH ", + "SAH3 ", + "SSIG1 ", + "SSIG2 ", + "SSIG3 ", + "SSIG4 ", + }; + return map[largeSceneryType]; + } - const List GetPreferedRideEntryOrder(uint8 rideType) + const char * GetWallObject(uint8 wallType) + { + static const char * map[] = { - static const List preferedRideEntryOrder[] = - { - { "SPDRCR "}, // RIDE_TYPE_SPIRAL_ROLLER_COASTER - { "TOGST "}, // RIDE_TYPE_STAND_UP_ROLLER_COASTER - { "ARRSW1 ", "VEKVAMP ", "ARRSW2 "}, // RIDE_TYPE_SUSPENDED_SWINGING_COASTER - { "NEMT "}, // RIDE_TYPE_INVERTED_ROLLER_COASTER - { "ZLDB ", "ZLOG "}, // RIDE_TYPE_JUNIOR_ROLLER_COASTER - { "NRL ", "NRL2 ", "AML1 ", "TRAM1 "}, // RIDE_TYPE_MINIATURE_RAILWAY - { "MONO1 ", "MONO2 ", "MONO3 "}, // RIDE_TYPE_MONORAIL - { "BATFL ", "SKYTR "}, // RIDE_TYPE_MINI_SUSPENDED_COASTER - { "RBOAT ", "BBOAT ", "CBOAT ", "SWANS ", "TRIKE ", "JSKI " }, // RIDE_TYPE_BOAT_RIDE - { "WMOUSE ", "WMMINE "}, // RIDE_TYPE_WOODEN_WILD_MOUSE - { "STEEP1 ", "STEEP2 ", "SBOX "}, // RIDE_TYPE_STEEPLECHASE - { "SPCAR ", "RCR ", "TRUCK1 ", "VCR ", "CTCAR " }, // RIDE_TYPE_CAR_RIDE - { "SSC1 " }, // RIDE_TYPE_LAUNCHED_FREEFALL - { "BOB1 ", "INTBOB " }, // RIDE_TYPE_BOBSLEIGH_COASTER - { "OBS1 ", "OBS2 " }, // RIDE_TYPE_OBSERVATION_TOWER - { "SCHT1 " }, // RIDE_TYPE_LOOPING_ROLLER_COASTER - { "DING1 " }, // RIDE_TYPE_DINGHY_SLIDE - { "AMT1 " }, // RIDE_TYPE_MINE_TRAIN_COASTER - { "CLIFT1 ", "CLIFT2 " }, // RIDE_TYPE_CHAIRLIFT - { "ARRT1 ", "ARRT2 " }, // RIDE_TYPE_CORKSCREW_ROLLER_COASTER - { }, // RIDE_TYPE_MAZE - { }, // RIDE_TYPE_SPIRAL_SLIDE - { "KART1 " }, // RIDE_TYPE_GO_KARTS - { "LFB1 " }, // RIDE_TYPE_LOG_FLUME - { "RAPBOAT " }, // RIDE_TYPE_RIVER_RAPIDS - { }, // RIDE_TYPE_DODGEMS - { }, // RIDE_TYPE_PIRATE_SHIP - { }, // RIDE_TYPE_SWINGING_INVERTER_SHIP - { }, // RIDE_TYPE_FOOD_STALL - { }, // RIDE_TYPE_1D - { }, // RIDE_TYPE_DRINK_STALL - { }, // RIDE_TYPE_1F - { }, // RIDE_TYPE_SHOP - { }, // RIDE_TYPE_MERRY_GO_ROUND - { }, // RIDE_TYPE_22 - { }, // RIDE_TYPE_INFORMATION_KIOSK - { }, // RIDE_TYPE_TOILETS - { }, // RIDE_TYPE_FERRIS_WHEEL - { }, // RIDE_TYPE_MOTION_SIMULATOR - { }, // RIDE_TYPE_3D_CINEMA - { }, // RIDE_TYPE_TOP_SPIN - { }, // RIDE_TYPE_SPACE_RINGS - { "REVF1 " }, // RIDE_TYPE_REVERSE_FREEFALL_COASTER - { "LIFT1 " }, // RIDE_TYPE_LIFT - { "BMVD " }, // RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER - { }, // RIDE_TYPE_CASH_MACHINE - { }, // RIDE_TYPE_TWIST - { }, // RIDE_TYPE_HAUNTED_HOUSE - { }, // RIDE_TYPE_FIRST_AID - { }, // RIDE_TYPE_CIRCUS_SHOW - { "GTC ", "HMCAR " }, // RIDE_TYPE_GHOST_TRAIN - { "BMSD ", "BMSU ", "BMFL ", "BMRB ", "GOLTR " }, // RIDE_TYPE_TWISTER_ROLLER_COASTER - { "PTCT1 ", "MFT ", "PTCT2 " }, // RIDE_TYPE_WOODEN_ROLLER_COASTER - { "SFRIC1 " }, // RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER - { "SMC1 ", "SMC2 ", "WMSPIN " }, // RIDE_TYPE_WILD_MOUSE - { "ARRX " }, // RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER - { }, // RIDE_TYPE_38 - { "BMAIR " }, // RIDE_TYPE_FLYING_ROLLER_COASTER - { }, // RIDE_TYPE_3A - { "VREEL " }, // RIDE_TYPE_VIRGINIA_REEL - { "SPBOAT " }, // RIDE_TYPE_SPLASH_BOATS - { "HELICAR " }, // RIDE_TYPE_MINI_HELICOPTERS - { "VEKST " }, // RIDE_TYPE_LAY_DOWN_ROLLER_COASTER - { "SMONO " }, // RIDE_TYPE_SUSPENDED_MONORAIL - { }, // RIDE_TYPE_40 - { "REVCAR " }, // RIDE_TYPE_REVERSER_ROLLER_COASTER - { "UTCAR ", "UTCARR " }, // RIDE_TYPE_HEARTLINE_TWISTER_COASTER - { }, // RIDE_TYPE_MINI_GOLF - { "INTST " }, // RIDE_TYPE_GIGA_COASTER - { "GDROP1 " }, // RIDE_TYPE_ROTO_DROP - { }, // RIDE_TYPE_FLYING_SAUCERS - { }, // RIDE_TYPE_CROOKED_HOUSE - { "MONBK " }, // RIDE_TYPE_MONORAIL_CYCLES - { "SLCT ", "SLCFO ", "VEKDV " }, // RIDE_TYPE_COMPACT_INVERTED_COASTER - { "CSTBOAT " }, // RIDE_TYPE_WATER_COASTER - { "THCAR " }, // RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER - { "IVMC1 " }, // RIDE_TYPE_INVERTED_HAIRPIN_COASTER - { }, // RIDE_TYPE_MAGIC_CARPET - { "SUBMAR " }, // RIDE_TYPE_SUBMARINE_RIDE - { "RFTBOAT " }, // RIDE_TYPE_RIVER_RAFTS - { }, // RIDE_TYPE_50 - { }, // RIDE_TYPE_ENTERPRISE - { }, // RIDE_TYPE_52 - { }, // RIDE_TYPE_53 - { }, // RIDE_TYPE_54 - { }, // RIDE_TYPE_55 - { "INTINV " }, // RIDE_TYPE_INVERTED_IMPULSE_COASTER - { "WCATC ", "RCKC ", "JSTAR1 " }, // RIDE_TYPE_MINI_ROLLER_COASTER - { "PMT1 " }, // RIDE_TYPE_MINE_RIDE - { "PREMT1 " }, // RIDE_TYPE_59 - }; // RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER - return preferedRideEntryOrder[rideType]; - } + "WMF ", + "WMFG ", + "WRW ", + "WEW ", + "WHG ", + "WHGG ", + "WCW1 ", + "WCW2 ", + "WSW ", + "WSWG ", + "WMW ", + "WALLGL16", + "WFW1 ", + "WFWG ", + "WPW1 ", + "WPW2 ", + "WPF ", + "WPFG ", + "WWTW ", + "WMWW ", + "WSW1 ", + "WSW2 ", + "WGW2 ", + "WBW ", + "WBR1 ", + "WBRG ", + "WALLCFAR", + "WALLPOST", + "WBR2 ", + "WBR3 ", + "WPW3 ", + "WJF ", + "WCH ", + "WCHG ", + "WC1 ", + "WC2 ", + "WC3 ", + "WC4 ", + "WC5 ", + "WC6 ", + "WC7 ", + "WC8 ", + "WC9 ", + "WC10 ", + "WC11 ", + "WC12 ", + "WC13 ", + "WC14 ", + "WC15 ", + "WC16 ", + "WC17 ", + "WC18 ", + "WALLBRDR", + "WALLBR32", + "WALLBR16", + "WALLBR8 ", + "WALLCF8 ", + "WALLCF16", + "WALLCF32", + "WALLBB8 ", + "WALLBB16", + "WALLBB32", + "WALLRS8 ", + "WALLRS16", + "WALLRS32", + "WALLCB8 ", + "WALLCB16", + "WALLCB32", + "WALLGL8 ", + "WALLGL32", + "WALLWD8 ", + "WALLWD16", + "WALLWD32", + "WALLTN32", + "WALLJN32", + "WALLMN32", + "WALLSP32", + "WALLPG32", + "WALLU132", + "WALLU232", + "WALLCZ32", + "WALLCW32", + "WALLCY32", + "WALLCX32", + "WBR1A ", + "WBR2A ", + "WRWA ", + "WWTWA ", + "WALLIG16", + "WALLIG24", + "WALLCO16", + "WALLCFDR", + "WALLCBDR", + "WALLBRWN", + "WALLCFWN", + "WALLCBWN", + }; + return map[wallType]; + } + + const char * GetSceneryGroupObject(uint8 sceneryGroupType) + { + static const char * map[] = + { + " ", // RCT1_SCENERY_THEME_GENERAL + "SCGMINE ", // RCT1_SCENERY_THEME_MINE + "SCGCLASS", // RCT1_SCENERY_THEME_CLASSICAL_ROMAN + "SCGEGYPT", // RCT1_SCENERY_THEME_EGYPTIAN + "SCGMART ", // RCT1_SCENERY_THEME_MARTIAN + "SCGWOND ", // RCT1_SCENERY_THEME_TOYLAND + "SCGJURAS", // RCT1_SCENERY_THEME_JURASSIC + "SCGSPOOK", // RCT1_SCENERY_THEME_GRAVEYARD + "SCGJUNGL", // RCT1_SCENERY_THEME_JUNGLE + "SCGABSTR", // RCT1_SCENERY_THEME_ABSTRACT + "SCGSNOW ", // RCT1_SCENERY_THEME_SNOW_ICE + "SCGMEDIE", // RCT1_SCENERY_THEME_MEDIEVAL + "SCGSPACE", // RCT1_SCENERY_THEME_SPACE + "SCGHALLO", // RCT1_SCENERY_THEME_CREEPY + "SCGURBAN", // RCT1_SCENERY_THEME_URBAN + "SCGORIEN", // RCT1_SCENERY_THEME_PAGODA + }; + return map[sceneryGroupType]; + } + + const char * GetWaterObject(uint8 waterType) + { + static const char * map[] = + { + "WTRCYAN ", + "WTRORNG ", + }; + return map[waterType]; + } + + const List GetPreferedRideEntryOrder(uint8 rideType) + { + static const List preferedRideEntryOrder[] = + { + { "SPDRCR "}, // RIDE_TYPE_SPIRAL_ROLLER_COASTER + { "TOGST "}, // RIDE_TYPE_STAND_UP_ROLLER_COASTER + { "ARRSW1 ", "VEKVAMP ", "ARRSW2 "}, // RIDE_TYPE_SUSPENDED_SWINGING_COASTER + { "NEMT "}, // RIDE_TYPE_INVERTED_ROLLER_COASTER + { "ZLDB ", "ZLOG "}, // RIDE_TYPE_JUNIOR_ROLLER_COASTER + { "NRL ", "NRL2 ", "AML1 ", "TRAM1 "}, // RIDE_TYPE_MINIATURE_RAILWAY + { "MONO1 ", "MONO2 ", "MONO3 "}, // RIDE_TYPE_MONORAIL + { "BATFL ", "SKYTR "}, // RIDE_TYPE_MINI_SUSPENDED_COASTER + { "RBOAT ", "BBOAT ", "CBOAT ", "SWANS ", "TRIKE ", "JSKI " }, // RIDE_TYPE_BOAT_RIDE + { "WMOUSE ", "WMMINE "}, // RIDE_TYPE_WOODEN_WILD_MOUSE + { "STEEP1 ", "STEEP2 ", "SBOX "}, // RIDE_TYPE_STEEPLECHASE + { "SPCAR ", "RCR ", "TRUCK1 ", "VCR ", "CTCAR " }, // RIDE_TYPE_CAR_RIDE + { "SSC1 " }, // RIDE_TYPE_LAUNCHED_FREEFALL + { "BOB1 ", "INTBOB " }, // RIDE_TYPE_BOBSLEIGH_COASTER + { "OBS1 ", "OBS2 " }, // RIDE_TYPE_OBSERVATION_TOWER + { "SCHT1 " }, // RIDE_TYPE_LOOPING_ROLLER_COASTER + { "DING1 " }, // RIDE_TYPE_DINGHY_SLIDE + { "AMT1 " }, // RIDE_TYPE_MINE_TRAIN_COASTER + { "CLIFT1 ", "CLIFT2 " }, // RIDE_TYPE_CHAIRLIFT + { "ARRT1 ", "ARRT2 " }, // RIDE_TYPE_CORKSCREW_ROLLER_COASTER + { }, // RIDE_TYPE_MAZE + { }, // RIDE_TYPE_SPIRAL_SLIDE + { "KART1 " }, // RIDE_TYPE_GO_KARTS + { "LFB1 " }, // RIDE_TYPE_LOG_FLUME + { "RAPBOAT " }, // RIDE_TYPE_RIVER_RAPIDS + { }, // RIDE_TYPE_DODGEMS + { }, // RIDE_TYPE_PIRATE_SHIP + { }, // RIDE_TYPE_SWINGING_INVERTER_SHIP + { }, // RIDE_TYPE_FOOD_STALL + { }, // RIDE_TYPE_1D + { }, // RIDE_TYPE_DRINK_STALL + { }, // RIDE_TYPE_1F + { }, // RIDE_TYPE_SHOP + { }, // RIDE_TYPE_MERRY_GO_ROUND + { }, // RIDE_TYPE_22 + { }, // RIDE_TYPE_INFORMATION_KIOSK + { }, // RIDE_TYPE_TOILETS + { }, // RIDE_TYPE_FERRIS_WHEEL + { }, // RIDE_TYPE_MOTION_SIMULATOR + { }, // RIDE_TYPE_3D_CINEMA + { }, // RIDE_TYPE_TOP_SPIN + { }, // RIDE_TYPE_SPACE_RINGS + { "REVF1 " }, // RIDE_TYPE_REVERSE_FREEFALL_COASTER + { "LIFT1 " }, // RIDE_TYPE_LIFT + { "BMVD " }, // RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER + { }, // RIDE_TYPE_CASH_MACHINE + { }, // RIDE_TYPE_TWIST + { }, // RIDE_TYPE_HAUNTED_HOUSE + { }, // RIDE_TYPE_FIRST_AID + { }, // RIDE_TYPE_CIRCUS_SHOW + { "GTC ", "HMCAR " }, // RIDE_TYPE_GHOST_TRAIN + { "BMSD ", "BMSU ", "BMFL ", "BMRB ", "GOLTR " }, // RIDE_TYPE_TWISTER_ROLLER_COASTER + { "PTCT1 ", "MFT ", "PTCT2 " }, // RIDE_TYPE_WOODEN_ROLLER_COASTER + { "SFRIC1 " }, // RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER + { "SMC1 ", "SMC2 ", "WMSPIN " }, // RIDE_TYPE_WILD_MOUSE + { "ARRX " }, // RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER + { }, // RIDE_TYPE_38 + { "BMAIR " }, // RIDE_TYPE_FLYING_ROLLER_COASTER + { }, // RIDE_TYPE_3A + { "VREEL " }, // RIDE_TYPE_VIRGINIA_REEL + { "SPBOAT " }, // RIDE_TYPE_SPLASH_BOATS + { "HELICAR " }, // RIDE_TYPE_MINI_HELICOPTERS + { "VEKST " }, // RIDE_TYPE_LAY_DOWN_ROLLER_COASTER + { "SMONO " }, // RIDE_TYPE_SUSPENDED_MONORAIL + { }, // RIDE_TYPE_40 + { "REVCAR " }, // RIDE_TYPE_REVERSER_ROLLER_COASTER + { "UTCAR ", "UTCARR " }, // RIDE_TYPE_HEARTLINE_TWISTER_COASTER + { }, // RIDE_TYPE_MINI_GOLF + { "INTST " }, // RIDE_TYPE_GIGA_COASTER + { "GDROP1 " }, // RIDE_TYPE_ROTO_DROP + { }, // RIDE_TYPE_FLYING_SAUCERS + { }, // RIDE_TYPE_CROOKED_HOUSE + { "MONBK " }, // RIDE_TYPE_MONORAIL_CYCLES + { "SLCT ", "SLCFO ", "VEKDV " }, // RIDE_TYPE_COMPACT_INVERTED_COASTER + { "CSTBOAT " }, // RIDE_TYPE_WATER_COASTER + { "THCAR " }, // RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER + { "IVMC1 " }, // RIDE_TYPE_INVERTED_HAIRPIN_COASTER + { }, // RIDE_TYPE_MAGIC_CARPET + { "SUBMAR " }, // RIDE_TYPE_SUBMARINE_RIDE + { "RFTBOAT " }, // RIDE_TYPE_RIVER_RAFTS + { }, // RIDE_TYPE_50 + { }, // RIDE_TYPE_ENTERPRISE + { }, // RIDE_TYPE_52 + { }, // RIDE_TYPE_53 + { }, // RIDE_TYPE_54 + { }, // RIDE_TYPE_55 + { "INTINV " }, // RIDE_TYPE_INVERTED_IMPULSE_COASTER + { "WCATC ", "RCKC ", "JSTAR1 " }, // RIDE_TYPE_MINI_ROLLER_COASTER + { "PMT1 " }, // RIDE_TYPE_MINE_RIDE + { "PREMT1 " }, // RIDE_TYPE_59 + }; // RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER + return preferedRideEntryOrder[rideType]; } }