From f14738836ae9ca53353e8b71dc855b46302d4be9 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 9 Jan 2017 18:35:34 +0000 Subject: [PATCH 1/4] Prevent overflows for many rating operatings --- src/openrct2/ride/ride_ratings.c | 315 +++++++++++++++++++------------ 1 file changed, 195 insertions(+), 120 deletions(-) diff --git a/src/openrct2/ride/ride_ratings.c b/src/openrct2/ride/ride_ratings.c index 0487394d88..9d85d9c3f3 100644 --- a/src/openrct2/ride/ride_ratings.c +++ b/src/openrct2/ride/ride_ratings.c @@ -79,6 +79,8 @@ static void ride_ratings_calculate(rct_ride *ride); static void ride_ratings_calculate_value(rct_ride *ride); static void ride_ratings_score_close_proximity(rct_map_element *mapElement); +static void ride_ratings_add(rating_tuple * rating, sint32 excitement, sint32 intensity, sint32 nausea); + /** * * rct2: 0x006B5A2A @@ -789,9 +791,10 @@ static void ride_ratings_apply_adjustments(rct_ride *ride, rating_tuple *ratings rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); // 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); + ride_ratings_add(ratings, + (((sint32)ratings->excitement * rideEntry->excitement_multipler) >> 7), + (((sint32)ratings->intensity * rideEntry->intensity_multipler) >> 7), + (((sint32)ratings->nausea * rideEntry->nausea_multipler) >> 7)); // Apply total air time #ifdef ORIGINAL_RATINGS @@ -810,13 +813,17 @@ static void ride_ratings_apply_adjustments(rct_ride *ride, rating_tuple *ratings } #else if (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_HAS_AIR_TIME) { + sint32 excitementModifier; + sint32 nauseaModifier; if (rideEntry->flags & RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS) { // Limit airtime bonus for heartline twister coaster (see issues #2031 and #2064) - ratings->excitement += min(ride->total_air_time, 96) / 8; + excitementModifier = min(ride->total_air_time, 96) / 8; } else { - ratings->excitement += ride->total_air_time / 8; + excitementModifier = ride->total_air_time / 8; } - ratings->nausea += ride->total_air_time / 16; + nauseaModifier = ride->total_air_time / 16; + + ride_ratings_add(ratings, excitementModifier, 0, nauseaModifier); } #endif } @@ -845,7 +852,7 @@ static void set_unreliability_factor(rct_ride *ride) { // The bigger the difference in lift speed and minimum the higher the unreliability uint8 lift_speed_adjustment = RideLiftData[ride->type].minimum_speed; - ride->unreliability_factor += (ride->lift_hill_speed - lift_speed_adjustment) * 2; + ride->unreliability_factor += (ride->lift_hill_speed - lift_speed_adjustment) * 2; } static uint32 get_proximity_score_helper_1(uint16 x, uint16 max, uint32 multiplier) @@ -1196,9 +1203,10 @@ static rating_tuple ride_ratings_get_drop_ratings(rct_ride *ride) 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; + ride_ratings_add(&result, + ((ride->highest_drop_height * 2) * 16000) >> 16, + ((ride->highest_drop_height * 2) * 32000) >> 16, + ((ride->highest_drop_height * 2) * 10240) >> 16); return result; } @@ -1254,95 +1262,140 @@ static sint32 ride_ratings_get_scenery_score(rct_ride *ride) static void ride_ratings_set(rating_tuple *ratings, sint32 excitement, sint32 intensity, sint32 nausea) { - ratings->excitement = excitement; - ratings->intensity = intensity; - ratings->nausea = nausea; + *ratings = (rating_tuple){ 0 }; + ride_ratings_add(ratings, excitement, intensity, nausea); +} + +/** + * Add to a ride rating with overflow protection. + */ +static void ride_ratings_add(rating_tuple * rating, sint32 excitement, sint32 intensity, sint32 nausea) +{ + sint32 newExcitement = rating->excitement + excitement; + sint32 newIntensity = rating->intensity + intensity; + sint32 newNausea = rating->nausea + nausea; + rating->excitement = clamp(0, newExcitement, INT16_MAX); + rating->intensity = clamp(0, newIntensity, INT16_MAX); + rating->nausea = clamp(0, newNausea, INT16_MAX); } static void ride_ratings_apply_length(rating_tuple *ratings, rct_ride *ride, sint32 maxLength, sint32 excitementMultiplier) { - ratings->excitement += (min(ride_get_total_length(ride) >> 16, maxLength) * excitementMultiplier) >> 16; + ride_ratings_add(ratings, + (min(ride_get_total_length(ride) >> 16, maxLength) * excitementMultiplier) >> 16, + 0, + 0); } static void ride_ratings_apply_synchronisation(rating_tuple *ratings, rct_ride *ride, sint32 excitement, sint32 intensity) { if ((ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS) && - ride_has_adjacent_station(ride)) { - ratings->excitement += excitement; - ratings->intensity += intensity; + ride_has_adjacent_station(ride) + ) { + ride_ratings_add(ratings, excitement, intensity, 0); } } static void ride_ratings_apply_train_length(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier) { - ratings->excitement += ((ride->num_cars_per_train - 1) * excitementMultiplier) >> 16; + ride_ratings_add(ratings, + ((ride->num_cars_per_train - 1) * excitementMultiplier) >> 16, + 0, + 0); } static void ride_ratings_apply_max_speed(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) { - ratings->excitement += ((ride->max_speed >> 16) * excitementMultiplier) >> 16; - ratings->intensity += ((ride->max_speed >> 16) * intensityMultiplier) >> 16; - ratings->nausea += ((ride->max_speed >> 16) * nauseaMultiplier) >> 16; + sint32 modifier = ride->max_speed >> 16; + ride_ratings_add(ratings, + (modifier * excitementMultiplier) >> 16, + (modifier * intensityMultiplier) >> 16, + (modifier * nauseaMultiplier) >> 16); } static void ride_ratings_apply_average_speed(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier) { - ratings->excitement += ((ride->average_speed >> 16) * excitementMultiplier) >> 16; - ratings->intensity += ((ride->average_speed >> 16) * intensityMultiplier) >> 16; + sint32 modifier = ride->average_speed >> 16; + ride_ratings_add(ratings, + (modifier * excitementMultiplier) >> 16, + (modifier * intensityMultiplier) >> 16, + 0); } static void ride_ratings_apply_duration(rating_tuple *ratings, rct_ride *ride, sint32 maxDuration, sint32 excitementMultiplier) { - ratings->excitement += (min(ride_get_total_time(ride), maxDuration) * excitementMultiplier) >> 16; + ride_ratings_add(ratings, + (min(ride_get_total_time(ride), maxDuration) * excitementMultiplier) >> 16, + 0, + 0); } static void ride_ratings_apply_gforces(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) { rating_tuple subRating = ride_ratings_get_gforce_ratings(ride); - ratings->excitement += (subRating.excitement * excitementMultiplier) >> 16; - ratings->intensity += (subRating.intensity * intensityMultiplier) >> 16; - ratings->nausea += (subRating.nausea * nauseaMultiplier) >> 16; + ride_ratings_add(ratings, + (subRating.excitement * excitementMultiplier) >> 16, + (subRating.intensity * intensityMultiplier) >> 16, + (subRating.nausea * nauseaMultiplier) >> 16); } static void ride_ratings_apply_turns(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) { rating_tuple subRating = ride_ratings_get_turns_ratings(ride); - ratings->excitement += (subRating.excitement * excitementMultiplier) >> 16; - ratings->intensity += (subRating.intensity * intensityMultiplier) >> 16; - ratings->nausea += (subRating.nausea * nauseaMultiplier) >> 16; + ride_ratings_add(ratings, + (subRating.excitement * excitementMultiplier) >> 16, + (subRating.intensity * intensityMultiplier) >> 16, + (subRating.nausea * nauseaMultiplier) >> 16); } static void ride_ratings_apply_drops(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) { rating_tuple subRating = ride_ratings_get_drop_ratings(ride); - ratings->excitement += (subRating.excitement * excitementMultiplier) >> 16; - ratings->intensity += (subRating.intensity * intensityMultiplier) >> 16; - ratings->nausea += (subRating.nausea * nauseaMultiplier) >> 16; + ride_ratings_add(ratings, + (subRating.excitement * excitementMultiplier) >> 16, + (subRating.intensity * intensityMultiplier) >> 16, + (subRating.nausea * nauseaMultiplier) >> 16); } static void ride_ratings_apply_sheltered_ratings(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) { rating_tuple subRating = ride_ratings_get_sheltered_ratings(ride); - ratings->excitement += (subRating.excitement * excitementMultiplier) >> 16; - ratings->intensity += (subRating.intensity * intensityMultiplier) >> 16; - ratings->nausea += (subRating.nausea * nauseaMultiplier) >> 16; + ride_ratings_add(ratings, + (subRating.excitement * excitementMultiplier) >> 16, + (subRating.intensity * intensityMultiplier) >> 16, + (subRating.nausea * nauseaMultiplier) >> 16); } static void ride_ratings_apply_operation_option(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) { - ratings->excitement += (ride->operation_option * excitementMultiplier) >> 16; - ratings->intensity += (ride->operation_option * intensityMultiplier) >> 16; - ratings->nausea += (ride->operation_option * nauseaMultiplier) >> 16; + ride_ratings_add(ratings, + (ride->operation_option * excitementMultiplier) >> 16, + (ride->operation_option * intensityMultiplier) >> 16, + (ride->operation_option * nauseaMultiplier) >> 16); +} + +static void ride_ratings_apply_rotations(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier, sint32 intensityMultiplier, sint32 nauseaMultiplier) +{ + ride_ratings_add(ratings, + ride->rotations * excitementMultiplier, + ride->rotations * intensityMultiplier, + ride->rotations * nauseaMultiplier); } static void ride_ratings_apply_proximity(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier) { - ratings->excitement += (ride_ratings_get_proximity_score() * excitementMultiplier) >> 16; + ride_ratings_add(ratings, + (ride_ratings_get_proximity_score() * excitementMultiplier) >> 16, + 0, + 0); } static void ride_ratings_apply_scenery(rating_tuple *ratings, rct_ride *ride, sint32 excitementMultiplier) { - ratings->excitement += (ride_ratings_get_scenery_score(ride) * excitementMultiplier) >> 16; + ride_ratings_add(ratings, + (ride_ratings_get_scenery_score(ride) * excitementMultiplier) >> 16, + 0, + 0); } static void ride_ratings_apply_highest_drop_height_penalty(rating_tuple *ratings, rct_ride *ride, sint32 minHighestDropHeight, sint32 excitementPenalty, sint32 intensityPenalty, sint32 nauseaPenalty) @@ -1392,17 +1445,15 @@ static void ride_ratings_apply_max_lateral_g_penalty(rating_tuple *ratings, rct_ static void ride_ratings_apply_excessive_lateral_g_penalty(rating_tuple *ratings, rct_ride *ride) { - #ifndef ORIGINAL_RATINGS +#ifndef ORIGINAL_RATINGS if (ride->max_lateral_g > FIXED_2DP(2,80)) { - ratings->intensity += FIXED_2DP(3,75); - ratings->nausea += FIXED_2DP(2,00); + ride_ratings_add(ratings, 0, FIXED_2DP(3,75), FIXED_2DP(2,00)); } if (ride->max_lateral_g > FIXED_2DP(3,10)) { ratings->excitement /= 2; - ratings->intensity += FIXED_2DP(8,50); - ratings->nausea += FIXED_2DP(4,00); + ride_ratings_add(ratings, 0, FIXED_2DP(8,50), FIXED_2DP(4,00)); } - #endif +#endif } static void ride_ratings_apply_first_length_penalty(rating_tuple *ratings, rct_ride *ride, sint32 minFirstLength, sint32 excitementPenalty, sint32 intensityPenalty, sint32 nauseaPenalty) @@ -1752,8 +1803,9 @@ static void ride_ratings_calculate_boat_ride(rct_ride *ride) ride_ratings_set(&ratings, RIDE_RATING(1,90), RIDE_RATING(0,80), RIDE_RATING(0,90)); // Most likely checking if the ride has does not have a circuit - if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) - ratings.excitement += RIDE_RATING(0,20); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) { + ride_ratings_add(&ratings, RIDE_RATING(0,20), 0, 0); + } ride_ratings_apply_proximity(&ratings, ride, 11183); ride_ratings_apply_scenery(&ratings, ride, 22310); @@ -1900,12 +1952,14 @@ static void ride_ratings_calculate_launched_freefall(rct_ride *ride) ride_ratings_set(&ratings, RIDE_RATING(2,70), RIDE_RATING(3,00), RIDE_RATING(3,50)); if (ride->mode == RIDE_MODE_DOWNWARD_LAUNCH) { - ratings.excitement += RIDE_RATING(0,30); - ratings.intensity += RIDE_RATING(0,65); - ratings.nausea += RIDE_RATING(0,45); + ride_ratings_add(&ratings, + RIDE_RATING(0,30), + RIDE_RATING(0,65), + RIDE_RATING(0,45)); } - ratings.excitement += ((ride_get_total_length(ride) >> 16) * 32768) >> 16; + sint32 excitementModifier = ((ride_get_total_length(ride) >> 16) * 32768) >> 16; + ride_ratings_add(&ratings, excitementModifier, 0, 0); #ifdef ORIGINAL_RATINGS ride_ratings_apply_operation_option(&ratings, ride, 0, 1355917, 451972); @@ -1918,9 +1972,7 @@ static void ride_ratings_calculate_launched_freefall(rct_ride *ride) // nausea were fixed regardless of how high the ride is. The following // calculation is based on roto-drop which is a similar mechanic. sint32 lengthFactor = ((ride_get_total_length(ride) >> 16) * 209715) >> 16; - ratings.excitement += lengthFactor; - ratings.intensity += lengthFactor * 2; - ratings.nausea += lengthFactor * 2; + ride_ratings_add(&ratings, lengthFactor, lengthFactor * 2, lengthFactor * 2); } #endif @@ -1988,8 +2040,10 @@ static void ride_ratings_calculate_observation_tower(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(1,50), RIDE_RATING(0,00), RIDE_RATING(0,10)); - ratings.excitement += ((ride_get_total_length(ride) >> 16) * 45875) >> 16; - ratings.nausea += ((ride_get_total_length(ride) >> 16) * 26214) >> 16; + ride_ratings_add(&ratings, + ((ride_get_total_length(ride) >> 16) * 45875) >> 16, + 0, + ((ride_get_total_length(ride) >> 16) * 26214) >> 16); ride_ratings_apply_proximity(&ratings, ride, 20130); ride_ratings_apply_scenery(&ratings, ride, 83662); @@ -2234,8 +2288,10 @@ static void ride_ratings_calculate_maze(rct_ride *ride) ride_ratings_set(&ratings, RIDE_RATING(1,30), RIDE_RATING(0,50), RIDE_RATING(0,00)); sint32 size = min(ride->maze_tiles, 100); - ratings.excitement += size; - ratings.intensity += size * 2; + ride_ratings_add(&ratings, + size, + size * 2, + 0); ride_ratings_apply_scenery(&ratings, ride, 22310); @@ -2263,9 +2319,10 @@ static void ride_ratings_calculate_spiral_slide(rct_ride *ride) // Unlimited slides boost if (ride->mode == RIDE_MODE_UNLIMITED_RIDES_PER_ADMISSION) { - ratings.excitement += RIDE_RATING(0, 40); - ratings.intensity += RIDE_RATING(0, 20); - ratings.nausea += RIDE_RATING(0, 25); + ride_ratings_add(&ratings, + RIDE_RATING(0,40), + RIDE_RATING(0,20), + RIDE_RATING(0,25)); } ride_ratings_apply_scenery(&ratings, ride, 25098); @@ -2295,12 +2352,16 @@ static void ride_ratings_calculate_go_karts(rct_ride *ride) ride_ratings_apply_length(&ratings, ride, 700, 32768); if (ride->mode == RIDE_MODE_RACE && ride->num_vehicles >= 4) { - ratings.excitement += RIDE_RATING(1,40); - ratings.intensity += RIDE_RATING(0,50); + ride_ratings_add(&ratings, + RIDE_RATING(1,40), + RIDE_RATING(0,50), + 0); sint32 lapsFactor = (ride->num_laps - 1) * 30; - ratings.excitement += lapsFactor; - ratings.intensity += lapsFactor / 2; + ride_ratings_add(&ratings, + lapsFactor, + lapsFactor / 2, + 0); } ride_ratings_apply_turns(&ratings, ride, 4458, 3476, 5718); @@ -2403,14 +2464,24 @@ static void ride_ratings_calculate_dodgems(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(1,30), RIDE_RATING(0,50), RIDE_RATING(0,35)); - if (ride->num_vehicles >= 4) - ratings.excitement += RIDE_RATING(0,40); + if (ride->num_vehicles >= 4) { + ride_ratings_add(&ratings, + RIDE_RATING(0,40), + 0, + 0); + } - ratings.excitement += ride->operation_option; - ratings.intensity += ride->operation_option / 2; + ride_ratings_add(&ratings, + ride->operation_option, + ride->operation_option / 2, + 0); - if (ride->num_vehicles >= 4) - ratings.excitement += RIDE_RATING(0,40); + if (ride->num_vehicles >= 4) { + ride_ratings_add(&ratings, + RIDE_RATING(0,40), + 0, + 0); + } ride_ratings_apply_scenery(&ratings, ride, 5577); @@ -2436,9 +2507,10 @@ static void ride_ratings_calculate_pirate_ship(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(1,50), RIDE_RATING(1,90), RIDE_RATING(1,41)); - ratings.excitement += ride->operation_option * 5; - ratings.intensity += ride->operation_option * 5; - ratings.nausea += ride->operation_option * 10; + ride_ratings_add(&ratings, + ride->operation_option * 5, + ride->operation_option * 5, + ride->operation_option * 10); ride_ratings_apply_scenery(&ratings, ride, 16732); @@ -2464,9 +2536,10 @@ static void ride_ratings_calculate_inverter_ship(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(2,50), RIDE_RATING(2,70), RIDE_RATING(2,74)); - ratings.excitement += ride->operation_option * 11; - ratings.intensity += ride->operation_option * 22; - ratings.nausea += ride->operation_option * 22; + ride_ratings_add(&ratings, + ride->operation_option * 11, + ride->operation_option * 22, + ride->operation_option * 22); ride_ratings_apply_scenery(&ratings, ride, 11155); @@ -2509,14 +2582,8 @@ static void ride_ratings_calculate_merry_go_round(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(0,60), RIDE_RATING(0,15), RIDE_RATING(0,30)); - - sint32 rotationsFactor = ride->rotations * 5; - ratings.excitement += rotationsFactor; - ratings.intensity += rotationsFactor; - ratings.nausea += rotationsFactor; - + ride_ratings_apply_rotations(&ratings, ride, 5, 5, 5); ride_ratings_apply_scenery(&ratings, ride, 19521); - ride_ratings_apply_intensity_penalty(&ratings); ride_ratings_apply_adjustments(ride, &ratings); @@ -2550,14 +2617,8 @@ static void ride_ratings_calculate_ferris_wheel(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(0,60), RIDE_RATING(0,25), RIDE_RATING(0,30)); - - sint32 rotationsFactor = ride->rotations * 25; - ratings.excitement += rotationsFactor; - ratings.intensity += rotationsFactor; - ratings.nausea += rotationsFactor; - + ride_ratings_apply_rotations(&ratings, ride, 25, 25, 25); ride_ratings_apply_scenery(&ratings, ride, 41831); - ride_ratings_apply_intensity_penalty(&ratings); ride_ratings_apply_adjustments(ride, &ratings); @@ -2751,8 +2812,10 @@ static void ride_ratings_calculate_lift(rct_ride *ride) ride_ratings_set(&ratings, RIDE_RATING(1,11), RIDE_RATING(0,35), RIDE_RATING(0,30)); totalLength = ride_get_total_length(ride) >> 16; - ratings.excitement += (totalLength * 45875) >> 16; - ratings.nausea += (totalLength * 26214) >> 16; + ride_ratings_add(&ratings, + (totalLength * 45875) >> 16, + 0, + (totalLength * 26214) >> 16); ride_ratings_apply_proximity(&ratings, ride, 11183); ride_ratings_apply_scenery(&ratings, ride, 83662); @@ -2826,13 +2889,8 @@ static void ride_ratings_calculate_twist(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(1,13), RIDE_RATING(0,97), RIDE_RATING(1,90)); - - ratings.excitement += ride->rotations * 20; - ratings.intensity += ride->rotations * 20; - ratings.nausea += ride->rotations * 20; - + ride_ratings_apply_rotations(&ratings, ride, 20, 20, 20); ride_ratings_apply_scenery(&ratings, ride, 13943); - ride_ratings_apply_intensity_penalty(&ratings); ride_ratings_apply_adjustments(ride, &ratings); @@ -3125,9 +3183,10 @@ static void ride_ratings_calculate_reverser_roller_coaster(rct_ride *ride) sint32 numReversers = min(gRideRatingsCalcData.num_reversers, 6); ride_rating reverserRating = numReversers * RIDE_RATING(0,20); - ratings.excitement += reverserRating; - ratings.intensity += reverserRating; - ratings.nausea += reverserRating; + ride_ratings_add(&ratings, + reverserRating, + reverserRating, + reverserRating); ride_ratings_apply_duration(&ratings, ride, 150, 26214); ride_ratings_apply_gforces(&ratings, ride, 28672, 23831, 49648); @@ -3215,7 +3274,10 @@ static void ride_ratings_calculate_mini_golf(rct_ride *ride) ride_ratings_apply_scenery(&ratings, ride, 27887); // Apply golf holes factor - ratings.excitement += (ride->holes & 0x1F) * 5; + ride_ratings_add(&ratings, + (ride->holes & 0x1F) * 5, + 0, + 0); // Apply no golf holes penalty if ((ride->inversions & 0x1F) == 0) { @@ -3573,9 +3635,10 @@ static void ride_ratings_calculate_roto_drop(rct_ride *ride) ride_ratings_set(&ratings, RIDE_RATING(2,80), RIDE_RATING(3,50), RIDE_RATING(3,50)); sint32 lengthFactor = ((ride_get_total_length(ride) >> 16) * 209715) >> 16; - ratings.excitement += lengthFactor; - ratings.intensity += lengthFactor * 2; - ratings.nausea += lengthFactor * 2; + ride_ratings_add(&ratings, + lengthFactor, + lengthFactor * 2, + lengthFactor * 2); ride_ratings_apply_proximity(&ratings, ride, 11183); ride_ratings_apply_scenery(&ratings, ride, 25098); @@ -3605,14 +3668,24 @@ static void ride_ratings_calculate_flying_saucers(rct_ride *ride) .nausea = RIDE_RATING(0,39) }; - if (ride->num_vehicles >= 4) - ratings.excitement += RIDE_RATING(0,40); + if (ride->num_vehicles >= 4) { + ride_ratings_add(&ratings, + RIDE_RATING(0,40), + 0, + 0); + } - ratings.excitement += ride->time_limit; - ratings.intensity += ride->time_limit / 2; + ride_ratings_add(&ratings, + ride->time_limit, + ride->time_limit / 2, + 0); - if (ride->num_vehicles >= 4) - ratings.excitement += RIDE_RATING(0,40); + if (ride->num_vehicles >= 4) { + ride_ratings_add(&ratings, + RIDE_RATING(0, 40), + 0, + 0); + } ride_ratings_apply_scenery(&ratings, ride, 5577); @@ -3858,9 +3931,10 @@ static void ride_ratings_calculate_magic_carpet(rct_ride *ride) rating_tuple ratings; ride_ratings_set(&ratings, RIDE_RATING(2,45), RIDE_RATING(1,60), RIDE_RATING(2,60)); - ratings.excitement += ride->operation_option * 10; - ratings.intensity += ride->operation_option * 20; - ratings.nausea += ride->operation_option * 20; + ride_ratings_add(&ratings, + ride->operation_option * 10, + ride->operation_option * 20, + ride->operation_option * 20); ride_ratings_apply_scenery(&ratings, ride, 11155); @@ -3946,9 +4020,10 @@ static void ride_ratings_calculate_enterprise(rct_ride *ride) .nausea = RIDE_RATING(5,72) }; - ratings.excitement += ride->operation_option; - ratings.intensity += ride->operation_option * 16; - ratings.nausea += ride->operation_option * 16; + ride_ratings_add(&ratings, + ride->operation_option, + ride->operation_option * 16, + ride->operation_option * 16); ride_ratings_apply_scenery(&ratings, ride, 19521); From 463fadbcf6c553e322cec7649136628a71a17e93 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 9 Jan 2017 18:47:25 +0000 Subject: [PATCH 2/4] Protect ride rating names from extreme numbers --- src/openrct2/windows/ride.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/openrct2/windows/ride.c b/src/openrct2/windows/ride.c index 3d8bab1f89..dc03fbe972 100644 --- a/src/openrct2/windows/ride.c +++ b/src/openrct2/windows/ride.c @@ -4890,6 +4890,12 @@ static void window_ride_music_paint(rct_window *w, rct_drawpixelinfo *dpi) #pragma region Measurements +static rct_string_id get_rating_name(ride_rating rating) +{ + sint32 index = clamp(0, rating >> 8, countof(RatingNames) - 1); + return RatingNames[index]; +} + /** * * rct2: 0x006D2804 @@ -5220,15 +5226,17 @@ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) { // Excitement + rct_string_id ratingName = get_rating_name(ride->excitement); set_format_arg(0, uint32, ride->excitement); - set_format_arg(4, rct_string_id, RatingNames[min(ride->excitement >> 8, 5)]); + set_format_arg(4, rct_string_id, ratingName); rct_string_id stringId = ride->excitement == RIDE_RATING_UNDEFINED ? STR_EXCITEMENT_RATING_NOT_YET_AVAILABLE : STR_EXCITEMENT_RATING; gfx_draw_string_left(dpi, stringId, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 10; // Intensity + ratingName = get_rating_name(ride->intensity); set_format_arg(0, uint32, ride->intensity); - set_format_arg(4, rct_string_id, RatingNames[min(ride->intensity >> 8, 5)]); + set_format_arg(4, rct_string_id, ratingName); stringId = STR_INTENSITY_RATING; if (ride->excitement == RIDE_RATING_UNDEFINED) @@ -5240,8 +5248,9 @@ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi y += 10; // Nausea + ratingName = get_rating_name(ride->nausea); set_format_arg(0, uint32, ride->nausea); - set_format_arg(4, rct_string_id, RatingNames[min(ride->nausea >> 8, 5)]); + set_format_arg(4, rct_string_id, ratingName); stringId = ride->excitement == RIDE_RATING_UNDEFINED ? STR_NAUSEA_RATING_NOT_YET_AVAILABLE : STR_NAUSEA_RATING; gfx_draw_string_left(dpi, stringId, gCommonFormatArgs, COLOUR_BLACK, x, y); y += 20; From 1ea9a61f98502febbc37f7eb14ee02ab48d22db3 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 5 Jun 2017 20:17:39 +0100 Subject: [PATCH 3/4] Increase network version --- src/openrct2/network/network.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h index ec5d657004..bb33322ff0 100644 --- a/src/openrct2/network/network.h +++ b/src/openrct2/network/network.h @@ -56,7 +56,7 @@ extern "C" { // This define specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "6" +#define NETWORK_STREAM_VERSION "7" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION #ifdef __cplusplus From 4860932fa1c579c888cc2b20a4b9fbf331945fea Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 5 Jun 2017 20:22:47 +0100 Subject: [PATCH 4/4] Update changelog [ci skip] --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index d8a3aa5359..1e22959b25 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -4,6 +4,7 @@ - Improved: Mouse can now be dragged to select scenery when saving track designs - Fix: [#3178, #5456] Paths with non-ASCII characters not handled properly on macOS. - Fix: [#3681] Steel Twister rollercoaster always shows all track designs +- Fix: [#5009] Ride rating calculations can overflow - Fix: Track components added by OpenRCT2 are now usable in older scenarios. - Technical: [#5458] Begin offering headless build with reduced compile- and run-time dependencies