Changeset - r6069:a949fb2ff608
[Not reviewed]
master
0 1 0
tron - 18 years ago 2007-02-18 11:27:09
tron@openttd.org
(svn r8799) -Fix

Reduce variable scope
1 file changed with 182 insertions and 290 deletions:
0 comments (0 inline, 0 general)
src/station_cmd.cpp
Show inline comments
 
@@ -39,39 +39,33 @@
 

	
 
/**
 
 * Called if a new block is added to the station-pool
 
 */
 
static void StationPoolNewBlock(uint start_item)
 
{
 
	Station *st;
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 *  TODO - This is just a temporary stage, this will be removed. */
 
	for (st = GetStation(start_item); st != NULL; st = (st->index + 1U < GetStationPoolSize()) ? GetStation(st->index + 1U) : NULL) st->index = start_item++;
 
	for (Station *st = GetStation(start_item); st != NULL; st = (st->index + 1U < GetStationPoolSize()) ? GetStation(st->index + 1U) : NULL) st->index = start_item++;
 
}
 

	
 
static void StationPoolCleanBlock(uint start_item, uint end_item)
 
{
 
	uint i;
 

	
 
	for (i = start_item; i <= end_item; i++) {
 
	for (uint i = start_item; i <= end_item; i++) {
 
		Station *st = GetStation(i);
 
		if (st->IsValid()) st->~Station();
 
	}
 
}
 

	
 
/**
 
 * Called if a new block is added to the roadstop-pool
 
 */
 
static void RoadStopPoolNewBlock(uint start_item)
 
{
 
	RoadStop *rs;
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 * TODO - This is just a temporary stage, this will be removed. */
 
	for (rs = GetRoadStop(start_item); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
 
	for (RoadStop *rs = GetRoadStop(start_item); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
 
		rs->xy    = INVALID_TILE;
 
		rs->index = start_item++;
 
	}
 
}
 

	
 
DEFINE_OLD_POOL(Station, Station, StationPoolNewBlock, StationPoolCleanBlock)
 
@@ -81,29 +75,28 @@ DEFINE_OLD_POOL(RoadStop, RoadStop, Road
 
extern void UpdateAirplanesOnNewStation(Station *st);
 

	
 

	
 
RoadStop* GetRoadStopByTile(TileIndex tile, RoadStop::Type type)
 
{
 
	const Station* st = GetStationByTile(tile);
 
	RoadStop* rs;
 

	
 
	for (rs = st->GetPrimaryRoadStop(type); rs->xy != tile; rs = rs->next) {
 

	
 
	for (RoadStop *rs = st->GetPrimaryRoadStop(type);; rs = rs->next) {
 
		if (rs->xy == tile) return rs;
 
		assert(rs->next != NULL);
 
	}
 

	
 
	return rs;
 
}
 

	
 

	
 
static uint GetNumRoadStopsInStation(const Station* st, RoadStop::Type type)
 
{
 
	uint num = 0;
 
	const RoadStop *rs;
 

	
 
	assert(st != NULL);
 
	for (rs = st->GetPrimaryRoadStop(type); rs != NULL; rs = rs->next) num++;
 
	for (const RoadStop *rs = st->GetPrimaryRoadStop(type); rs != NULL; rs = rs->next) {
 
		num++;
 
	}
 

	
 
	return num;
 
}
 

	
 

	
 
/* Calculate the radius of the station. Basicly it is the biggest
 
@@ -149,19 +142,17 @@ static Station* GetStationAround(TileInd
 
 * @param industry when type == MP_INDUSTRY, the type of the industry,
 
 *                 in all other cases this parameter is ignored
 
 * @result the noumber of matching tiles around
 
 */
 
static int CountMapSquareAround(TileIndex tile, TileType type, IndustryType industry)
 
{
 
	TileIndex cur_tile;
 
	int dx, dy;
 
	int num = 0;
 

	
 
	for (dx = -3; dx <= 3; dx++) {
 
		for (dy = -3; dy <= 3; dy++) {
 
			cur_tile = TILE_MASK(tile + TileDiffXY(dx, dy));
 
	for (int dx = -3; dx <= 3; dx++) {
 
		for (int dy = -3; dy <= 3; dy++) {
 
			TileIndex cur_tile = TILE_MASK(tile + TileDiffXY(dx, dy));
 

	
 
			if (IsTileType(cur_tile, type)) {
 
				switch (type) {
 
					case MP_INDUSTRY:
 
						if (GetIndustryType(cur_tile) == industry)
 
							num++;
 
@@ -198,13 +189,12 @@ static bool GenerateStationName(Station 
 
		1 << M(STR_SV_STNAME_HELIPORT),         /* 5 */
 
	};
 

	
 
	Town *t = st->town;
 
	uint32 free_names = (uint32)-1;
 
	int found;
 
	uint z,z2;
 
	unsigned long tmp;
 

	
 
	{
 
		Station *s;
 

	
 
		FOR_ALL_STATIONS(s) {
 
@@ -263,20 +253,22 @@ static bool GenerateStationName(Station 
 
		found = _opt.landscape == LT_DESERT ?
 
			M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS);
 
		goto done;
 
	}
 

	
 
	/* check elevation compared to town */
 
	z = GetTileZ(tile);
 
	z2 = GetTileZ(t->xy);
 
	if (z < z2) {
 
		found = M(STR_SV_STNAME_VALLEY);
 
		if (HASBIT(free_names, M(STR_SV_STNAME_VALLEY))) goto done;
 
	} else if (z > z2) {
 
		found = M(STR_SV_STNAME_HEIGHTS);
 
		if (HASBIT(free_names, M(STR_SV_STNAME_HEIGHTS))) goto done;
 
	{
 
		uint z = GetTileZ(tile);
 
		uint z2 = GetTileZ(t->xy);
 
		if (z < z2) {
 
			found = M(STR_SV_STNAME_VALLEY);
 
			if (HASBIT(free_names, M(STR_SV_STNAME_VALLEY))) goto done;
 
		} else if (z > z2) {
 
			found = M(STR_SV_STNAME_HEIGHTS);
 
			if (HASBIT(free_names, M(STR_SV_STNAME_HEIGHTS))) goto done;
 
		}
 
	}
 

	
 
	/* check direction compared to town */
 
	{
 
		static const int8 _direction_and_table[] = {
 
			~( (1<<M(STR_SV_STNAME_WEST)) | (1<<M(STR_SV_STNAME_EAST)) | (1<<M(STR_SV_STNAME_NORTH)) ),
 
@@ -356,15 +348,14 @@ static void UpdateStationVirtCoordDirty(
 
}
 

	
 
// Get a mask of the cargo types that the station accepts.
 
static uint GetAcceptanceMask(const Station *st)
 
{
 
	uint mask = 0;
 
	uint i;
 

	
 
	for (i = 0; i != NUM_CARGO; i++) {
 

	
 
	for (uint i = 0; i != NUM_CARGO; i++) {
 
		if (st->goods[i].waiting_acceptance & 0x8000) mask |= 1 << i;
 
	}
 
	return mask;
 
}
 

	
 
// Items contains the two cargo names that are to be accepted or rejected.
 
@@ -380,41 +371,36 @@ static void ShowRejectOrAcceptNews(const
 
}
 

	
 
// Get a list of the cargo types being produced around the tile.
 
void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile,
 
	int w, int h, int rad)
 
{
 
	int x,y;
 
	int x1,y1,x2,y2;
 
	int xc,yc;
 

	
 
	memset(produced, 0, sizeof(AcceptedCargo));
 

	
 
	x = TileX(tile);
 
	y = TileY(tile);
 
	int x = TileX(tile);
 
	int y = TileY(tile);
 

	
 
	// expand the region by rad tiles on each side
 
	// while making sure that we remain inside the board.
 
	x2 = min(x + w + rad, MapSizeX());
 
	x1 = max(x - rad, 0);
 

	
 
	y2 = min(y + h + rad, MapSizeY());
 
	y1 = max(y - rad, 0);
 
	int x2 = min(x + w + rad, MapSizeX());
 
	int x1 = max(x - rad, 0);
 

	
 
	int y2 = min(y + h + rad, MapSizeY());
 
	int y1 = max(y - rad, 0);
 

	
 
	assert(x1 < x2);
 
	assert(y1 < y2);
 
	assert(w > 0);
 
	assert(h > 0);
 

	
 
	for (yc = y1; yc != y2; yc++) {
 
		for (xc = x1; xc != x2; xc++) {
 
	for (int yc = y1; yc != y2; yc++) {
 
		for (int xc = x1; xc != x2; xc++) {
 
			if (!(IS_INSIDE_1D(xc, x, w) && IS_INSIDE_1D(yc, y, h))) {
 
				GetProducedCargoProc *gpc;
 
				TileIndex tile = TileXY(xc, yc);
 

	
 
				gpc = _tile_type_procs[GetTileType(tile)]->get_produced_cargo_proc;
 
				GetProducedCargoProc *gpc = _tile_type_procs[GetTileType(tile)]->get_produced_cargo_proc;
 
				if (gpc != NULL) {
 
					CargoID cargos[2] = { CT_INVALID, CT_INVALID };
 

	
 
					gpc(tile, cargos);
 
					if (cargos[0] != CT_INVALID) {
 
						produced[cargos[0]]++;
 
@@ -429,43 +415,38 @@ void GetProductionAroundTiles(AcceptedCa
 
}
 

	
 
// Get a list of the cargo types that are accepted around the tile.
 
void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile,
 
	int w, int h, int rad)
 
{
 
	int x,y;
 
	int x1,y1,x2,y2;
 
	int xc,yc;
 

	
 
	memset(accepts, 0, sizeof(AcceptedCargo));
 

	
 
	x = TileX(tile);
 
	y = TileY(tile);
 
	int x = TileX(tile);
 
	int y = TileY(tile);
 

	
 
	// expand the region by rad tiles on each side
 
	// while making sure that we remain inside the board.
 
	x2 = min(x + w + rad, MapSizeX());
 
	y2 = min(y + h + rad, MapSizeY());
 
	x1 = max(x - rad, 0);
 
	y1 = max(y - rad, 0);
 
	int x2 = min(x + w + rad, MapSizeX());
 
	int y2 = min(y + h + rad, MapSizeY());
 
	int x1 = max(x - rad, 0);
 
	int y1 = max(y - rad, 0);
 

	
 
	assert(x1 < x2);
 
	assert(y1 < y2);
 
	assert(w > 0);
 
	assert(h > 0);
 

	
 
	for (yc = y1; yc != y2; yc++) {
 
		for (xc = x1; xc != x2; xc++) {
 
	for (int yc = y1; yc != y2; yc++) {
 
		for (int xc = x1; xc != x2; xc++) {
 
			TileIndex tile = TileXY(xc, yc);
 

	
 
			if (!IsTileType(tile, MP_STATION)) {
 
				AcceptedCargo ac;
 
				uint i;
 

	
 
				GetAcceptedCargo(tile, ac);
 
				for (i = 0; i < lengthof(ac); ++i) accepts[i] += ac[i];
 
				for (uint i = 0; i < lengthof(ac); ++i) accepts[i] += ac[i];
 
			}
 
		}
 
	}
 
}
 

	
 
typedef struct ottd_Rectangle {
 
@@ -487,27 +468,23 @@ static inline void MergePoint(ottd_Recta
 
}
 

	
 
// Update the acceptance for a station.
 
// show_msg controls whether to display a message that acceptance was changed.
 
static void UpdateStationAcceptance(Station *st, bool show_msg)
 
{
 
	uint old_acc, new_acc;
 
	const RoadStop *cur_rs;
 
	int i;
 
	// Don't update acceptance for a buoy
 
	if (st->IsBuoy()) return;
 

	
 
	ottd_Rectangle rect;
 
	int rad;
 
	AcceptedCargo accepts;
 

	
 
	rect.min_x = MapSizeX();
 
	rect.min_y = MapSizeY();
 
	rect.max_x = rect.max_y = 0;
 
	// Don't update acceptance for a buoy
 
	if (st->IsBuoy()) return;
 
	rect.max_x = 0;
 
	rect.max_y = 0;
 

	
 
	/* old accepted goods types */
 
	old_acc = GetAcceptanceMask(st);
 
	uint old_acc = GetAcceptanceMask(st);
 

	
 
	// Put all the tiles that span an area in the table.
 
	if (st->train_tile != 0) {
 
		MergePoint(&rect, st->train_tile);
 
		MergePoint(&rect,
 
			st->train_tile + TileDiffXY(st->trainst_w - 1, st->trainst_h - 1)
 
@@ -522,49 +499,48 @@ static void UpdateStationAcceptance(Stat
 
			st->airport_tile + TileDiffXY(afc->size_x - 1, afc->size_y - 1)
 
		);
 
	}
 

	
 
	if (st->dock_tile != 0) MergePoint(&rect, st->dock_tile);
 

	
 
	for (cur_rs = st->bus_stops; cur_rs != NULL; cur_rs = cur_rs->next) {
 
		MergePoint(&rect, cur_rs->xy);
 
	for (const RoadStop *rs = st->bus_stops; rs != NULL; rs = rs->next) {
 
		MergePoint(&rect, rs->xy);
 
	}
 

	
 
	for (cur_rs = st->truck_stops; cur_rs != NULL; cur_rs = cur_rs->next) {
 
		MergePoint(&rect, cur_rs->xy);
 
	for (const RoadStop *rs = st->truck_stops; rs != NULL; rs = rs->next) {
 
		MergePoint(&rect, rs->xy);
 
	}
 

	
 
	rad = (_patches.modified_catchment) ? FindCatchmentRadius(st) : 4;
 

	
 
	// And retrieve the acceptance.
 
	AcceptedCargo accepts;
 
	if (rect.max_x >= rect.min_x) {
 
		GetAcceptanceAroundTiles(
 
			accepts,
 
			TileXY(rect.min_x, rect.min_y),
 
			rect.max_x - rect.min_x + 1,
 
			rect.max_y - rect.min_y + 1,
 
			rad
 
			_patches.modified_catchment ? FindCatchmentRadius(st) : 4
 
		);
 
	} else {
 
		memset(accepts, 0, sizeof(accepts));
 
	}
 

	
 
	// Adjust in case our station only accepts fewer kinds of goods
 
	for (i = 0; i != NUM_CARGO; i++) {
 
	for (uint i = 0; i != NUM_CARGO; i++) {
 
		uint amt = min(accepts[i], 15);
 

	
 
		// Make sure the station can accept the goods type.
 
		if ((i != CT_PASSENGERS && !(st->facilities & (byte)~FACIL_BUS_STOP)) ||
 
				(i == CT_PASSENGERS && !(st->facilities & (byte)~FACIL_TRUCK_STOP)))
 
			amt = 0;
 

	
 
		SB(st->goods[i].waiting_acceptance, 12, 4, amt);
 
	}
 

	
 
	// Only show a message in case the acceptance was actually changed.
 
	new_acc = GetAcceptanceMask(st);
 
	uint new_acc = GetAcceptanceMask(st);
 
	if (old_acc == new_acc)
 
		return;
 

	
 
	// show a message to report that the acceptance was changed?
 
	if (show_msg && st->owner == _local_player && st->facilities) {
 
		/* List of accept and reject strings for different number of
 
@@ -607,13 +583,13 @@ static void UpdateStationAcceptance(Stat
 
	// redraw the station view since acceptance changed
 
	InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4);
 
}
 

	
 
static void UpdateStationSignCoord(Station *st)
 
{
 
	StationRect *r = &st->rect;
 
	const StationRect *r = &st->rect;
 

	
 
	if (r->IsEmpty()) return; // no tiles belong to this station
 

	
 
	// clamp sign coord to be inside the station rect
 
	st->xy = TileXY(clampu(TileX(st->xy), r->left, r->right), clampu(TileY(st->xy), r->top, r->bottom));
 
	UpdateStationVirtCoordDirty(st);
 
@@ -636,27 +612,24 @@ static void DeleteStationIfEmpty(Station
 
static int32 ClearTile_Station(TileIndex tile, byte flags);
 

	
 
// Tries to clear the given area. Returns the cost in case of success.
 
// Or an error code if it failed.
 
int32 CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint invalid_dirs, StationID* station)
 
{
 
	int32 cost = 0, ret;
 

	
 
	Slope tileh;
 
	uint z;
 
	int32 cost = 0;
 
	int allowed_z = -1;
 
	int flat_z;
 

	
 
	BEGIN_TILE_LOOP(tile_cur, w, h, tile)
 

	
 
	BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
 
		if (MayHaveBridgeAbove(tile_cur) && IsBridgeAbove(tile_cur)) {
 
			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
		}
 

	
 
		if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
 

	
 
		tileh = GetTileSlope(tile_cur, &z);
 
		uint z;
 
		Slope tileh = GetTileSlope(tile_cur, &z);
 

	
 
		/* Prohibit building if
 
		 *   1) The tile is "steep" (i.e. stretches two height levels)
 
		 * -OR-
 
		 *   2) The tile is non-flat if
 
		 *     a) the player building is an "old-school" AI
 
@@ -665,13 +638,13 @@ int32 CheckFlatLandBelow(TileIndex tile,
 
		 */
 
		if (IsSteepSlope(tileh) ||
 
				((_is_old_ai_player || !_patches.build_on_slopes) && tileh != SLOPE_FLAT)) {
 
			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 
		}
 

	
 
		flat_z = z;
 
		int flat_z = z;
 
		if (tileh != SLOPE_FLAT) {
 
			// need to check so the entrance to the station is not pointing at a slope.
 
			if ((invalid_dirs&1 && !(tileh & SLOPE_NE) && (uint)w_cur == w) ||
 
					(invalid_dirs&2 && !(tileh & SLOPE_SE) && h_cur == 1) ||
 
					(invalid_dirs&4 && !(tileh & SLOPE_SW) && w_cur == 1) ||
 
					(invalid_dirs&8 && !(tileh & SLOPE_NW) && (uint)h_cur == h)) {
 
@@ -701,24 +674,25 @@ int32 CheckFlatLandBelow(TileIndex tile,
 
					*station = st;
 
				} else if (*station != st) {
 
					return_cmd_error(STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING);
 
				}
 
			}
 
		} else {
 
			ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			int32 ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			if (CmdFailed(ret)) return ret;
 
			cost += ret;
 
		}
 
	END_TILE_LOOP(tile_cur, w, h, tile)
 
	} END_TILE_LOOP(tile_cur, w, h, tile)
 

	
 
	return cost;
 
}
 

	
 
static bool CanExpandRailroadStation(Station* st, uint* fin, Axis axis)
 
static bool CanExpandRailroadStation(const Station* st, uint* fin, Axis axis)
 
{
 
	uint curw = st->trainst_w, curh = st->trainst_h;
 
	uint curw = st->trainst_w;
 
	uint curh = st->trainst_h;
 
	TileIndex tile = fin[0];
 
	uint w = fin[1];
 
	uint h = fin[2];
 

	
 
	if (_patches.nonuniform_stations) {
 
		// determine new size of train station region..
 
@@ -821,58 +795,51 @@ static void GetStationLayout(byte *layou
 
 * - p2 = (bit  0- 3) - railtype (p2 & 0xF)
 
 * - p2 = (bit  8-15) - custom station class
 
 * - p2 = (bit 16-23) - custom station id
 
 */
 
int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Station *st;
 
	int w_org, h_org;
 
	int32 cost, ret;
 
	StationID est;
 
	int plat_len, numtracks;
 
	Axis axis;
 
	uint finalvalues[3];
 
	const StationSpec *statspec;
 
	int specindex;
 
	int32 ret;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	/* Does the authority allow this? */
 
	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile_org)) return CMD_ERROR;
 
	if (!ValParamRailtype(p2 & 0xF)) return CMD_ERROR;
 

	
 
	/* unpack parameters */
 
	axis = (Axis)(p1 & 1);
 
	numtracks = GB(p1,  8, 8);
 
	plat_len  = GB(p1, 16, 8);
 
	/* w = length, h = num_tracks */
 
	Axis axis = (Axis)GB(p1, 0, 1);
 
	uint numtracks = GB(p1,  8, 8);
 
	uint plat_len  = GB(p1, 16, 8);
 
	if (axis == AXIS_X) {
 
		w_org = plat_len;
 
		h_org = numtracks;
 
	} else {
 
		h_org = plat_len;
 
		w_org = numtracks;
 
	}
 

	
 
	if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR;
 

	
 
	// these values are those that will be stored in train_tile and station_platforms
 
	uint finalvalues[3];
 
	finalvalues[0] = tile_org;
 
	finalvalues[1] = w_org;
 
	finalvalues[2] = h_org;
 

	
 
	// Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station)
 
	est = INVALID_STATION;
 
	StationID est = INVALID_STATION;
 
	// If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug
 
	//  for detail info, see: https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365
 
	ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
 
	if (CmdFailed(ret)) return ret;
 
	cost = ret + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len;
 
	int32 cost = ret + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len;
 

	
 
	// Make sure there are no similar stations around us.
 
	st = GetStationAround(tile_org, w_org, h_org, est);
 
	Station *st = GetStationAround(tile_org, w_org, h_org, est);
 
	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 

	
 
	// See if there is a deleted station close to us.
 
	if (st == NULL) st = GetClosestStationFromTile(tile_org);
 

	
 
	/* In case of new station if DC_EXEC is NOT set we still need to create the station
 
@@ -911,14 +878,14 @@ int32 CmdBuildRailroadStation(TileIndex 
 
	}
 

	
 
	/* Check if the given station class is valid */
 
	if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR;
 

	
 
	/* Check if we can allocate a custom stationspec to this station */
 
	statspec = GetCustomStationSpec((StationClassID)GB(p2, 8, 8), GB(p2, 16, 8));
 
	specindex = AllocateSpecToStation(statspec, st, flags & DC_EXEC);
 
	const StationSpec *statspec = GetCustomStationSpec((StationClassID)GB(p2, 8, 8), GB(p2, 16, 8));
 
	int specindex = AllocateSpecToStation(statspec, st, flags & DC_EXEC);
 
	if (specindex == -1) return CMD_ERROR;
 

	
 
	if (statspec != NULL) {
 
		/* Perform NewStation checks */
 

	
 
		/* Check if the station size is permitted */
 
@@ -997,49 +964,48 @@ int32 CmdBuildRailroadStation(TileIndex 
 

	
 
static void MakeRailwayStationAreaSmaller(Station *st)
 
{
 
	uint w = st->trainst_w;
 
	uint h = st->trainst_h;
 
	TileIndex tile = st->train_tile;
 
	uint i;
 

	
 
restart:
 

	
 
	// too small?
 
	if (w != 0 && h != 0) {
 
		// check the left side, x = constant, y changes
 
		for (i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(0, i));) {
 
		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(0, i));) {
 
			// the left side is unused?
 
			if (++i == h) {
 
				tile += TileDiffXY(1, 0);
 
				w--;
 
				goto restart;
 
			}
 
		}
 

	
 
		// check the right side, x = constant, y changes
 
		for (i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(w - 1, i));) {
 
		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(w - 1, i));) {
 
			// the right side is unused?
 
			if (++i == h) {
 
				w--;
 
				goto restart;
 
			}
 
		}
 

	
 
		// check the upper side, y = constant, x changes
 
		for (i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, 0));) {
 
		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, 0));) {
 
			// the left side is unused?
 
			if (++i == w) {
 
				tile += TileDiffXY(0, 1);
 
				h--;
 
				goto restart;
 
			}
 
		}
 

	
 
		// check the lower side, y = constant, x changes
 
		for (i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, h - 1));) {
 
		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, h - 1));) {
 
			// the left side is unused?
 
			if (++i == w) {
 
				h--;
 
				goto restart;
 
			}
 
		}
 
@@ -1057,19 +1023,17 @@ restart:
 
 * @param tile tile of station piece to remove
 
 * @param p1 unused
 
 * @param p2 unused
 
 */
 
int32 CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Station *st;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	// make sure the specified tile belongs to the current player, and that it is a railroad station.
 
	if (!IsTileType(tile, MP_STATION) || !IsRailwayStation(tile) || !_patches.nonuniform_stations) return CMD_ERROR;
 
	st = GetStationByTile(tile);
 
	Station *st = GetStationByTile(tile);
 
	if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile))) return CMD_ERROR;
 

	
 
	// if we reached here, it means we can actually delete it. do that.
 
	if (flags & DC_EXEC) {
 
		uint specindex = GetCustomStationSpecIndex(tile);
 
		Track track = GetRailStationTrack(tile);
 
@@ -1096,30 +1060,28 @@ int32 CmdRemoveFromRailroadStation(TileI
 
	return _price.remove_rail_station;
 
}
 

	
 

	
 
static int32 RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
 
{
 
	int w,h;
 
	int32 cost = 0;
 

	
 
	/* if there is flooding and non-uniform stations are enabled, remove platforms tile by tile */
 
	if (_current_player == OWNER_WATER && _patches.nonuniform_stations)
 
		return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAILROAD_STATION);
 

	
 
	/* Current player owns the station? */
 
	if (_current_player != OWNER_WATER && !CheckOwnership(st->owner))
 
		return CMD_ERROR;
 

	
 
	/* determine width and height of platforms */
 
	tile = st->train_tile;
 
	w = st->trainst_w;
 
	h = st->trainst_h;
 
	int w = st->trainst_w;
 
	int h = st->trainst_h;
 

	
 
	assert(w != 0 && h != 0);
 

	
 
	int32 cost = 0;
 
	/* clear all areas of the station */
 
	do {
 
		int w_bak = w;
 
		do {
 
			// for nonuniform stations, only remove tiles that are actually train station tiles
 
			if (st->TileBelongsToRailStation(tile)) {
 
@@ -1205,16 +1167,12 @@ static RoadStop **FindRoadStopSpot(bool 
 
 * @param p1 entrance direction (DiagDirection)
 
 * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
 
 *           bit 1: 0 for normal, 1 for drive-through
 
 */
 
int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Station *st;
 
	RoadStop *road_stop;
 
	int32 cost;
 
	int32 ret;
 
	bool type = HASBIT(p2, 0);
 
	bool is_drive_through = HASBIT(p2, 1);
 
	bool build_over_road  = is_drive_through && IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
 
	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
 
	Owner cur_owner = _current_player;
 

	
 
@@ -1232,25 +1190,25 @@ int32 CmdBuildRoadStop(TileIndex tile, u
 
	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
 
		return CMD_ERROR;
 

	
 
	if (build_over_road) flags ^= DC_AUTO;
 

	
 
	if (town_owned_road) _current_player = OWNER_TOWN;
 
	ret = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL);
 
	int32 ret = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL);
 
	_current_player = cur_owner;
 
	if (CmdFailed(ret)) return ret;
 
	cost = build_over_road ? 0 : ret; // Don't add cost of clearing road when overbuilding
 

	
 
	st = GetStationAround(tile, 1, 1, INVALID_STATION);
 
	int32 cost = build_over_road ? 0 : ret; // Don't add cost of clearing road when overbuilding
 

	
 
	Station *st = GetStationAround(tile, 1, 1, INVALID_STATION);
 
	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 

	
 
	/* Find a station close to us */
 
	if (st == NULL) st = GetClosestStationFromTile(tile);
 

	
 
	//give us a road stop in the list, and check if something went wrong
 
	road_stop = new RoadStop(tile);
 
	RoadStop *road_stop = new RoadStop(tile);
 
	if (road_stop == NULL) {
 
		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
 
	}
 

	
 
	/* ensure that in case of error (or no DC_EXEC) the new road stop gets deleted upon return */
 
	AutoPtrT<RoadStop> rs_auto_delete(road_stop);
 
@@ -1315,20 +1273,20 @@ int32 CmdBuildRoadStop(TileIndex tile, u
 
	return cost;
 
}
 

	
 
// Remove a bus station
 
static int32 RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
 
{
 
	RoadStop **primary_stop;
 
	RoadStop *cur_stop;
 
	bool is_truck = IsTruckStop(tile);
 

	
 
	if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) {
 
		return CMD_ERROR;
 
	}
 

	
 
	bool is_truck = IsTruckStop(tile);
 

	
 
	RoadStop **primary_stop;
 
	RoadStop *cur_stop;
 
	if (is_truck) { // truck stop
 
		primary_stop = &st->truck_stops;
 
		cur_stop = GetRoadStopByTile(tile, RoadStop::TRUCK);
 
	} else {
 
		primary_stop = &st->bus_stops;
 
		cur_stop = GetRoadStopByTile(tile, RoadStop::BUS);
 
@@ -1368,27 +1326,21 @@ static int32 RemoveRoadStop(Station *st,
 
 * @param tile tile to remove the stop from
 
 * @param p1 not used
 
 * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
 
 */
 
int32 CmdRemoveRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Station* st;
 
	bool is_drive_through;
 
	bool is_towns_road = false;
 
	RoadBits road_bits;
 
	int32 ret;
 

	
 
	/* Make sure the specified tile is a road stop of the correct type */
 
	if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile) || (uint32)GetRoadStopType(tile) != p2) return CMD_ERROR;
 
	st = GetStationByTile(tile);
 
	Station *st = GetStationByTile(tile);
 
	/* Save the stop info before it is removed */
 
	is_drive_through = IsDriveThroughStopTile(tile);
 
	road_bits = GetAnyRoadBits(tile);
 
	if (is_drive_through) is_towns_road = GetStopBuiltOnTownRoad(tile);
 

	
 
	ret = RemoveRoadStop(st, flags, tile);
 
	bool is_drive_through = IsDriveThroughStopTile(tile);
 
	RoadBits road_bits = GetAnyRoadBits(tile);
 
	bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
 

	
 
	int32 ret = RemoveRoadStop(st, flags, tile);
 

	
 
	/* If the stop was a drive-through stop replace the road */
 
	if ((flags & DC_EXEC) && !CmdFailed(ret) && is_drive_through) {
 
		uint index = 0;
 
		Owner cur_owner = _current_player;
 

	
 
@@ -1499,52 +1451,47 @@ static const byte * const _airport_secti
 
 * @param tile tile where airport will be built
 
 * @param p1 airport type, @see airport.h
 
 * @param p2 unused
 
 */
 
int32 CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Town *t;
 
	Station *st;
 
	int32 cost;
 
	int32 ret;
 
	int w, h;
 
	bool airport_upgrade = true;
 
	const AirportFTAClass* afc;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	/* Check if a valid, buildable airport was chosen for construction */
 
	if (p1 > lengthof(_airport_sections) || !HASBIT(GetValidAirports(), p1)) return CMD_ERROR;
 

	
 
	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
 
		return CMD_ERROR;
 

	
 
	t = ClosestTownFromTile(tile, (uint)-1);
 
	Town *t = ClosestTownFromTile(tile, (uint)-1);
 

	
 
	/* Check if local auth refuses a new airport */
 
	{
 
		uint num = 0;
 
		const Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (st->town == t && st->facilities&FACIL_AIRPORT && st->airport_type != AT_OILRIG)
 
				num++;
 
		}
 
		if (num >= 2) {
 
			SetDParam(0, t->index);
 
			return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES);
 
		}
 
	}
 

	
 
	afc = GetAirport(p1);
 
	w = afc->size_x;
 
	h = afc->size_y;
 

	
 
	ret = CheckFlatLandBelow(tile, w, h, flags, 0, NULL);
 
	const AirportFTAClass *afc = GetAirport(p1);
 
	int w = afc->size_x;
 
	int h = afc->size_y;
 

	
 
	int32 ret = CheckFlatLandBelow(tile, w, h, flags, 0, NULL);
 
	if (CmdFailed(ret)) return ret;
 
	cost = ret;
 

	
 
	st = GetStationAround(tile, w, h, INVALID_STATION);
 
	int32 cost = ret;
 

	
 
	Station *st = GetStationAround(tile, w, h, INVALID_STATION);
 
	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 

	
 
	/* Find a station close to us */
 
	if (st == NULL) st = GetClosestStationFromTile(tile);
 

	
 
	if (w > _patches.station_spread || h > _patches.station_spread) {
 
@@ -1626,40 +1573,34 @@ int32 CmdBuildAirport(TileIndex tile, ui
 

	
 
	return cost;
 
}
 

	
 
static int32 RemoveAirport(Station *st, uint32 flags)
 
{
 
	TileIndex tile;
 
	int w,h;
 
	int32 cost;
 

	
 
	if (_current_player != OWNER_WATER && !CheckOwnership(st->owner))
 
		return CMD_ERROR;
 

	
 
	tile = st->airport_tile;
 
	TileIndex tile = st->airport_tile;
 

	
 
	const AirportFTAClass *afc = st->Airport();
 
	w = afc->size_x;
 
	h = afc->size_y;
 

	
 
	cost = w * h * _price.remove_airport;
 
	int w = afc->size_x;
 
	int h = afc->size_y;
 

	
 
	int32 cost = w * h * _price.remove_airport;
 

	
 
	BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
 
		if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
 

	
 
		if (flags & DC_EXEC) {
 
			DeleteAnimatedTile(tile_cur);
 
			DoClearSquare(tile_cur);
 
		}
 
	} END_TILE_LOOP(tile_cur, w,h,tile)
 

	
 
	if (flags & DC_EXEC) {
 
		uint i;
 

	
 
		for (i = 0; i < afc->nof_depots; ++i) {
 
		for (uint i = 0; i < afc->nof_depots; ++i) {
 
			DeleteWindowById(
 
				WC_VEHICLE_DEPOT, tile + ToTileIndexDiff(afc->airport_depots[i])
 
			);
 
		}
 

	
 
		st->rect.AfterRemoveRect(st, tile, w, h);
 
@@ -1678,20 +1619,18 @@ static int32 RemoveAirport(Station *st, 
 
 * @param tile tile where to place the bouy
 
 * @param p1 unused
 
 * @param p2 unused
 
 */
 
int32 CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Station *st;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	if (!IsClearWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 

	
 
	/* allocate and initialize new station */
 
	st = new Station(tile);
 
	Station *st = new Station(tile);
 
	if (st == NULL) return CMD_ERROR;
 

	
 
	/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
 
	AutoPtrT<Station> st_auto_delete(st);
 

	
 
	st->town = ClosestTownFromTile(tile, (uint)-1);
 
@@ -1738,18 +1677,16 @@ static bool CheckShipsOnBuoy(Station *st
 
	}
 
	return false;
 
}
 

	
 
static int32 RemoveBuoy(Station *st, uint32 flags)
 
{
 
	TileIndex tile;
 

	
 
	/* XXX: strange stuff */
 
	if (!IsValidPlayer(_current_player))  return_cmd_error(INVALID_STRING_ID);
 

	
 
	tile = st->dock_tile;
 
	TileIndex tile = st->dock_tile;
 

	
 
	if (CheckShipsOnBuoy(st))   return_cmd_error(STR_BUOY_IS_IN_USE);
 
	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		st->dock_tile = 0;
 
@@ -1789,19 +1726,17 @@ static const byte _dock_h_chk[4] = { 1, 
 
 * @param tile tile where dock will be built
 
 * @param p1 unused
 
 * @param p2 unused
 
 */
 
int32 CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	TileIndex tile_cur;
 
	DiagDirection direction;
 
	int32 cost;
 
	Station *st;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	DiagDirection direction;
 
	switch (GetTileSlope(tile, NULL)) {
 
		case SLOPE_SW: direction = DIAGDIR_NE; break;
 
		case SLOPE_SE: direction = DIAGDIR_NW; break;
 
		case SLOPE_NW: direction = DIAGDIR_SE; break;
 
		case SLOPE_NE: direction = DIAGDIR_SW; break;
 
		default: return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
@@ -1811,13 +1746,13 @@ int32 CmdBuildDock(TileIndex tile, uint3
 

	
 
	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 

	
 
	cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(cost)) return CMD_ERROR;
 

	
 
	tile_cur = tile + TileOffsByDiagDir(direction);
 
	TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
 

	
 
	if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
 

	
 
	if (!IsTileType(tile_cur, MP_WATER) || GetTileSlope(tile_cur, NULL) != SLOPE_FLAT) {
 
		return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
	}
 
@@ -1828,13 +1763,13 @@ int32 CmdBuildDock(TileIndex tile, uint3
 
	tile_cur += TileOffsByDiagDir(direction);
 
	if (!IsTileType(tile_cur, MP_WATER) || GetTileSlope(tile_cur, NULL) != SLOPE_FLAT) {
 
		return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
	}
 

	
 
	/* middle */
 
	st = GetStationAround(
 
	Station *st = GetStationAround(
 
		tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
 
		_dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION);
 
	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 

	
 
	/* Find a station close to us */
 
	if (st == NULL) st = GetClosestStationFromTile(tile);
 
@@ -1886,19 +1821,16 @@ int32 CmdBuildDock(TileIndex tile, uint3
 
	}
 
	return _price.build_dock;
 
}
 

	
 
static int32 RemoveDock(Station *st, uint32 flags)
 
{
 
	TileIndex tile1;
 
	TileIndex tile2;
 

	
 
	if (!CheckOwnership(st->owner)) return CMD_ERROR;
 

	
 
	tile1 = st->dock_tile;
 
	tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
 
	TileIndex tile1 = st->dock_tile;
 
	TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
 

	
 
	if (!EnsureNoVehicle(tile1)) return CMD_ERROR;
 
	if (!EnsureNoVehicle(tile2)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DoClearSquare(tile1);
 
@@ -1928,23 +1860,21 @@ const DrawTileSprites *GetStationTileLay
 

	
 
/* For drawing canal edges on buoys */
 
extern void DrawCanalWater(TileIndex tile);
 

	
 
static void DrawTile_Station(TileInfo *ti)
 
{
 
	const DrawTileSeqStruct *dtss;
 
	const DrawTileSprites *t = NULL;
 
	RailType railtype = GetRailType(ti->tile);
 
	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 
	uint32 relocation = 0;
 
	const Station *st = NULL;
 
	const StationSpec *statspec = NULL;
 
	PlayerID owner = GetTileOwner(ti->tile);
 
	SpriteID image;
 

	
 
	SpriteID palette;
 

	
 
	if (IsValidPlayer(owner)) {
 
		palette = PLAYER_SPRITE_COLOR(owner);
 
	} else {
 
		// Some stations are not owner by a player, namely oil rigs
 
		palette = PALETTE_TO_GREY;
 
	}
 
@@ -1976,13 +1906,13 @@ static void DrawTile_Station(TileInfo *t
 
			}
 
		}
 
	}
 

	
 
	if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationGfx(ti->tile)];
 

	
 
	image = t->ground_sprite;
 
	SpriteID image = t->ground_sprite;
 
	if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) {
 
		image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
 
		image += rti->custom_ground_offset;
 
	} else {
 
		image += rti->total_offset;
 
	}
 
@@ -1992,22 +1922,22 @@ static void DrawTile_Station(TileInfo *t
 
	DrawGroundSprite(image, HASBIT(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE);
 

	
 
	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
 

	
 
	if (IsBuoyTile(ti->tile) && (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER))) DrawCanalWater(ti->tile);
 

	
 
	const DrawTileSeqStruct *dtss;
 
	foreach_draw_tile_seq(dtss, t->seq) {
 
		SpriteID pal;
 

	
 
		image = dtss->image;
 
		if (relocation == 0 || HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) {
 
			image += rti->total_offset;
 
		} else {
 
			image += relocation;
 
		}
 

	
 
		SpriteID pal;
 
		if (_display_opt & DO_TRANS_BUILDINGS) {
 
			SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
 
			pal = PALETTE_TO_TRANSPARENT;
 
		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
 
			pal = palette;
 
		} else {
 
@@ -2026,24 +1956,20 @@ static void DrawTile_Station(TileInfo *t
 
		}
 
	}
 
}
 

	
 
void StationPickerDrawSprite(int x, int y, RailType railtype, int image)
 
{
 
	SpriteID pal, img;
 
	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 
	SpriteID pal = PLAYER_SPRITE_COLOR(_local_player);
 
	const DrawTileSprites *t = &_station_display_datas[image];
 

	
 
	SpriteID img = t->ground_sprite;
 
	DrawSprite(img + rti->total_offset, HASBIT(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
 

	
 
	const DrawTileSeqStruct *dtss;
 
	const DrawTileSprites *t;
 
	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 

	
 
	pal = PLAYER_SPRITE_COLOR(_local_player);
 

	
 
	t = &_station_display_datas[image];
 

	
 
	img = t->ground_sprite;
 
	DrawSprite(img + rti->total_offset, HASBIT(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
 

	
 
	foreach_draw_tile_seq(dtss, t->seq) {
 
		Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z);
 
		DrawSprite(dtss->image + rti->total_offset, pal, x + pt.x, y + pt.y);
 
	}
 
}
 

	
 
@@ -2061,17 +1987,16 @@ static void GetAcceptedCargo_Station(Til
 
{
 
	/* not used */
 
}
 

	
 
static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
 
{
 
	StringID str;
 

	
 
	td->owner = GetTileOwner(tile);
 
	td->build_date = GetStationByTile(tile)->build_date;
 

	
 
	StringID str;
 
	switch (GetStationType(tile)) {
 
		default: NOT_REACHED();
 
		case STATION_RAIL:    str = STR_305E_RAILROAD_STATION; break;
 
		case STATION_AIRPORT:
 
			str = (IsHangar(tile) ? STR_305F_AIRCRAFT_HANGAR : STR_3060_AIRPORT);
 
			break;
 
@@ -2159,15 +2084,14 @@ static void AnimateTile_Station(TileInde
 
		{ GFX_RADAR_METROPOLITAN_FIRST,  GFX_RADAR_METROPOLITAN_LAST,  3 },
 
		{ GFX_RADAR_DISTRICTWE_FIRST,    GFX_RADAR_DISTRICTWE_LAST,    3 },
 
		{ GFX_WINDSACK_INTERCON_FIRST,   GFX_WINDSACK_INTERCON_LAST,   1 }
 
	};
 

	
 
	StationGfx gfx = GetStationGfx(tile);
 
	const AnimData* i;
 

	
 
	for (i = data; i != endof(data); i++) {
 

	
 
	for (const AnimData *i = data; i != endof(data); i++) {
 
		if (i->from <= gfx && gfx <= i->to) {
 
			if ((_tick_counter & i->delay) == 0) {
 
				SetStationGfx(tile, gfx < i->to ? gfx + 1 : i->from);
 
				MarkTileDirtyByTile(tile);
 
			}
 
			break;
 
@@ -2276,28 +2200,24 @@ static void StationHandleBigTick(Station
 
}
 

	
 
static inline void byte_inc_sat(byte *p) { byte b = *p + 1; if (b != 0) *p = b; }
 

	
 
static void UpdateStationRating(Station *st)
 
{
 
	GoodsEntry *ge;
 
	int rating;
 
	StationID index;
 
	int waiting;
 
	bool waiting_changed = false;
 

	
 
	byte_inc_sat(&st->time_since_load);
 
	byte_inc_sat(&st->time_since_unload);
 

	
 
	ge = st->goods;
 
	GoodsEntry *ge = st->goods;
 
	do {
 
		if (ge->enroute_from != INVALID_STATION) {
 
			byte_inc_sat(&ge->enroute_time);
 
			byte_inc_sat(&ge->days_since_pickup);
 

	
 
			rating = 0;
 
			int rating = 0;
 

	
 
			{
 
				int b = ge->last_speed;
 
				if ((b-=85) >= 0)
 
					rating += b >> 2;
 
			}
 
@@ -2320,21 +2240,19 @@ static void UpdateStationRating(Station 
 
				(rating += 25, days > 12) ||
 
				(rating += 25, days > 6) ||
 
				(rating += 45, days > 3) ||
 
				(rating += 35, true);
 
			}
 

	
 
			{
 
				waiting = GB(ge->waiting_acceptance, 0, 12);
 
				(rating -= 90, waiting > 1500) ||
 
				(rating += 55, waiting > 1000) ||
 
				(rating += 35, waiting > 600) ||
 
				(rating += 10, waiting > 300) ||
 
				(rating += 20, waiting > 100) ||
 
				(rating += 10, true);
 
			}
 
			int waiting = GB(ge->waiting_acceptance, 0, 12);
 
			(rating -= 90, waiting > 1500) ||
 
			(rating += 55, waiting > 1000) ||
 
			(rating += 35, waiting > 600) ||
 
			(rating += 10, waiting > 300) ||
 
			(rating += 20, waiting > 100) ||
 
			(rating += 10, true);
 

	
 
			{
 
				int or_ = ge->rating; // old rating
 

	
 
				// only modify rating in steps of -2, -1, 0, 1 or 2
 
				ge->rating = rating = or_ + clamp(clamp(rating, 0, 255) - or_, -2, 2);
 
@@ -2358,50 +2276,43 @@ static void UpdateStationRating(Station 
 

	
 
				if (waiting_changed) SB(ge->waiting_acceptance, 0, 12, waiting);
 
			}
 
		}
 
	} while (++ge != endof(st->goods));
 

	
 
	index = st->index;
 

	
 
	StationID index = st->index;
 
	if (waiting_changed) {
 
		InvalidateWindow(WC_STATION_VIEW, index);
 
	} else {
 
		InvalidateWindowWidget(WC_STATION_VIEW, index, 5);
 
	}
 
}
 

	
 
/* called for every station each tick */
 
static void StationHandleSmallTick(Station *st)
 
{
 
	byte b;
 

	
 
	if (st->facilities == 0) return;
 

	
 
	b = st->delete_ctr + 1;
 
	byte b = st->delete_ctr + 1;
 
	if (b >= 185) b = 0;
 
	st->delete_ctr = b;
 

	
 
	if (b == 0) UpdateStationRating(st);
 
}
 

	
 
void OnTick_Station(void)
 
{
 
	uint i;
 
	Station *st;
 

	
 
	if (_game_mode == GM_EDITOR) return;
 

	
 
	i = _station_tick_ctr;
 
	uint i = _station_tick_ctr;
 
	if (++_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
 

	
 
	if (IsValidStationID(i)) StationHandleBigTick(GetStation(i));
 

	
 
	FOR_ALL_STATIONS(st) {
 
		StationHandleSmallTick(st);
 
	}
 
	Station *st;
 
	FOR_ALL_STATIONS(st) StationHandleSmallTick(st);
 
}
 

	
 
void StationMonthlyLoop(void)
 
{
 
}
 

	
 
@@ -2410,15 +2321,13 @@ void ModifyStationRatingAround(TileIndex
 
{
 
	Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->owner == owner &&
 
				DistanceManhattan(tile, st->xy) <= radius) {
 
			uint i;
 

	
 
			for (i = 0; i != NUM_CARGO; i++) {
 
			for (uint i = 0; i != NUM_CARGO; i++) {
 
				GoodsEntry* ge = &st->goods[i];
 

	
 
				if (ge->enroute_from != INVALID_STATION) {
 
					ge->rating = clamp(ge->rating + amount, 0, 255);
 
				}
 
			}
 
@@ -2443,21 +2352,18 @@ static void UpdateStationWaiting(Station
 
 * @param tile unused
 
 * @param p1 station ID that is to be renamed
 
 * @param p2 unused
 
 */
 
int32 CmdRenameStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	StringID str;
 
	Station *st;
 

	
 
	if (!IsValidStationID(p1) || _cmd_text[0] == '\0') return CMD_ERROR;
 
	st = GetStation(p1);
 
	Station *st = GetStation(p1);
 

	
 
	if (!CheckOwnership(st->owner)) return CMD_ERROR;
 

	
 
	str = AllocateNameUnique(_cmd_text, 6);
 
	StringID str = AllocateNameUnique(_cmd_text, 6);
 
	if (str == 0) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		StringID old_str = st->string_id;
 

	
 
		st->string_id = str;
 
@@ -2473,24 +2379,19 @@ int32 CmdRenameStation(TileIndex tile, u
 
}
 

	
 

	
 
uint MoveGoodsToStation(TileIndex tile, int w, int h, int type, uint amount)
 
{
 
	Station* around[8];
 
	uint i;
 
	uint moved;
 
	uint best_rating, best_rating2;
 
	Station *st1, *st2;
 
	uint t;
 
	int rad = 0;
 

	
 
	for (uint i = 0; i < lengthof(around); i++) around[i] = NULL;
 

	
 
	int w_prod; //width and height of the "producer" of the cargo
 
	int h_prod;
 
	int max_rad;
 

	
 
	for (i = 0; i < lengthof(around); i++) around[i] = NULL;
 

	
 
	if (_patches.modified_catchment) {
 
		w_prod = w;
 
		h_prod = h;
 
		w += 16;
 
		h += 16;
 
		max_rad = 8;
 
@@ -2500,20 +2401,18 @@ uint MoveGoodsToStation(TileIndex tile, 
 
		w += 8;
 
		h += 8;
 
		max_rad = 4;
 
	}
 

	
 
	BEGIN_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad))
 
		Station* st;
 

	
 
		cur_tile = TILE_MASK(cur_tile);
 
		if (!IsTileType(cur_tile, MP_STATION)) continue;
 

	
 
		st = GetStationByTile(cur_tile);
 

	
 
		for (i = 0; i != lengthof(around); i++) {
 
		Station *st = GetStationByTile(cur_tile);
 

	
 
		for (uint i = 0; i != lengthof(around); i++) {
 
			if (around[i] == NULL) {
 
				if (!st->IsBuoy() &&
 
						(st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights
 
						st->goods[type].rating != 0 &&
 
						(!_patches.selectgoods || st->goods[type].last_speed > 0) && // if last_speed is 0, no vehicle has been there.
 
						((st->facilities & ~FACIL_BUS_STOP)   != 0 || type == CT_PASSENGERS) && // if we have other fac. than a bus stop, or the cargo is passengers
 
@@ -2559,22 +2458,24 @@ uint MoveGoodsToStation(TileIndex tile, 
 

	
 
	/* no stations around at all? */
 
	if (around[0] == NULL) return 0;
 

	
 
	if (around[1] == NULL) {
 
		/* only one station around */
 
		moved = (amount * around[0]->goods[type].rating >> 8) + 1;
 
		uint moved = (amount * around[0]->goods[type].rating >> 8) + 1;
 
		UpdateStationWaiting(around[0], type, moved);
 
		return moved;
 
	}
 

	
 
	/* several stations around, find the two with the highest rating */
 
	st2 = st1 = NULL;
 
	best_rating = best_rating2 = 0;
 

	
 
	for (i = 0; i != lengthof(around) && around[i] != NULL; i++) {
 
	Station *st1 = NULL;
 
	Station *st2 = NULL;
 
	uint best_rating  = 0;
 
	uint best_rating2 = 0;
 

	
 
	for (uint i = 0; i != lengthof(around) && around[i] != NULL; i++) {
 
		if (around[i]->goods[type].rating >= best_rating) {
 
			best_rating2 = best_rating;
 
			st2 = st1;
 

	
 
			best_rating = around[i]->goods[type].rating;
 
			st1 = around[i];
 
@@ -2589,15 +2490,15 @@ uint MoveGoodsToStation(TileIndex tile, 
 
	assert(best_rating != 0 || best_rating2 != 0);
 

	
 
	/* the 2nd highest one gets a penalty */
 
	best_rating2 >>= 1;
 

	
 
	/* amount given to station 1 */
 
	t = (best_rating * (amount + 1)) / (best_rating + best_rating2);
 

	
 
	moved = 0;
 
	uint t = (best_rating * (amount + 1)) / (best_rating + best_rating2);
 

	
 
	uint moved = 0;
 
	if (t != 0) {
 
		moved = t * best_rating / 256 + 1;
 
		amount -= t;
 
		UpdateStationWaiting(st1, type, moved);
 
	}
 

	
 
@@ -2609,13 +2510,12 @@ uint MoveGoodsToStation(TileIndex tile, 
 

	
 
	return moved;
 
}
 

	
 
void BuildOilRig(TileIndex tile)
 
{
 
	uint j;
 
	Station *st = new Station();
 

	
 
	if (st == NULL) {
 
		DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
 
		return;
 
	}
 
@@ -2643,13 +2543,13 @@ void BuildOilRig(TileIndex tile)
 
	st->time_since_unload = 255;
 
	st->delete_ctr = 0;
 
	st->last_vehicle_type = VEH_Invalid;
 
	st->facilities = FACIL_AIRPORT | FACIL_DOCK;
 
	st->build_date = _date;
 

	
 
	for (j = 0; j != NUM_CARGO; j++) {
 
	for (uint j = 0; j != NUM_CARGO; j++) {
 
		st->goods[j].waiting_acceptance = 0;
 
		st->goods[j].days_since_pickup = 0;
 
		st->goods[j].enroute_from = INVALID_STATION;
 
		st->goods[j].enroute_from_xy = INVALID_TILE;
 
		st->goods[j].rating = 175;
 
		st->goods[j].last_speed = 0;
 
@@ -2689,14 +2589,12 @@ static void ChangeTileOwner_Station(Tile
 
		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
	}
 
}
 

	
 
static int32 ClearTile_Station(TileIndex tile, byte flags)
 
{
 
	Station *st;
 

	
 
	if (flags & DC_AUTO) {
 
		switch (GetStationType(tile)) {
 
			case STATION_RAIL:    return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD);
 
			case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST);
 
			case STATION_TRUCK:   return_cmd_error(STR_3047_MUST_DEMOLISH_TRUCK_STATION);
 
			case STATION_BUS:     return_cmd_error(STR_3046_MUST_DEMOLISH_BUS_STATION);
 
@@ -2705,13 +2603,13 @@ static int32 ClearTile_Station(TileIndex
 
			case STATION_OILRIG:
 
				SetDParam(0, STR_4807_OIL_RIG);
 
				return_cmd_error(STR_4800_IN_THE_WAY);
 
		}
 
	}
 

	
 
	st = GetStationByTile(tile);
 
	Station *st = GetStationByTile(tile);
 

	
 
	switch (GetStationType(tile)) {
 
		case STATION_RAIL:    return RemoveRailroadStation(st, tile, flags);
 
		case STATION_AIRPORT: return RemoveAirport(st, flags);
 
		case STATION_TRUCK:
 
			if (IsDriveThroughStopTile(tile) && GetStopBuiltOnTownRoad(tile))
 
@@ -2743,29 +2641,25 @@ void InitializeStations(void)
 

	
 
}
 

	
 

	
 
void AfterLoadStations(void)
 
{
 
	/* Update the speclists of all stations to point to the currently loaded custom stations. */
 
	Station *st;
 
	uint i;
 
	TileIndex tile;
 

	
 
	/* Update the speclists of all stations to point to the currently loaded custom stations. */
 
	FOR_ALL_STATIONS(st) {
 
		for (i = 0; i < st->num_specs; i++) {
 
		for (uint i = 0; i < st->num_specs; i++) {
 
			if (st->speclist[i].grfid == 0) continue;
 

	
 
			st->speclist[i].spec = GetCustomStationSpecByGrf(st->speclist[i].grfid, st->speclist[i].localidx);
 
		}
 
	}
 

	
 
	for (tile = 0; tile < MapSize(); tile++) {
 
	for (TileIndex tile = 0; tile < MapSize(); tile++) {
 
		if (GetTileType(tile) != MP_STATION) continue;
 
		st = GetStationByTile(tile);
 
		st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
 
		GetStationByTile(tile)->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
 
	}
 
}
 

	
 

	
 
extern const TileTypeProcs _tile_type_station_procs = {
 
	DrawTile_Station,           /* draw_tile_proc */
 
@@ -2879,16 +2773,14 @@ static const SaveLoad _station_speclist_
 
	SLE_END()
 
};
 

	
 

	
 
static void SaveLoad_STNS(Station *st)
 
{
 
	uint i;
 

	
 
	SlObject(st, _station_desc);
 
	for (i = 0; i != NUM_CARGO; i++) {
 
	for (uint i = 0; i != NUM_CARGO; i++) {
 
		SlObject(&st->goods[i], _goods_desc);
 

	
 
		/* In older versions, enroute_from had 0xFF as INVALID_STATION, is now 0xFFFF */
 
		if (CheckSavegameVersion(7) && st->goods[i].enroute_from == 0xFF) {
 
			st->goods[i].enroute_from = INVALID_STATION;
 
		}
 
@@ -2901,13 +2793,15 @@ static void SaveLoad_STNS(Station *st)
 
		}
 
	}
 

	
 
	if (st->num_specs != 0) {
 
		/* Allocate speclist memory when loading a game */
 
		if (st->speclist == NULL) st->speclist = CallocT<StationSpecList>(st->num_specs);
 
		for (i = 0; i < st->num_specs; i++) SlObject(&st->speclist[i], _station_speclist_desc);
 
		for (uint i = 0; i < st->num_specs; i++) {
 
			SlObject(&st->speclist[i], _station_speclist_desc);
 
		}
 
	}
 
}
 

	
 
static void Save_STNS(void)
 
{
 
	Station *st;
 
@@ -2963,8 +2857,6 @@ static void Load_ROADSTOP(void)
 
}
 

	
 
extern const ChunkHandler _station_chunk_handlers[] = {
 
	{ 'STNS', Save_STNS,      Load_STNS,      CH_ARRAY },
 
	{ 'ROAD', Save_ROADSTOP,  Load_ROADSTOP,  CH_ARRAY | CH_LAST},
 
};
 

	
 

	
0 comments (0 inline, 0 general)