diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 505725ffa4..fef57276cd 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -33,6 +33,8 @@ + + @@ -72,6 +74,8 @@ + + @@ -195,4 +199,4 @@ - \ No newline at end of file + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index e71a9b1250..f6568613c3 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -78,6 +78,12 @@ Header Files + + Header Files + + + Header Files + Header Files @@ -194,6 +200,12 @@ Source Files + + Source Files + + + Source Files + Source Files @@ -308,4 +320,4 @@ Resource Files - \ No newline at end of file + diff --git a/src/config.c b/src/config.c index aa164ce818..f1f62e5cb7 100644 --- a/src/config.c +++ b/src/config.c @@ -615,4 +615,3 @@ static void config_error(char *msg){ } - diff --git a/src/finance.c b/src/finance.c index ad0626a52f..cceea4ee5d 100644 --- a/src/finance.c +++ b/src/finance.c @@ -126,7 +126,7 @@ void finance_pay_ride_upkeep() if (ride->type == RIDE_TYPE_NULL) continue; - if (!(ride->var_1D0 & 0x1000)) { + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED)) { ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); ride->var_196 = 25855; // durability? @@ -191,4 +191,4 @@ void sub_69E869() value += RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32); value = ror32(value, 3); RCT2_GLOBAL(0x013587C4, sint32) = value; -} \ No newline at end of file +} diff --git a/src/news_item.c b/src/news_item.c index 5cc8083781..85eab71a89 100644 --- a/src/news_item.c +++ b/src/news_item.c @@ -206,8 +206,7 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * // Find which ride peep is on ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[peep->current_ride]); - // Check if there are trains on the track (first bit of var_1D0) - if (!(ride->var_1D0 & 1)) { + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) { *x = SPRITE_LOCATION_NULL; break; } diff --git a/src/ride.h b/src/ride.h index ba6814d20f..6d1c7ab6d7 100644 --- a/src/ride.h +++ b/src/ride.h @@ -29,6 +29,8 @@ */ typedef struct { uint8 type; // 0x000 + // pointer to static info. for example, wild mouse type is 0x36, subtype is + // 0x4c. uint8 subtype; // 0x001 uint16 pad_002; uint8 mode; // 0x004 @@ -46,11 +48,24 @@ typedef struct { uint16 exits[4]; // 0x072 uint8 pad_07A[0x0C]; uint16 train_car_map[1]; // 0x086 Points to the first car in the train - uint8 pad_088[0x68]; - sint16 var_0F0; - sint16 var_0F2; - sint16 var_0F4; - uint8 pad_0F6[0x2E]; + uint8 pad_088[0x3F]; + + // Not sure if these should be uint or sint. + uint8 var_0C7; + uint8 var_0C8; + uint8 var_0C9; + + uint8 pad_0CA[0x1B]; + + sint32 var_0E4; + sint32 var_0E8; + sint32 var_0EC; + sint32 var_0F0; + uint8 pad_0F4[0x20]; + uint8 var_114; + // Track length? Number of track segments? + uint8 var_115; + uint8 pad_116[0x0F]; sint16 var_124; sint16 var_126; sint16 var_128; @@ -78,15 +93,22 @@ typedef struct { sint16 upkeep_cost; // 0x182 uint8 pad_184[0x12]; uint16 var_196; - uint8 pad_198; + // used in computing excitement, nausea, etc + uint8 var_198; uint8 var_199; uint8 pad_19A[0x1A]; money32 profit; // 0x1B4 uint8 queue_time[4]; // 0x1B8 - uint8 pad_1BC[0x12]; + uint8 pad_1BC[0x11]; + uint8 var_1CD; uint16 guests_favourite; // 0x1CE - uint32 var_1D0; - uint8 pad_1D4[0x2C]; + uint32 lifecycle_flags; + uint8 pad_1D4[0x20]; + // Example value for wild mouse ride is d5 (before it's been constructed) + // I tried searching the IDA file for "1F4" but couldn't find places where + // this is written to. + uint16 var_1F4; + uint8 pad_1F6[0x0a]; uint16 queue_length[4]; // 0x200 uint8 pad_208[0x58]; } rct_ride; @@ -106,6 +128,27 @@ enum { RIDE_CLASS_KIOSK_OR_FACILITY }; +// Constants used by the lifecycle_flags property at 0x1D0 +enum { + RIDE_LIFECYCLE_ON_TRACK = 1, + RIDE_LIFECYCLE_TESTED = 1 << 1, + RIDE_LIFECYCLE_TEST_IN_PROGRESS = 1 << 2, + RIDE_LIFECYCLE_NO_RAW_STATS = 1 << 3, + RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING = 1 << 4, + RIDE_LIFECYCLE_ON_RIDE_PHOTO = 1 << 5, + + RIDE_LIFECYCLE_BROKEN_DOWN = 1 << 7, + + RIDE_LIFECYCLE_CRASHED = 1 << 10, + + RIDE_LIFECYCLE_EVER_BEEN_OPENED = 1 << 12, + RIDE_LIFECYCLE_MUSIC = 1 << 13, + RIDE_LIFECYCLE_INDESTRUCTIBLE = 1 << 14, + RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK = 1 << 15, + + RIDE_LIFECYCLE_CABLE_LIFT = 1 << 17 +}; + enum { RIDE_TYPE_NULL = 255, RIDE_TYPE_SPIRAL_ROLLER_COASTER = 0, @@ -230,7 +273,7 @@ enum { RIDE_MODE_3D_FILM_MOUSE_TAILS, RIDE_MODE_SPACE_RINGS, RIDE_MODE_BEGINNERS, - RIDE_MODE_LIM_POWERED_LAUNCH, + RIDE_MODE_LIM_POWERED_LAUNCH, // 0x17 RIDE_MODE_FILM_THRILL_RIDERS, RIDE_MODE_3D_FILM_STORM_CHASERS, RIDE_MODE_3D_FILM_SPACE_RAIDERS, @@ -242,7 +285,7 @@ enum { RIDE_MODE_CROOKED_HOUSE, RIDE_MODE_FREEFALL_DROP, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, - RIDE_MODE_POWERED_LAUNCH2, // RCT2 style? + RIDE_MODE_POWERED_LAUNCH2, // 0x23. RCT2 style? RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED }; diff --git a/src/ride_data.c b/src/ride_data.c new file mode 100644 index 0000000000..aefda2a666 --- /dev/null +++ b/src/ride_data.c @@ -0,0 +1,585 @@ +/* + * Whether a particular ride has a running track or not. Will probably end up + * being used in various places in the game. + * + * Data source is 0x0097E3AC + * + * Generating function is here + * https://gist.github.com/kevinburke/eaeb1d8149a6eef0dcc1 + */ + +#include +#include "rct2.h" +#include "ride_data.h" + +const bool hasRunningTrack[0x60] = { + true, // 0 Spiral Roller coaster + true, // 1 Stand Up Coaster + true, // 2 Suspended Swinging + true, // 3 Inverted + true, // 4 Steel Mini Coaster + true, // 5 Mini Railroad + true, // 6 Monorail + true, // 7 Mini Suspended Coaster + false, // 8 Bumper Boats + true, // 9 Wooden Wild Mine/Mouse + true, // a Steeplechase/Motorbike/Soap Box Derby + true, // b Car Ride + true, // c Launched Freefall + true, // d Bobsleigh Coaster + true, // e Observation Tower + true, // f Looping Roller Coaster + true, // 10 Dinghy Slide + true, // 11 Mine Train Coaster + true, // 12 Chairlift + true, // 13 Corkscrew Roller Coaster + false, // 14 Maze + false, // 15 Spiral Slide + true, // 16 Go Karts + true, // 17 Log Flume + true, // 18 River Rapids + false, // 19 Bumper Cars + false, // 1a Pirate Ship + false, // 1b Swinging Inverter Ship + false, // 1c Food Stall + false, // 1d (none) + false, // 1e Drink Stall + false, // 1f (none) + false, // 20 Shop (all types) + false, // 21 Merry Go Round + false, // 22 Balloon Stall (maybe) + false, // 23 Information Kiosk + false, // 24 Bathroom + false, // 25 Ferris Wheel + false, // 26 Motion Simulator + false, // 27 3D Cinema + false, // 28 Gravitron + false, // 29 Space Rings + true, // 2a Reverse Freefall Coaster + true, // 2b Elevator + true, // 2c Vertical Drop Roller Coaster + false, // 2d ATM + false, // 2e Twist + false, // 2f Haunted House + false, // 30 First Aid + false, // 31 Circus Show + true, // 32 Ghost Train + true, // 33 Twister Roller Coaster + true, // 34 Wooden Roller Coaster + true, // 35 Side-Friction Roller Coaster + true, // 36 Wild Mouse + true, // 37 Multi Dimension Coaster + true, // 38 (none) + true, // 39 Flying Roller Coaster + true, // 3a (none) + true, // 3b Virginia Reel + true, // 3c Splash Boats + true, // 3d Mini Helicopters + true, // 3e Lay-down Roller Coaster + true, // 3f Suspended Monorail + true, // 40 (none) + true, // 41 Reverser Roller Coaster + true, // 42 Heartline Twister Roller Coaster + true, // 43 Mini Golf + true, // 44 Giga Coaster + true, // 45 Roto-Drop + false, // 46 Flying Saucers + false, // 47 Crooked House + true, // 48 Monorail Cycles + true, // 49 Compact Inverted Coaster + true, // 4a Water Coaster + true, // 4b Air Powered Vertical Coaster + true, // 4c Inverted Hairpin Coaster + false, // 4d Magic Carpet + false, // 4e Submarine Ride + true, // 4f River Rafts + false, // 50 (none) + false, // 51 Enterprise + false, // 52 (none) + false, // 53 (none) + false, // 54 (none) + true, // 55 (none) + true, // 56 Inverted Impulse Coaster + true, // 57 Mini Roller Coaster + true, // 58 Mine Ride + true, // 59 LIM Launched Roller Coaster +}; + +/** + * Data about ride running costs. This is widely adjusted by the upkeep + * function, so values that don't make much sense here (a roller coaster having + * cheaper upkeep than a car ride) are fixed later on. + * + * data generation script: https://gist.github.com/kevinburke/6bcf4a8fcc95faad7bac + */ +const uint8 initialUpkeepCosts[0x60] = { + 41, // 00 Spiral Roller coaster + 40, // 01 Stand Up Coaster + 40, // 02 Suspended Swinging + 40, // 03 Inverted + 40, // 04 Steel Mini Coaster + 60, // 05 Mini Railroad + 65, // 06 Monorail + 40, // 07 Mini Suspended Coaster + 50, // 08 Bumper Boats + 40, // 09 Wooden Wild Mine/Mouse + 40, // 0a Steeplechase/Motorbike/Soap Box Derby + 70, // 0b Car Ride + 50, // 0c Launched Freefall + 40, // 0d Bobsleigh Coaster + 50, // 0e Observation Tower + 40, // 0f Looping Roller Coaster + 40, // 10 Dinghy Slide + 40, // 11 Mine Train Coaster + 60, // 12 Chairlift + 40, // 13 Corkscrew Roller Coaster + 50, // 14 Maze + 50, // 15 Spiral Slide + 50, // 16 Go Karts + 80, // 17 Log Flume + 82, // 18 River Rapids + 50, // 19 Bumper Cars + 50, // 1a Pirate Ship + 50, // 1b Swinging Inverter Ship + 50, // 1c Food Stall + 50, // 1d (none) + 50, // 1e Drink Stall + 50, // 1f (none) + 50, // 20 Shop (all types) + 50, // 21 Merry Go Round + 50, // 22 Balloon Stall (maybe) + 50, // 23 Information Kiosk + 50, // 24 Bathroom + 50, // 25 Ferris Wheel + 50, // 26 Motion Simulator + 50, // 27 3D Cinema + 50, // 28 Gravitron + 50, // 29 Space Rings + 80, // 2a Reverse Freefall Coaster + 50, // 2b Elevator + 44, // 2c Vertical Drop Roller Coaster + 40, // 2d ATM + 50, // 2e Twist + 50, // 2f Haunted House + 45, // 30 First Aid + 50, // 31 Circus Show + 80, // 32 Ghost Train + 43, // 33 Twister Roller Coaster + 40, // 34 Wooden Roller Coaster + 39, // 35 Side-Friction Roller Coaster + 40, // 36 Wild Mouse + 75, // 37 Multi Dimension Coaster + 75, // 38 (none) + 49, // 39 Flying Roller Coaster + 49, // 3a (none) + 39, // 3b Virginia Reel + 70, // 3c Splash Boats + 70, // 3d Mini Helicopters + 49, // 3e Lay-down Roller Coaster + 70, // 3f Suspended Monorail + 49, // 40 (none) + 39, // 41 Reverser Roller Coaster + 47, // 42 Heartline Twister Roller Coaster + 30, // 43 Mini Golf + 10, // 44 Giga Coaster + 50, // 45 Roto-Drop + 90, // 46 Flying Saucers + 30, // 47 Crooked House + 47, // 48 Monorail Cycles + 40, // 49 Compact Inverted Coaster + 60, // 4a Water Coaster + 90, // 4b Air Powered Vertical Coaster + 40, // 4c Inverted Hairpin Coaster + 50, // 4d Magic Carpet + 50, // 4e Submarine Ride + 50, // 4f River Rafts + 50, // 50 (none) + 50, // 51 Enterprise + 50, // 52 (none) + 50, // 53 (none) + 50, // 54 (none) + 40, // 55 (none) + 180, // 56 Inverted Impulse Coaster + 35, // 57 Mini Roller Coaster + 50, // 58 Mine Ride + 42, // 59 LIM Launched Roller Coaster +}; + +const uint8 costPerTrackPiece[0x60] = { + 80, // 00 Spiral Roller coaster + 80, // 01 Stand Up Coaster + 80, // 02 Suspended Swinging + 80, // 03 Inverted + 80, // 04 Steel Mini Coaster + 0, // 05 Mini Railroad + 0, // 06 Monorail + 80, // 07 Mini Suspended Coaster + 0, // 08 Bumper Boats + 80, // 09 Wooden Wild Mine/Mouse + 80, // 0a Steeplechase/Motorbike/Soap Box Derby + 0, // 0b Car Ride + 0, // 0c Launched Freefall + 80, // 0d Bobsleigh Coaster + 0, // 0e Observation Tower + 80, // 0f Looping Roller Coaster + 80, // 10 Dinghy Slide + 80, // 11 Mine Train Coaster + 0, // 12 Chairlift + 80, // 13 Corkscrew Roller Coaster + 0, // 14 Maze + 0, // 15 Spiral Slide + 0, // 16 Go Karts + 0, // 17 Log Flume + 0, // 18 River Rapids + 0, // 19 Bumper Cars + 0, // 1a Pirate Ship + 0, // 1b Swinging Inverter Ship + 0, // 1c Food Stall + 0, // 1d (none) + 0, // 1e Drink Stall + 0, // 1f (none) + 0, // 20 Shop (all types) + 0, // 21 Merry Go Round + 0, // 22 Balloon Stall (maybe) + 0, // 23 Information Kiosk + 0, // 24 Bathroom + 0, // 25 Ferris Wheel + 0, // 26 Motion Simulator + 0, // 27 3D Cinema + 0, // 28 Gravitron + 0, // 29 Space Rings + 0, // 2a Reverse Freefall Coaster + 0, // 2b Elevator + 80, // 2c Vertical Drop Roller Coaster + 0, // 2d ATM + 0, // 2e Twist + 0, // 2f Haunted House + 0, // 30 First Aid + 0, // 31 Circus Show + 0, // 32 Ghost Train + 80, // 33 Twister Roller Coaster + 80, // 34 Wooden Roller Coaster + 80, // 35 Side-Friction Roller Coaster + 80, // 36 Wild Mouse + 90, // 37 Multi Dimension Coaster + 90, // 38 (none) + 90, // 39 Flying Roller Coaster + 90, // 3a (none) + 80, // 3b Virginia Reel + 0, // 3c Splash Boats + 0, // 3d Mini Helicopters + 90, // 3e Lay-down Roller Coaster + 0, // 3f Suspended Monorail + 90, // 40 (none) + 80, // 41 Reverser Roller Coaster + 80, // 42 Heartline Twister Roller Coaster + 80, // 43 Mini Golf + 80, // 44 Giga Coaster + 0, // 45 Roto-Drop + 0, // 46 Flying Saucers + 0, // 47 Crooked House + 0, // 48 Monorail Cycles + 80, // 49 Compact Inverted Coaster + 80, // 4a Water Coaster + 0, // 4b Air Powered Vertical Coaster + 80, // 4c Inverted Hairpin Coaster + 0, // 4d Magic Carpet + 0, // 4e Submarine Ride + 0, // 4f River Rafts + 0, // 50 (none) + 0, // 51 Enterprise + 0, // 52 (none) + 0, // 53 (none) + 0, // 54 (none) + 80, // 55 (none) + 80, // 56 Inverted Impulse Coaster + 80, // 57 Mini Roller Coaster + 80, // 58 Mine Ride + 80, // 59 LIM Launched Roller Coaster +}; + +/** + * Data initially at 0x0097E3B4 + */ +const uint8 rideUnknownData1[0x60] = { + 10, // 00 Spiral Roller coaster + 10, // 01 Stand Up Coaster + 20, // 02 Suspended Swinging + 13, // 03 Inverted + 8, // 04 Steel Mini Coaster + 10, // 05 Mini Railroad + 10, // 06 Monorail + 10, // 07 Mini Suspended Coaster + 4, // 08 Bumper Boats + 9, // 09 Wooden Wild Mine/Mouse + 10, // 0a Steeplechase/Motorbike/Soap Box Derby + 8, // 0b Car Ride + 10, // 0c Launched Freefall + 10, // 0d Bobsleigh Coaster + 10, // 0e Observation Tower + 10, // 0f Looping Roller Coaster + 4, // 10 Dinghy Slide + 10, // 11 Mine Train Coaster + 4, // 12 Chairlift + 11, // 13 Corkscrew Roller Coaster + 0, // 14 Maze + 0, // 15 Spiral Slide + 8, // 16 Go Karts + 9, // 17 Log Flume + 10, // 18 River Rapids + 5, // 19 Bumper Cars + 0, // 1a Pirate Ship + 0, // 1b Swinging Inverter Ship + 0, // 1c Food Stall + 0, // 1d (none) + 0, // 1e Drink Stall + 0, // 1f (none) + 0, // 20 Shop (all types) + 0, // 21 Merry Go Round + 0, // 22 Balloon Stall (maybe) + 0, // 23 Information Kiosk + 0, // 24 Bathroom + 0, // 25 Ferris Wheel + 0, // 26 Motion Simulator + 0, // 27 3D Cinema + 0, // 28 Gravitron + 0, // 29 Space Rings + 0, // 2a Reverse Freefall Coaster + 10, // 2b Elevator + 11, // 2c Vertical Drop Roller Coaster + 0, // 2d ATM + 0, // 2e Twist + 0, // 2f Haunted House + 0, // 30 First Aid + 0, // 31 Circus Show + 8, // 32 Ghost Train + 11, // 33 Twister Roller Coaster + 10, // 34 Wooden Roller Coaster + 10, // 35 Side-Friction Roller Coaster + 9, // 36 Wild Mouse + 11, // 37 Multi Dimension Coaster + 11, // 38 (none) + 11, // 39 Flying Roller Coaster + 11, // 3a (none) + 10, // 3b Virginia Reel + 9, // 3c Splash Boats + 8, // 3d Mini Helicopters + 11, // 3e Lay-down Roller Coaster + 10, // 3f Suspended Monorail + 11, // 40 (none) + 10, // 41 Reverser Roller Coaster + 11, // 42 Heartline Twister Roller Coaster + 11, // 43 Mini Golf + 12, // 44 Giga Coaster + 10, // 45 Roto-Drop + 5, // 46 Flying Saucers + 0, // 47 Crooked House + 8, // 48 Monorail Cycles + 13, // 49 Compact Inverted Coaster + 8, // 4a Water Coaster + 0, // 4b Air Powered Vertical Coaster + 9, // 4c Inverted Hairpin Coaster + 0, // 4d Magic Carpet + 4, // 4e Submarine Ride + 9, // 4f River Rafts + 0, // 50 (none) + 0, // 51 Enterprise + 0, // 52 (none) + 0, // 53 (none) + 0, // 54 (none) + 11, // 55 (none) + 11, // 56 Inverted Impulse Coaster + 8, // 57 Mini Roller Coaster + 10, // 58 Mine Ride + 9, // 59 LIM Launched Roller Coaster +}; + +/** + * Data at 0x0097E3B6, originally set to either be 3 or 0 and replaced here by + * a boolean table. This may be exactly the same as hasRunningTrack above. + */ +const bool rideUnknownData2[0x60] = { + true, // 00 Spiral Roller coaster + true, // 01 Stand Up Coaster + true, // 02 Suspended Swinging + true, // 03 Inverted + true, // 04 Steel Mini Coaster + true, // 05 Mini Railroad + true, // 06 Monorail + true, // 07 Mini Suspended Coaster + false, // 08 Bumper Boats + true, // 09 Wooden Wild Mine/Mouse + true, // 0a Steeplechase/Motorbike/Soap Box Derby + true, // 0b Car Ride + false, // 0c Launched Freefall + true, // 0d Bobsleigh Coaster + false, // 0e Observation Tower + true, // 0f Looping Roller Coaster + true, // 10 Dinghy Slide + true, // 11 Mine Train Coaster + true, // 12 Chairlift + true, // 13 Corkscrew Roller Coaster + false, // 14 Maze + false, // 15 Spiral Slide + false, // 16 Go Karts + false, // 17 Log Flume + false, // 18 River Rapids + false, // 19 Bumper Cars + false, // 1a Pirate Ship + false, // 1b Swinging Inverter Ship + false, // 1c Food Stall + false, // 1d (none) + false, // 1e Drink Stall + false, // 1f (none) + false, // 20 Shop (all types) + false, // 21 Merry Go Round + false, // 22 Balloon Stall (maybe) + false, // 23 Information Kiosk + false, // 24 Bathroom + false, // 25 Ferris Wheel + false, // 26 Motion Simulator + false, // 27 3D Cinema + false, // 28 Gravitron + false, // 29 Space Rings + false, // 2a Reverse Freefall Coaster + false, // 2b Elevator + true, // 2c Vertical Drop Roller Coaster + false, // 2d ATM + false, // 2e Twist + false, // 2f Haunted House + false, // 30 First Aid + false, // 31 Circus Show + true, // 32 Ghost Train + true, // 33 Twister Roller Coaster + true, // 34 Wooden Roller Coaster + true, // 35 Side-Friction Roller Coaster + true, // 36 Wild Mouse + true, // 37 Multi Dimension Coaster + true, // 38 (none) + true, // 39 Flying Roller Coaster + true, // 3a (none) + true, // 3b Virginia Reel + false, // 3c Splash Boats + true, // 3d Mini Helicopters + true, // 3e Lay-down Roller Coaster + true, // 3f Suspended Monorail + true, // 40 (none) + true, // 41 Reverser Roller Coaster + true, // 42 Heartline Twister Roller Coaster + true, // 43 Mini Golf + true, // 44 Giga Coaster + false, // 45 Roto-Drop + false, // 46 Flying Saucers + false, // 47 Crooked House + true, // 48 Monorail Cycles + true, // 49 Compact Inverted Coaster + true, // 4a Water Coaster + false, // 4b Air Powered Vertical Coaster + true, // 4c Inverted Hairpin Coaster + false, // 4d Magic Carpet + false, // 4e Submarine Ride + false, // 4f River Rafts + false, // 50 (none) + false, // 51 Enterprise + false, // 52 (none) + false, // 53 (none) + false, // 54 (none) + true, // 55 (none) + true, // 56 Inverted Impulse Coaster + true, // 57 Mini Roller Coaster + true, // 58 Mine Ride + true, // 59 LIM Launched Roller Coaster +}; + +const uint8 rideUnknownData3[0x60] = { + 10, // 00 Spiral Roller coaster + 10, // 01 Stand Up Coaster + 10, // 02 Suspended Swinging + 10, // 03 Inverted + 5, // 04 Steel Mini Coaster + 5, // 05 Mini Railroad + 10, // 06 Monorail + 10, // 07 Mini Suspended Coaster + 0, // 08 Bumper Boats + 10, // 09 Wooden Wild Mine/Mouse + 10, // 0a Steeplechase/Motorbike/Soap Box Derby + 5, // 0b Car Ride + 0, // 0c Launched Freefall + 10, // 0d Bobsleigh Coaster + 0, // 0e Observation Tower + 10, // 0f Looping Roller Coaster + 10, // 10 Dinghy Slide + 10, // 11 Mine Train Coaster + 10, // 12 Chairlift + 10, // 13 Corkscrew Roller Coaster + 0, // 14 Maze + 0, // 15 Spiral Slide + 0, // 16 Go Karts + 10, // 17 Log Flume + 10, // 18 River Rapids + 0, // 19 Bumper Cars + 0, // 1a Pirate Ship + 0, // 1b Swinging Inverter Ship + 0, // 1c Food Stall + 0, // 1d (none) + 0, // 1e Drink Stall + 0, // 1f (none) + 0, // 20 Shop (all types) + 0, // 21 Merry Go Round + 0, // 22 Balloon Stall (maybe) + 0, // 23 Information Kiosk + 0, // 24 Bathroom + 0, // 25 Ferris Wheel + 0, // 26 Motion Simulator + 0, // 27 3D Cinema + 0, // 28 Gravitron + 0, // 29 Space Rings + 10, // 2a Reverse Freefall Coaster + 0, // 2b Elevator + 10, // 2c Vertical Drop Roller Coaster + 0, // 2d ATM + 0, // 2e Twist + 0, // 2f Haunted House + 0, // 30 First Aid + 0, // 31 Circus Show + 5, // 32 Ghost Train + 10, // 33 Twister Roller Coaster + 10, // 34 Wooden Roller Coaster + 10, // 35 Side-Friction Roller Coaster + 10, // 36 Wild Mouse + 15, // 37 Multi Dimension Coaster + 15, // 38 (none) + 15, // 39 Flying Roller Coaster + 15, // 3a (none) + 10, // 3b Virginia Reel + 10, // 3c Splash Boats + 5, // 3d Mini Helicopters + 15, // 3e Lay-down Roller Coaster + 10, // 3f Suspended Monorail + 15, // 40 (none) + 10, // 41 Reverser Roller Coaster + 10, // 42 Heartline Twister Roller Coaster + 10, // 43 Mini Golf + 40, // 44 Giga Coaster + 0, // 45 Roto-Drop + 0, // 46 Flying Saucers + 0, // 47 Crooked House + 5, // 48 Monorail Cycles + 10, // 49 Compact Inverted Coaster + 10, // 4a Water Coaster + 10, // 4b Air Powered Vertical Coaster + 10, // 4c Inverted Hairpin Coaster + 0, // 4d Magic Carpet + 0, // 4e Submarine Ride + 10, // 4f River Rafts + 0, // 50 (none) + 0, // 51 Enterprise + 0, // 52 (none) + 0, // 53 (none) + 0, // 54 (none) + 10, // 55 (none) + 10, // 56 Inverted Impulse Coaster + 10, // 57 Mini Roller Coaster + 10, // 58 Mine Ride + 10, // 59 LIM Launched Roller Coaster +}; \ No newline at end of file diff --git a/src/ride_data.h b/src/ride_data.h new file mode 100644 index 0000000000..d107ad6aac --- /dev/null +++ b/src/ride_data.h @@ -0,0 +1,35 @@ +/***************************************************************************** + * Copyright (c) 2014 Kevin Burke + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#ifndef _RIDE_DATA_H_ +#define _RIDE_DATA_H_ + +#include +#include "rct2.h" + +extern const bool hasRunningTrack[0x60]; +extern const uint8 initialUpkeepCosts[0x60]; +extern const uint8 costPerTrackPiece[0x60]; + +extern const uint8 rideUnknownData1[0x60]; +extern const bool rideUnknownData2[0x60]; +extern const uint8 rideUnknownData3[0x60]; + +#endif \ No newline at end of file diff --git a/src/ride_ratings.c b/src/ride_ratings.c new file mode 100644 index 0000000000..915c78a3e2 --- /dev/null +++ b/src/ride_ratings.c @@ -0,0 +1,260 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#include "addresses.h" +#include "ride.h" +#include "ride_data.h" +#include "ride_ratings.h" + +/** + * rct2: 0x0065C4D4 + * + * Compute excitement, intensity, etc. for a crooked house ride. + */ +void crooked_house_excitement(rct_ride *ride) +{ + // Set lifecycle bits + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->var_198 = 5; + sub_655FD6(ride); + + ride_rating excitement = RIDE_RATING(2,15); + ride_rating intensity = RIDE_RATING(0,62); + ride_rating nausea = RIDE_RATING(0,34); + + // NB this should get marked out by the compiler, if it's smart. + excitement = apply_intensity_penalty(excitement, intensity); + rating_tuple tup = per_ride_rating_adjustments(ride, excitement, intensity, nausea); + excitement = tup.excitement; + intensity = tup.intensity; + nausea = tup.nausea; + + ride->excitement = excitement; + ride->intensity = intensity; + ride->nausea = nausea; + + ride->upkeep_cost = compute_upkeep(ride); + // Upkeep flag? or a dirtiness flag + ride->var_14D |= 2; + + // clear all bits except lowest 5 + ride->var_114 &= 0x1f; + // set 6th,7th,8th bits + ride->var_114 |= 0xE0; +} + +/** + * rct2: sub_65E621 + * + * I think this function computes ride upkeep? Though it is weird that the + * + * inputs + * - edi: ride ptr + */ +uint16 compute_upkeep(rct_ride *ride) +{ + // data stored at 0x0057E3A8, incrementing 18 bytes at a time + uint16 upkeep = initialUpkeepCosts[ride->type]; + + uint16 trackCost = costPerTrackPiece[ride->type]; + uint8 dl = ride->var_115; + + dl = dl >> 6; + dl = dl & 3; + upkeep += trackCost * dl; + + uint32 cuml = ride->var_0E4; + cuml += ride->var_0E8; + cuml += ride->var_0EC; + cuml += ride->var_0F0; + cuml = cuml >> 0x10; + + // The data originally here was 20's and 0's. The 20's all represented + // rides that had tracks. The 0's were fixed rides like crooked house or + // bumper cars. + // Data source is 0x0097E3AC + if (hasRunningTrack[ride->type]) { + cuml = cuml * 20; + } + cuml = cuml >> 0x0A; + upkeep += (uint16)cuml; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) { + // The original code read from a table starting at 0x0097E3AE and + // incrementing by 0x12 bytes between values. However, all of these + // values were 40. I have replaced the table lookup with the constant + // 40 in this case. + upkeep += 40; + } + + // Originally this data was at 0x0097E3B0 and incrementing in 18 byte + // offsets. The value here for every ride is 80, except for the reverser, + // which is 10 + uint16 eax; + if (ride->type == RIDE_TYPE_REVERSER_ROLLER_COASTER) { + eax = 10; + } else { + eax = 80; + } + + // not sure what this value is; it's only written to in one place, where + // it's incremented. + sint16 dx = RCT2_GLOBAL(0x0138B5CC, sint16); + upkeep += eax * dx; + + dx = RCT2_GLOBAL(0x0138B5CA, sint16); + // Originally there was a lookup into a table at 0x0097E3B0 and + // incrementing in 18 byte offsets. The value here for every ride was 20, + // so it's been replaced here by the constant. + upkeep += 20 * dx; + + // these seem to be adhoc adjustments to a ride's upkeep/cost, times + // various variables set on the ride itself. + + // https://gist.github.com/kevinburke/e19b803cd2769d96c540 + upkeep += rideUnknownData1[ride->type] * ride->var_0C8; + + // either set to 3 or 0, extra boosts for some rides including mini golf + if (rideUnknownData2[ride->type]) { + upkeep += 3 * ride->var_0C9; + } + + // slight upkeep boosts for some rides - 5 for mini railroad, 10 for log + // flume/rapids, 10 for roller coaster, 28 for giga coaster + upkeep += rideUnknownData3[ride->type] * ride->var_0C7; + + if (ride->mode == RIDE_MODE_REVERSE_INCLINED_SHUTTLE) { + upkeep += 30; + } else if (ride->mode == RIDE_MODE_POWERED_LAUNCH) { + upkeep += 160; + } else if (ride->mode == RIDE_MODE_LIM_POWERED_LAUNCH) { + upkeep += 320; + } else if (ride->mode == RIDE_MODE_POWERED_LAUNCH2 || + ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) { + upkeep += 220; + } + + // multiply by 5/8 + upkeep = upkeep * 10; + upkeep = upkeep >> 4; + return upkeep; +} + +/** + * rct2: 0x0065E7FB + * + * inputs + * - bx: excitement + * - cx: intensity + * - bp: nausea + * - edi: ride ptr + */ +rating_tuple per_ride_rating_adjustments(rct_ride *ride, ride_rating excitement, + ride_rating intensity, ride_rating nausea) +{ + // NB: The table here is allocated dynamically. Reading the exe will tell + // you nothing + uint32 subtype_p = RCT2_GLOBAL(0x009ACFA4 + ride->subtype * 4, uint32); + + // example value here: 12 (?) + sint16 ctr = RCT2_GLOBAL(subtype_p + 0x1b2, sint16); + excitement = excitement + ((excitement * ctr) >> 7); + + ctr = RCT2_GLOBAL(subtype_p + 0x1b3, sint16); + intensity = intensity + ((intensity * ctr) >> 7); + + ctr = RCT2_GLOBAL(subtype_p + 0x1b4, sint16); + nausea = nausea + ((nausea * ctr) >> 7); + + // As far as I can tell, this flag detects whether the ride is a roller + // coaster, or a log flume or rapids. Everything else it's not set. + // more detail: https://gist.github.com/kevinburke/d951e74e678b235eef3e + uint16 ridetype_var = RCT2_GLOBAL(0x0097D4F2 + ride->type * 8, uint16); + if (ridetype_var & 0x80) { + uint16 ax = ride->var_1F4; + if (RCT2_GLOBAL(subtype_p + 8, uint32) & 0x800) { + // 65e86e + ax = ax - 96; + if (ax >= 0) { + ax = ax >> 3; + excitement = excitement - ax; + ax = ax >> 1; + nausea = nausea - ax; + } + } else { + ax = ax >> 3; + excitement = excitement + ax; + ax = ax >> 1; + nausea += ax; + } + } + rating_tuple tup = { excitement, intensity, nausea }; + return tup; +} + +/** + * rct2: 0x0065E7A3 + * + * inputs from x86 + * - bx: excitement + * - cx: intensity + * - bp: nausea + * + * returns: the excitement level, with intensity penalties applied + */ +ride_rating apply_intensity_penalty(ride_rating excitement, ride_rating intensity) +{ + // intensity penalty + if (intensity >= 1000) { + excitement = excitement - (excitement >> 2); + } + if (intensity >= 1100) { + excitement = excitement - (excitement >> 2); + } + if (intensity >= 1200) { + excitement = excitement - (excitement >> 2); + } + if (intensity >= 1320) { + excitement = excitement - (excitement >> 2); + } + if (intensity >= 1450) { + excitement = excitement - (excitement >> 2); + } + return excitement; +} + +/** + * rct2: 0x00655FD6 + * + * Take ride property 1CD, make some modifications, store the modified value in + * property 198. + */ +void sub_655FD6(rct_ride *ride) +{ + uint8 al = ride->var_1CD; + // No idea what this address is; maybe like compensation of some kind? The + // maximum possible value? + // List of ride names/values is here: + // https://gist.github.com/kevinburke/5eebcda14d94e6ee99c0 + al -= RCT2_ADDRESS(0x0097D7C9, uint8)[4 * ride->type]; + al = al << 1; + ride->var_198 += al; +} diff --git a/src/ride_ratings.h b/src/ride_ratings.h new file mode 100644 index 0000000000..28ad8bc451 --- /dev/null +++ b/src/ride_ratings.h @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (c) 2014 Kevin Burke + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#ifndef _RIDE_RATINGS_H_ +#define _RIDE_RATINGS_H_ + +#include "rct2.h" + +typedef fixed16_2dp ride_rating; + +#define RIDE_RATING(whole, fraction) FIXED_2DP(whole, fraction) + +// Used for return values, for functions that modify all three. +typedef struct { + ride_rating excitement; + ride_rating intensity; + ride_rating nausea; +} rating_tuple; + +void crooked_house_excitement(rct_ride *ride); +void sub_655FD6(rct_ride *ride); +ride_rating apply_intensity_penalty(ride_rating excitement, ride_rating intensity); +rating_tuple per_ride_rating_adjustments(rct_ride *ride, ride_rating excitement, + ride_rating intensity, ride_rating nausea); +uint16 compute_upkeep(rct_ride *ride); + +#endif \ No newline at end of file