Changeset - r16982:4a4e85b95d1e
[Not reviewed]
master
0 12 0
rubidium - 14 years ago 2011-01-04 22:50:09
rubidium@openttd.org
(svn r21728) -Fix/Feature [FS#4331]: (configurably) limit amount of tiles that can be cleared/terraformed by a company
12 files changed with 86 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/company_base.h
Show inline comments
 
@@ -66,12 +66,15 @@ struct CompanyProperties {
 

	
 
	byte quarters_of_bankruptcy;     ///< Number of quarters (a quarter is 3 months) that the company has a negative balance.
 
	CompanyMask bankrupt_asked;      ///< which companies were asked about buying it?
 
	int16 bankrupt_timeout;          ///< If bigger than \c 0, amount of time to wait for an answer on an offer to buy this company.
 
	Money bankrupt_value;
 

	
 
	uint32 terraform_limit;          ///< Amount of tileheights we can (still) terraform (times 65536).
 
	uint32 clear_limit;              ///< Amount of tiles we can (still) clear (times 65536).
 

	
 
	/**
 
	 * If \c true, the company is (also) controlled by the computer (a NoAI program).
 
	 * @note It is possible that the user is also participating in such a company.
 
	 */
 
	bool is_ai;
 

	
src/company_cmd.cpp
Show inline comments
 
@@ -55,12 +55,15 @@ INSTANTIATE_POOL_METHODS(Company)
 
 */
 
Company::Company(uint16 name_1, bool is_ai)
 
{
 
	this->name_1 = name_1;
 
	this->location_of_HQ = INVALID_TILE;
 
	this->is_ai = is_ai;
 
	this->terraform_limit = _settings_game.construction.terraform_frame_burst << 16;
 
	this->clear_limit     = _settings_game.construction.clear_frame_burst << 16;
 

	
 
	for (uint j = 0; j < 4; j++) this->share_owners[j] = COMPANY_SPECTATOR;
 
	InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY);
 
}
 

	
 
/** Destructor. */
 
Company::~Company()
 
@@ -249,12 +252,22 @@ void SubtractMoneyFromCompanyFract(Compa
 
	c->money_fraction = m - (byte)cost;
 
	cost >>= 8;
 
	if (c->money_fraction > m) cost++;
 
	if (cost != 0) SubtractMoneyFromAnyCompany(c, CommandCost(cst.GetExpensesType(), cost));
 
}
 

	
 
/** Update the landscaping limits per company. */
 
void UpdateLandscapingLimits()
 
{
 
	Company *c;
 
	FOR_ALL_COMPANIES(c) {
 
		c->terraform_limit = min(c->terraform_limit + _settings_game.construction.terraform_per_64k_frames, _settings_game.construction.terraform_frame_burst << 16);
 
		c->clear_limit     = min(c->clear_limit     + _settings_game.construction.clear_per_64k_frames,     _settings_game.construction.clear_frame_burst << 16);
 
	}
 
}
 

	
 
/**
 
 * Set the right DParams to get the name of an owner.
 
 * @param owner the owner to get the name of.
 
 * @param tile  optional tile to get the right town.
 
 * @pre if tile == 0, then owner can't be OWNER_TOWN.
 
 */
src/company_func.h
Show inline comments
 
@@ -20,12 +20,13 @@ bool MayCompanyTakeOver(CompanyID cbig, 
 
void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner);
 
void GetNameOfOwner(Owner owner, TileIndex tile);
 
void SetLocalCompany(CompanyID new_company);
 
void ShowBuyCompanyDialog(CompanyID company);
 
void CompanyAdminUpdate(const Company *company);
 
void CompanyAdminBankrupt(CompanyID company_id);
 
void UpdateLandscapingLimits();
 

	
 
extern CompanyByte _local_company;
 
extern CompanyByte _current_company;
 

	
 
extern Colours _company_colours[MAX_COMPANIES];
 
extern CompanyManagerFace _company_manager_face;
src/landscape.cpp
Show inline comments
 
@@ -29,12 +29,13 @@
 
#include "landscape_type.h"
 
#include "animated_tile_func.h"
 
#include "core/random_func.hpp"
 
#include "object_base.h"
 
#include "water_map.h"
 
#include "economy_func.h"
 
#include "company_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 

	
 
extern const TileTypeProcs
 
	_tile_type_clear_procs,
 
@@ -613,12 +614,17 @@ CommandCost CmdLandscapeClear(TileIndex 
 
	if ((flags & DC_FORCE_CLEAR_TILE) && HasTileWaterClass(tile) && IsTileOnWater(tile) && !IsWaterTile(tile) && !IsCoastTile(tile)) {
 
		if ((flags & DC_AUTO) && GetWaterClass(tile) == WATER_CLASS_CANAL) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
 
		do_clear = true;
 
		cost.AddCost(GetWaterClass(tile) == WATER_CLASS_CANAL ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER]);
 
	}
 

	
 
	Company *c = (flags & DC_AUTO) ? NULL : Company::GetIfValid(_current_company);
 
	if (c != NULL && (int)GB(c->clear_limit, 16, 16) < 1) {
 
		return_cmd_error(STR_ERROR_CLEARING_LIMIT_REACHED);
 
	}
 

	
 
	const ClearedObjectArea *coa = FindClearedObject(tile);
 

	
 
	/* If this tile was the first tile which caused object destruction, always
 
	 * pass it on to the tile_type_proc. That way multiple test runs and the exec run stay consistent. */
 
	if (coa != NULL && coa->first_tile != tile) {
 
		/* If this tile belongs to an object which was already cleared via another tile, pretend it has been
 
@@ -630,13 +636,16 @@ CommandCost CmdLandscapeClear(TileIndex 
 
			return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
 
		}
 
	} else {
 
		cost.AddCost(_tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags));
 
	}
 

	
 
	if (do_clear && (flags & DC_EXEC)) DoClearSquare(tile);
 
	if (flags & DC_EXEC) {
 
		if (c != NULL) c->clear_limit -= 1 << 16;
 
		if (do_clear) DoClearSquare(tile);
 
	}
 
	return cost;
 
}
 

	
 
/**
 
 * Clear a big piece of landscape
 
 * @param tile end tile of area dragging
 
@@ -653,19 +662,25 @@ CommandCost CmdClearArea(TileIndex tile,
 

	
 
	Money money = GetAvailableMoneyForCommand();
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	CommandCost last_error = CMD_ERROR;
 
	bool had_success = false;
 

	
 
	const Company *c = (flags & DC_AUTO) ? NULL : Company::GetIfValid(_current_company);
 
	int limit = (c == NULL ? INT32_MAX : GB(c->clear_limit, 16, 16));
 

	
 
	TileArea ta(tile, p1);
 
	TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(ta);
 
	for (; *iter != INVALID_TILE; ++(*iter)) {
 
		TileIndex t = *iter;
 
		CommandCost ret = DoCommand(t, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
		if (ret.Failed()) {
 
			last_error = ret;
 

	
 
			/* We may not clear more tiles. */
 
			if (c != NULL && GB(c->clear_limit, 16, 16) < 1) break;
 
			continue;
 
		}
 

	
 
		had_success = true;
 
		if (flags & DC_EXEC) {
 
			money -= ret.GetCost();
 
@@ -681,12 +696,15 @@ CommandCost CmdClearArea(TileIndex tile,
 
			if ((TileX(off) == 0 || TileX(off) == ta.w - 1U) && (TileY(off) == 0 || TileY(off) == ta.h - 1U)) {
 
				/* big explosion in each corner, or small explosion for single tiles */
 
				CreateEffectVehicleAbove(TileX(t) * TILE_SIZE + TILE_SIZE / 2, TileY(t) * TILE_SIZE + TILE_SIZE / 2, 2,
 
					ta.w == 1 && ta.h == 1 ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
 
				);
 
			}
 
		} else {
 
			/* When we're at the clearing limit we better bail (unneed) testing as well. */
 
			if (ret.GetCost() != 0 && --limit <= 0) break;
 
		}
 
		cost.AddCost(ret);
 
	}
 

	
 
	delete iter;
 
	return had_success ? cost : last_error;
src/lang/english.txt
Show inline comments
 
@@ -3473,12 +3473,14 @@ STR_ERROR_CAN_T_DO_THIS                 
 
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED                           :{WHITE}Building must be demolished first
 
STR_ERROR_CAN_T_CLEAR_THIS_AREA                                 :{WHITE}Can't clear this area...
 
STR_ERROR_SITE_UNSUITABLE                                       :{WHITE}... site unsuitable
 
STR_ERROR_ALREADY_BUILT                                         :{WHITE}... already built
 
STR_ERROR_OWNED_BY                                              :{WHITE}... owned by {STRING2}
 
STR_ERROR_AREA_IS_OWNED_BY_ANOTHER                              :{WHITE}... area is owned by another company
 
STR_ERROR_TERRAFORM_LIMIT_REACHED                               :{WHITE}... terraforming limit reached
 
STR_ERROR_CLEARING_LIMIT_REACHED                                :{WHITE}... tile clearing limit reached
 
STR_ERROR_NAME_MUST_BE_UNIQUE                                   :{WHITE}Name must be unique
 
STR_ERROR_GENERIC_OBJECT_IN_THE_WAY                             :{WHITE}{1:STRING} in the way
 
STR_ERROR_NOT_ALLOWED_WHILE_PAUSED                              :{WHITE}Not allowed while paused
 

	
 
# Local authority errors
 
STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS                 :{WHITE}{TOWN} local authority refuses to allow this
src/openttd.cpp
Show inline comments
 
@@ -1233,24 +1233,26 @@ static void CheckCaches()
 
 * That check is enforced in DoCommand.
 
 */
 
void StateGameLoop()
 
{
 
	/* dont execute the state loop during pause */
 
	if (_pause_mode != PM_UNPAUSED) {
 
		UpdateLandscapingLimits();
 
		CallWindowTickEvent();
 
		return;
 
	}
 
	if (IsGeneratingWorld()) return;
 

	
 
	ClearStorageChanges(false);
 

	
 
	if (_game_mode == GM_EDITOR) {
 
		RunTileLoop();
 
		CallVehicleTicks();
 
		CallLandscapeTick();
 
		ClearStorageChanges(true);
 
		UpdateLandscapingLimits();
 

	
 
		CallWindowTickEvent();
 
		NewsLoop();
 
	} else {
 
		if (_debug_desync_level > 2 && _date_fract == 0 && (_date & 0x1F) == 0) {
 
			/* Save the desync savegame if needed. */
 
@@ -1270,12 +1272,13 @@ void StateGameLoop()
 
		RunTileLoop();
 
		CallVehicleTicks();
 
		CallLandscapeTick();
 
		ClearStorageChanges(true);
 

	
 
		AI::GameLoop();
 
		UpdateLandscapingLimits();
 

	
 
		CallWindowTickEvent();
 
		NewsLoop();
 
		cur_company.Restore();
 
	}
 

	
src/saveload/afterload.cpp
Show inline comments
 
@@ -2402,12 +2402,19 @@ bool AfterLoadGame()
 
		FOR_ALL_TRAINS(t) {
 
			if (!HasBit(t->flags, 5)) continue;
 

	
 
			ClrBit(t->flags, 5);
 
			SetBit(t->vehicle_flags, VF_PATHFINDER_LOST);
 
		}
 

	
 
		/* Introduced terraform/clear limits. */
 
		Company *c;
 
		FOR_ALL_COMPANIES(c) {
 
			c->terraform_limit = _settings_game.construction.terraform_frame_burst << 16;
 
			c->clear_limit     = _settings_game.construction.clear_frame_burst << 16;
 
		}
 
	}
 

	
 
	/* Road stops is 'only' updating some caches */
 
	AfterLoadRoadStops();
 
	AfterLoadLabelMaps();
 

	
src/saveload/company_sl.cpp
Show inline comments
 
@@ -137,12 +137,15 @@ static const SaveLoad _company_desc[] = 
 
	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 13,                  2, SL_MAX_VERSION),
 

	
 
	SLE_CONDVAR(CompanyProperties, is_ai,                 SLE_BOOL,                    2, SL_MAX_VERSION),
 
	SLE_CONDNULL(1, 107, 111), ///< is_noai
 
	SLE_CONDNULL(1, 4, 99),
 

	
 
	SLE_CONDVAR(CompanyProperties, terraform_limit,       SLE_UINT32,                156, SL_MAX_VERSION),
 
	SLE_CONDVAR(CompanyProperties, clear_limit,           SLE_UINT32,                156, SL_MAX_VERSION),
 

	
 
	SLE_END()
 
};
 

	
 
