1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-24 00:03:11 +01:00

Properly check 'Finish 5 roller coasters' criteria, fixes #597

This fixes the following things:
- The objective was not available when using money (despite it being used on such scenarios in RCT1)
- The scenario editor set the 'partially finished flag' on every single ride
- The scenario editor did not check if there were five finished roller coasters
- When checking the goal, there was no check if the ride was a roller coaster
- When checking the goal, there was no check if the ride was one of the roller coasters to be completed
This commit is contained in:
Gymnasiast
2017-06-29 14:00:51 +02:00
committed by Michael Steenbeek
parent 74a14505cd
commit 4e87ad6ac3
8 changed files with 131 additions and 76 deletions

View File

@@ -4430,7 +4430,7 @@ STR_6118 :A gentle roller coaster for people who haven't yet got the courage
STR_6119 :A cheap and easy to build roller coaster, but with a limited height
STR_6120 :{BABYBLUE}New vehicle now available for {STRINGID}:{NEWLINE}{STRINGID}
STR_6121 :{SMALLFONT}{BLACK}Extends the park's land rights all the way to the edges of the map
STR_6122 :There are not enough roller coasters in this scenario!
#############
# Scenarios #

View File

@@ -13,6 +13,7 @@
- Fix: [#259] Money making glitch involving swamps (original bug)
- Fix: [#441] Construction rights over entrance path erased (original bug)
- Fix: [#578] Ride ghosts show up in ride list during construction (original bug)
- Fix: [#597] 'Finish 5 roller coasters' goal not properly checked (original bug)
- Fix: [#739] Crocodile Ride (Log Flume) never allows more than five boats (original bug)
- Fix: [#837] Can't move windows on title screen to where the toolbar would be (original bug)
- Fix: [#1705] Time Twister's Medieval entrance has incorrect scrolling (original bug)

View File

@@ -3789,6 +3789,8 @@ enum {
STR_CHEAT_OWN_ALL_LAND_TIP = 6121,
STR_NOT_ENOUGH_ROLLER_COASTERS = 6122,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@@ -945,7 +945,7 @@ static money32 track_place(sint32 rideIndex, sint32 type, sint32 originX, sint32
uint64 enabledTrackPieces = rideEntry->enabledTrackPieces & RideTypePossibleTrackConfigurations[ride->type];
uint32 rideTypeFlags = RideProperties[ride->type].flags;
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && type == 1) {
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && type == TRACK_ELEM_END_STATION) {
gGameCommandErrorText = STR_NOT_ALLOWED_TO_MODIFY_STATION;
return MONEY32_UNDEFINED;
}
@@ -1508,7 +1508,7 @@ static money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 o
return MONEY32_UNDEFINED;
}
if (mapElement->flags & (1 << 6)){
if (mapElement->flags & MAP_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE){
gGameCommandErrorText = STR_YOU_ARE_NOT_ALLOWED_TO_REMOVE_THIS_SECTION;
return MONEY32_UNDEFINED;
}

View File

@@ -660,38 +660,78 @@ uint32 scenario_rand_max(uint32 max)
* Prepare rides, for the finish five rollercoasters objective.
* rct2: 0x006788F7
*/
static void scenario_prepare_rides_for_save()
static bool scenario_prepare_rides_for_save()
{
sint32 isFiveCoasterObjective = gScenarioObjectiveType == OBJECTIVE_FINISH_5_ROLLERCOASTERS;
sint32 i;
rct_ride * ride;
uint8 rcs = 0;
// Set all existing track to be indestructible
FOR_ALL_RIDES(i, ride)
{
const rct_ride_entry * rideEntry = get_ride_entry(ride->subtype);
// If there are more than 5 roller coasters, only mark the first five.
if (isFiveCoasterObjective &&
rideEntry != NULL &&
((rideEntry->category[0] == RIDE_GROUP_ROLLERCOASTER || rideEntry->category[1] == RIDE_GROUP_ROLLERCOASTER) &&
rcs < 5))
{
ride->lifecycle_flags |= RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK;
rcs++;
}
else
{
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK;
}
}
if (isFiveCoasterObjective && rcs < 5)
{
gGameCommandErrorText = STR_NOT_ENOUGH_ROLLER_COASTERS;
return false;
}
bool markTrackAsIndestructible;
map_element_iterator it;
map_element_iterator_begin(&it);
do {
if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_TRACK) {
if (isFiveCoasterObjective)
it.element->flags |= 0x40;
else
it.element->flags &= ~0x40;
}
} while (map_element_iterator_next(&it));
do
{
if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_TRACK)
{
markTrackAsIndestructible = false;
// Set all existing rides to have indestructible track
sint32 i;
rct_ride *ride;
FOR_ALL_RIDES(i, ride) {
if (isFiveCoasterObjective)
ride->lifecycle_flags |= RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK;
else
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK;
if (isFiveCoasterObjective)
{
ride = get_ride(it.element->properties.track.ride_index);
// In the previous step, this flag was set on the first five roller coasters.
if (ride != NULL && ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK)
{
markTrackAsIndestructible = true;
}
}
if (markTrackAsIndestructible)
{
it.element->flags |= MAP_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE;
}
else
{
it.element->flags &= ~MAP_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE;
}
}
}
while (map_element_iterator_next(&it));
return true;
}
/**
*
* rct2: 0x006726C7
*/
sint32 scenario_prepare_for_save()
bool scenario_prepare_for_save()
{
gS6Info.entry.flags = 255;
@@ -712,7 +752,11 @@ sint32 scenario_prepare_for_save()
gS6Info.objective_arg_2 = gScenarioObjectiveCurrency;
gS6Info.objective_arg_3 = gScenarioObjectiveNumGuests;
scenario_prepare_rides_for_save();
// This can return false if the goal is 'Finish 5 roller coaster' and there are too few.
if (!scenario_prepare_rides_for_save())
{
return false;
}
if (gScenarioObjectiveType == OBJECTIVE_GUESTS_AND_RATING)
gParkFlags |= PARK_FLAGS_PARK_OPEN;
@@ -720,7 +764,7 @@ sint32 scenario_prepare_for_save()
// Fix #2385: saved scenarios did not initialise temperatures to selected climate
climate_reset(gClimate);
return 1;
return true;
}
/**
@@ -972,15 +1016,25 @@ static void scenario_objective_check_finish_5_rollercoasters()
{
money32 objectiveRideExcitement = gScenarioObjectiveCurrency;
// ORIGINAL BUG?:
// This does not check if the rides are even rollercoasters nevermind the right rollercoasters to be finished.
// It also did not exclude null rides.
// Originally, this did not check for null rides, neither did it check if
// the rides are even rollercoasters, never mind the right rollercoasters to be finished.
sint32 i;
rct_ride* ride;
rct_ride * ride;
sint32 rcs = 0;
FOR_ALL_RIDES(i, ride)
if (ride->status != RIDE_STATUS_CLOSED && ride->excitement >= objectiveRideExcitement)
{
const rct_ride_entry * rideEntry = get_ride_entry(ride->subtype);
if (rideEntry == NULL)
{
continue;
}
if (ride->status != RIDE_STATUS_CLOSED &&
ride->excitement >= objectiveRideExcitement &&
(ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && // Set on partially finished coasters
(rideEntry->category[0] == RIDE_GROUP_ROLLERCOASTER || rideEntry->category[1] == RIDE_GROUP_ROLLERCOASTER))
rcs++;
}
if (rcs >= 5)
scenario_success();

View File

@@ -405,7 +405,7 @@ uint32 scenario_rand();
uint32 scenario_rand_max(uint32 max);
sint32 scenario_prepare_for_save();
bool scenario_prepare_for_save();
sint32 scenario_save(const utf8 * path, sint32 flags);
void scenario_remove_trackless_rides(rct_s6_data *s6);
void scenario_fix_ghosts(rct_s6_data *s6);

View File

@@ -440,62 +440,58 @@ static void window_editor_objective_options_main_resize(rct_window *w)
static void window_editor_objective_options_show_objective_dropdown(rct_window *w)
{
sint32 i, numItems, objectiveType;
sint32 numItems = 0, objectiveType;
rct_widget *dropdownWidget;
uint32 parkFlags;
dropdownWidget = &w->widgets[WIDX_OBJECTIVE];
parkFlags = gParkFlags;
numItems = 0;
if (!(parkFlags & PARK_FLAGS_NO_MONEY_SCENARIO)) {
numItems += 2;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_HAVE_FUN;
numItems++;
if (!(parkFlags & PARK_FLAGS_NO_MONEY_SCENARIO))
{
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_AT_A_GIVEN_DATE;
numItems++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_MONTHLY_PROFIT_FROM_FOOD_MERCHANDISE;
numItems++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_REPAY_LOAN_AND_ACHIEVE_A_GIVEN_PARK_VALUE;
numItems++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_PARK_VALUE_AT_A_GIVEN_DATE;
numItems++;
if (parkFlags & PARK_FLAGS_PARK_FREE_ENTRY)
{
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_MONTHLY_INCOME_FROM_RIDE_TICKETS;
numItems++;
}
numItems += 5;
i = 0;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_HAVE_FUN;
i++;
if (!(parkFlags & PARK_FLAGS_NO_MONEY_SCENARIO)) {
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_AT_A_GIVEN_DATE;
i++;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_MONTHLY_PROFIT_FROM_FOOD_MERCHANDISE;
i++;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_REPAY_LOAN_AND_ACHIEVE_A_GIVEN_PARK_VALUE;
i++;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_PARK_VALUE_AT_A_GIVEN_DATE;
i++;
if (parkFlags & PARK_FLAGS_PARK_FREE_ENTRY) {
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_MONTHLY_INCOME_FROM_RIDE_TICKETS;
i++;
}
}
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_IN_PARK;
i++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_IN_PARK;
numItems++;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS;
i++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS;
numItems++;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS_OF_A_GIVEN_LENGTH;
i++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS_OF_A_GIVEN_LENGTH;
numItems++;
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = STR_OBJECTIVE_DROPDOWN_FINISH_BUILDING_5_ROLLER_COASTERS;
i++;
gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[numItems] = STR_OBJECTIVE_DROPDOWN_FINISH_BUILDING_5_ROLLER_COASTERS;
numItems++;
window_dropdown_show_text_custom_width(
w->x + dropdownWidget->left,
@@ -509,9 +505,11 @@ static void window_editor_objective_options_show_objective_dropdown(rct_window *
);
objectiveType = gScenarioObjectiveType;
for (i = 0; i < numItems; i++) {
if (gDropdownItemsArgs[i] - STR_OBJECTIVE_DROPDOWN_NONE == objectiveType) {
dropdown_set_checked(i, true);
for (sint32 j = 0; j < numItems; j++)
{
if (gDropdownItemsArgs[j] - STR_OBJECTIVE_DROPDOWN_NONE == objectiveType)
{
dropdown_set_checked(j, true);
break;
}
}

View File

@@ -155,7 +155,7 @@ enum {
MAP_ELEMENT_FLAG_GHOST = (1 << 4),
MAP_ELEMENT_FLAG_BROKEN = (1 << 5),
MAP_ELEMENT_FLAG_BLOCK_BRAKE_CLOSED = (1 << 5),
MAP_ELEMENT_FLAG_CANNOT_REMOVE_TRACK = (1 << 6),
MAP_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE = (1 << 6),
MAP_ELEMENT_FLAG_LAST_TILE = (1 << 7)
};