From 6f28914f61c746aee581fac040fa9d35a6cbd96a Mon Sep 17 00:00:00 2001 From: Maximilian Bottin Date: Thu, 18 Mar 2021 20:30:11 +0100 Subject: [PATCH] Fix #14296: Allow early scenario completion in multiplayer --- src/openrct2-ui/windows/Options.cpp | 17 ++++++++++++ .../actions/ScenarioSetSettingAction.cpp | 4 +++ .../actions/ScenarioSetSettingAction.h | 1 + src/openrct2/network/NetworkBase.cpp | 4 ++- src/openrct2/scenario/Scenario.cpp | 27 ++++++++++++++----- src/openrct2/scenario/Scenario.h | 3 ++- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index c8b8b6269a..f8e20dda26 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1793,6 +1794,14 @@ static void window_options_misc_mouseup(rct_window* w, rct_widgetindex widgetInd break; case WIDX_ALLOW_EARLY_COMPLETION: gConfigGeneral.allow_early_completion ^= 1; + // Only the server can control this setting and needs to send the + // current value of allow_early_completion to all clients + if (network_get_mode() == NETWORK_MODE_SERVER) + { + auto setAllowEarlyCompletionAction = ScenarioSetSettingAction( + ScenarioSetSetting::AllowEarlyCompletion, gConfigGeneral.allow_early_completion); + GameActions::Execute(&setAllowEarlyCompletionAction); + } config_save_default(); w->Invalidate(); break; @@ -1898,6 +1907,14 @@ static void window_options_misc_invalidate(rct_window* w) { w->disabled_widgets |= (1ULL << WIDX_REAL_NAME_CHECKBOX); window_options_misc_widgets[WIDX_REAL_NAME_CHECKBOX].tooltip = STR_OPTION_DISABLED_DURING_NETWORK_PLAY; + // Disable the use of the allow_early_completion option during network play on clients. + // This is to prevent confusion on clients because changing this setting during network play wouldn't change + // the way scenarios are completed during this network-session + if (network_get_mode() == NETWORK_MODE_CLIENT) + { + w->disabled_widgets |= (1ULL << WIDX_ALLOW_EARLY_COMPLETION); + window_options_misc_widgets[WIDX_ALLOW_EARLY_COMPLETION].tooltip = STR_OPTION_DISABLED_DURING_NETWORK_PLAY; + } } WidgetSetCheckboxValue(w, WIDX_REAL_NAME_CHECKBOX, gConfigGeneral.show_real_names_of_guests); diff --git a/src/openrct2/actions/ScenarioSetSettingAction.cpp b/src/openrct2/actions/ScenarioSetSettingAction.cpp index 4ae585d2d4..6bd4291e86 100644 --- a/src/openrct2/actions/ScenarioSetSettingAction.cpp +++ b/src/openrct2/actions/ScenarioSetSettingAction.cpp @@ -13,6 +13,7 @@ #include "../interface/Window.h" #include "../management/Finance.h" #include "../peep/Peep.h" +#include "../scenario/Scenario.h" #include "../util/Util.h" #include "../world/Park.h" @@ -236,6 +237,9 @@ GameActions::Result::Ptr ScenarioSetSettingAction::Execute() const gParkFlags &= ~PARK_FLAGS_DIFFICULT_GUEST_GENERATION; } break; + case ScenarioSetSetting::AllowEarlyCompletion: + gAllowEarlyCompletionInNetworkPlay = _value; + break; default: log_error("Invalid setting: %u", _setting); return MakeResult(GameActions::Status::InvalidParameters, STR_NONE); diff --git a/src/openrct2/actions/ScenarioSetSettingAction.h b/src/openrct2/actions/ScenarioSetSettingAction.h index ef9e44805f..625418696a 100644 --- a/src/openrct2/actions/ScenarioSetSettingAction.h +++ b/src/openrct2/actions/ScenarioSetSettingAction.h @@ -34,6 +34,7 @@ enum class ScenarioSetSetting : uint8_t ForbidHighConstruction, ParkRatingHigherDifficultyLevel, GuestGenerationHigherDifficultyLevel, + AllowEarlyCompletion, Count }; diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 632e9ff58e..ff26bfdd3f 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -36,7 +36,7 @@ // This string 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 "3" +#define NETWORK_STREAM_VERSION "4" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; @@ -2754,6 +2754,7 @@ bool NetworkBase::LoadMap(IStream* stream) gCheatsDisableRideValueAging = stream->ReadValue() != 0; gConfigGeneral.show_real_names_of_guests = stream->ReadValue() != 0; gCheatsIgnoreResearchStatus = stream->ReadValue() != 0; + gAllowEarlyCompletionInNetworkPlay = stream->ReadValue() != 0; gLastAutoSaveUpdate = AUTOSAVE_PAUSE; result = true; @@ -2803,6 +2804,7 @@ bool NetworkBase::SaveMap(IStream* stream, const std::vectorWriteValue(gCheatsDisableRideValueAging); stream->WriteValue(gConfigGeneral.show_real_names_of_guests); stream->WriteValue(gCheatsIgnoreResearchStatus); + stream->WriteValue(gConfigGeneral.allow_early_completion); result = true; } diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index a4b845ea9a..456fd0f929 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -73,6 +73,7 @@ random_engine_t gScenarioRand; Objective gScenarioObjective; +bool gAllowEarlyCompletionInNetworkPlay; uint16_t gScenarioParkRatingWarningDays; money32 gScenarioCompletedCompanyValue; money32 gScenarioCompanyValueRecord; @@ -288,7 +289,6 @@ static void scenario_day_update() { finance_update_daily_profit(); peep_update_days_in_queue(); - bool allowEarlyCompletion = gConfigGeneral.allow_early_completion && (network_get_mode() == NETWORK_MODE_NONE); switch (gScenarioObjective.Type) { case OBJECTIVE_10_ROLLERCOASTERS: @@ -299,7 +299,7 @@ static void scenario_day_update() scenario_objective_check(); break; default: - if (allowEarlyCompletion) + if (AllowEarlyCompletion()) scenario_objective_check(); break; } @@ -713,9 +713,8 @@ ObjectiveStatus Objective::CheckGuestsBy() const { int16_t parkRating = gParkRating; int32_t currentMonthYear = gDateMonthsElapsed; - bool allowEarlyCompletion = gConfigGeneral.allow_early_completion && (network_get_mode() == NETWORK_MODE_NONE); - if (currentMonthYear == MONTH_COUNT * Year || allowEarlyCompletion) + if (currentMonthYear == MONTH_COUNT * Year || AllowEarlyCompletion()) { if (parkRating >= 600 && gNumGuestsInPark >= NumGuests) { @@ -735,9 +734,8 @@ ObjectiveStatus Objective::CheckParkValueBy() const int32_t currentMonthYear = gDateMonthsElapsed; money32 objectiveParkValue = Currency; money32 parkValue = gParkValue; - bool allowEarlyCompletion = gConfigGeneral.allow_early_completion && (network_get_mode() == NETWORK_MODE_NONE); - if (currentMonthYear == MONTH_COUNT * Year || allowEarlyCompletion) + if (currentMonthYear == MONTH_COUNT * Year || AllowEarlyCompletion()) { if (parkValue >= objectiveParkValue) { @@ -944,6 +942,23 @@ ObjectiveStatus Objective::CheckMonthlyFoodIncome() const return ObjectiveStatus::Undecided; } +/* + * Returns the AllowEarlyCompletion-Option to be used + * depending on the Current Network-Mode. + */ +bool AllowEarlyCompletion() +{ + switch (network_get_mode()) + { + case NETWORK_MODE_CLIENT: + return gAllowEarlyCompletionInNetworkPlay; + case NETWORK_MODE_NONE: + case NETWORK_MODE_SERVER: + default: + return gConfigGeneral.allow_early_completion; + } +} + static void scenario_objective_check() { auto status = gScenarioObjective.Check(); diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index 5174ab3518..cb3daaf3dd 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -431,7 +431,7 @@ extern uint32_t gScenarioTicks; extern random_engine_t gScenarioRand; extern Objective gScenarioObjective; - +extern bool gAllowEarlyCompletionInNetworkPlay; extern uint16_t gScenarioParkRatingWarningDays; extern money32 gScenarioCompletedCompanyValue; extern money32 gScenarioCompanyValueRecord; @@ -452,6 +452,7 @@ void load_from_sc6(const char* path); void scenario_begin(); void scenario_update(); bool scenario_create_ducks(); +bool AllowEarlyCompletion(); const random_engine_t::state_type& scenario_rand_state(); void scenario_rand_seed(random_engine_t::result_type s0, random_engine_t::result_type s1);