diff --git a/src/company_base.h b/src/company_base.h index 3f40af8387..0d2e0621b8 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -89,6 +89,7 @@ struct CompanyProperties { uint32 clear_limit; ///< Amount of tiles we can (still) clear (times 65536). uint32 tree_limit; ///< Amount of trees we can (still) plant (times 65536). uint32 purchase_land_limit; ///< Amount of tiles we can (still) purchase (times 65536). + uint32 build_object_limit; ///< Amount of tiles we can (still) build objects on (times 65536). /** * If \c true, the company is (also) controlled by the computer (a NoAI program). @@ -107,7 +108,7 @@ struct CompanyProperties { face(0), money(0), money_fraction(0), current_loan(0), colour(0), block_preview(0), location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0), months_of_bankruptcy(0), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0), - terraform_limit(0), clear_limit(0), tree_limit(0), purchase_land_limit(0), is_ai(false) {} + terraform_limit(0), clear_limit(0), tree_limit(0), purchase_land_limit(0), build_object_limit(0), is_ai(false) {} }; struct Company : CompanyPool::PoolItem<&_company_pool>, CompanyProperties { diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 0bd5dda5dc..82212abda8 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -66,6 +66,7 @@ Company::Company(uint16 name_1, bool is_ai) this->clear_limit = _settings_game.construction.clear_frame_burst << 16; this->tree_limit = _settings_game.construction.tree_frame_burst << 16; this->purchase_land_limit = _settings_game.construction.purchase_land_frame_burst << 16; + this->build_object_limit = _settings_game.construction.build_object_frame_burst << 16; for (uint j = 0; j < 4; j++) this->share_owners[j] = COMPANY_SPECTATOR; InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY); @@ -279,6 +280,7 @@ void UpdateLandscapingLimits() c->clear_limit = min(c->clear_limit + _settings_game.construction.clear_per_64k_frames, (uint32)_settings_game.construction.clear_frame_burst << 16); c->tree_limit = min(c->tree_limit + _settings_game.construction.tree_per_64k_frames, (uint32)_settings_game.construction.tree_frame_burst << 16); c->purchase_land_limit = min(c->purchase_land_limit + _settings_game.construction.purchase_land_per_64k_frames, (uint32)_settings_game.construction.purchase_land_frame_burst << 16); + c->build_object_limit = min(c->build_object_limit + _settings_game.construction.build_object_per_64k_frames, (uint32)_settings_game.construction.build_object_frame_burst << 16); } } diff --git a/src/lang/english.txt b/src/lang/english.txt index 724a72d498..027077fe0d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5561,6 +5561,7 @@ STR_ERROR_COMPANY_HEADQUARTERS_IN :{WHITE}... comp STR_ERROR_CAN_T_PURCHASE_THIS_LAND :{WHITE}Can't purchase this land area... STR_ERROR_YOU_ALREADY_OWN_IT :{WHITE}... you already own it! STR_ERROR_PURCHASE_LAND_LIMIT_REACHED :{WHITE}... land area purchasing limit reached +STR_ERROR_BUILD_OBJECT_LIMIT_REACHED :{WHITE}... object construction limit reached # Group related errors STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Can't create group... diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index 0b8f733eb9..83b834985d 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -304,11 +304,13 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 } int hq_score = 0; + int build_object_size = 0; Company *c = nullptr; switch (type) { case OBJECT_TRANSMITTER: case OBJECT_LIGHTHOUSE: if (!IsTileFlat(tile)) return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); + build_object_size = 1; break; case OBJECT_OWNED_LAND: @@ -344,8 +346,18 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 /* This may never be constructed using this method. */ return CMD_ERROR; - default: // i.e. NewGRF provided. + default: { // i.e. NewGRF provided. + const ObjectSpec *spec = ObjectSpec::Get(type); + build_object_size = GB(spec->size, 0, 4) * GB(spec->size, 4, 4); break; + } + } + + if (build_object_size > 0) { + c = Company::GetIfValid(_current_company); + if (c != nullptr && (int)GB(c->build_object_limit, 16, 16) < build_object_size) { + return_cmd_error(STR_ERROR_BUILD_OBJECT_LIMIT_REACHED); + } } if (flags & DC_EXEC) { @@ -355,6 +367,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (type == OBJECT_HQ) UpdateCompanyHQ(tile, hq_score); if (type == OBJECT_OWNED_LAND && c != nullptr) c->purchase_land_limit -= 1 << 16; + if (build_object_size > 0 && c != nullptr) c->build_object_limit -= build_object_size << 16; } cost.AddCost(ObjectSpec::Get(type)->GetBuildCost() * size_x * size_y); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index c13f5ab6ed..52ccff6e4b 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3750,6 +3750,13 @@ bool AfterLoadGame() } } + if (SlXvIsFeatureMissing(XSLFI_BUILD_OBJECT_RATE_LIMIT)) { + /* Introduced build object limit. */ + for (Company *c : Company::Iterate()) { + c->build_object_limit = _settings_game.construction.build_object_frame_burst << 16; + } + } + if (SlXvIsFeaturePresent(XSLFI_MORE_COND_ORDERS, 1, 1)) { for (Order *order : Order::Iterate()) { // Insertion of OCV_MAX_RELIABILITY between OCV_REMAINING_LIFETIME and OCV_CARGO_WAITING diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 60c3fa6c66..d5184712b1 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -293,6 +293,7 @@ static const SaveLoad _company_desc[] = { SLE_CONDVAR(CompanyProperties, clear_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION), SLE_CONDVAR(CompanyProperties, tree_limit, SLE_UINT32, SLV_175, SL_MAX_VERSION), SLE_CONDVAR_X(CompanyProperties, purchase_land_limit, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BUY_LAND_RATE_LIMIT)), + SLE_CONDVAR_X(CompanyProperties, build_object_limit, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BUILD_OBJECT_RATE_LIMIT)), SLE_END() }; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 4cd072185e..2186f7fa69 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -128,6 +128,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_EXTRA_CHEATS, XSCF_NULL, 1, 1, "extra_cheats", nullptr, nullptr, "CHTX" }, { XSLFI_TOWN_MULTI_BUILDING, XSCF_NULL, 1, 1, "town_multi_building", nullptr, nullptr, nullptr }, { XSLFI_SHIP_LOST_COUNTER, XSCF_NULL, 1, 1, "ship_lost_counter", nullptr, nullptr, nullptr }, + { XSLFI_BUILD_OBJECT_RATE_LIMIT,XSCF_NULL, 1, 1, "build_object_rate_limit", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 6b25e67757..c3e6ad9cbe 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -85,6 +85,7 @@ enum SlXvFeatureIndex { XSLFI_EXTRA_CHEATS, ///< Extra cheats XSLFI_TOWN_MULTI_BUILDING, ///< Allow multiple stadium/church buildings in a single town XSLFI_SHIP_LOST_COUNTER, ///< Ship lost counter + XSLFI_BUILD_OBJECT_RATE_LIMIT, ///< Build object rate limit XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/settings_type.h b/src/settings_type.h index be6b15ea85..995b750e30 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -400,6 +400,8 @@ struct ConstructionSettings { uint16 tree_frame_burst; ///< how many trees may, over a short period, be planted? uint32 purchase_land_per_64k_frames; ///< how many tiles may, over a long period, be purchased per 65536 frames? uint16 purchase_land_frame_burst; ///< how many tiles may, over a short period, be purchased? + uint32 build_object_per_64k_frames; ///< how many tiles may, over a long period, have objects built on them per 65536 frames? + uint16 build_object_frame_burst; ///< how many tiles may, over a short period, have objects built on them? uint8 tree_growth_rate; ///< tree growth rate }; diff --git a/src/table/settings.ini b/src/table/settings.ini index cc111e7d1f..2b2305bb57 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -651,6 +651,28 @@ interval = 1 cat = SC_EXPERT patxname = ""buy_land_rate_limit.construction.purchase_land_frame_burst"" +[SDT_VAR] +base = GameSettings +var = construction.build_object_per_64k_frames +type = SLE_UINT32 +def = 32 << 16 +min = 0 +max = 1 << 30 +interval = 1 +cat = SC_EXPERT +patxname = ""build_object_rate_limit.construction.build_object_per_64k_frames"" + +[SDT_VAR] +base = GameSettings +var = construction.build_object_frame_burst +type = SLE_UINT16 +def = 2048 +min = 0 +max = 1 << 30 +interval = 1 +cat = SC_EXPERT +patxname = ""build_object_rate_limit.construction.build_object_frame_burst"" + [SDT_BOOL] base = GameSettings var = construction.autoslope