diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 7290414c00..f84112be17 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -27,6 +27,7 @@ #include "tile_map.h" #include "newgrf.h" #include "error.h" +#include "network/network.h" #include "widgets/cheat_widget.h" @@ -147,20 +148,6 @@ static int32 ClickChangeMaxHlCheat(int32 p1, int32 p2) return _settings_game.construction.max_heightlevel; } -/** Available cheats. */ -enum CheatNumbers { - CHT_MONEY, ///< Change amount of money. - CHT_CHANGE_COMPANY, ///< Switch company. - CHT_EXTRA_DYNAMITE, ///< Dynamite anything. - CHT_CROSSINGTUNNELS, ///< Allow tunnels to cross each other. - CHT_NO_JETCRASH, ///< Disable jet-airplane crashes. - CHT_SETUP_PROD, ///< Allow manually editing of industry production. - CHT_EDIT_MAX_HL, ///< Edit maximum allowed heightlevel - CHT_CHANGE_DATE, ///< Do time traveling. - - CHT_NUM_CHEATS, ///< Number of cheats. -}; - /** * Signature of handler function when user clicks at a cheat. * @param p1 The new value. @@ -168,8 +155,14 @@ enum CheatNumbers { */ typedef int32 CheckButtonClick(int32 p1, int32 p2); +enum CheatNetworkMode { + CNM_ALL, + CNM_LOCAL_ONLY, +}; + /** Information of a cheat. */ struct CheatEntry { + CheatNetworkMode mode; ///< network/local mode VarType type; ///< type of selector StringID str; ///< string with descriptive text void *variable; ///< pointer to the variable @@ -182,14 +175,14 @@ struct CheatEntry { * Order matches with the values of #CheatNumbers */ static const CheatEntry _cheats_ui[] = { - {SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat }, - {SLE_UINT8, STR_CHEAT_CHANGE_COMPANY, &_local_company, &_cheats.switch_company.been_used, &ClickChangeCompanyCheat }, - {SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, nullptr }, - {SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, nullptr }, - {SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr }, - {SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat }, - {SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.max_heightlevel, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat }, - {SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, + {CNM_LOCAL_ONLY, SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat }, + {CNM_LOCAL_ONLY, SLE_UINT8, STR_CHEAT_CHANGE_COMPANY, &_local_company, &_cheats.switch_company.been_used, &ClickChangeCompanyCheat }, + {CNM_ALL, SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, nullptr }, + {CNM_ALL, SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, nullptr }, + {CNM_ALL, SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr }, + {CNM_LOCAL_ONLY, SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat }, + {CNM_LOCAL_ONLY, SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.max_heightlevel, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat }, + {CNM_LOCAL_ONLY, SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, }; assert_compile(CHT_NUM_CHEATS == lengthof(_cheats_ui)); @@ -237,6 +230,7 @@ struct CheatWindow : Window { for (int i = 0; i != lengthof(_cheats_ui); i++) { const CheatEntry *ce = &_cheats_ui[i]; + if (_networking && ce->mode == CNM_LOCAL_ONLY) continue; DrawSprite((*ce->been_used) ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, box_left, y + icon_y_offset + 2); @@ -286,8 +280,11 @@ struct CheatWindow : Window { if (widget != WID_C_PANEL) return; uint width = 0; + uint lines = 0; for (int i = 0; i != lengthof(_cheats_ui); i++) { const CheatEntry *ce = &_cheats_ui[i]; + if (_networking && ce->mode == CNM_LOCAL_ONLY) continue; + lines++; switch (ce->type) { case SLE_BOOL: SetDParam(0, STR_CONFIG_SETTING_ON); @@ -325,7 +322,7 @@ struct CheatWindow : Window { size->width = width + 20 + this->box_width + SETTING_BUTTON_WIDTH /* stuff on the left */ + 10 /* extra spacing on right */; this->header_height = GetStringHeight(STR_CHEATS_WARNING, size->width - WD_FRAMERECT_LEFT - WD_FRAMERECT_RIGHT) + WD_PAR_VSEP_WIDE; - size->height = this->header_height + WD_FRAMERECT_TOP + WD_PAR_VSEP_NORMAL + WD_FRAMERECT_BOTTOM + this->line_height * lengthof(_cheats_ui); + size->height = this->header_height + WD_FRAMERECT_TOP + WD_PAR_VSEP_NORMAL + WD_FRAMERECT_BOTTOM + this->line_height * lines; } void OnClick(Point pt, int widget, int click_count) override @@ -336,6 +333,11 @@ struct CheatWindow : Window { bool rtl = _current_text_dir == TD_RTL; if (rtl) x = wid->current_x - x; + for (uint i = 0; i != lengthof(_cheats_ui) && i <= btn; i++) { + const CheatEntry *ce = &_cheats_ui[i]; + if (_networking && ce->mode == CNM_LOCAL_ONLY) btn++; + } + if (btn >= lengthof(_cheats_ui)) return; const CheatEntry *ce = &_cheats_ui[btn]; @@ -358,12 +360,12 @@ struct CheatWindow : Window { /* Not clicking a button? */ if (!IsInsideMM(x, 10 + this->box_width, 10 + this->box_width + SETTING_BUTTON_WIDTH)) return; - *ce->been_used = true; + if (!_networking) *ce->been_used = true; switch (ce->type) { case SLE_BOOL: value ^= 1; - if (ce->proc != nullptr) ce->proc(value, 0); + if (ce->proc != nullptr && !_networking) ce->proc(value, 0); break; default: @@ -375,7 +377,13 @@ struct CheatWindow : Window { break; } - if (value != oldvalue) WriteValue(ce->variable, ce->type, (int64)value); + if (value != oldvalue) { + if (_networking) { + DoCommandP(0, (uint32)btn, (uint32)value, CMD_CHEAT_SETTING); + } else { + WriteValue(ce->variable, ce->type, (int64)value); + } + } this->SetTimeout(); @@ -390,6 +398,8 @@ struct CheatWindow : Window { void OnQueryTextFinished(char *str) override { + if (_networking) return; + /* Was 'cancel' pressed or nothing entered? */ if (str == nullptr || StrEmpty(str)) return; diff --git a/src/cheat_type.h b/src/cheat_type.h index 3d70d527f9..d8ebc1143e 100644 --- a/src/cheat_type.h +++ b/src/cheat_type.h @@ -37,6 +37,20 @@ struct Cheats { Cheat edit_max_hl; ///< edit the maximum heightlevel; this is a cheat because of the fact that it needs to reset NewGRF game state and doing so as a simple configuration breaks the expectation of many }; +/** Available cheats. */ +enum CheatNumbers { + CHT_MONEY, ///< Change amount of money. + CHT_CHANGE_COMPANY, ///< Switch company. + CHT_EXTRA_DYNAMITE, ///< Dynamite anything. + CHT_CROSSINGTUNNELS, ///< Allow tunnels to cross each other. + CHT_NO_JETCRASH, ///< Disable jet-airplane crashes. + CHT_SETUP_PROD, ///< Allow manually editing of industry production. + CHT_EDIT_MAX_HL, ///< Edit maximum allowed heightlevel + CHT_CHANGE_DATE, ///< Do time traveling. + + CHT_NUM_CHEATS, ///< Number of cheats. +}; + extern Cheats _cheats; #endif /* CHEAT_TYPE_H */ diff --git a/src/command.cpp b/src/command.cpp index 4f214f7e77..72bdc5fc8a 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -160,6 +160,7 @@ CommandProc CmdClearArea; CommandProc CmdGiveMoney; CommandProc CmdMoneyCheat; CommandProc CmdChangeBankBalance; +CommandProc CmdCheatSetting; CommandProc CmdBuildCanal; CommandProc CmdBuildLock; @@ -380,6 +381,7 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdMoneyCheat, CMD_OFFLINE, CMDT_CHEAT ), // CMD_MONEY_CHEAT DEF_CMD(CmdChangeBankBalance, CMD_DEITY, CMDT_MONEY_MANAGEMENT ), // CMD_CHANGE_BANK_BALANCE + DEF_CMD(CmdCheatSetting, CMD_SERVER, CMDT_CHEAT ), // CMD_CHEAT_SETTING DEF_CMD(CmdBuildCanal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_CANAL DEF_CMD(CmdCreateSubsidy, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_SUBSIDY DEF_CMD(CmdCompanyCtrl, CMD_SPECTATOR | CMD_CLIENT_ID | CMD_NO_EST, CMDT_SERVER_SETTING ), // CMD_COMPANY_CTRL diff --git a/src/command_type.h b/src/command_type.h index b461f25958..59c9a052b0 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -318,6 +318,7 @@ enum Commands { CMD_MONEY_CHEAT, ///< do the money cheat CMD_CHANGE_BANK_BALANCE, ///< change bank balance to charge costs or give money from a GS + CMD_CHEAT_SETTING, ///< change a cheat setting CMD_BUILD_CANAL, ///< build a canal CMD_CREATE_SUBSIDY, ///< create a new subsidy diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index 3e7bf25c69..0ba0c9673e 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -20,6 +20,7 @@ #include "company_gui.h" #include "company_base.h" #include "core/backup_type.hpp" +#include "cheat_type.h" #include "table/strings.h" @@ -200,6 +201,42 @@ CommandCost CmdMoneyCheat(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 return CommandCost(EXPENSES_OTHER, -(int32)p1); } +/** + * Change the value of a cheat setting. + * @param tile unused + * @param flags operation to perform + * @param p1 the cheat number + * @param p2 the cheat value + * @param text unused + * @return the cost of this operation or an error + */ +CommandCost CmdCheatSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + Cheat *cht = nullptr; + switch ((CheatNumbers) p1) { + case CHT_EXTRA_DYNAMITE: + cht = &_cheats.magic_bulldozer; + break; + + case CHT_CROSSINGTUNNELS: + cht = &_cheats.crossing_tunnels; + break; + + case CHT_NO_JETCRASH: + cht = &_cheats.no_jetcrash; + break; + + default: + return CMD_ERROR; + } + if (flags & DC_EXEC) { + cht->value = p2; + cht->been_used = true; + SetWindowDirty(WC_CHEATS, 0); + } + return CommandCost(); +} + /** * Change the bank bank balance of a company by inserting or removing money without affecting the loan. * @param tile unused diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 1700954850..b53bf38e9d 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1286,6 +1286,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SETTINGS_ACCESS _network_settings_access = p->Recv_bool(); + DeleteWindowById(WC_CHEATS, 0); ReInitAllWindows(); return NETWORK_RECV_STATUS_OKAY; diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index e12d1c618b..62a5714405 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2154,7 +2154,7 @@ struct MainToolbarWindow : Window { case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickScreenshot(SC_ZOOMEDIN); break; case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickScreenshot(SC_DEFAULTZOOM); break; case MTHK_GIANT_SCREENSHOT: MenuClickScreenshot(SC_WORLD); break; - case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break; + case MTHK_CHEATS: if (!_networking || _network_server || _network_settings_access) ShowCheatWindow(); break; case MTHK_TERRAFORM: ShowTerraformToolbar(); break; case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break; case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;