static const SaveLoad _company_settings_desc[] = {
 
	/* Engine renewal settings */
 
	SLE_CONDNULL(512, 16, 18),
src/saveload/saveload.cpp
Show inline comments
 
@@ -217,14 +217,15 @@
 
 *  150   20857
 
 *  151   20918
 
 *  152   21171
 
 *  153   21263
 
 *  154   21426
 
 *  155   21453
 
 *  156   !!TODO!!
 
 */
 
extern const uint16 SAVEGAME_VERSION = 155; ///< Current savegame version of OpenTTD.
 
extern const uint16 SAVEGAME_VERSION = 156; ///< Current savegame version of OpenTTD.
 

	
 
SavegameType _savegame_type; ///< type of savegame we are loading
 

	
 
uint32 _ttdp_version;     ///< version of TTDP savegame (if applicable)
 
uint16 _sl_version;       ///< the major savegame version identifier
 
byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
src/settings_type.h
Show inline comments
 
@@ -211,12 +211,17 @@ struct ConstructionSettings {
 
	bool   road_stop_on_competitor_road;     ///< allow building of drive-through road stops on roads owned by competitors
 
	uint8  raw_industry_construction;        ///< type of (raw) industry construction (none, "normal", prospecting)
 
	uint8  industry_platform;                ///< the amount of flat land around an industry
 
	bool   freeform_edges;                   ///< allow terraforming the tiles at the map edges
 
	uint8  extra_tree_placement;             ///< (dis)allow building extra trees in-game
 
	uint8  command_pause_level;              ///< level/amount of commands that can't be executed while paused
 

	
 
	uint32 terraform_per_64k_frames;         ///< how many tile heights may, over a long period, be terraformed per 65536 frames?
 
	uint16 terraform_frame_burst;            ///< how many tile heights may, over a short period, be terraformed?
 
	uint32 clear_per_64k_frames;             ///< how many tiles may, over a long period, be cleared per 65536 frames?
 
	uint16 clear_frame_burst;                ///< how many tiles may, over a short period, be cleared?
 
};
 

	
 
/** Settings related to the AI. */
 
struct AISettings {
 
	bool   ai_in_multiplayer;                ///< so we allow AIs in multiplayer
 
	bool   ai_disable_veh_train;             ///< disable types for AI
src/table/settings.h
Show inline comments
 
@@ -369,12 +369,16 @@ const SettingDesc _settings[] = {
 
 SDT_CONDOMANY(GameSettings, game_creation.landscape,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0,   3, _climates,        STR_NULL,                                  NULL, ConvertLandscape),
 
	 SDT_CONDVAR(GameSettings, game_creation.snow_line,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, DEF_SNOWLINE_HEIGHT * TILE_HEIGHT, MIN_SNOWLINE_HEIGHT * TILE_HEIGHT, MAX_SNOWLINE_HEIGHT * TILE_HEIGHT, 0, STR_NULL,     NULL),
 
 SDT_CONDOMANY(GameSettings, vehicle.road_side,                    SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 1,   1, _roadsides,       STR_NULL,                                  CheckRoadSide, NULL),
 

	
 
	    SDT_BOOL(GameSettings, construction.build_on_slopes,                                        0,NN,  true,                    STR_CONFIG_SETTING_BUILDONSLOPES,          NULL),
 
	 SDT_CONDVAR(GameSettings, construction.command_pause_level,     SLE_UINT8,154, SL_MAX_VERSION, 0,MS|NN,  1,     0,       3, 1, STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL, NULL),
 
	 SDT_CONDVAR(GameSettings, construction.terraform_per_64k_frames,SLE_UINT32,156,SL_MAX_VERSION, 0, 0, 64 << 16, 0,  1 << 30, 1, STR_NULL, NULL),
 
	 SDT_CONDVAR(GameSettings, construction.terraform_frame_burst,  SLE_UINT16,156, SL_MAX_VERSION, 0, 0, 4096,     0,  1 << 30, 1, STR_NULL, NULL),
 
	 SDT_CONDVAR(GameSettings, construction.clear_per_64k_frames,   SLE_UINT32,156, SL_MAX_VERSION, 0, 0, 64 << 16, 0,  1 << 30, 1, STR_NULL, NULL),
 
	 SDT_CONDVAR(GameSettings, construction.clear_frame_burst,      SLE_UINT16,156, SL_MAX_VERSION, 0, 0, 4096,     0,  1 << 30, 1, STR_NULL, NULL),
 
	SDT_CONDBOOL(GameSettings, construction.autoslope,                          75, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_SETTING_AUTOSLOPE,              NULL),
 
	    SDT_BOOL(GameSettings, construction.extra_dynamite,                                         0, 0,  true,                    STR_CONFIG_SETTING_EXTRADYNAMITE,          NULL),
 
	    SDT_BOOL(GameSettings, construction.longbridges,                                            0,NN,  true,                    STR_CONFIG_SETTING_LONGBRIDGES,            NULL),
 
	    SDT_BOOL(GameSettings, construction.signal_side,                                            N,NN,  true,                    STR_CONFIG_SETTING_SIGNALSIDE,             RedrawScreen),
 
	    SDT_BOOL(GameSettings, station.never_expire_airports,                                       0,NN, false,                    STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS,  NULL),
 
	 SDT_CONDVAR(GameSettings, economy.town_layout,                  SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_ORIGINAL,TL_BEGIN,NUM_TLS - 1, 1, STR_CONFIG_SETTING_TOWN_LAYOUT,  TownFoundingChanged),
src/terraform_cmd.cpp
Show inline comments
 
@@ -15,12 +15,14 @@
 
#include "tunnel_map.h"
 
#include "bridge_map.h"
 
#include "functions.h"
 
#include "economy_func.h"
 
#include "genworld.h"
 
#include "object_base.h"
 
#include "company_base.h"
 
#include "company_func.h"
 

	
 
#include "table/strings.h"
 

	
 
/*
 
 * In one terraforming command all four corners of a initial tile can be raised/lowered (though this is not available to the player).
 
 * The maximal amount of height modifications is archieved when raising a complete flat land from sea level to MAX_TILE_HEIGHT or vice versa.
 
@@ -343,12 +345,17 @@ CommandCost CmdTerraformLand(TileIndex t
 
				return cost;
 
			}
 
			if (pass == 1) total_cost.AddCost(cost);
 
		}
 
	}
 

	
 
	Company *c = Company::GetIfValid(_current_company);
 
	if (c != NULL && (int)GB(c->terraform_limit, 16, 16) < ts.modheight_count) {
 
		return_cmd_error(STR_ERROR_TERRAFORM_LIMIT_REACHED);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		/* change the height */
 
		{
 
			int count;
 
			TerraformerHeightMod *mod;
 

	
 
@@ -365,12 +372,14 @@ CommandCost CmdTerraformLand(TileIndex t
 
			int count;
 
			TileIndex *ti = ts.tile_table;
 
			for (count = ts.tile_table_count; count != 0; count--, ti++) {
 
				MarkTileDirtyByTile(*ti);
 
			}
 
		}
 

	
 
		if (c != NULL) c->terraform_limit -= ts.modheight_count << 16;
 
	}
 
	return total_cost;
 
}
 

	
 

	
 
/**
 
@@ -408,37 +417,52 @@ CommandCost CmdLevelLand(TileIndex tile,
 

	
 
	Money money = GetAvailableMoneyForCommand();
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	CommandCost last_error(lm == LM_LEVEL ? STR_ERROR_ALREADY_LEVELLED : INVALID_STRING_ID);
 
	bool had_success = false;
 

	
 
	const Company *c = Company::GetIfValid(_current_company);
 
	int limit = (c == NULL ? INT32_MAX : GB(c->terraform_limit, 16, 16));
 

	
 
	TileArea ta(tile, p1);
 
	TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(ta);
 
	for (; *iter != INVALID_TILE; ++(*iter)) {
 
		TileIndex t = *iter;
 
		uint curh = TileHeight(t);
 
		while (curh != h) {
 
			CommandCost ret = DoCommand(t, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
 
			if (ret.Failed()) {
 
				last_error = ret;
 

	
 
				/* Did we reach the limit? */
 
				if (ret.GetErrorMessage() == STR_ERROR_TERRAFORM_LIMIT_REACHED) limit = 0;
 
				break;
 
			}
 

	
 
			if (flags & DC_EXEC) {
 
				money -= ret.GetCost();
 
				if (money < 0) {
 
					_additional_cash_required = ret.GetCost();
 
					delete iter;
 
					return cost;
 
				}
 
				DoCommand(t, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
 
			} else {
 
				/* When we're at the terraform limit we better bail (unneeded) testing as well.
 
				 * This will probably cause the terraforming cost to be underestimated, but only
 
				 * when it's near the terraforming limit. Even then, the estimation is
 
				 * completely off due to it basically counting terraforming double, so it being
 
				 * cut off earlier might even give a better estimate in some cases. */
 
				if (--limit <= 0) break;
 
			}
 

	
 
			cost.AddCost(ret);
 
			curh += (curh > h) ? -1 : 1;
 
			had_success = true;
 
		}
 

	
 
		if (limit <= 0) break;
 
	}
 

	
 
	delete iter;
 
	return had_success ? cost : last_error;
 
}
0 comments (0 inline, 0 general)