diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 4d1b1b7526..b126cb1b2f 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -171,7 +171,7 @@ static int32_t ClickChangeMaxHlCheat(int32_t new_value, int32_t) enum CheatNumbers { CHT_MONEY, ///< Change amount of money. CHT_CHANGE_COMPANY, ///< Switch company. - CHT_EXTRA_DYNAMITE, ///< Dynamite anything. + CHT_EXTRA_DYNAMITE, ///< UNUSED: 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. @@ -205,7 +205,6 @@ struct CheatEntry { 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 }, @@ -214,7 +213,7 @@ static const CheatEntry _cheats_ui[] = { {SLE_INT32, STR_CHEAT_CHANGE_DATE, &TimerGameCalendar::year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, }; -static_assert(CHT_NUM_CHEATS == lengthof(_cheats_ui)); +static_assert(CHT_NUM_CHEATS == lengthof(_cheats_ui) + 1); // Removed from the UI: Magic Bulldozer. /** Widget definitions of the cheat GUI. */ static constexpr NWidgetPart _nested_cheat_widgets[] = { diff --git a/src/cheat_type.h b/src/cheat_type.h index 8c5dc981b1..2679ee67c4 100644 --- a/src/cheat_type.h +++ b/src/cheat_type.h @@ -24,7 +24,7 @@ struct Cheat { * Only add new entries at the end of the struct! */ struct Cheats { - Cheat magic_bulldozer; ///< dynamite industries, objects + Cheat magic_bulldozer; ///< REMOVED: dynamite industries, objects Cheat switch_company; ///< change to another company Cheat money; ///< get rich or poor Cheat crossing_tunnels; ///< allow tunnels that cross each other diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 9039c8c60f..6310bada03 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -493,13 +493,33 @@ static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags) Industry *i = Industry::GetByTile(tile); const IndustrySpec *indspec = GetIndustrySpec(i->type); + /* Check if the player can bulldoze the industry. */ + bool bulldoze_allowed = _settings_game.construction.bulldoze_industries; + if (bulldoze_allowed) { + /* Don't bulldoze industries that have recently had any cargo transported...*/ + for (const auto &p : i->produced) { + if (p.history[LAST_MONTH].PctTransported() > 0) { + bulldoze_allowed = false; + break; + } + } + + /* ...or received. */ + for (const auto &a : i->accepted) { + if (a.last_accepted + EconomyTime::DAYS_IN_ECONOMY_YEAR > TimerGameEconomy::date) { + bulldoze_allowed = false; + break; + } + } + } + /* water can destroy industries * in editor you can bulldoze industries * with magic_bulldozer cheat you can destroy industries * (area around OILRIG is water, so water shouldn't flood it */ if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR && - !_cheats.magic_bulldozer.value) || + !bulldoze_allowed) || ((flags & DC_AUTO) != 0) || (_current_company == OWNER_WATER && ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) || diff --git a/src/lang/english.txt b/src/lang/english.txt index ede50e8dda..fc82859d89 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1399,6 +1399,12 @@ STR_CONFIG_SETTING_INDUSTRY_PLATFORM_HELPTEXT :Amount of flat STR_CONFIG_SETTING_MULTIPINDTOWN :Allow multiple similar industries per town: {STRING2} STR_CONFIG_SETTING_MULTIPINDTOWN_HELPTEXT :Normally, a town does not want more than one industry of each type. With this setting, it will allow several industries of the same type in the same town +STR_CONFIG_SETTING_BULLDOZE_INDUSTRIES :Allow bulldozing unserved industries +STR_CONFIG_SETTING_BULLDOZE_INDUSTRIES_HELPTEXT :Allow industries to be demolished if 0% of their output is currently being transported + +STR_CONFIG_SETTING_BULLDOZE_OBJECTS :Allow bulldozing immovable objects +STR_CONFIG_SETTING_BULLDOZE_OBJECTS_HELPTEXT :Allow lighthouses, transmitters, and NewGRF objects to be demolished + STR_CONFIG_SETTING_SIGNALSIDE :Show signals: {STRING2} STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :Select on which side of the track to place signals ###length 3 diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index d4f28477b9..59b8fed6c9 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -566,13 +566,13 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags) /* No further limitations for the editor. */ } else if (GetTileOwner(tile) == OWNER_NONE) { /* Owned by nobody and unremovable, so we can only remove it with brute force! */ - if (!_cheats.magic_bulldozer.value && (spec->flags & OBJECT_FLAG_CANNOT_REMOVE) != 0) return CMD_ERROR; + if (!_settings_game.construction.bulldoze_objects && (spec->flags & OBJECT_FLAG_CANNOT_REMOVE) != 0) return CMD_ERROR; } else if (CheckTileOwnership(tile).Failed()) { /* We don't own it!. */ return CommandCost(STR_ERROR_OWNED_BY); } else if ((spec->flags & OBJECT_FLAG_CANNOT_REMOVE) != 0 && (spec->flags & OBJECT_FLAG_AUTOREMOVE) == 0) { - /* In the game editor or with cheats we can remove, otherwise we can't. */ - if (!_cheats.magic_bulldozer.value) { + /* We might be allowed to remove immovable objects. */ + if (!_settings_game.construction.bulldoze_objects) { if (type == OBJECT_HQ) return CommandCost(STR_ERROR_COMPANY_HEADQUARTERS_IN); return CMD_ERROR; } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 27b1283840..24064993f9 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -279,8 +279,6 @@ CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, R if (!town_check) return CommandCost(); - if (_cheats.magic_bulldozer.value) return CommandCost(); - Town *t = ClosestTownFromTile(tile, UINT_MAX); if (t == nullptr) return CommandCost(); diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index ef1d43c9cd..765aaf0262 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -17,8 +17,8 @@ #include "../safeguards.h" static const SaveLoad _cheats_desc[] = { - SLE_VAR(Cheats, magic_bulldozer.been_used, SLE_BOOL), - SLE_VAR(Cheats, magic_bulldozer.value, SLE_BOOL), + SLE_CONDVAR(Cheats, magic_bulldozer.been_used, SLE_BOOL, SL_MIN_VERSION, SLV_REMOVE_MAGIC_BULLDOZER), + SLE_CONDVAR(Cheats, magic_bulldozer.value, SLE_BOOL, SL_MIN_VERSION, SLV_REMOVE_MAGIC_BULLDOZER), SLE_VAR(Cheats, switch_company.been_used, SLE_BOOL), SLE_VAR(Cheats, switch_company.value, SLE_BOOL), SLE_VAR(Cheats, money.been_used, SLE_BOOL), diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 8caa133ef8..6d510d6b51 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -395,6 +395,7 @@ enum SaveLoadVersion : uint16_t { SLV_PATH_CACHE_FORMAT, ///< 346 PR#12345 Vehicle path cache format changed. SLV_ANIMATED_TILE_STATE_IN_MAP, ///< 347 PR#13082 Animated tile state saved for improved performance. SLV_INCREASE_HOUSE_LIMIT, ///< 348 PR#12288 Increase house limit to 4096. + SLV_REMOVE_MAGIC_BULLDOZER, ///< 349 PR#13265 Remove Magic Bulldozer cheat. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 5cac7581c2..4810684c74 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2150,6 +2150,8 @@ static SettingsContainer &GetSettingsTree() limitations->Add(new SettingEntry("construction.command_pause_level")); limitations->Add(new SettingEntry("construction.autoslope")); limitations->Add(new SettingEntry("construction.extra_dynamite")); + limitations->Add(new SettingEntry("construction.bulldoze_industries")); + limitations->Add(new SettingEntry("construction.bulldoze_objects")); limitations->Add(new SettingEntry("construction.map_height_limit")); limitations->Add(new SettingEntry("construction.max_bridge_length")); limitations->Add(new SettingEntry("construction.max_bridge_height")); diff --git a/src/settings_type.h b/src/settings_type.h index b086bc2950..a445fe0318 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -392,6 +392,8 @@ struct ConstructionSettings { bool crossing_with_competitor; ///< allow building of level crossings with competitor roads or rails uint8_t raw_industry_construction; ///< type of (raw) industry construction (none, "normal", prospecting) uint8_t industry_platform; ///< the amount of flat land around an industry + bool bulldoze_industries; ///< whether players can bulldozed unserved industries + bool bulldoze_objects; ///< whether objects can be bulldozed, even if immovable bool freeform_edges; ///< allow terraforming the tiles at the map edges uint8_t extra_tree_placement; ///< (dis)allow building extra trees in-game uint8_t command_pause_level; ///< level/amount of commands that can't be executed while paused diff --git a/src/table/settings/world_settings.ini b/src/table/settings/world_settings.ini index ab30a3e500..90938c287b 100644 --- a/src/table/settings/world_settings.ini +++ b/src/table/settings/world_settings.ini @@ -561,6 +561,20 @@ strhelp = STR_CONFIG_SETTING_INDUSTRY_PLATFORM_HELPTEXT strval = STR_CONFIG_SETTING_TILE_LENGTH cat = SC_EXPERT +[SDT_BOOL] +var = construction.bulldoze_industries +def = false +str = STR_CONFIG_SETTING_BULLDOZE_INDUSTRIES +strhelp = STR_CONFIG_SETTING_BULLDOZE_INDUSTRIES_HELPTEXT +cat = SC_BASIC + +[SDT_BOOL] +var = construction.bulldoze_objects +def = false +str = STR_CONFIG_SETTING_BULLDOZE_OBJECTS +strhelp = STR_CONFIG_SETTING_BULLDOZE_OBJECTS_HELPTEXT +cat = SC_BASIC + [SDT_BOOL] var = construction.freeform_edges from = SLV_111 diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 204268d1e6..a8f0ce889e 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -729,7 +729,7 @@ static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlag flags) if (Company::IsValidID(_current_company)) { if (rating > t->ratings[_current_company] && !(flags & DC_NO_TEST_TOWN_RATING) && - !_cheats.magic_bulldozer.value && _settings_game.difficulty.town_council_tolerance != TOWN_COUNCIL_PERMISSIVE) { + _settings_game.difficulty.town_council_tolerance != TOWN_COUNCIL_PERMISSIVE) { SetDParam(0, t->index); return CommandCost(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS); } @@ -3974,12 +3974,8 @@ static int GetRating(const Town *t) */ void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags) { - /* if magic_bulldozer cheat is active, town doesn't penalize for removing stuff */ - if (t == nullptr || (flags & DC_NO_MODIFY_TOWN_RATING) || - !Company::IsValidID(_current_company) || - (_cheats.magic_bulldozer.value && add < 0)) { - return; - } + if (t == nullptr || !Company::IsValidID(_current_company)) return; + if (flags & DC_NO_MODIFY_TOWN_RATING) return; int rating = GetRating(t); if (add < 0) { @@ -4011,11 +4007,8 @@ void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags) */ CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type) { - /* if magic_bulldozer cheat is active, town doesn't restrict your destructive actions */ - if (t == nullptr || !Company::IsValidID(_current_company) || - _cheats.magic_bulldozer.value || (flags & DC_NO_TEST_TOWN_RATING)) { - return CommandCost(); - } + if (t == nullptr || !Company::IsValidID(_current_company)) return CommandCost(); + if (flags & DC_NO_MODIFY_TOWN_RATING) return CommandCost(); /* minimum rating needed to be allowed to remove stuff */ static const int needed_rating[][TOWN_RATING_CHECK_TYPE_COUNT] = { diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 9ccf76e95c..a6bcc54784 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -811,7 +811,7 @@ static inline CommandCost CheckAllowRemoveTunnelBridge(TileIndex tile) if (tram_rt != INVALID_ROADTYPE) tram_owner = GetRoadOwner(tile, RTT_TRAM); /* We can remove unowned road and if the town allows it */ - if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) { + if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite)) { /* Town does not allow */ return CheckTileOwnership(tile); }