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:
committed by
Michael Steenbeek
parent
74a14505cd
commit
4e87ad6ac3
@@ -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 #
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user