1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

import research list as best as possible

This commit is contained in:
Ted John
2016-04-16 23:56:09 +01:00
parent 88a26f17b0
commit 72e625c5a3
5 changed files with 279 additions and 43 deletions

View File

@@ -576,3 +576,21 @@ void game_command_set_research_funding(int* eax, int* ebx, int* ecx, int* edx, i
*ebx = 0;
}
void research_insert_ride_entry(uint8 entryIndex, bool researched)
{
rct_ride_entry *rideEntry = get_ride_entry(entryIndex);
uint8 category = rideEntry->category[0];
for (int i = 0; i < 3; i++) {
uint8 rideType = rideEntry->ride_type[i];
if (rideType != 255) {
research_insert(researched, 0x10000 | (rideType << 8) | entryIndex, category);
}
}
}
void research_insert_scenery_group_entry(uint8 entryIndex, bool researched)
{
rct_scenery_set_entry *scenerySetEntry = g_scenerySetEntries[entryIndex];
research_insert(researched, entryIndex, RESEARCH_CATEGORY_SCENERYSET);
}

View File

@@ -85,4 +85,7 @@ void research_finish_item(sint32 entryIndex);
void research_insert(int researched, int entryIndex, int category);
void research_remove(sint32 entryIndex);
void research_insert_ride_entry(uint8 entryIndex, bool researched);
void research_insert_scenery_group_entry(uint8 entryIndex, bool researched);
#endif

View File

