From 4e827bb64ed8d3b267b4746c71f5151cf54faca5 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 02:43:39 +0100 Subject: [PATCH 1/9] start implementing ride_ratings_update_all --- src/ride/ride_ratings.c | 247 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 1 deletion(-) diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index dc90c724da..a6b9160871 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -19,16 +19,261 @@ *****************************************************************************/ #include "../addresses.h" +#include "../world/map.h" #include "ride.h" #include "ride_data.h" #include "ride_ratings.h" +enum { + RIDE_RATINGS_STATE_FIND_NEXT_RIDE, + RIDE_RATINGS_STATE_INITIALISE +}; + +#define _rideRatingsState RCT2_GLOBAL(0x0138B591, uint8) +#define _rideRatingsCurrentRide RCT2_GLOBAL(0x00138B590, uint8) + +static void ride_ratings_update_state_0(); +static void ride_ratings_update_state_1(); +static void ride_ratings_update_state_2(); +static void ride_ratings_update_state_3(); +static void ride_ratings_update_state_4(); +static void ride_ratings_update_state_5(); +static void loc_6B5BB2(); + +int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + + eax = *x; + ecx = *y; + esi = (int)mapElement; + RCT2_CALLFUNC_X(0x006C6402, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + *x = *((uint16*)&eax); + *y = *((uint16*)&ecx); + *z = *((uint8*)&edx); + return 1; +} + /** + * * rct2: 0x006B5A2A */ void ride_ratings_update_all() { - RCT2_CALLPROC_EBPSAFE(0x006B5A2A); + // RCT2_CALLPROC_EBPSAFE(0x006B5A2A); + + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) + return; + + switch (_rideRatingsState) { + case RIDE_RATINGS_STATE_FIND_NEXT_RIDE: + ride_ratings_update_state_0(); + break; + case RIDE_RATINGS_STATE_INITIALISE: + ride_ratings_update_state_1(); + break; + case 2: + ride_ratings_update_state_2(); + break; + case 3: + ride_ratings_update_state_3(); + break; + case 4: + ride_ratings_update_state_4(); + break; + case 5: + ride_ratings_update_state_5(); + break; + } +} + +/** + * + * rct2: 0x006B5A5C + */ +static void ride_ratings_update_state_0() +{ + rct_ride *ride; + + _rideRatingsCurrentRide += 1; + if (_rideRatingsCurrentRide == 255) + _rideRatingsCurrentRide = 0; + + ride = GET_RIDE(_rideRatingsCurrentRide); + if (ride->type != RIDE_TYPE_NULL && ride->status != RIDE_STATUS_CLOSED) + _rideRatingsState = RIDE_RATINGS_STATE_INITIALISE; +} + +/** + * + * rct2: 0x006B5A94 + */ +static void ride_ratings_update_state_1() +{ + RCT2_GLOBAL(0x0138B594, uint16) = 0; + RCT2_GLOBAL(0x0138B596, uint16) = 0; + RCT2_GLOBAL(0x0138B598, uint16) = 0; + RCT2_GLOBAL(0x0138B59A, uint16) = 0; + RCT2_GLOBAL(0x0138B59C, uint16) = 0; + RCT2_GLOBAL(0x0138B59E, uint16) = 0; + RCT2_GLOBAL(0x0138B5A0, uint16) = 0; + RCT2_GLOBAL(0x0138B5A2, uint16) = 0; + RCT2_GLOBAL(0x0138B5A4, uint16) = 0; + RCT2_GLOBAL(0x0138B5A6, uint16) = 0; + RCT2_GLOBAL(0x0138B5A8, uint16) = 0; + RCT2_GLOBAL(0x0138B5AA, uint16) = 0; + RCT2_GLOBAL(0x0138B5AC, uint16) = 0; + RCT2_GLOBAL(0x0138B5AE, uint16) = 0; + RCT2_GLOBAL(0x0138B5B0, uint16) = 0; + RCT2_GLOBAL(0x0138B5B2, uint16) = 0; + RCT2_GLOBAL(0x0138B5B4, uint16) = 0; + RCT2_GLOBAL(0x0138B5B6, uint16) = 0; + RCT2_GLOBAL(0x0138B5B8, uint16) = 0; + RCT2_GLOBAL(0x0138B5BA, uint16) = 0; + RCT2_GLOBAL(0x0138B5BC, uint16) = 0; + RCT2_GLOBAL(0x0138B5BE, uint16) = 0; + RCT2_GLOBAL(0x0138B5C0, uint16) = 0; + RCT2_GLOBAL(0x0138B5C2, uint16) = 0; + RCT2_GLOBAL(0x0138B5C4, uint16) = 0; + RCT2_GLOBAL(0x0138B5C6, uint16) = 0; + RCT2_GLOBAL(0x0138B5C8, uint16) = 0; + RCT2_GLOBAL(0x0138B5CA, uint16) = 0; + RCT2_GLOBAL(0x0138B5CC, uint16) = 0; + _rideRatingsState = 2; + RCT2_GLOBAL(0x0138B5CE, uint16) = 0; + loc_6B5BB2(); +} + +/** + * + * rct2: 0x006B5BB2 + */ +static void loc_6B5BB2() +{ + rct_ride *ride; + int i, x, y, z; + + ride = GET_RIDE(_rideRatingsCurrentRide); + if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; + return; + } + + if (ride->type == RIDE_TYPE_MAZE) { + _rideRatingsState = 3; + return; + } + + for (i = 0; i < 4; i++) { + if (ride->station_starts[i] != 0xFFFF) { + RCT2_GLOBAL(0x0138B5CE, uint16) &= ~1; + if (ride->entrances[i] == 0xFFFF) + RCT2_GLOBAL(0x0138B5CE, uint16) |= 1; + + x = (ride->station_starts[i] & 0xFF) * 32; + y = (ride->station_starts[i] >> 8) * 32; + z = ride->station_heights[i] * 8; + + RCT2_GLOBAL(0x0138B584, uint16) = x; + RCT2_GLOBAL(0x0138B586, uint16) = y; + RCT2_GLOBAL(0x0138B588, uint16) = z; + RCT2_GLOBAL(0x0138B592, uint8) = 255; + RCT2_GLOBAL(0x0138B58A, uint16) = x; + RCT2_GLOBAL(0x0138B58C, uint16) = y; + RCT2_GLOBAL(0x0138B58E, uint16) = z; + return; + } + } + + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; +} + +/** + * + * rct2: 0x006B5C66 + */ +static void ride_ratings_update_state_2() +{ + RCT2_CALLPROC_EBPSAFE(0x006B5C66); +} + +/** + * + * rct2: 0x006B5E4D + */ +static void ride_ratings_update_state_3() +{ + RCT2_CALLPROC_EBPSAFE(0x006B5E4D); +} + +/** + * + * rct2: 0x006B5BAB + */ +static void ride_ratings_update_state_4() +{ + _rideRatingsState = 5; + loc_6B5BB2(); +} + +/** + * + * rct2: 0x006B5D72 + */ +static void ride_ratings_update_state_5() +{ + // sub_6C6402 returns a carry, CALLFUNC doesn't support this + // so have to wait for sub_6C6402 to be decompiled + RCT2_CALLPROC_EBPSAFE(0x006B5D72); + return; + + rct_ride *ride; + rct_map_element *mapElement; + int x, y, z, trackType; + + ride = GET_RIDE(_rideRatingsCurrentRide); + if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; + return; + } + + x = RCT2_GLOBAL(0x0138B584, uint16) / 32; + y = RCT2_GLOBAL(0x0138B586, uint16) / 32; + z = RCT2_GLOBAL(0x0138B588, uint16) / 8; + + mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + trackType = RCT2_GLOBAL(0x0138B592, uint8); + + do { + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK) + continue; + if (mapElement->base_height != z) + continue; + + if (trackType == 255 || trackType == mapElement->properties.track.type) { + RCT2_CALLPROC_X(0x006B5F9D, 0, 0, 0, 0, (int)mapElement, 0, 0); + + x = RCT2_GLOBAL(0x0138B584, uint16); + y = RCT2_GLOBAL(0x0138B586, uint16); + if (!sub_6C6402(mapElement, &x, &y, &z)) { + _rideRatingsState = 3; + return; + } + + x >>= 16; + y >>= 16; + if (x == RCT2_GLOBAL(0x0138B58A, uint16) && y == RCT2_GLOBAL(0x0138B58C, uint16) && z == RCT2_GLOBAL(0x0138B58E, uint16)) { + _rideRatingsState = 3; + return; + } + RCT2_GLOBAL(0x0138B584, uint16) = x; + RCT2_GLOBAL(0x0138B586, uint16) = y; + RCT2_GLOBAL(0x0138B588, uint16) = z; + RCT2_GLOBAL(0x0138B592, uint8) = mapElement->properties.track.type; + } + } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; } /** From 409d54dbfc772586af00b63bceb5c7919315bed8 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 03:28:09 +0100 Subject: [PATCH 2/9] implement ride_ratings_update_state_3 --- src/ride/ride_ratings.c | 71 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index a6b9160871..50dc86d85e 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -19,6 +19,7 @@ *****************************************************************************/ #include "../addresses.h" +#include "../interface/window.h" #include "../world/map.h" #include "ride.h" #include "ride_data.h" @@ -29,6 +30,8 @@ enum { RIDE_RATINGS_STATE_INITIALISE }; +typedef void (*ride_ratings_calculation)(rct_ride *ride); + #define _rideRatingsState RCT2_GLOBAL(0x0138B591, uint8) #define _rideRatingsCurrentRide RCT2_GLOBAL(0x00138B590, uint8) @@ -39,6 +42,8 @@ static void ride_ratings_update_state_3(); static void ride_ratings_update_state_4(); static void ride_ratings_update_state_5(); static void loc_6B5BB2(); +static void ride_ratings_calculate(rct_ride *ride); +static void ride_ratings_reliability_calculate(rct_ride *ride); int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z) { @@ -203,7 +208,20 @@ static void ride_ratings_update_state_2() */ static void ride_ratings_update_state_3() { - RCT2_CALLPROC_EBPSAFE(0x006B5E4D); + rct_ride *ride; + + ride = GET_RIDE(_rideRatingsCurrentRide); + if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; + return; + } + + ride_ratings_calculate(ride); + RCT2_CALLPROC_X(0x00655F64, 0, 0, 0, 0, 0, (int)ride, 0); + ride_ratings_reliability_calculate(ride); + + window_invalidate_by_id(WC_RIDE, _rideRatingsCurrentRide); + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; } /** @@ -276,6 +294,57 @@ static void ride_ratings_update_state_5() _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; } +static void ride_ratings_calculate(rct_ride *ride) +{ + ride_ratings_calculation calcFunc = RCT2_ADDRESS(0x0097E050, ride_ratings_calculation)[ride->type]; + RCT2_CALLPROC_EBPSAFE((int)calcFunc); + // calcFunc(ride); +} + +static void ride_ratings_reliability_calculate(rct_ride *ride) +{ + rct_ride *ride2; + int i, otherRidesOfSameType; + + if (ride->excitement == (ride_rating)0xFFFF) + return; + + int reliability = + (((ride->excitement * RCT2_GLOBAL(0x0097CD1E + (ride->type * 6), sint16)) * 32) >> 15) + + (((ride->intensity * RCT2_GLOBAL(0x0097CD20 + (ride->type * 6), sint16)) * 32) >> 15) + + (((ride->nausea * RCT2_GLOBAL(0x0097CD22 + (ride->type * 6), sint16)) * 32) >> 15); + + int monthsOld = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16) - ride->build_date; + + // New ride reward + if (monthsOld <= 12) { + reliability += 10; + if (monthsOld <= 4) + reliability += 20; + } + + // Old ride penalty + if (monthsOld >= 40) reliability -= reliability / 4; + if (monthsOld >= 64) reliability -= reliability / 4; + if (monthsOld < 200) { + if (monthsOld >= 88) reliability -= reliability / 4; + if (monthsOld >= 104) reliability -= reliability / 4; + if (monthsOld >= 120) reliability -= reliability / 2; + if (monthsOld >= 128) reliability -= reliability / 2; + } + + // Other ride of same type penalty + otherRidesOfSameType = 0; + FOR_ALL_RIDES(i, ride2) { + if (ride2->type == ride->type) + otherRidesOfSameType++; + } + if (otherRidesOfSameType > 1) + reliability -= reliability / 4; + + ride->reliability = max(0, reliability); +} + /** * rct2: 0x0065C4D4 * From 3377187a76084acf46b1f923099306444ff72567 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 13:25:09 +0100 Subject: [PATCH 3/9] implement ride rating calculation table and a few other things --- src/ride/ride_ratings.c | 298 +++++++++++++++++++++++++++++++--------- 1 file changed, 234 insertions(+), 64 deletions(-) diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 50dc86d85e..266eef6b20 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -27,13 +27,19 @@ enum { RIDE_RATINGS_STATE_FIND_NEXT_RIDE, - RIDE_RATINGS_STATE_INITIALISE + RIDE_RATINGS_STATE_INITIALISE, + RIDE_RATINGS_STATE_2, + RIDE_RATINGS_STATE_CALCULATE, + RIDE_RATINGS_STATE_4, + RIDE_RATINGS_STATE_5 }; typedef void (*ride_ratings_calculation)(rct_ride *ride); #define _rideRatingsState RCT2_GLOBAL(0x0138B591, uint8) -#define _rideRatingsCurrentRide RCT2_GLOBAL(0x00138B590, uint8) +#define _rideRatingsCurrentRide RCT2_GLOBAL(0x0138B590, uint8) + +static const ride_ratings_calculation ride_ratings_calculate_func_table[91]; static void ride_ratings_update_state_0(); static void ride_ratings_update_state_1(); @@ -59,14 +65,26 @@ int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z) return 1; } +int sub_6C60C2(rct_map_element *mapElement, int *x, int *y, int *z) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + + eax = *x; + ecx = *y; + esi = (int)mapElement; + RCT2_CALLFUNC_X(0x006C6402, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + *x = *((uint16*)&eax); + *y = *((uint16*)&ecx); + *z = *((uint8*)&edx); + return 1; +} + /** * * rct2: 0x006B5A2A */ void ride_ratings_update_all() { - // RCT2_CALLPROC_EBPSAFE(0x006B5A2A); - if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) return; @@ -77,16 +95,16 @@ void ride_ratings_update_all() case RIDE_RATINGS_STATE_INITIALISE: ride_ratings_update_state_1(); break; - case 2: + case RIDE_RATINGS_STATE_2: ride_ratings_update_state_2(); break; - case 3: + case RIDE_RATINGS_STATE_CALCULATE: ride_ratings_update_state_3(); break; - case 4: + case RIDE_RATINGS_STATE_4: ride_ratings_update_state_4(); break; - case 5: + case RIDE_RATINGS_STATE_5: ride_ratings_update_state_5(); break; } @@ -144,7 +162,7 @@ static void ride_ratings_update_state_1() RCT2_GLOBAL(0x0138B5C8, uint16) = 0; RCT2_GLOBAL(0x0138B5CA, uint16) = 0; RCT2_GLOBAL(0x0138B5CC, uint16) = 0; - _rideRatingsState = 2; + _rideRatingsState = RIDE_RATINGS_STATE_2; RCT2_GLOBAL(0x0138B5CE, uint16) = 0; loc_6B5BB2(); } @@ -165,7 +183,7 @@ static void loc_6B5BB2() } if (ride->type == RIDE_TYPE_MAZE) { - _rideRatingsState = 3; + _rideRatingsState = RIDE_RATINGS_STATE_CALCULATE; return; } @@ -199,7 +217,63 @@ static void loc_6B5BB2() */ static void ride_ratings_update_state_2() { + // sub_6C6402 returns a carry, CALLFUNC doesn't support this + // so have to wait for sub_6C60C2 to be decompiled RCT2_CALLPROC_EBPSAFE(0x006B5C66); + return; + + rct_ride *ride; + rct_map_element *mapElement; + int x, y, z, trackType, entranceIndex; + + ride = GET_RIDE(_rideRatingsCurrentRide); + if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; + return; + } + + x = RCT2_GLOBAL(0x0138B584, uint16) / 32; + y = RCT2_GLOBAL(0x0138B586, uint16) / 32; + z = RCT2_GLOBAL(0x0138B588, uint16) / 8; + + mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + trackType = RCT2_GLOBAL(0x0138B592, uint8); + + do { + if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK) + continue; + if (mapElement->base_height != z) + continue; + + if (trackType == 255 || (!(mapElement->properties.track.sequence & 0x0F) && trackType == mapElement->properties.track.type)) { + if (trackType == 1) { + entranceIndex = (mapElement->properties.track.sequence >> 4) & 7; + RCT2_GLOBAL(0x0138B5CE, uint16) &= ~1; + if (ride->entrances[entranceIndex] == 0xFFFF) + RCT2_GLOBAL(0x0138B5CE, uint16) |= 1; + } + + RCT2_CALLPROC_X(0x006B5F9D, 0, 0, 0, 0, (int)mapElement, 0, 0); + + x = RCT2_GLOBAL(0x0138B584, uint16); + y = RCT2_GLOBAL(0x0138B586, uint16); + if (!sub_6C60C2(mapElement, &x, &y, &z)) { + _rideRatingsState = RIDE_RATINGS_STATE_4; + return; + } + + if (x == RCT2_GLOBAL(0x0138B58A, uint16) && y == RCT2_GLOBAL(0x0138B58C, uint16) && z == RCT2_GLOBAL(0x0138B58E, uint16)) { + _rideRatingsState = RIDE_RATINGS_STATE_CALCULATE; + return; + } + RCT2_GLOBAL(0x0138B584, uint16) = x; + RCT2_GLOBAL(0x0138B586, uint16) = y; + RCT2_GLOBAL(0x0138B588, uint16) = z; + RCT2_GLOBAL(0x0138B592, uint8) = mapElement->properties.track.type; + } + } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + + _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; } /** @@ -230,7 +304,7 @@ static void ride_ratings_update_state_3() */ static void ride_ratings_update_state_4() { - _rideRatingsState = 5; + _rideRatingsState = RIDE_RATINGS_STATE_5; loc_6B5BB2(); } @@ -274,14 +348,14 @@ static void ride_ratings_update_state_5() x = RCT2_GLOBAL(0x0138B584, uint16); y = RCT2_GLOBAL(0x0138B586, uint16); if (!sub_6C6402(mapElement, &x, &y, &z)) { - _rideRatingsState = 3; + _rideRatingsState = RIDE_RATINGS_STATE_CALCULATE; return; } x >>= 16; y >>= 16; if (x == RCT2_GLOBAL(0x0138B58A, uint16) && y == RCT2_GLOBAL(0x0138B58C, uint16) && z == RCT2_GLOBAL(0x0138B58E, uint16)) { - _rideRatingsState = 3; + _rideRatingsState = RIDE_RATINGS_STATE_CALCULATE; return; } RCT2_GLOBAL(0x0138B584, uint16) = x; @@ -296,9 +370,15 @@ static void ride_ratings_update_state_5() static void ride_ratings_calculate(rct_ride *ride) { - ride_ratings_calculation calcFunc = RCT2_ADDRESS(0x0097E050, ride_ratings_calculation)[ride->type]; - RCT2_CALLPROC_EBPSAFE((int)calcFunc); - // calcFunc(ride); + ride_ratings_calculation calcFunc; + + calcFunc = ride_ratings_calculate_func_table[ride->type]; + if (calcFunc == NULL) { + calcFunc = RCT2_ADDRESS(0x0097E050, ride_ratings_calculation)[ride->type]; + RCT2_CALLPROC_X((int)calcFunc, 0, 0, 0, 0, 0, (int)ride, 0); + } else { + calcFunc(ride); + } } static void ride_ratings_reliability_calculate(rct_ride *ride) @@ -345,43 +425,6 @@ static void ride_ratings_reliability_calculate(rct_ride *ride) ride->reliability = max(0, reliability); } -/** - * 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->inversions &= 0x1F; - // set 6th,7th,8th bits - ride->inversions |= 0xE0; -} /** * rct2: sub_65E621 @@ -554,19 +597,146 @@ ride_rating apply_intensity_penalty(ride_rating excitement, ride_rating intensit } /** - * rct2: 0x00655FD6 * - * Take ride property 1CD, make some modifications, store the modified value in - * property 198. + * rct2: 0x00655FD6 */ void sub_655FD6(rct_ride *ride) { - uint8 al = ride->lift_hill_speed; - // 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; + ride->var_198 += (ride->lift_hill_speed - RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4]) * 2; } + +#pragma region Ride rating calculation functions + +void ride_ratings_calculate_crooked_house(rct_ride *ride) +{ + rating_tuple ratings; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->var_198 = 5; + sub_655FD6(ride); + + ratings.excitement = RIDE_RATING(2,15); + ratings.intensity = RIDE_RATING(0,62); + ratings.nausea = RIDE_RATING(0,34); + + ratings.excitement = apply_intensity_penalty(ratings.excitement, ratings.intensity); + ratings = per_ride_rating_adjustments(ride, ratings.excitement, ratings.intensity, ratings.nausea); + + ride->excitement = ratings.excitement; + ride->intensity = ratings.intensity; + ride->nausea = ratings.nausea; + + ride->upkeep_cost = compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= 0xE0; +} + +void ride_ratings_calculate_bathroom(rct_ride *ride) +{ + ride->upkeep_cost = compute_upkeep(ride); + ride->var_14D |= 2; +} + +#pragma endregion + +#pragma region Ride rating calculation function table + +// rct2: 0x0097E050 +static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { + NULL, // SPIRAL_ROLLER_COASTER + NULL, // STAND_UP_ROLLER_COASTER + NULL, // SUSPENDED_SWINGING_COASTER + NULL, // INVERTED_ROLLER_COASTER + NULL, // JUNIOR_ROLLER_COASTER + NULL, // MINIATURE_RAILWAY + NULL, // MONORAIL + NULL, // MINI_SUSPENDED_COASTER + NULL, // BUMPER_BOATS + NULL, // WOODEN_WILD_MOUSE + NULL, // STEEPLECHASE + NULL, // CAR_RIDE + NULL, // LAUNCHED_FREEFALL + NULL, // BOBSLEIGH_COASTER + NULL, // OBSERVATION_TOWER + NULL, // LOOPING_ROLLER_COASTER + NULL, // DINGHY_SLIDE + NULL, // MINE_TRAIN_COASTER + NULL, // CHAIRLIFT + NULL, // CORKSCREW_ROLLER_COASTER + NULL, // MAZE + NULL, // SPIRAL_SLIDE + NULL, // GO_KARTS + NULL, // LOG_FLUME + NULL, // RIVER_RAPIDS + NULL, // BUMPER_CARS + NULL, // PIRATE_SHIP + NULL, // SWINGING_INVERTER_SHIP + NULL, // FOOD_STALL + NULL, // 1D + NULL, // DRINK_STALL + NULL, // 1F + NULL, // SHOP + NULL, // MERRY_GO_ROUND + NULL, // 22 + NULL, // INFORMATION_KIOSK + ride_ratings_calculate_bathroom, // BATHROOM + NULL, // FERRIS_WHEEL + NULL, // MOTION_SIMULATOR + NULL, // 3D_CINEMA + NULL, // TOP_SPIN + NULL, // SPACE_RINGS + NULL, // REVERSE_FREEFALL_COASTER + NULL, // ELEVATOR + NULL, // VERTICAL_DROP_ROLLER_COASTER + NULL, // ATM + NULL, // TWIST + NULL, // HAUNTED_HOUSE + NULL, // FIRST_AID + NULL, // CIRCUS_SHOW + NULL, // GHOST_TRAIN + NULL, // TWISTER_ROLLER_COASTER + NULL, // WOODEN_ROLLER_COASTER + NULL, // SIDE_FRICTION_ROLLER_COASTER + NULL, // WILD_MOUSE + NULL, // MULTI_DIMENSION_ROLLER_COASTER + NULL, // 38 + NULL, // FLYING_ROLLER_COASTER + NULL, // 3A + NULL, // VIRGINIA_REEL + NULL, // SPLASH_BOATS + NULL, // MINI_HELICOPTERS + NULL, // LAY_DOWN_ROLLER_COASTER + NULL, // SUSPENDED_MONORAIL + NULL, // 40 + NULL, // REVERSER_ROLLER_COASTER + NULL, // HEARTLINE_TWISTER_COASTER + NULL, // MINI_GOLF + NULL, // GIGA_COASTER + NULL, // ROTO_DROP + NULL, // FLYING_SAUCERS + ride_ratings_calculate_crooked_house, // CROOKED_HOUSE + NULL, // MONORAIL_CYCLES + NULL, // COMPACT_INVERTED_COASTER + NULL, // WATER_COASTER + NULL, // AIR_POWERED_VERTICAL_COASTER + NULL, // INVERTED_HAIRPIN_COASTER + NULL, // MAGIC_CARPET + NULL, // SUBMARINE_RIDE + NULL, // RIVER_RAFTS + NULL, // 50 + NULL, // ENTERPRISE + NULL, // 52 + NULL, // 53 + NULL, // 54 + NULL, // 55 + NULL, // INVERTED_IMPULSE_COASTER + NULL, // MINI_ROLLER_COASTER + NULL, // MINE_RIDE + NULL, // LIM_LAUNCHED_ROLLER_COASTER + NULL, // 90 +}; + +#pragma endregion \ No newline at end of file From 5928b685eaefae4222db9bdcafa138ad16aa550b Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 14:14:10 +0100 Subject: [PATCH 4/9] add more ride ratings calculations and refactor --- src/ride/ride_ratings.c | 310 ++++++++++++++++++++-------------------- src/ride/ride_ratings.h | 2 +- 2 files changed, 159 insertions(+), 153 deletions(-) diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 266eef6b20..2d3fa2aac5 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -425,7 +425,6 @@ static void ride_ratings_reliability_calculate(rct_ride *ride) ride->reliability = max(0, reliability); } - /** * rct2: sub_65E621 * @@ -434,7 +433,7 @@ static void ride_ratings_reliability_calculate(rct_ride *ride) * inputs * - edi: ride ptr */ -uint16 compute_upkeep(rct_ride *ride) +static uint16 ride_compute_upkeep(rct_ride *ride) { // data stored at 0x0057E3A8, incrementing 18 bytes at a time uint16 upkeep = initialUpkeepCosts[ride->type]; @@ -527,87 +526,64 @@ uint16 compute_upkeep(rct_ride *ride) * - bp: nausea * - edi: ride ptr */ -rating_tuple per_ride_rating_adjustments(rct_ride *ride, ride_rating excitement, - ride_rating intensity, ride_rating nausea) +static void ride_ratings_apply_adjustments(rct_ride *ride, rating_tuple *ratings) { - // NB: The table here is allocated dynamically. Reading the exe will tell - // you nothing - rct_ride_type *rideType = gRideTypeList[ride->subtype]; + rct_ride_type *rideEntry; + + rideEntry = gRideTypeList[ride->subtype]; - // example value here: 12 (?) - excitement = excitement + ((excitement * rideType->excitement_multipler) >> 7); - intensity = intensity + ((intensity * rideType->intensity_multipler) >> 7); - nausea = nausea + ((nausea * rideType->nausea_multipler) >> 7); + // Apply ride entry multipliers + ratings->excitement += ((ratings->excitement * rideEntry->excitement_multipler) >> 7); + ratings->intensity += ((ratings->intensity * rideEntry->intensity_multipler ) >> 7); + ratings->nausea += ((ratings->nausea * rideEntry->nausea_multipler ) >> 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->total_air_time; - if (rideType->var_008 & 0x800) { - // 65e86e - ax = ax - 96; - if (ax >= 0) { - ax = ax >> 3; - excitement = excitement - ax; - ax = ax >> 1; - nausea = nausea - ax; + uint16 flags = RCT2_GLOBAL(0x0097D4F2 + ride->type * 8, uint16); + if (flags & 0x80) { + uint16 totalAirTime = ride->total_air_time; + if (rideEntry->var_008 & 0x800) { + totalAirTime -= 96; + if (totalAirTime >= 0) { + ratings->excitement -= totalAirTime / 8; + ratings->nausea -= totalAirTime / 16; } } else { - ax = ax >> 3; - excitement = excitement + ax; - ax = ax >> 1; - nausea += ax; + ratings->excitement += totalAirTime / 8; + ratings->nausea += totalAirTime / 16; } } - 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 + * Lowers excitment, the higher the intensity. + * rct2: 0x0065E7A3 */ -ride_rating apply_intensity_penalty(ride_rating excitement, ride_rating intensity) +static void ride_ratings_apply_intensity_penalty(rating_tuple *ratings) { - // 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; + static const ride_rating intensityBounds[] = { 1000, 1100, 1200, 1320, 1450 }; + int i; + + ride_rating excitement = ratings->excitement; + for (i = 0; i < countof(intensityBounds); i++) + if (ratings->intensity >= intensityBounds[i]) + excitement -= excitement / 4; + ratings->excitement = excitement; } /** * * rct2: 0x00655FD6 */ -void sub_655FD6(rct_ride *ride) +static void sub_655FD6(rct_ride *ride) { ride->var_198 += (ride->lift_hill_speed - RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4]) * 2; } #pragma region Ride rating calculation functions -void ride_ratings_calculate_crooked_house(rct_ride *ride) +static void ride_ratings_calculate_crooked_house(rct_ride *ride) { rating_tuple ratings; @@ -620,23 +596,53 @@ void ride_ratings_calculate_crooked_house(rct_ride *ride) ratings.intensity = RIDE_RATING(0,62); ratings.nausea = RIDE_RATING(0,34); - ratings.excitement = apply_intensity_penalty(ratings.excitement, ratings.intensity); - ratings = per_ride_rating_adjustments(ride, ratings.excitement, ratings.intensity, ratings.nausea); + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); ride->excitement = ratings.excitement; ride->intensity = ratings.intensity; ride->nausea = ratings.nausea; - ride->upkeep_cost = compute_upkeep(ride); + ride->upkeep_cost = ride_compute_upkeep(ride); ride->var_14D |= 2; ride->inversions &= 0x1F; ride->inversions |= 0xE0; } -void ride_ratings_calculate_bathroom(rct_ride *ride) +static void ride_ratings_calculate_food_stall(rct_ride *ride) { - ride->upkeep_cost = compute_upkeep(ride); + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; +} + +static void ride_ratings_calculate_drink_stall(rct_ride *ride) +{ + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; +} + +static void ride_ratings_calculate_shop(rct_ride *ride) +{ + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; +} + +static void ride_ratings_calculate_information_kiosk(rct_ride *ride) +{ + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; +} + +static void ride_ratings_calculate_bathroom(rct_ride *ride) +{ + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; +} + +static void ride_ratings_calculate_first_aid(rct_ride *ride) +{ + ride->upkeep_cost = ride_compute_upkeep(ride); ride->var_14D |= 2; } @@ -646,97 +652,97 @@ void ride_ratings_calculate_bathroom(rct_ride *ride) // rct2: 0x0097E050 static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { - NULL, // SPIRAL_ROLLER_COASTER - NULL, // STAND_UP_ROLLER_COASTER - NULL, // SUSPENDED_SWINGING_COASTER - NULL, // INVERTED_ROLLER_COASTER - NULL, // JUNIOR_ROLLER_COASTER - NULL, // MINIATURE_RAILWAY - NULL, // MONORAIL - NULL, // MINI_SUSPENDED_COASTER - NULL, // BUMPER_BOATS - NULL, // WOODEN_WILD_MOUSE - NULL, // STEEPLECHASE - NULL, // CAR_RIDE - NULL, // LAUNCHED_FREEFALL - NULL, // BOBSLEIGH_COASTER - NULL, // OBSERVATION_TOWER - NULL, // LOOPING_ROLLER_COASTER - NULL, // DINGHY_SLIDE - NULL, // MINE_TRAIN_COASTER - NULL, // CHAIRLIFT - NULL, // CORKSCREW_ROLLER_COASTER - NULL, // MAZE - NULL, // SPIRAL_SLIDE - NULL, // GO_KARTS - NULL, // LOG_FLUME - NULL, // RIVER_RAPIDS - NULL, // BUMPER_CARS - NULL, // PIRATE_SHIP - NULL, // SWINGING_INVERTER_SHIP - NULL, // FOOD_STALL - NULL, // 1D - NULL, // DRINK_STALL - NULL, // 1F - NULL, // SHOP - NULL, // MERRY_GO_ROUND - NULL, // 22 - NULL, // INFORMATION_KIOSK - ride_ratings_calculate_bathroom, // BATHROOM - NULL, // FERRIS_WHEEL - NULL, // MOTION_SIMULATOR - NULL, // 3D_CINEMA - NULL, // TOP_SPIN - NULL, // SPACE_RINGS - NULL, // REVERSE_FREEFALL_COASTER - NULL, // ELEVATOR - NULL, // VERTICAL_DROP_ROLLER_COASTER - NULL, // ATM - NULL, // TWIST - NULL, // HAUNTED_HOUSE - NULL, // FIRST_AID - NULL, // CIRCUS_SHOW - NULL, // GHOST_TRAIN - NULL, // TWISTER_ROLLER_COASTER - NULL, // WOODEN_ROLLER_COASTER - NULL, // SIDE_FRICTION_ROLLER_COASTER - NULL, // WILD_MOUSE - NULL, // MULTI_DIMENSION_ROLLER_COASTER - NULL, // 38 - NULL, // FLYING_ROLLER_COASTER - NULL, // 3A - NULL, // VIRGINIA_REEL - NULL, // SPLASH_BOATS - NULL, // MINI_HELICOPTERS - NULL, // LAY_DOWN_ROLLER_COASTER - NULL, // SUSPENDED_MONORAIL - NULL, // 40 - NULL, // REVERSER_ROLLER_COASTER - NULL, // HEARTLINE_TWISTER_COASTER - NULL, // MINI_GOLF - NULL, // GIGA_COASTER - NULL, // ROTO_DROP - NULL, // FLYING_SAUCERS - ride_ratings_calculate_crooked_house, // CROOKED_HOUSE - NULL, // MONORAIL_CYCLES - NULL, // COMPACT_INVERTED_COASTER - NULL, // WATER_COASTER - NULL, // AIR_POWERED_VERTICAL_COASTER - NULL, // INVERTED_HAIRPIN_COASTER - NULL, // MAGIC_CARPET - NULL, // SUBMARINE_RIDE - NULL, // RIVER_RAFTS - NULL, // 50 - NULL, // ENTERPRISE - NULL, // 52 - NULL, // 53 - NULL, // 54 - NULL, // 55 - NULL, // INVERTED_IMPULSE_COASTER - NULL, // MINI_ROLLER_COASTER - NULL, // MINE_RIDE - NULL, // LIM_LAUNCHED_ROLLER_COASTER - NULL, // 90 + NULL, // SPIRAL_ROLLER_COASTER + NULL, // STAND_UP_ROLLER_COASTER + NULL, // SUSPENDED_SWINGING_COASTER + NULL, // INVERTED_ROLLER_COASTER + NULL, // JUNIOR_ROLLER_COASTER + NULL, // MINIATURE_RAILWAY + NULL, // MONORAIL + NULL, // MINI_SUSPENDED_COASTER + NULL, // BUMPER_BOATS + NULL, // WOODEN_WILD_MOUSE + NULL, // STEEPLECHASE + NULL, // CAR_RIDE + NULL, // LAUNCHED_FREEFALL + NULL, // BOBSLEIGH_COASTER + NULL, // OBSERVATION_TOWER + NULL, // LOOPING_ROLLER_COASTER + NULL, // DINGHY_SLIDE + NULL, // MINE_TRAIN_COASTER + NULL, // CHAIRLIFT + NULL, // CORKSCREW_ROLLER_COASTER + NULL, // MAZE + NULL, // SPIRAL_SLIDE + NULL, // GO_KARTS + NULL, // LOG_FLUME + NULL, // RIVER_RAPIDS + NULL, // BUMPER_CARS + NULL, // PIRATE_SHIP + NULL, // SWINGING_INVERTER_SHIP + ride_ratings_calculate_food_stall, // FOOD_STALL + NULL, // 1D + ride_ratings_calculate_drink_stall, // DRINK_STALL + NULL, // 1F + ride_ratings_calculate_shop, // SHOP + NULL, // MERRY_GO_ROUND + NULL, // 22 + ride_ratings_calculate_information_kiosk, // INFORMATION_KIOSK + ride_ratings_calculate_bathroom, // BATHROOM + NULL, // FERRIS_WHEEL + NULL, // MOTION_SIMULATOR + NULL, // 3D_CINEMA + NULL, // TOP_SPIN + NULL, // SPACE_RINGS + NULL, // REVERSE_FREEFALL_COASTER + NULL, // ELEVATOR + NULL, // VERTICAL_DROP_ROLLER_COASTER + NULL, // ATM + NULL, // TWIST + NULL, // HAUNTED_HOUSE + ride_ratings_calculate_first_aid, // FIRST_AID + NULL, // CIRCUS_SHOW + NULL, // GHOST_TRAIN + NULL, // TWISTER_ROLLER_COASTER + NULL, // WOODEN_ROLLER_COASTER + NULL, // SIDE_FRICTION_ROLLER_COASTER + NULL, // WILD_MOUSE + NULL, // MULTI_DIMENSION_ROLLER_COASTER + NULL, // 38 + NULL, // FLYING_ROLLER_COASTER + NULL, // 3A + NULL, // VIRGINIA_REEL + NULL, // SPLASH_BOATS + NULL, // MINI_HELICOPTERS + NULL, // LAY_DOWN_ROLLER_COASTER + NULL, // SUSPENDED_MONORAIL + NULL, // 40 + NULL, // REVERSER_ROLLER_COASTER + NULL, // HEARTLINE_TWISTER_COASTER + NULL, // MINI_GOLF + NULL, // GIGA_COASTER + NULL, // ROTO_DROP + NULL, // FLYING_SAUCERS + ride_ratings_calculate_crooked_house, // CROOKED_HOUSE + NULL, // MONORAIL_CYCLES + NULL, // COMPACT_INVERTED_COASTER + NULL, // WATER_COASTER + NULL, // AIR_POWERED_VERTICAL_COASTER + NULL, // INVERTED_HAIRPIN_COASTER + NULL, // MAGIC_CARPET + NULL, // SUBMARINE_RIDE + NULL, // RIVER_RAFTS + NULL, // 50 + NULL, // ENTERPRISE + NULL, // 52 + NULL, // 53 + NULL, // 54 + NULL, // 55 + NULL, // INVERTED_IMPULSE_COASTER + NULL, // MINI_ROLLER_COASTER + NULL, // MINE_RIDE + NULL, // LIM_LAUNCHED_ROLLER_COASTER + NULL, // 90 }; #pragma endregion \ No newline at end of file diff --git a/src/ride/ride_ratings.h b/src/ride/ride_ratings.h index b2f5509e5b..adb492aa32 100644 --- a/src/ride/ride_ratings.h +++ b/src/ride/ride_ratings.h @@ -30,6 +30,6 @@ 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); +uint16 ride_compute_upkeep(rct_ride *ride); #endif \ No newline at end of file From 69ab8700dc9eac9f722f5eea052d7dd49a9d45bd Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 18:18:20 +0100 Subject: [PATCH 5/9] implement ride_ratings_get_scenery_score --- src/ride/ride.h | 11 ++++-- src/ride/ride_ratings.c | 81 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/ride/ride.h b/src/ride/ride.h index a329bea947..f4bdf678db 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -145,9 +145,14 @@ typedef struct { sint16 var_136; money16 price; // 0x138 uint8 pad_13A[0x06]; - ride_rating excitement; // 0x140 - ride_rating intensity; // 0x142 - ride_rating nausea; // 0x144 + union { + rating_tuple ratings; // 0x140 + struct { + ride_rating excitement; // 0x140 + ride_rating intensity; // 0x142 + ride_rating nausea; // 0x144 + }; + }; uint16 reliability; // 0x146 uint16 pad_148; uint16 var_14A; diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 2d3fa2aac5..6ea1319185 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -581,6 +581,55 @@ static void sub_655FD6(rct_ride *ride) ride->var_198 += (ride->lift_hill_speed - RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4]) * 2; } +/** + * Calculates a score based on the surrounding scenery. + * rct2: 0x0065E557 + */ +static int ride_ratings_get_scenery_score(rct_ride *ride) +{ + int i, x, y, z, xx, yy, type, numSceneryItems; + uint16 stationXY; + rct_map_element *mapElement; + + for (i = 0; i < 4; i++) { + stationXY = ride->station_starts[i]; + if (stationXY != 0xFFFF) + break; + } + if (i == 4) + return 0; + + if (ride->type == RIDE_TYPE_MAZE) + stationXY = ride->entrances[0]; + + x = stationXY & 0xFF; + y = stationXY >> 8; + z = map_element_height(x * 32, y * 32); + + // Check if station is underground, returns a fixed mediocre score since you can't have scenery underground + if (z > ride->station_heights[i] * 8) + return 40; + + // Count surrounding scenery items + numSceneryItems = 0; + for (yy = y - 5; yy <= y + 5; yy++) { + for (xx = x - 5; xx <= x + 5; xx++) { + // Count scenery items on this tile + mapElement = TILE_MAP_ELEMENT_POINTER(yy * 256 + xx); + do { + if (mapElement->flags & 0x10) + continue; + + type = mapElement->type & MAP_ELEMENT_TYPE_MASK; + if (type == MAP_ELEMENT_TYPE_SCENERY || type == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) + numSceneryItems++; + } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } + } + + return min(numSceneryItems, 47) * 5; +} + #pragma region Ride rating calculation functions static void ride_ratings_calculate_crooked_house(rct_ride *ride) @@ -599,9 +648,7 @@ static void ride_ratings_calculate_crooked_house(rct_ride *ride) ride_ratings_apply_intensity_penalty(&ratings); ride_ratings_apply_adjustments(ride, &ratings); - ride->excitement = ratings.excitement; - ride->intensity = ratings.intensity; - ride->nausea = ratings.nausea; + ride->ratings = ratings; ride->upkeep_cost = ride_compute_upkeep(ride); ride->var_14D |= 2; @@ -628,6 +675,32 @@ static void ride_ratings_calculate_shop(rct_ride *ride) ride->var_14D |= 2; } +static void ride_ratings_calculate_merry_go_round(rct_ride *ride) +{ + rating_tuple ratings; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->var_198 = 16; + sub_655FD6(ride); + + int unk = ride->var_0D0 * 5; + ratings.excitement = unk + RIDE_RATING(0,60) + ((ride_ratings_get_scenery_score(ride) * 19521) >> 16); + ratings.intensity = unk + RIDE_RATING(0,15); + ratings.nausea = unk + RIDE_RATING(0,30); + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= 7 << 5; +} + static void ride_ratings_calculate_information_kiosk(rct_ride *ride) { ride->upkeep_cost = ride_compute_upkeep(ride); @@ -685,7 +758,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { ride_ratings_calculate_drink_stall, // DRINK_STALL NULL, // 1F ride_ratings_calculate_shop, // SHOP - NULL, // MERRY_GO_ROUND + ride_ratings_calculate_merry_go_round, // MERRY_GO_ROUND NULL, // 22 ride_ratings_calculate_information_kiosk, // INFORMATION_KIOSK ride_ratings_calculate_bathroom, // BATHROOM From 77e3c7a65d75af3e56241d435b26b4698122f852 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 18:55:56 +0100 Subject: [PATCH 6/9] implement ride_ratings_calculate_elevator and related functions --- src/ride/ride_ratings.c | 67 +++++++++++++++++++++++++++++++++++++++-- src/ride/ride_ratings.h | 6 ---- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 6ea1319185..7b1a1ee0a1 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -51,7 +51,7 @@ static void loc_6B5BB2(); static void ride_ratings_calculate(rct_ride *ride); static void ride_ratings_reliability_calculate(rct_ride *ride); -int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z) +static int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -65,7 +65,7 @@ int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z) return 1; } -int sub_6C60C2(rct_map_element *mapElement, int *x, int *y, int *z) +static int sub_6C60C2(rct_map_element *mapElement, int *x, int *y, int *z) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -581,6 +581,29 @@ static void sub_655FD6(rct_ride *ride) ride->var_198 += (ride->lift_hill_speed - RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4]) * 2; } +/** + * + * rct2: 0x0065E277 + */ +static int sub_65E277() +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + RCT2_CALLFUNC_X(0x0065E277, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return ebx; +} + +/** + * + * rct2: 0x0065E72D + */ +static int sub_65E72D(rct_ride *ride) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + edi = (int)ride; + RCT2_CALLFUNC_X(0x0065E277, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return edx & 0xFFFF; +} + /** * Calculates a score based on the surrounding scenery. * rct2: 0x0065E557 @@ -713,6 +736,44 @@ static void ride_ratings_calculate_bathroom(rct_ride *ride) ride->var_14D |= 2; } +static void ride_ratings_calculate_elevator(rct_ride *ride) +{ + rating_tuple ratings; + int totalLength; + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) + return; + + ride->var_198 = 15; + sub_655FD6(ride); + + // Base ratings + ratings.excitement = RIDE_RATING(1,11); + ratings.intensity = RIDE_RATING(0,35); + ratings.nausea = RIDE_RATING(0,30); + + // Apply length factor + totalLength = ride->length[0] + ride->length[1] + ride->length[2] + ride->length[3]; + ratings.excitement += ((totalLength >> 16) * 45875) >> 16; + ratings.excitement += (sub_65E277() * 11183) >> 16; + ratings.excitement += (ride_ratings_get_scenery_score(ride) * 83662) >> 16; + ratings.nausea += ((totalLength >> 16) * 26214) >> 16; + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= 7 << 5; + + if ((sub_65E72D(ride) >> 8) >= 5) + ride->excitement /= 4; +} + static void ride_ratings_calculate_first_aid(rct_ride *ride) { ride->upkeep_cost = ride_compute_upkeep(ride); @@ -768,7 +829,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { NULL, // TOP_SPIN NULL, // SPACE_RINGS NULL, // REVERSE_FREEFALL_COASTER - NULL, // ELEVATOR + ride_ratings_calculate_elevator, // ELEVATOR NULL, // VERTICAL_DROP_ROLLER_COASTER NULL, // ATM NULL, // TWIST diff --git a/src/ride/ride_ratings.h b/src/ride/ride_ratings.h index adb492aa32..5baa99e2e9 100644 --- a/src/ride/ride_ratings.h +++ b/src/ride/ride_ratings.h @@ -25,11 +25,5 @@ #include "ride.h" void ride_ratings_update_all(); -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 ride_compute_upkeep(rct_ride *ride); #endif \ No newline at end of file From 13b42804041ef0055f6dd7078dd9bca3de505bc3 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 22:05:52 +0100 Subject: [PATCH 7/9] add more ride_rating calculation functions --- src/ride/ride.h | 4 +- src/ride/ride_ratings.c | 182 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 175 insertions(+), 11 deletions(-) diff --git a/src/ride/ride.h b/src/ride/ride.h index f4bdf678db..cded00a7b9 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -164,7 +164,9 @@ typedef struct { uint16 var_158; uint8 pad_15A; uint8 num_riders; // 0x15B - uint8 pad_15C[0x24]; + uint8 pad_15C[2]; + uint16 maze_tiles; + uint8 pad_160[0x20]; sint16 build_date; // 0x180 money16 upkeep_cost; // 0x182 uint16 race_winner; // 0x184 diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 7b1a1ee0a1..5e20890f2a 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -604,6 +604,26 @@ static int sub_65E72D(rct_ride *ride) return edx & 0xFFFF; } +static rating_tuple sub_65DDD1(rct_ride *ride) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + edi = (int)ride; + RCT2_CALLFUNC_X(0x0065DDD1, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + rating_tuple rating = { ebx, ecx, ebp }; + return rating; +} + +static rating_tuple sub_65E1C2(rct_ride *ride) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + edi = (int)ride; + RCT2_CALLFUNC_X(0x0065E1C2, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + rating_tuple rating = { ebx, ecx, ebp }; + return rating; +} + /** * Calculates a score based on the surrounding scenery. * rct2: 0x0065E557 @@ -655,18 +675,26 @@ static int ride_ratings_get_scenery_score(rct_ride *ride) #pragma region Ride rating calculation functions -static void ride_ratings_calculate_crooked_house(rct_ride *ride) +static void ride_ratings_calculate_maze(rct_ride *ride) { rating_tuple ratings; ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; - ride->var_198 = 5; + ride->var_198 = 8; sub_655FD6(ride); - ratings.excitement = RIDE_RATING(2,15); - ratings.intensity = RIDE_RATING(0,62); - ratings.nausea = RIDE_RATING(0,34); + // Base ratings + ratings.excitement = RIDE_RATING(1,30); + ratings.intensity = RIDE_RATING(0,50); + ratings.nausea = RIDE_RATING(0,00); + + // Apply size factor + int unk = min(ride->maze_tiles, 100); + ratings.excitement += unk; + ratings.intensity += unk / 2; + + ratings.excitement += (ride_ratings_get_scenery_score(ride) * 22310) >> 16; ride_ratings_apply_intensity_penalty(&ratings); ride_ratings_apply_adjustments(ride, &ratings); @@ -677,7 +705,7 @@ static void ride_ratings_calculate_crooked_house(rct_ride *ride) ride->var_14D |= 2; ride->inversions &= 0x1F; - ride->inversions |= 0xE0; + ride->inversions |= 0 << 5; } static void ride_ratings_calculate_food_stall(rct_ride *ride) @@ -736,6 +764,32 @@ static void ride_ratings_calculate_bathroom(rct_ride *ride) ride->var_14D |= 2; } +static void ride_ratings_calculate_ferris_wheel(rct_ride *ride) +{ + rating_tuple ratings; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->var_198 = 16; + sub_655FD6(ride); + + int unk = ride->var_0D0 * 25; + ratings.excitement = unk + RIDE_RATING(0,60) + ((ride_ratings_get_scenery_score(ride) * 41831) >> 16); + ratings.intensity = unk + RIDE_RATING(0,25); + ratings.nausea = unk + RIDE_RATING(0,30); + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= 0 << 5; +} + static void ride_ratings_calculate_elevator(rct_ride *ride) { rating_tuple ratings; @@ -774,12 +828,120 @@ static void ride_ratings_calculate_elevator(rct_ride *ride) ride->excitement /= 4; } +static void ride_ratings_calculate_haunted_house(rct_ride *ride) +{ + rating_tuple ratings; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->var_198 = 8; + sub_655FD6(ride); + + ratings.excitement = RIDE_RATING(3,41); + ratings.intensity = RIDE_RATING(1,53); + ratings.nausea = RIDE_RATING(0,10); + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= 0xE0; +} + +static void ride_ratings_calculate_mini_golf(rct_ride *ride) +{ + rating_tuple ratings, unkRating; + + // RCT2_CALLPROC_X(0x0065BF97, 0, 0, 0, 0, 0, (int)ride, 0); return; + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) + return; + + ride->var_198 = 0; + sub_655FD6(ride); + + // Base ratings + ratings.excitement = RIDE_RATING(1,50); + ratings.intensity = RIDE_RATING(0,90); + ratings.nausea = RIDE_RATING(0,00); + + // Apply length factor + int length = (ride->length[0] + ride->length[1] + ride->length[2] + ride->length[3]) >> 16; + ratings.excitement += (min(6000, length) * 873) >> 16; + + // Apply ? + unkRating = sub_65DDD1(ride); + ratings.excitement += (unkRating.excitement * 14860) >> 16; + + // Apply ? + unkRating = sub_65E1C2(ride); + ratings.excitement += (unkRating.excitement * 5140) >> 16; + ratings.intensity += (unkRating.intensity * 6553) >> 16; + ratings.nausea += (unkRating.nausea * 4681) >> 16; + + // Apply ? + ratings.excitement += (sub_65E277() * 15657) >> 16; + + ratings.excitement += (ride_ratings_get_scenery_score(ride) * 27887) >> 16; + + // Apply golf holes factor + ratings.excitement += (ride->inversions & 0x1F) * 5; + + // Apply no golf holes penalty + if ((ride->inversions & 0x1F) == 0) { + ratings.excitement /= 8; + ratings.intensity /= 2; + ratings.nausea /= 2; + } + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= sub_65E72D(ride) << 5; +} + static void ride_ratings_calculate_first_aid(rct_ride *ride) { ride->upkeep_cost = ride_compute_upkeep(ride); ride->var_14D |= 2; } +static void ride_ratings_calculate_crooked_house(rct_ride *ride) +{ + rating_tuple ratings; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->var_198 = 5; + sub_655FD6(ride); + + ratings.excitement = RIDE_RATING(2,15); + ratings.intensity = RIDE_RATING(0,62); + ratings.nausea = RIDE_RATING(0,34); + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= 0xE0; +} + #pragma endregion #pragma region Ride rating calculation function table @@ -806,7 +968,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { NULL, // MINE_TRAIN_COASTER NULL, // CHAIRLIFT NULL, // CORKSCREW_ROLLER_COASTER - NULL, // MAZE + ride_ratings_calculate_maze, // MAZE NULL, // SPIRAL_SLIDE NULL, // GO_KARTS NULL, // LOG_FLUME @@ -823,7 +985,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { NULL, // 22 ride_ratings_calculate_information_kiosk, // INFORMATION_KIOSK ride_ratings_calculate_bathroom, // BATHROOM - NULL, // FERRIS_WHEEL + ride_ratings_calculate_ferris_wheel, // FERRIS_WHEEL NULL, // MOTION_SIMULATOR NULL, // 3D_CINEMA NULL, // TOP_SPIN @@ -833,7 +995,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { NULL, // VERTICAL_DROP_ROLLER_COASTER NULL, // ATM NULL, // TWIST - NULL, // HAUNTED_HOUSE + ride_ratings_calculate_haunted_house, // HAUNTED_HOUSE ride_ratings_calculate_first_aid, // FIRST_AID NULL, // CIRCUS_SHOW NULL, // GHOST_TRAIN @@ -853,7 +1015,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { NULL, // 40 NULL, // REVERSER_ROLLER_COASTER NULL, // HEARTLINE_TWISTER_COASTER - NULL, // MINI_GOLF + ride_ratings_calculate_mini_golf, // MINI_GOLF NULL, // GIGA_COASTER NULL, // ROTO_DROP NULL, // FLYING_SAUCERS From c91c4f7ea08ed19bf76ba145907f65b59f784463 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 23:07:20 +0100 Subject: [PATCH 8/9] implement mine train coaster rating calculation --- src/ride/ride.h | 17 ++++- src/ride/ride_ratings.c | 158 +++++++++++++++++++++++++++++++++++++++- src/windows/ride.c | 2 +- 3 files changed, 170 insertions(+), 7 deletions(-) diff --git a/src/ride/ride.h b/src/ride/ride.h index cded00a7b9..77cf17829f 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -117,7 +117,8 @@ typedef struct { uint8 var_0D0; uint8 pad_0D1[0x3]; uint8 measurement_index; // 0x0D4 - uint8 pad_0D5[0x3]; + uint8 var_0D5; + uint8 pad_0D6[0x2]; sint32 max_speed; // 0x0D8 sint32 average_speed; // 0x0DC uint8 pad_0E0[0x4]; @@ -126,13 +127,21 @@ typedef struct { fixed16_2dp max_positive_vertical_g; // 0x0FC fixed16_2dp max_negative_vertical_g; // 0x0FE fixed16_2dp max_lateral_g; // 0x100 - uint8 pad_102[0x12]; - uint8 inversions; // 0x114 (???X XXXX) holes for mini golf + uint8 pad_102[0xC]; + uint16 var_10E; + uint16 var_110; + uint16 var_112; + union { + uint8 inversions; // 0x114 (???X XXXX) + uint8 holes; // 0x114 (???X XXXX) + }; uint8 drops; // 0x115 (??XX XXXX) uint8 pad_116; uint8 highest_drop_height; // 0x117 uint32 var_118; - uint8 pad_11C[0x08]; + uint8 pad_11C[0x02]; + uint8 var_11E; + uint8 pad_11F[0x05]; sint16 var_124; sint16 var_126; sint16 var_128; diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 5e20890f2a..acec609401 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -604,6 +604,10 @@ static int sub_65E72D(rct_ride *ride) return edx & 0xFFFF; } +/** + * + * rct2: 0x0065DDD1 + */ static rating_tuple sub_65DDD1(rct_ride *ride) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -614,6 +618,10 @@ static rating_tuple sub_65DDD1(rct_ride *ride) return rating; } +/** + * + * rct2: 0x0065E1C2 + */ static rating_tuple sub_65E1C2(rct_ride *ride) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -624,6 +632,34 @@ static rating_tuple sub_65E1C2(rct_ride *ride) return rating; } +/** + * + * rct2: 0x0065DCDC + */ +static rating_tuple ride_ratings_get_gforce_ratings(rct_ride *ride) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + edi = (int)ride; + RCT2_CALLFUNC_X(0x0065DCDC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + rating_tuple rating = { ebx, ecx, ebp }; + return rating; +} + +/** + * + * rct2: 0x0065E139 + */ +static rating_tuple ride_ratings_get_drop_ratings(rct_ride *ride) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + edi = (int)ride; + RCT2_CALLFUNC_X(0x0065E139, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + rating_tuple rating = { ebx, ecx, ebp }; + return rating; +} + /** * Calculates a score based on the surrounding scenery. * rct2: 0x0065E557 @@ -675,6 +711,124 @@ static int ride_ratings_get_scenery_score(rct_ride *ride) #pragma region Ride rating calculation functions +static void ride_ratings_calculate_mine_train_coaster(rct_ride *ride) +{ + rating_tuple ratings, unkRating; + int totalLength, time; + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) + return; + + ride->var_198 = 16; + sub_655FD6(ride); + + // Base ratings + ratings.excitement = RIDE_RATING(2,90); + ratings.intensity = RIDE_RATING(2,30); + ratings.nausea = RIDE_RATING(2,10); + + // Apply length of ride factor + totalLength = (ride->length[0] + ride->length[1] + ride->length[2] + ride->length[3]) >> 16; + ratings.excitement += (min(6000, totalLength) * 764) >> 16; + + // Apply racing coaster factor + if (ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS) { + ratings.excitement += RIDE_RATING(0,40); + ratings.intensity += RIDE_RATING(0,05); + } + + // Apply length of train factor + ratings.excitement += ((ride->num_cars_per_train - 1) * 187245) >> 16; + + // Apply maximum speed factor + ratings.excitement += ((ride->max_speed >> 16) * 44281) >> 16; + ratings.intensity += ((ride->max_speed >> 16) * 88562) >> 16; + ratings.nausea += ((ride->max_speed >> 16) * 35424) >> 16; + + // Apply average speed factor + ratings.excitement += ((ride->average_speed >> 16) * 291271) >> 16; + ratings.intensity += ((ride->average_speed >> 16) * 436906) >> 16; + + // Apply ride duration factor + time = ride->time[0] + ride->time[1] + ride->time[2] + ride->time[3]; + ratings.excitement += (min(150, time) * 26214) >> 16; + + // Apply G forces factor + unkRating = ride_ratings_get_gforce_ratings(ride); + ratings.excitement += (unkRating.excitement * 40960) >> 16; + ratings.intensity += (unkRating.intensity * 35746) >> 16; + ratings.nausea += (unkRating.nausea * 49648) >> 16; + + // Apply ? + unkRating = sub_65DDD1(ride); + ratings.excitement += (unkRating.excitement * 29721) >> 16; + ratings.intensity += (unkRating.intensity * 34767) >> 16; + ratings.nausea += (unkRating.nausea * 45749) >> 16; + + // Apply drops factor + unkRating = ride_ratings_get_drop_ratings(ride); + ratings.excitement += (unkRating.excitement * 29127) >> 16; + ratings.intensity += (unkRating.intensity * 46811) >> 16; + ratings.nausea += (unkRating.nausea * 49152) >> 16; + + // Apply ? + unkRating = sub_65E1C2(ride); + ratings.excitement += (unkRating.excitement * 19275) >> 16; + ratings.intensity += (unkRating.intensity * 32768) >> 16; + ratings.nausea += (unkRating.nausea * 35108) >> 16; + + // Apply ? + ratings.excitement += (sub_65E277() * 21472) >> 16; + + ratings.excitement += (ride_ratings_get_scenery_score(ride) * 16732) >> 16; + + // Apply low highest drop penalty + if (ride->highest_drop_height < 8) { + ride->excitement /= 2; + ride->intensity /= 2; + ride->nausea /= 2; + } + + // Apply low max speed penalty + if (ride->max_speed < 0xA0000) { + ride->excitement /= 2; + ride->intensity /= 2; + ride->nausea /= 2; + } + + // Apply low maximum negative vertical G force penalty + if (ride->max_negative_vertical_g > FIXED_2DP(0,10)) { + ride->excitement /= 2; + ride->intensity /= 2; + ride->nausea /= 2; + } + + // Apply short ride penalty + if (ride->length[0] < 0x1720000) { + ride->excitement /= 2; + ride->intensity /= 2; + ride->nausea /= 2; + } + + // Apply low number of drops penalty + if ((ride->drops & 0x3F) < 2) { + ride->excitement /= 2; + ride->intensity /= 2; + ride->nausea /= 2; + } + + ride_ratings_apply_intensity_penalty(&ratings); + ride_ratings_apply_adjustments(ride, &ratings); + + ride->ratings = ratings; + + ride->upkeep_cost = ride_compute_upkeep(ride); + ride->var_14D |= 2; + + ride->inversions &= 0x1F; + ride->inversions |= sub_65E72D(ride) << 5; +} + static void ride_ratings_calculate_maze(rct_ride *ride) { rating_tuple ratings; @@ -890,7 +1044,7 @@ static void ride_ratings_calculate_mini_golf(rct_ride *ride) ratings.excitement += (ride_ratings_get_scenery_score(ride) * 27887) >> 16; // Apply golf holes factor - ratings.excitement += (ride->inversions & 0x1F) * 5; + ratings.excitement += (ride->holes & 0x1F) * 5; // Apply no golf holes penalty if ((ride->inversions & 0x1F) == 0) { @@ -965,7 +1119,7 @@ static const ride_ratings_calculation ride_ratings_calculate_func_table[91] = { NULL, // OBSERVATION_TOWER NULL, // LOOPING_ROLLER_COASTER NULL, // DINGHY_SLIDE - NULL, // MINE_TRAIN_COASTER + ride_ratings_calculate_mine_train_coaster, // MINE_TRAIN_COASTER NULL, // CHAIRLIFT NULL, // CORKSCREW_ROLLER_COASTER ride_ratings_calculate_maze, // MAZE diff --git a/src/windows/ride.c b/src/windows/ride.c index 6cec49b004..013c0eb255 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -4602,7 +4602,7 @@ static void window_ride_measurements_paint() if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_NO_RAW_STATS)) { if (ride->type == RIDE_TYPE_MINI_GOLF) { // Holes - holes = ride->inversions & 0x1F; + holes = ride->holes & 0x1F; gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y); y += 10; } else { From 8190fa48beef2b67f8474af2d7c62312dcc55c7a Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 11 Oct 2014 23:50:04 +0100 Subject: [PATCH 9/9] implement rating calculations for g forces and drops --- src/ride/ride_ratings.c | 96 +++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 27 deletions(-) diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index acec609401..964538abba 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -638,12 +638,41 @@ static rating_tuple sub_65E1C2(rct_ride *ride) */ static rating_tuple ride_ratings_get_gforce_ratings(rct_ride *ride) { - int eax, ebx, ecx, edx, esi, edi, ebp; - edi = (int)ride; - RCT2_CALLFUNC_X(0x0065DCDC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + rating_tuple result; + fixed16_2dp gforce; - rating_tuple rating = { ebx, ecx, ebp }; - return rating; + result.excitement = 0; + result.intensity = 0; + result.nausea = 0; + + // Apply maximum positive G force factor + result.excitement += (ride->max_positive_vertical_g * 5242) >> 16; + result.intensity += (ride->max_positive_vertical_g * 52428) >> 16; + result.nausea += (ride->max_positive_vertical_g * 17039) >> 16; + + // Apply maximum negative G force factor + gforce = ride->max_negative_vertical_g; + result.excitement += (clamp(-FIXED_2DP(2,50), gforce, FIXED_2DP(0,00)) * -15728) >> 16; + result.intensity += ((gforce - FIXED_2DP(1,00)) * -52428) >> 16; + result.nausea += ((gforce - FIXED_2DP(1,00)) * -14563) >> 16; + + // Apply lateral G force factor + result.excitement += (min(FIXED_2DP(1,50), ride->max_lateral_g) * 26214) >> 16; + result.intensity += (ride->max_lateral_g * 65536) >> 16; + result.nausea += (ride->max_lateral_g * 21845) >> 16; + + // Very high lateral G force penalty + if (ride->max_lateral_g > FIXED_2DP(2,80)) { + result.intensity += FIXED_2DP(3,75); + result.nausea += FIXED_2DP(2,00); + } + if (ride->max_lateral_g > FIXED_2DP(3,10)) { + result.excitement /= 2; + result.intensity += FIXED_2DP(8,50); + result.nausea += FIXED_2DP(4,00); + } + + return result; } /** @@ -652,12 +681,25 @@ static rating_tuple ride_ratings_get_gforce_ratings(rct_ride *ride) */ static rating_tuple ride_ratings_get_drop_ratings(rct_ride *ride) { - int eax, ebx, ecx, edx, esi, edi, ebp; - edi = (int)ride; - RCT2_CALLFUNC_X(0x0065E139, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + rating_tuple result; + int drops; - rating_tuple rating = { ebx, ecx, ebp }; - return rating; + result.excitement = 0; + result.intensity = 0; + result.nausea = 0; + + // Apply number of drops factor + drops = ride->drops & 0x3F; + result.excitement += (min(9, drops) * 728177) >> 16; + result.intensity += (drops * 928426) >> 16; + result.nausea += (drops * 655360) >> 16; + + // Apply highest drop factor + result.excitement += ((ride->highest_drop_height * 2) * 16000) >> 16; + result.intensity += ((ride->highest_drop_height * 2) * 32000) >> 16; + result.nausea += ((ride->highest_drop_height * 2) * 10240) >> 16; + + return result; } /** @@ -713,7 +755,7 @@ static int ride_ratings_get_scenery_score(rct_ride *ride) static void ride_ratings_calculate_mine_train_coaster(rct_ride *ride) { - rating_tuple ratings, unkRating; + rating_tuple ratings, subRating; int totalLength, time; if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) @@ -754,28 +796,28 @@ static void ride_ratings_calculate_mine_train_coaster(rct_ride *ride) ratings.excitement += (min(150, time) * 26214) >> 16; // Apply G forces factor - unkRating = ride_ratings_get_gforce_ratings(ride); - ratings.excitement += (unkRating.excitement * 40960) >> 16; - ratings.intensity += (unkRating.intensity * 35746) >> 16; - ratings.nausea += (unkRating.nausea * 49648) >> 16; + subRating = ride_ratings_get_gforce_ratings(ride); + ratings.excitement += (subRating.excitement * 40960) >> 16; + ratings.intensity += (subRating.intensity * 35746) >> 16; + ratings.nausea += (subRating.nausea * 49648) >> 16; // Apply ? - unkRating = sub_65DDD1(ride); - ratings.excitement += (unkRating.excitement * 29721) >> 16; - ratings.intensity += (unkRating.intensity * 34767) >> 16; - ratings.nausea += (unkRating.nausea * 45749) >> 16; + subRating = sub_65DDD1(ride); + ratings.excitement += (subRating.excitement * 29721) >> 16; + ratings.intensity += (subRating.intensity * 34767) >> 16; + ratings.nausea += (subRating.nausea * 45749) >> 16; // Apply drops factor - unkRating = ride_ratings_get_drop_ratings(ride); - ratings.excitement += (unkRating.excitement * 29127) >> 16; - ratings.intensity += (unkRating.intensity * 46811) >> 16; - ratings.nausea += (unkRating.nausea * 49152) >> 16; + subRating = ride_ratings_get_drop_ratings(ride); + ratings.excitement += (subRating.excitement * 29127) >> 16; + ratings.intensity += (subRating.intensity * 46811) >> 16; + ratings.nausea += (subRating.nausea * 49152) >> 16; // Apply ? - unkRating = sub_65E1C2(ride); - ratings.excitement += (unkRating.excitement * 19275) >> 16; - ratings.intensity += (unkRating.intensity * 32768) >> 16; - ratings.nausea += (unkRating.nausea * 35108) >> 16; + subRating = sub_65E1C2(ride); + ratings.excitement += (subRating.excitement * 19275) >> 16; + ratings.intensity += (subRating.intensity * 32768) >> 16; + ratings.nausea += (subRating.nausea * 35108) >> 16; // Apply ? ratings.excitement += (sub_65E277() * 21472) >> 16;