@@ -222,7 +222,6 @@ void rct1_fix_landscape()
rct1_load_default_objects();
reset_loaded_objects();
rct1_fix_walls();
rct1_fix_scenery();
rct1_fix_terrain();
rct1_fix_entrance_positions();
rct1_reset_research();
@@ -390,34 +389,6 @@ static void rct1_fix_terrain()
}
}
/**
*
* rct2: 0x006A2956
*/
static void rct1_fix_scenery()
{
rct_map_element *element;
map_element_iterator it;
map_element_iterator_begin(&it);
while (map_element_iterator_next(&it)) {
element = it.element;
if (map_element_get_type(element) != MAP_ELEMENT_TYPE_SCENERY)
continue;
switch (element->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)
element->properties.scenery.colour_2 = COLOUR_WHITE;
break;
}
}
}
/**
* This isn't really RCT1 specific anymore.
* rct2: 0x006A2A68
@@ -671,6 +642,17 @@ static void rct1_fix_colours()
colour = RCT1ColourConversionTable[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 = RCT1ColourConversionTable[
@@ -1684,14 +1666,29 @@ static const rct_object_entry RCT1DefaultObjectsPathBits[] = {
static const rct_object_entry RCT1DefaultObjectsSceneryGroup[] = {
{ 0x00000087, { "SCGTREES" }, 0 },
{ 0x00000087, { "SCGPATHX" }, 0 },
{ 0x00000087, { "SCGSHRUB" }, 0 },
{ 0x00000087, { "SCGGARDN" }, 0 },
{ 0x00000087, { "SCGPATHX" }, 0 },
{ 0x00000087, { "SCGFENCE" }, 0 },
{ 0x00000087, { "SCGMART " }, 0 },
{ 0x00000087, { "SCGWOND " }, 0 },
{ 0x00000087, { "SCGSNOW " }, 0 },
{ 0x00000087, { "SCGWALLS" }, 0 }
{ 0x00000087, { "SCGWALLS" }, 0 },
{ 0x00000087, { "SCGMINE " }, 0 }, // RCT1_SCENERY_THEME_MINE_THEME
{ 0x00000087, { "SCGCLASS" }, 0 }, // RCT1_SCENERY_THEME_CLASSICAL_ROMAN
{ 0x00000087, { "SCGEGYPT" }, 0 }, // RCT1_SCENERY_THEME_EGYPTIAN
{ 0x00000087, { "SCGMART " }, 0 }, // RCT1_SCENERY_THEME_MARTIAN
{ 0x00000087, { "SCGWOND " }, 0 }, // RCT1_SCENERY_THEME_TOYLAND
{ 0x00000087, { "SCGJURAS" }, 0 }, // RCT1_SCENERY_THEME_JURASSIC
{ 0x00000087, { "SCGSPOOK" }, 0 }, // RCT1_SCENERY_THEME_GRAVEYARD
{ 0x00000087, { "SCGJUNGL" }, 0 }, // RCT1_SCENERY_THEME_JUNGLE
{ 0x00000087, { "SCGABSTR" }, 0 }, // RCT1_SCENERY_THEME_ABSTRACT
{ 0x00000087, { "SCGSNOW " }, 0 }, // RCT1_SCENERY_THEME_SNOW_ICE
{ 0x00000087, { "SCGMEDIE" }, 0 }, // RCT1_SCENERY_THEME_MEDIEVAL
{ 0x00000087, { "SCGSPACE" }, 0 }, // RCT1_SCENERY_THEME_SPACE
{ 0x00000087, { "SCGHALLO" }, 0 }, // RCT1_SCENERY_THEME_CREEPY
// Not enough space to fit these last two themes (think about doing dynamic list)
// { 0x00000087, { "SCGURBAN" }, 0 }, // RCT1_SCENERY_THEME_URBAN
// { 0x00000087, { "SCGORIEN" }, 0 }, // RCT1_SCENERY_THEME_PAGODA
};
static const rct_object_entry RCT1DefaultObjectsParkEntrance[] = {
@@ -2011,6 +2008,27 @@ bool rideTypeShouldLoseSeparateFlag(rct_ride_entry *ride)
return remove_flag;
}
const uint8 RCT1SceneryGroupConvertTable[] = {
255, // RCT1_SCENERY_THEME_GENERAL
6, // RCT1_SCENERY_THEME_MINE_THEME
7, // RCT1_SCENERY_THEME_CLASSICAL_ROMAN
8, // RCT1_SCENERY_THEME_EGYPTIAN
9, // RCT1_SCENERY_THEME_MARTIAN
255, // RCT1_SCENERY_THEME_JUMPING_FOUNTAINS
10, // RCT1_SCENERY_THEME_WONDERLAND
11, // RCT1_SCENERY_THEME_JURASSIC
12, // RCT1_SCENERY_THEME_SPOOKY
13, // RCT1_SCENERY_THEME_JUNGLE
14, // RCT1_SCENERY_THEME_ABSTRACT
255, // RCT1_SCENERY_THEME_GARDEN_CLOCK
15, // RCT1_SCENERY_THEME_SNOW_ICE
16, // RCT1_SCENERY_THEME_MEDIEVAL
17, // RCT1_SCENERY_THEME_SPACE
18, // RCT1_SCENERY_THEME_CREEPY
255, // RCT1_SCENERY_THEME_URBAN
255 // RCT1_SCENERY_THEME_PAGODA
};
#pragma endregion
#pragma region RCT1 Scenario / Saved Game Import
@@ -2192,7 +2210,6 @@ static void rct1_import_map_elements(rct1_s4 *s4)
rct1_fix_paths();
rct1_fix_walls();
rct1_fix_banners(s4);
rct1_fix_scenery();
rct1_fix_terrain();
rct1_fix_entrance_positions();
@@ -2363,6 +2380,134 @@ static void rct1_import_ride(rct1_s4 *s4, rct_ride *dst, rct1_ride *src)
dst->excitement = (ride_rating)-1;
}
static uint8 rct1_convert_vehicle_to_ride_entry_index(uint8 rct1RideType, uint8 vehicle)
{
uint8 rideEntryIndex = rct1RideType;
if (vehicle < countof(RCT1AlternativeVehicleMappings)) {
vehicle = RCT1AlternativeVehicleMappings[vehicle];
if (vehicle != USE_DEFAULT_VEHICLE) {
rideEntryIndex = vehicle;
}
}
return rideEntryIndex;
}
static bool _rct1ResearchRideEntryUsed[128];
static bool _rct1ResearchRideTypeUsed[128];
static void rct1_research_insert_vehicle(const rct1_research_item *researchItem, bool researched)
{
uint8 rct1RideType = researchItem->related_ride;
uint8 vehicle = researchItem->item;
uint8 rideEntryIndex = rct1_convert_vehicle_to_ride_entry_index(rct1RideType, vehicle);
if (!_rct1ResearchRideEntryUsed[rideEntryIndex]) {
_rct1ResearchRideEntryUsed[rideEntryIndex] = true;
research_insert_ride_entry(rideEntryIndex, researched);
}
}
/**
* In RollerCoaster Tycoon 1 the research was divided up into scenery themes,
* rides, vehicles for rides and special track pieces for rides. Currently
* OpenRCT2 does not support researching of special track pieces and whether
* vehicles are research-able depends on the vehicle object.
*
* TODO We might probably want to sort the researched items by the prefered
* RCT1 order so the right image shows in the new ride window. This is
* only relevant if RCT1 ride sorting is turned off.
*/
static void rct1_import_research_list(const rct1_s4 *s4)
{
int maxResearchItems = countof(s4->research_items);
const rct1_research_item *researchItems = s4->research_items;
// Loopy Landscapes stores research items in a different place
int gameVersion = sawyercoding_detect_rct1_version(s4->game_version) & FILE_VERSION_MASK;
if (gameVersion == FILE_VERSION_RCT1_LL) {
maxResearchItems = countof(s4->research_items_LL);
researchItems = s4->research_items_LL;
}
// Initialise the "seen" tables
memset(_rct1ResearchRideEntryUsed, 0, sizeof(_rct1ResearchRideEntryUsed));
memset(_rct1ResearchRideTypeUsed, 0, sizeof(_rct1ResearchRideTypeUsed));
// 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 (int i = 0; i < maxResearchItems; i++) {
const rct1_research_item *researchItem = &researchItems[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 = RCT1SceneryGroupConvertTable[rct1SceneryTheme];
if (sceneryGroupEntryIndex != 255) {
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 (int j = 0; j < maxResearchItems; j++) {
const rct1_research_item *researchItem2 = &researchItems[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) {
rct1_research_insert_vehicle(researchItem, researched);
}
numVehicles++;
}
}
if (numVehicles == 0) {
// No vehicles found so just add the default for this ride
if (!_rct1ResearchRideEntryUsed[rideEntryIndex]) {
_rct1ResearchRideEntryUsed[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 (_rct1ResearchRideTypeUsed[researchItem->related_ride]) {
rct1_research_insert_vehicle(researchItem, researched);
}
break;
case RCT1_RESEARCH_CATEGORY_SPECIAL:
// Not supported
break;
}
}
research_remove_non_separate_vehicle_types();
}
static void rct1_import_s4_properly(rct1_s4 *s4)
{
int mapSize = s4->map_size == 0 ? 128 : s4->map_size;
@@ -2396,7 +2541,7 @@ static void rct1_import_s4_properly(rct1_s4 *s4)
// Fix object availability
research_reset_items();
research_populate_list_researched();
rct1_import_research_list(s4);
// Map elements
rct1_import_map_elements(s4);

View File

@@ -165,6 +165,14 @@ typedef struct {
uint8 unk_17A[230];
} rct1_ride;
typedef struct {
uint8 item;
uint8 related_ride;
uint8 category;
uint8 flags;
uint8 expenditure_area;
} rct1_research_item;
/**
* RCT1,AA,LL scenario / saved game structure.
* size: 0x1F850C
@@ -226,7 +234,7 @@ typedef struct {
uint8 last_research_ride;
uint8 last_research_category;
uint8 last_research_flag;
rct_research_item research_items[200];
rct1_research_item research_items[200];
uint8 next_research_item;
uint8 next_research_ride;
uint8 next_research_category;
@@ -291,7 +299,7 @@ typedef struct {
uint8 unk_199C96[3];
uint8 water_colour;
uint16 unk_199C9A;
rct_research_item research_items_LL[180];
rct1_research_item research_items_LL[180];
uint8 unk_19A020[5468];
rct_banner banners[100];
char string_table[1024][32];
@@ -527,6 +535,71 @@ enum{
};
enum {
RCT1_SCENERY_THEME_GENERAL,
RCT1_SCENERY_THEME_MINE,
RCT1_SCENERY_THEME_CLASSICAL_ROMAN,
RCT1_SCENERY_THEME_EGYPTIAN,
RCT1_SCENERY_THEME_MARTIAN,
RCT1_SCENERY_THEME_JUMPING_FOUNTAINS, // Single researchable scenery item
RCT1_SCENERY_THEME_WONDERLAND,
RCT1_SCENERY_THEME_JURASSIC,
RCT1_SCENERY_THEME_SPOOKY,
RCT1_SCENERY_THEME_JUNGLE,
RCT1_SCENERY_THEME_ABSTRACT,
RCT1_SCENERY_THEME_GARDEN_CLOCK, // Single researchable scenery item
RCT1_SCENERY_THEME_SNOW_ICE,
RCT1_SCENERY_THEME_MEDIEVAL,
RCT1_SCENERY_THEME_SPACE,
RCT1_SCENERY_THEME_CREEPY,
RCT1_SCENERY_THEME_URBAN,
RCT1_SCENERY_THEME_PAGODA,
};
enum {
RCT1_RESEARCH_END_AVAILABLE = 0xFF,
RCT1_RESEARCH_END_RESEARCHABLE = 0xFE,
RCT1_RESEARCH_END = 0xFD,
};
enum {
RCT1_RESEARCH_CATEGORY_THEME,
RCT1_RESEARCH_CATEGORY_RIDE,
RCT1_RESEARCH_CATEGORY_VEHICLE,
RCT1_RESEARCH_CATEGORY_SPECIAL,
};
enum {
RCT1_RESEARCH_EXPENDITURE_ROLLERCOASTERS,
RCT1_RESEARCH_EXPENDITURE_THRILL_RIDES,
RCT1_RESEARCH_EXPENDITURE_GENTLE_TRANSPORT_RIDES,
RCT1_RESEARCH_EXPENDITURE_SHOPS,
RCT1_RESEARCH_EXPENDITURE_SCENERY_THEMEING,
RCT1_RESEARCH_EXPENDITURE_RIDE_IMPROVEMENTS,
};
// Unconfirmed special track elements for research
enum {
RCT1_RESEARCH_SPECIAL_BANKED_CURVES = 0x06,
RCT1_RESEARCH_SPECIAL_VERTICAL_LOOP = 0x07,
RCT1_RESEARCH_SPECIAL_STEEP_TWIST = 0x0C,
RCT1_RESEARCH_SPECIAL_INLINE_TWIST = 0x11,
RCT1_RESEARCH_SPECIAL_HALF_LOOP = 0x12,
RCT1_RESEARCH_SPECIAL_CORKSCREW = 0x13,
RCT1_RESEARCH_SPECIAL_BANKED_HELIX_A = 0x15,
RCT1_RESEARCH_SPECIAL_BANKED_HELIX_B = 0x16,
RCT1_RESEARCH_SPECIAL_HELIX = 0x17,
RCT1_RESEARCH_SPECIAL_ON_RIDE_PHOTO = 0x1A,
RCT1_RESEARCH_SPECIAL_WATER_SPLASH = 0x1B,
RCT1_RESEARCH_SPECIAL_VERTICAL_DROP = 0x1C,
RCT1_RESEARCH_SPECIAL_BARREL_ROLL = 0x1D,
RCT1_RESEARCH_SPECIAL_LAUNCHED_LIFT_HILL = 0x1E,
RCT1_RESEARCH_SPECIAL_LARGE_LOOP_AND_HALF = 0x1F,
RCT1_RESEARCH_SPECIAL_REVERSER_TURNTABLE = 0x21,
RCT1_RESEARCH_SPECIAL_HEARTLINE_ROLL = 0x22,
RCT1_RESEARCH_SPECIAL_REVERSING_SECTIONS = 0x23,
};
typedef struct{
uint8 type; // 0x00
uint8 vehicle_type; // 0x01

View File

@@ -168,11 +168,8 @@ typedef struct {
uint8 guest_count_change_modifier;
uint8 current_research_level;
uint8 pad_01357400[4];
uint32 dword_01357404;
uint32 dword_01357408;
uint32 dword_0135740C;
uint32 dword_01357410[5];
uint32 dword_01357424[8];
uint32 ride_types_researched[8];
uint32 ride_entries_researched[8];
uint32 dword_01357444[128];
uint32 dword_01357644[128];