Changeset - r25451:917146b539af
[Not reviewed]
src/industry_cmd.cpp
Show inline comments
 
@@ -140,49 +140,49 @@ const IndustryTileSpec *GetIndustryTileS
 

	
 
Industry::~Industry()
 
{
 
	if (CleaningPool()) return;
 

	
 
	/* Industry can also be destroyed when not fully initialized.
 
	 * This means that we do not have to clear tiles either.
 
	 * Also we must not decrement industry counts in that case. */
 
	if (this->location.w == 0) return;
 

	
 
	const bool has_neutral_station = this->neutral_station != nullptr;
 

	
 
	TILE_AREA_LOOP(tile_cur, this->location) {
 
	for (TileIndex tile_cur : this->location) {
 
		if (IsTileType(tile_cur, MP_INDUSTRY)) {
 
			if (GetIndustryIndex(tile_cur) == this->index) {
 
				DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur);
 

	
 
				/* MakeWaterKeepingClass() can also handle 'land' */
 
				MakeWaterKeepingClass(tile_cur, OWNER_NONE);
 
			}
 
		} else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
 
			DeleteOilRig(tile_cur);
 
		}
 
	}
 

	
 
	if (has_neutral_station) {
 
		/* Remove possible docking tiles */
 
		TILE_AREA_LOOP(tile_cur, this->location) {
 
		for (TileIndex tile_cur : this->location) {
 
			ClearDockingTilesCheckingNeighbours(tile_cur);
 
		}
 
	}
 

	
 
	if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
 
		TileArea ta = TileArea(this->location.tile, 0, 0).Expand(21);
 

	
 
		/* Remove the farmland and convert it to regular tiles over time. */
 
		TILE_AREA_LOOP(tile_cur, ta) {
 
		for (TileIndex tile_cur : ta) {
 
			if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
 
					GetIndustryIndexOfField(tile_cur) == this->index) {
 
				SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
 
			}
 
		}
 
	}
 

	
 
	/* don't let any disaster vehicle target invalid industry */
 
	ReleaseDisastersTargetingIndustry(this->index);
 

	
 
	/* Clear the persistent storage. */
 
	delete this->psa;
 
@@ -1032,37 +1032,37 @@ static void PlantFarmField(TileIndex til
 
	uint32 r = (Random() & 0x303) + 0x404;
 
	if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
 
	uint size_x = GB(r, 0, 8);
 
	uint size_y = GB(r, 8, 8);
 

	
 
	TileArea ta(tile - TileDiffXY(std::min(TileX(tile), size_x / 2), std::min(TileY(tile), size_y / 2)), size_x, size_y);
 
	ta.ClampToMap();
 

	
 
	if (ta.w == 0 || ta.h == 0) return;
 

	
 
	/* check the amount of bad tiles */
 
	int count = 0;
 
	TILE_AREA_LOOP(cur_tile, ta) {
 
	for (TileIndex cur_tile : ta) {
 
		assert(cur_tile < MapSize());
 
		count += IsSuitableForFarmField(cur_tile, false);
 
	}
 
	if (count * 2 < ta.w * ta.h) return;
 

	
 
	/* determine type of field */
 
	r = Random();
 
	uint counter = GB(r, 5, 3);
 
	uint field_type = GB(r, 8, 8) * 9 >> 8;
 

	
 
	/* make field */
 
	TILE_AREA_LOOP(cur_tile, ta) {
 
	for (TileIndex cur_tile : ta) {
 
		assert(cur_tile < MapSize());
 
		if (IsSuitableForFarmField(cur_tile, true)) {
 
			MakeField(cur_tile, field_type, industry);
 
			SetClearCounter(cur_tile, counter);
 
			MarkTileDirtyByTile(cur_tile);
 
		}
 
	}
 

	
 
	int type = 3;
 
	if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
 
		type = _plantfarmfield_type[Random() & 0xF];
 
	}
 
@@ -1106,25 +1106,25 @@ static bool SearchLumberMillTrees(TileIn
 
		return true;
 
	}
 
	return false;
 
}
 

	
 
/**
 
 * Perform a circular search around the Lumber Mill in order to find trees to cut
 
 * @param i industry
 
 */
 
static void ChopLumberMillTrees(Industry *i)
 
{
 
	/* We only want to cut trees if all tiles are completed. */
 
	TILE_AREA_LOOP(tile_cur, i->location) {
 
	for (TileIndex tile_cur : i->location) {
 
		if (i->TileBelongsToIndustry(tile_cur)) {
 
			if (!IsIndustryCompleted(tile_cur)) return;
 
		}
 
	}
 

	
 
	TileIndex tile = i->location.tile;
 
	if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, nullptr)) { // 40x40 tiles  to search.
 
		i->produced_cargo_waiting[0] = std::min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
 
	}
 
}
 

	
 
static void ProduceIndustryGoods(Industry *i)
 
@@ -1523,25 +1523,25 @@ static CommandCost CheckIfIndustryIsAllo
 
		return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
 
{
 
	/* Check if we don't leave the map */
 
	if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
 

	
 
	TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
 
	TILE_AREA_LOOP(tile_walk, ta) {
 
	for (TileIndex tile_walk : ta) {
 
		uint curh = TileHeight(tile_walk);
 
		/* Is the tile clear? */
 
		if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
 

	
 
		/* Don't allow too big of a change if this is the sub-tile check */
 
		if (internal != 0 && Delta(curh, height) > 1) return false;
 

	
 
		/* Different height, so the surrounding tiles of this tile
 
		 *  has to be correct too (in level, or almost in level)
 
		 *  else you get a chain-reaction of terraforming. */
 
		if (internal == 0 && curh != height) {
 
			if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
 
@@ -1578,45 +1578,45 @@ static bool CheckIfCanLevelIndustryPlatf
 

	
 
	/* TileArea::Expand is not used here as we need to abort
 
	 * instead of clamping if the bounds cannot expanded. */
 
	TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
 
			max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
 

	
 
	if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
 

	
 
	/* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
 
	 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
 
	Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 

	
 
	TILE_AREA_LOOP(tile_walk, ta) {
 
	for (TileIndex tile_walk : ta) {
 
		uint curh = TileHeight(tile_walk);
 
		if (curh != h) {
 
			/* This tile needs terraforming. Check if we can do that without
 
			 *  damaging the surroundings too much. */
 
			if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
 
				cur_company.Restore();
 
				return false;
 
			}
 
			/* This is not 100% correct check, but the best we can do without modifying the map.
 
			 *  What is missing, is if the difference in height is more than 1.. */
 
			if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
 
				cur_company.Restore();
 
				return false;
 
			}
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		/* Terraform the land under the industry */
 
		TILE_AREA_LOOP(tile_walk, ta) {
 
		for (TileIndex tile_walk : ta) {
 
			uint curh = TileHeight(tile_walk);
 
			while (curh != h) {
 
				/* We give the terraforming for free here, because we can't calculate
 
				 *  exact cost in the test-round, and as we all know, that will cause
 
				 *  a nice assert if they don't match ;) */
 
				DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
 
				curh += (curh > h) ? -1 : 1;
 
			}
 
		}
 
	}
 

	
 
	cur_company.Restore();
 
@@ -1630,25 +1630,25 @@ static bool CheckIfCanLevelIndustryPlatf
 
 * @param type Type of the new industry.
 
 * @return Succeeded or failed command.
 
 */
 
static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(type);
 

	
 
	/* On a large map with many industries, it may be faster to check an area. */
 
	static const int dmax = 14;
 
	if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
 
		const Industry* i = nullptr;
 
		TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax);
 
		TILE_AREA_LOOP(atile, tile_area) {
 
		for (TileIndex atile : tile_area) {
 
			if (GetTileType(atile) == MP_INDUSTRY) {
 
				const Industry *i2 = Industry::GetByTile(atile);
 
				if (i == i2) continue;
 
				i = i2;
 
				if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
 
				if (i->type == indspec->conflicting[0] ||
 
						i->type == indspec->conflicting[1] ||
 
						i->type == indspec->conflicting[2]) {
 
					return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
 
				}
 
			}
 
		}
src/newgrf_airporttiles.cpp
Show inline comments
 
@@ -298,17 +298,17 @@ void AnimateAirportTile(TileIndex tile)
 
void AirportTileAnimationTrigger(Station *st, TileIndex tile, AirpAnimationTrigger trigger, CargoID cargo_type)
 
{
 
	const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
 
	if (!HasBit(ats->animation.triggers, trigger)) return;
 

	
 
	AirportTileAnimationBase::ChangeAnimationFrame(CBID_AIRPTILE_ANIM_START_STOP, ats, st, tile, Random(), (uint8)trigger | (cargo_type << 8));
 
}
 

	
 
void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID cargo_type)
 
{
 
	if (st->airport.tile == INVALID_TILE) return;
 

	
 
	TILE_AREA_LOOP(tile, st->airport) {
 
	for (TileIndex tile : st->airport) {
 
		if (st->TileBelongsToAirport(tile)) AirportTileAnimationTrigger(st, tile, trigger, cargo_type);
 
	}
 
}
 

	
src/newgrf_industrytiles.cpp
Show inline comments
 
@@ -278,25 +278,25 @@ bool StartStopIndustryTileAnimation(Tile
 
	const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile));
 

	
 
	if (!HasBit(itspec->animation.triggers, iat)) return false;
 

	
 
	IndustryAnimationBase::ChangeAnimationFrame(CBID_INDTILE_ANIM_START_STOP, itspec, Industry::GetByTile(tile), tile, random, iat);
 
	return true;
 
}
 

	
 
bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigger iat)
 
{
 
	bool ret = true;
 
	uint32 random = Random();
 
	TILE_AREA_LOOP(tile, ind->location) {
 
	for (TileIndex tile : ind->location) {
 
		if (ind->TileBelongsToIndustry(tile)) {
 
			if (StartStopIndustryTileAnimation(tile, iat, random)) {
 
				SB(random, 0, 16, Random());
 
			} else {
 
				ret = false;
 
			}
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
@@ -363,20 +363,20 @@ void TriggerIndustryTile(TileIndex tile,
 
	DoTriggerIndustryTile(tile, trigger, ind, reseed_industry);
 
	DoReseedIndustry(ind, reseed_industry);
 
}
 

	
 
/**
 
 * Trigger a random trigger for all industry tiles.
 
 * @param ind Industry to trigger.
 
 * @param trigger Trigger to trigger.
 
 */
 
void TriggerIndustry(Industry *ind, IndustryTileTrigger trigger)
 
{
 
	uint32 reseed_industry = 0;
 
	TILE_AREA_LOOP(tile, ind->location) {
 
	for (TileIndex tile : ind->location) {
 
		if (ind->TileBelongsToIndustry(tile)) {
 
			DoTriggerIndustryTile(tile, trigger, ind, reseed_industry);
 
		}
 
	}
 
	DoReseedIndustry(ind, reseed_industry);
 
}
 

	
src/newgrf_object.cpp
Show inline comments
 
@@ -545,16 +545,16 @@ void TriggerObjectTileAnimation(Object *
 
}
 

	
 
/**
 
 * Trigger the update of animation on a whole object.
 
 * @param o       The object that got triggered.
 
 * @param trigger The trigger that is triggered.
 
 * @param spec    The spec associated with the object.
 
 */
 
void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const ObjectSpec *spec)
 
{
 
	if (!HasBit(spec->animation.triggers, trigger)) return;
 

	
 
	TILE_AREA_LOOP(tile, o->location) {
 
	for (TileIndex tile : o->location) {
 
		TriggerObjectTileAnimation(o, tile, trigger, spec);
 
	}
 
}
src/newgrf_station.cpp
Show inline comments
 
@@ -728,25 +728,25 @@ int AllocateSpecToStation(const StationS
 
 * Deallocate a StationSpec from a Station. Called when removing a single station tile.
 
 * @param st Station to work with.
 
 * @param specindex Index of the custom station within the Station's spec list.
 
 * @return Indicates whether the StationSpec was deallocated.
 
 */
 
void DeallocateSpecFromStation(BaseStation *st, byte specindex)
 
{
 
	/* specindex of 0 (default) is never freeable */
 
	if (specindex == 0) return;
 

	
 
	ETileArea area = ETileArea(st, INVALID_TILE, TA_WHOLE);
 
	/* Check all tiles over the station to check if the specindex is still in use */
 
	TILE_AREA_LOOP(tile, area) {
 
	for (TileIndex tile : area) {
 
		if (st->TileBelongsToRailStation(tile) && GetCustomStationSpecIndex(tile) == specindex) {
 
			return;
 
		}
 
	}
 

	
 
	/* This specindex is no longer in use, so deallocate it */
 
	st->speclist[specindex].spec     = nullptr;
 
	st->speclist[specindex].grfid    = 0;
 
	st->speclist[specindex].localidx = 0;
 

	
 
	/* If this was the highest spec index, reallocate */
 
	if (specindex == st->num_specs - 1) {
 
@@ -930,25 +930,25 @@ void TriggerStationAnimation(BaseStation
 

	
 
	/* Get Station if it wasn't supplied */
 
	if (st == nullptr) st = BaseStation::GetByTile(tile);
 

	
 
	/* Check the cached animation trigger bitmask to see if we need
 
	 * to bother with any further processing. */
 
	if (!HasBit(st->cached_anim_triggers, trigger)) return;
 

	
 
	uint16 random_bits = Random();
 
	ETileArea area = ETileArea(st, tile, tas[trigger]);
 

	
 
	/* Check all tiles over the station to check if the specindex is still in use */
 
	TILE_AREA_LOOP(tile, area) {
 
	for (TileIndex tile : area) {
 
		if (st->TileBelongsToRailStation(tile)) {
 
			const StationSpec *ss = GetStationSpec(tile);
 
			if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
 
				CargoID cargo;
 
				if (cargo_type == CT_INVALID) {
 
					cargo = CT_INVALID;
 
				} else {
 
					cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
 
				}
 
				StationAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, tile, (random_bits << 16) | Random(), (uint8)trigger | (cargo << 8));
 
			}
 
		}
 
@@ -986,25 +986,25 @@ void TriggerStationRandomisation(Station
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			if (st->goods[i].cargo.TotalCount() == 0) {
 
				SetBit(empty_mask, i);
 
			}
 
		}
 
	}
 

	
 
	/* Store triggers now for var 5F */
 
	SetBit(st->waiting_triggers, trigger);
 
	uint32 used_triggers = 0;
 

	
 
	/* Check all tiles over the station to check if the specindex is still in use */
 
	TILE_AREA_LOOP(tile, area) {
 
	for (TileIndex tile : area) {
 
		if (st->TileBelongsToRailStation(tile)) {
 
			const StationSpec *ss = GetStationSpec(tile);
 
			if (ss == nullptr) continue;
 

	
 
			/* Cargo taken "will only be triggered if all of those
 
			 * cargo types have no more cargo waiting." */
 
			if (trigger == SRT_CARGO_TAKEN) {
 
				if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
 
			}
 

	
 
			if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
 
				StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
src/object_cmd.cpp
Show inline comments
 
@@ -105,47 +105,47 @@ void BuildObject(ObjectType type, TileIn
 
	if ((spec->flags & OBJECT_FLAG_2CC_COLOUR) == 0) o->colour &= 0xF;
 

	
 
	if (HasBit(spec->callback_mask, CBM_OBJ_COLOUR)) {
 
		uint16 res = GetObjectCallback(CBID_OBJECT_COLOUR, o->colour, 0, spec, o, tile);
 
		if (res != CALLBACK_FAILED) {
 
			if (res >= 0x100) ErrorUnknownCallbackResult(spec->grf_prop.grffile->grfid, CBID_OBJECT_COLOUR, res);
 
			o->colour = GB(res, 0, 8);
 
		}
 
	}
 

	
 
	assert(o->town != nullptr);
 

	
 
	TILE_AREA_LOOP(t, ta) {
 
	for (TileIndex t : ta) {
 
		WaterClass wc = (IsWaterTile(t) ? GetWaterClass(t) : WATER_CLASS_INVALID);
 
		/* Update company infrastructure counts for objects build on canals owned by nobody. */
 
		if (wc == WATER_CLASS_CANAL && owner != OWNER_NONE && (IsTileOwner(tile, OWNER_NONE) || IsTileOwner(tile, OWNER_WATER))) {
 
			Company::Get(owner)->infrastructure.water++;
 
			DirtyCompanyInfrastructureWindows(owner);
 
		}
 
		MakeObject(t, owner, o->index, wc, Random());
 
		MarkTileDirtyByTile(t);
 
	}
 

	
 
	Object::IncTypeCount(type);
 
	if (spec->flags & OBJECT_FLAG_ANIMATION) TriggerObjectAnimation(o, OAT_BUILT, spec);
 
}
 

	
 
/**
 
 * Increase the animation stage of a whole structure.
 
 * @param tile The tile of the structure.
 
 */
 
static void IncreaseAnimationStage(TileIndex tile)
 
{
 
	TileArea ta = Object::GetByTile(tile)->location;
 
	TILE_AREA_LOOP(t, ta) {
 
	for (TileIndex t : ta) {
 
		SetAnimationFrame(t, GetAnimationFrame(t) + 1);
 
		MarkTileDirtyByTile(t);
 
	}
 
}
 

	
 
/** We encode the company HQ size in the animation stage. */
 
#define GetCompanyHQSize GetAnimationFrame
 
/** We encode the company HQ size in the animation stage. */
 
#define IncreaseCompanyHQSize IncreaseAnimationStage
 

	
 
/**
 
 * Update the CompanyHQ to the state associated with the given score
 
@@ -221,25 +221,25 @@ CommandCost CmdBuildObject(TileIndex til
 
	int size_y = GB(spec->size, HasBit(view, 0) ? 0 : 4, 4);
 
	TileArea ta(tile, size_x, size_y);
 

	
 
	if (type == OBJECT_OWNED_LAND) {
 
		/* Owned land is special as it can be placed on any slope. */
 
		cost.AddCost(DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR));
 
	} else {
 
		/* Check the surface to build on. At this time we can't actually execute the
 
		 * the CLEAR_TILE commands since the newgrf callback later on can check
 
		 * some information about the tiles. */
 
		bool allow_water = (spec->flags & (OBJECT_FLAG_BUILT_ON_WATER | OBJECT_FLAG_NOT_ON_LAND)) != 0;
 
		bool allow_ground = (spec->flags & OBJECT_FLAG_NOT_ON_LAND) == 0;
 
		TILE_AREA_LOOP(t, ta) {
 
		for (TileIndex t : ta) {
 
			if (HasTileWaterGround(t)) {
 
				if (!allow_water) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
 
				if (!IsWaterTile(t)) {
 
					/* Normal water tiles don't have to be cleared. For all other tile types clear
 
					 * the tile but leave the water. */
 
					cost.AddCost(DoCommand(t, 0, 0, flags & ~DC_NO_WATER & ~DC_EXEC, CMD_LANDSCAPE_CLEAR));
 
				} else {
 
					/* Can't build on water owned by another company. */
 
					Owner o = GetTileOwner(t);
 
					if (o != OWNER_NONE && o != OWNER_WATER) cost.AddCost(CheckOwnership(o, t));
 

	
 
					/* However, the tile has to be clear of vehicles. */
 
@@ -254,59 +254,59 @@ CommandCost CmdBuildObject(TileIndex til
 
						IsTileType(t, MP_OBJECT) &&
 
						IsTileOwner(t, _current_company) &&
 
						IsObjectType(t, OBJECT_HQ))) {
 
					cost.AddCost(DoCommand(t, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR));
 
				}
 
			}
 
		}
 

	
 
		/* So, now the surface is checked... check the slope of said surface. */
 
		int allowed_z;
 
		if (GetTileSlope(tile, &allowed_z) != SLOPE_FLAT) allowed_z++;
 

	
 
		TILE_AREA_LOOP(t, ta) {
 
		for (TileIndex t : ta) {
 
			uint16 callback = CALLBACK_FAILED;
 
			if (HasBit(spec->callback_mask, CBM_OBJ_SLOPE_CHECK)) {
 
				TileIndex diff = t - tile;
 
				callback = GetObjectCallback(CBID_OBJECT_LAND_SLOPE_CHECK, GetTileSlope(t), TileY(diff) << 4 | TileX(diff), spec, nullptr, t, view);
 
			}
 

	
 
			if (callback == CALLBACK_FAILED) {
 
				cost.AddCost(CheckBuildableTile(t, 0, allowed_z, false, false));
 
			} else {
 
				/* The meaning of bit 10 is inverted for a grf version < 8. */
 
				if (spec->grf_prop.grffile->grf_version < 8) ToggleBit(callback, 10);
 
				CommandCost ret = GetErrorMessageFromLocationCallbackResult(callback, spec->grf_prop.grffile, STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
 
				if (ret.Failed()) return ret;
 
			}
 
		}
 

	
 
		if (flags & DC_EXEC) {
 
			/* This is basically a copy of the loop above with the exception that we now
 
			 * execute the commands and don't check for errors, since that's already done. */
 
			TILE_AREA_LOOP(t, ta) {
 
			for (TileIndex t : ta) {
 
				if (HasTileWaterGround(t)) {
 
					if (!IsWaterTile(t)) {
 
						DoCommand(t, 0, 0, (flags & ~DC_NO_WATER) | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
 
					}
 
				} else {
 
					DoCommand(t, 0, 0, flags | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
 
				}
 
			}
 
		}
 
	}
 
	if (cost.Failed()) return cost;
 

	
 
	/* Finally do a check for bridges. */
 
	TILE_AREA_LOOP(t, ta) {
 
	for (TileIndex t : ta) {
 
		if (IsBridgeAbove(t) && (
 
				!(spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) ||
 
				(GetTileMaxZ(t) + spec->height >= GetBridgeHeight(GetSouthernBridgeEnd(t))))) {
 
			return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
 
		}
 
	}
 

	
 
	int hq_score = 0;
 
	switch (type) {
 
		case OBJECT_TRANSMITTER:
 
		case OBJECT_LIGHTHOUSE:
 
			if (!IsTileFlat(tile)) return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
 
@@ -429,25 +429,25 @@ static int GetSlopePixelZ_Object(TileInd
 
static Foundation GetFoundation_Object(TileIndex tile, Slope tileh)
 
{
 
	return IsObjectType(tile, OBJECT_OWNED_LAND) ? FOUNDATION_NONE : FlatteningFoundation(tileh);
 
}
 

	
 
/**
 
 * Perform the actual removal of the object from the map.
 
 * @param o The object to really clear.
 
 */
 
static void ReallyClearObjectTile(Object *o)
 
{
 
	Object::DecTypeCount(o->type);
 
	TILE_AREA_LOOP(tile_cur, o->location) {
 
	for (TileIndex tile_cur : o->location) {
 
		DeleteNewGRFInspectWindow(GSF_OBJECTS, tile_cur);
 

	
 
		MakeWaterKeepingClass(tile_cur, GetTileOwner(tile_cur));
 
	}
 
	delete o;
 
}
 

	
 
std::vector<ClearedObjectArea> _cleared_object_areas;
 

	
 
/**
 
 * Find the entry in _cleared_object_areas which occupies a certain tile.
 
 * @param tile Tile of interest
src/openttd.cpp
Show inline comments
 
@@ -1256,33 +1256,33 @@ static void CheckCaches()
 

	
 
	for (Station *st : Station::Iterate()) {
 
		for (CargoID c = 0; c < NUM_CARGO; c++) {
 
			byte buff[sizeof(StationCargoList)];
 
			memcpy(buff, &st->goods[c].cargo, sizeof(StationCargoList));
 
			st->goods[c].cargo.InvalidateCache();
 
			assert(memcmp(&st->goods[c].cargo, buff, sizeof(StationCargoList)) == 0);
 
		}
 

	
 
		/* Check docking tiles */
 
		TileArea ta;
 
		std::map<TileIndex, bool> docking_tiles;
 
		TILE_AREA_LOOP(tile, st->docking_station) {
 
		for (TileIndex tile : st->docking_station) {
 
			ta.Add(tile);
 
			docking_tiles[tile] = IsDockingTile(tile);
 
		}
 
		UpdateStationDockingTiles(st);
 
		if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) {
 
			DEBUG(desync, 2, "station docking mismatch: station %i, company %i", st->index, (int)st->owner);
 
		}
 
		TILE_AREA_LOOP(tile, ta) {
 
		for (TileIndex tile : ta) {
 
			if (docking_tiles[tile] != IsDockingTile(tile)) {
 
				DEBUG(desync, 2, "docking tile mismatch: tile %i", (int)tile);
 
			}
 
		}
 

	
 
		/* Check industries_near */
 
		IndustryList industries_near = st->industries_near;
 
		st->RecomputeCatchment();
 
		if (st->industries_near != industries_near) {
 
			DEBUG(desync, 2, "station industries near mismatch: station %i", st->index);
 
		}
 
	}
src/road_gui.cpp
Show inline comments
 
@@ -154,25 +154,25 @@ void CcRoadDepot(const CommandCost &resu
 
 *           bit 16..31: Station ID to join (NEW_STATION if build new one).
 
 * @param cmd Unused.
 
 * @see CmdBuildRoadStop
 
 */
 
void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
 
{
 
	if (result.Failed()) return;
 

	
 
	DiagDirection dir = (DiagDirection)GB(p2, 3, 2);
 
	if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
 
	if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
 
	TileArea roadstop_area(tile, GB(p1, 0, 8), GB(p1, 8, 8));
 
	TILE_AREA_LOOP(cur_tile, roadstop_area) {
 
	for (TileIndex cur_tile : roadstop_area) {
 
		ConnectRoadToStructure(cur_tile, dir);
 
		/* For a drive-through road stop build connecting road for other entrance. */
 
		if (HasBit(p2, 1)) ConnectRoadToStructure(cur_tile, ReverseDiagDir(dir));
 
	}
 
}
 

	
 
/**
 
 * Place a new road stop.
 
 * @param start_tile First tile of the area.
 
 * @param end_tile Last tile of the area.
 
 * @param p2 bit 0: 0 For bus stops, 1 for truck stops.
 
 *           bit 2: Allow stations directly adjacent to other stations.
src/saveload/station_sl.cpp
Show inline comments
 
@@ -77,25 +77,25 @@ void MoveBuoysToWaypoints()
 
		Waypoint *wp   = new (index) Waypoint(xy);
 
		wp->town       = town;
 
		wp->string_id  = train ? STR_SV_STNAME_WAYPOINT : STR_SV_STNAME_BUOY;
 
		wp->name       = name;
 
		wp->delete_ctr = 0; // Just reset delete counter for once.
 
		wp->build_date = build_date;
 
		wp->owner      = train ? GetTileOwner(xy) : OWNER_NONE;
 

	
 
		if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY;
 

	
 
		if (train) {
 
			/* When we make a rail waypoint of the station, convert the map as well. */
 
			TILE_AREA_LOOP(t, train_st) {
 
			for (TileIndex t : train_st) {
 
				if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != index) continue;
 

	
 
				SB(_me[t].m6, 3, 3, STATION_WAYPOINT);
 
				wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
 
			}
 

	
 
			wp->train_station = train_st;
 
			wp->facilities |= FACIL_TRAIN;
 
		} else if (IsBuoyTile(xy) && GetStationIndex(xy) == index) {
 
			wp->rect.BeforeAddTile(xy, StationRect::ADD_FORCE);
 
			wp->facilities |= FACIL_DOCK;
 
		}
src/script/api/script_industry.cpp
Show inline comments
 
@@ -177,47 +177,47 @@
 
{
 
	if (!IsValidIndustry(industry_id)) return false;
 

	
 
	return (::GetIndustrySpec(::Industry::Get(industry_id)->type)->behaviour & INDUSTRYBEH_AI_AIRSHIP_ROUTES) != 0;
 
}
 

	
 
/* static */ TileIndex ScriptIndustry::GetHeliportLocation(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return INVALID_TILE;
 
	if (!HasHeliport(industry_id)) return INVALID_TILE;
 

	
 
	const Industry *ind = ::Industry::Get(industry_id);
 
	TILE_AREA_LOOP(tile_cur, ind->location) {
 
	for (TileIndex tile_cur : ind->location) {
 
		if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
 
			return tile_cur;
 
		}
 
	}
 

	
 
	return INVALID_TILE;
 
}
 

	
 
/* static */ bool ScriptIndustry::HasDock(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return false;
 

	
 
	return (::GetIndustrySpec(::Industry::Get(industry_id)->type)->behaviour & INDUSTRYBEH_AI_AIRSHIP_ROUTES) != 0;
 
}
 

	
 
/* static */ TileIndex ScriptIndustry::GetDockLocation(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return INVALID_TILE;
 
	if (!HasDock(industry_id)) return INVALID_TILE;
 

	
 
	const Industry *ind = ::Industry::Get(industry_id);
 
	TILE_AREA_LOOP(tile_cur, ind->location) {
 
	for (TileIndex tile_cur : ind->location) {
 
		if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
 
			return tile_cur;
 
		}
 
	}
 

	
 
	return INVALID_TILE;
 
}
 

	
 
/* static */ IndustryType ScriptIndustry::GetIndustryType(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return INVALID_INDUSTRYTYPE;
 

	
src/script/api/script_order.cpp
Show inline comments
 
@@ -247,47 +247,47 @@ static int ScriptOrderPositionToRealOrde
 
			if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) return INVALID_TILE;
 

	
 
			if (v->type != VEH_AIRCRAFT) return ::Depot::Get(order->GetDestination())->xy;
 
			/* Aircraft's hangars are referenced by StationID, not DepotID */
 
			const Station *st = ::Station::Get(order->GetDestination());
 
			if (!st->airport.HasHangar()) return INVALID_TILE;
 
			return st->airport.GetHangarTile(0);
 
		}
 

	
 
		case OT_GOTO_STATION: {
 
			const Station *st = ::Station::Get(order->GetDestination());
 
			if (st->train_station.tile != INVALID_TILE) {
 
				TILE_AREA_LOOP(t, st->train_station) {
 
				for (TileIndex t : st->train_station) {
 
					if (st->TileBelongsToRailStation(t)) return t;
 
				}
 
			} else if (st->ship_station.tile != INVALID_TILE) {
 
				TILE_AREA_LOOP(t, st->ship_station) {
 
				for (TileIndex t : st->ship_station) {
 
					if (IsTileType(t, MP_STATION) && (IsDock(t) || IsOilRig(t)) && GetStationIndex(t) == st->index) return t;
 
				}
 
			} else if (st->bus_stops != nullptr) {
 
				return st->bus_stops->xy;
 
			} else if (st->truck_stops != nullptr) {
 
				return st->truck_stops->xy;
 
			} else if (st->airport.tile != INVALID_TILE) {
 
				TILE_AREA_LOOP(tile, st->airport) {
 
				for (TileIndex tile : st->airport) {
 
					if (st->TileBelongsToAirport(tile) && !::IsHangar(tile)) return tile;
 
				}
 
			}
 
			return INVALID_TILE;
 
		}
 

	
 
		case OT_GOTO_WAYPOINT: {
 
			const Waypoint *wp = ::Waypoint::Get(order->GetDestination());
 
			if (wp->train_station.tile != INVALID_TILE) {
 
				TILE_AREA_LOOP(t, wp->train_station) {
 
				for (TileIndex t : wp->train_station) {
 
					if (wp->TileBelongsToRailStation(t)) return t;
 
				}
 
			}
 
			/* If the waypoint has no rail waypoint tiles, it must have a buoy */
 
			return wp->xy;
 
		}
 
		default:               return INVALID_TILE;
 
	}
 
}
 

	
 
/* static */ ScriptOrder::ScriptOrderFlags ScriptOrder::GetOrderFlags(VehicleID vehicle_id, OrderPosition order_position)
 
{
src/script/api/script_tilelist.cpp
Show inline comments
 
@@ -12,59 +12,59 @@
 
#include "script_industry.hpp"
 
#include "../../industry.h"
 
#include "../../station_base.h"
 

	
 
#include "../../safeguards.h"
 

	
 
void ScriptTileList::AddRectangle(TileIndex t1, TileIndex t2)
 
{
 
	if (!::IsValidTile(t1)) return;
 
	if (!::IsValidTile(t2)) return;
 

	
 
	TileArea ta(t1, t2);
 
	TILE_AREA_LOOP(t, ta) this->AddItem(t);
 
	for (TileIndex t : ta) this->AddItem(t);
 
}
 

	
 
void ScriptTileList::AddTile(TileIndex tile)
 
{
 
	if (!::IsValidTile(tile)) return;
 

	
 
	this->AddItem(tile);
 
}
 

	
 
void ScriptTileList::RemoveRectangle(TileIndex t1, TileIndex t2)
 
{
 
	if (!::IsValidTile(t1)) return;
 
	if (!::IsValidTile(t2)) return;
 

	
 
	TileArea ta(t1, t2);
 
	TILE_AREA_LOOP(t, ta) this->RemoveItem(t);
 
	for (TileIndex t : ta) this->RemoveItem(t);
 
}
 

	
 
void ScriptTileList::RemoveTile(TileIndex tile)
 
{
 
	if (!::IsValidTile(tile)) return;
 

	
 
	this->RemoveItem(tile);
 
}
 

	
 
/**
 
 * Helper to get list of tiles that will cover an industry's production or acceptance.
 
 * @param i Industry in question
 
 * @param radius Catchment radius to test
 
 * @param bta BitmapTileArea to fill
 
 */
 
static void FillIndustryCatchment(const Industry *i, int radius, BitmapTileArea &bta)
 
{
 
	TILE_AREA_LOOP(cur_tile, i->location) {
 
	for (TileIndex cur_tile : i->location) {
 
		if (!::IsTileType(cur_tile, MP_INDUSTRY) || ::GetIndustryIndex(cur_tile) != i->index) continue;
 

	
 
		int tx = TileX(cur_tile);
 
		int ty = TileY(cur_tile);
 
		for (int y = -radius; y <= radius; y++) {
 
			if (ty + y < 0 || ty + y > (int)MapMaxY()) continue;
 
			for (int x = -radius; x <= radius; x++) {
 
				if (tx + x < 0 || tx + x > (int)MapMaxX()) continue;
 
				TileIndex tile = TileXY(tx + x, ty + y);
 
				if (!IsValidTile(tile)) continue;
 
				if (::IsTileType(tile, MP_INDUSTRY) && ::GetIndustryIndex(tile) == i->index) continue;
 
				bta.SetTile(tile);
 
@@ -147,19 +147,19 @@ ScriptTileList_StationType::ScriptTileLi
 
	const StationRect *rect = &::Station::Get(station_id)->rect;
 

	
 
	uint station_type_value = 0;
 
	/* Convert ScriptStation::StationType to ::StationType, but do it in a
 
	 *  bitmask, so we can scan for multiple entries at the same time. */
 
	if ((station_type & ScriptStation::STATION_TRAIN) != 0)      station_type_value |= (1 << ::STATION_RAIL);
 
	if ((station_type & ScriptStation::STATION_TRUCK_STOP) != 0) station_type_value |= (1 << ::STATION_TRUCK);
 
	if ((station_type & ScriptStation::STATION_BUS_STOP) != 0)   station_type_value |= (1 << ::STATION_BUS);
 
	if ((station_type & ScriptStation::STATION_AIRPORT) != 0)    station_type_value |= (1 << ::STATION_AIRPORT) | (1 << ::STATION_OILRIG);
 
	if ((station_type & ScriptStation::STATION_DOCK) != 0)       station_type_value |= (1 << ::STATION_DOCK)    | (1 << ::STATION_OILRIG);
 

	
 
	TileArea ta(::TileXY(rect->left, rect->top), rect->right - rect->left + 1, rect->bottom - rect->top + 1);
 
	TILE_AREA_LOOP(cur_tile, ta) {
 
	for (TileIndex cur_tile : ta) {
 
		if (!::IsTileType(cur_tile, MP_STATION)) continue;
 
		if (::GetStationIndex(cur_tile) != station_id) continue;
 
		if (!HasBit(station_type_value, ::GetStationType(cur_tile))) continue;
 
		this->AddTile(cur_tile);
 
	}
 
}
src/smallmap_gui.cpp
Show inline comments
 
@@ -741,25 +741,25 @@ void SmallMapWindow::SetZoomLevel(ZoomLe
 

	
 
/**
 
 * Decide which colours to show to the user for a group of tiles.
 
 * @param ta Tile area to investigate.
 
 * @return Colours to display.
 
 */
 
inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const
 
{
 
	int importance = 0;
 
	TileIndex tile = INVALID_TILE; // Position of the most important tile.
 
	TileType et = MP_VOID;         // Effective tile type at that position.
 

	
 
	TILE_AREA_LOOP(ti, ta) {
 
	for (TileIndex ti : ta) {
 
		TileType ttype = GetTileType(ti);
 

	
 
		switch (ttype) {
 
			case MP_TUNNELBRIDGE: {
 
				TransportType tt = GetTunnelBridgeTransportType(ti);
 

	
 
				switch (tt) {
 
					case TRANSPORT_RAIL: ttype = MP_RAILWAY; break;
 
					case TRANSPORT_ROAD: ttype = MP_ROAD;    break;
 
					default:             ttype = MP_WATER;   break;
 
				}
 
				break;
src/station.cpp
Show inline comments
 
@@ -407,52 +407,52 @@ void Station::RecomputeCatchment()
 
{
 
	this->industries_near.clear();
 
	this->RemoveFromAllNearbyLists();
 

	
 
	if (this->rect.IsEmpty()) {
 
		this->catchment_tiles.Reset();
 
		return;
 
	}
 

	
 
	if (!_settings_game.station.serve_neutral_industries && this->industry != nullptr) {
 
		/* Station is associated with an industry, so we only need to deliver to that industry. */
 
		this->catchment_tiles.Initialize(this->industry->location);
 
		TILE_AREA_LOOP(tile, this->industry->location) {
 
		for (TileIndex tile : this->industry->location) {
 
			if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == this->industry->index) {
 
				this->catchment_tiles.SetTile(tile);
 
			}
 
		}
 
		/* The industry's stations_near may have been computed before its neutral station was built so clear and re-add here. */
 
		for (Station *st : this->industry->stations_near) {
 
			st->industries_near.erase(this->industry);
 
		}
 
		this->industry->stations_near.clear();
 
		this->industry->stations_near.insert(this);
 
		this->industries_near.insert(this->industry);
 
		return;
 
	}
 

	
 
	this->catchment_tiles.Initialize(GetCatchmentRect());
 

	
 
	/* Loop finding all station tiles */
 
	TileArea ta(TileXY(this->rect.left, this->rect.top), TileXY(this->rect.right, this->rect.bottom));
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		if (!IsTileType(tile, MP_STATION) || GetStationIndex(tile) != this->index) continue;
 

	
 
		uint r = GetTileCatchmentRadius(tile, this);
 
		if (r == CA_NONE) continue;
 

	
 
		/* This tile sub-loop doesn't need to test any tiles, they are simply added to the catchment set. */
 
		TileArea ta2 = TileArea(tile, 1, 1).Expand(r);
 
		TILE_AREA_LOOP(tile2, ta2) this->catchment_tiles.SetTile(tile2);
 
		for (TileIndex tile2 : ta2) this->catchment_tiles.SetTile(tile2);
 
	}
 

	
 
	/* Search catchment tiles for towns and industries */
 
	BitmapTileIterator it(this->catchment_tiles);
 
	for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
 
		if (IsTileType(tile, MP_HOUSE)) {
 
			Town *t = Town::GetByTile(tile);
 
			t->stations_near.insert(this);
 
		}
 
		if (IsTileType(tile, MP_INDUSTRY)) {
 
			Industry *i = Industry::GetByTile(tile);
 

	
 
@@ -558,25 +558,25 @@ CommandCost StationRect::BeforeAddRect(T
 
/**
 
 * Check whether station tiles of the given station id exist in the given rectangle
 
 * @param st_id    Station ID to look for in the rectangle
 
 * @param left_a   Minimal tile X edge of the rectangle
 
 * @param top_a    Minimal tile Y edge of the rectangle
 
 * @param right_a  Maximal tile X edge of the rectangle (inclusive)
 
 * @param bottom_a Maximal tile Y edge of the rectangle (inclusive)
 
 * @return \c true if a station tile with the given \a st_id exists in the rectangle, \c false otherwise
 
 */
 
/* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
 
{
 
	TileArea ta(TileXY(left_a, top_a), TileXY(right_a, bottom_a));
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
bool StationRect::AfterRemoveTile(BaseStation *st, TileIndex tile)
 
{
 
	int x = TileX(tile);
 
	int y = TileY(tile);
 

	
 
	/* look if removed tile was on the bounding rect edge
src/station_base.h
Show inline comments
 
@@ -566,33 +566,33 @@ void RebuildStationKdtree();
 
 *             if coverage of that tile is acceptable for a given station or false if search should continue
 
 */
 
template<typename Func>
 
void ForAllStationsAroundTiles(const TileArea &ta, Func func)
 
{
 
	/* Not using, or don't have a nearby stations list, so we need to scan. */
 
	std::set<StationID> seen_stations;
 

	
 
	/* Scan an area around the building covering the maximum possible station
 
	 * to find the possible nearby stations. */
 
	uint max_c = _settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED;
 
	TileArea ta_ext = TileArea(ta).Expand(max_c);
 
	TILE_AREA_LOOP(tile, ta_ext) {
 
	for (TileIndex tile : ta_ext) {
 
		if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile));
 
	}
 

	
 
	for (StationID stationid : seen_stations) {
 
		Station *st = Station::GetIfValid(stationid);
 
		if (st == nullptr) continue; /* Waypoint */
 

	
 
		/* Check if station is attached to an industry */
 
		if (!_settings_game.station.serve_neutral_industries && st->industry != nullptr) continue;
 

	
 
		/* Test if the tile is within the station's catchment */
 
		TILE_AREA_LOOP(tile, ta) {
 
		for (TileIndex tile : ta) {
 
			if (st->TileIsInCatchment(tile)) {
 
				if (func(st, tile)) break;
 
			}
 
		}
 
	}
 
}
 

	
 
#endif /* STATION_BASE_H */
src/station_cmd.cpp
Show inline comments
 
@@ -96,25 +96,25 @@ bool IsHangar(TileIndex t)
 
 * @param ta the area to search over
 
 * @param closest_station the closest owned station found so far
 
 * @param company the company whose stations to look for
 
 * @param st to 'return' the found station
 
 * @return Succeeded command (if zero or one station found) or failed command (for two or more stations found).
 
 */
 
template <class T>
 
CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
 
{
 
	ta.Expand(1);
 

	
 
	/* check around to see if there are any stations there owned by the company */
 
	TILE_AREA_LOOP(tile_cur, ta) {
 
	for (TileIndex tile_cur : ta) {
 
		if (IsTileType(tile_cur, MP_STATION)) {
 
			StationID t = GetStationIndex(tile_cur);
 
			if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
 
			if (closest_station == INVALID_STATION) {
 
				closest_station = t;
 
			} else if (closest_station != t) {
 
				return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
 
			}
 
		}
 
	}
 
	*st = (closest_station == INVALID_STATION) ? nullptr : T::Get(closest_station);
 
	return CommandCost();
 
@@ -502,25 +502,25 @@ static void ShowRejectOrAcceptNews(const
 
 * @param w X extent of the area
 
 * @param h Y extent of the area
 
 * @param rad Search radius in addition to the given area
 
 */
 
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad)
 
{
 
	CargoArray produced;
 
	std::set<IndustryID> industries;
 
	TileArea ta = TileArea(tile, w, h).Expand(rad);
 

	
 
	/* Loop over all tiles to get the produced cargo of
 
	 * everything except industries */
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		if (IsTileType(tile, MP_INDUSTRY)) industries.insert(GetIndustryIndex(tile));
 
		AddProducedCargo(tile, produced);
 
	}
 

	
 
	/* Loop over the seen industries. They produce cargo for
 
	 * anything that is within 'rad' of any one of their tiles.
 
	 */
 
	for (IndustryID industry : industries) {
 
		const Industry *i = Industry::Get(industry);
 
		/* Skip industry with neutral station */
 
		if (i->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) continue;
 

	
 
@@ -540,25 +540,25 @@ CargoArray GetProductionAroundTiles(Tile
 
 * @param h Y extent of area
 
 * @param rad Search radius in addition to given area
 
 * @param always_accepted bitmask of cargo accepted by houses and headquarters; can be nullptr
 
 * @param ind Industry associated with neutral station (e.g. oil rig) or nullptr
 
 */
 
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted)
 
{
 
	CargoArray acceptance;
 
	if (always_accepted != nullptr) *always_accepted = 0;
 

	
 
	TileArea ta = TileArea(tile, w, h).Expand(rad);
 

	
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		/* Ignore industry if it has a neutral station. */
 
		if (!_settings_game.station.serve_neutral_industries && IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile)->neutral_station != nullptr) continue;
 

	
 
		AddAcceptedCargo(tile, acceptance, always_accepted);
 
	}
 

	
 
	return acceptance;
 
}
 

	
 
/**
 
 * Get the acceptance of cargoes around the station in.
 
 * @param st Station to get acceptance of.
 
@@ -863,25 +863,25 @@ static CommandCost CheckFlatLandAirport(
 
 * @param numtracks Number of platforms.
 
 * @return The cost in case of success, or an error code if it failed.
 
 */
 
static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, std::vector<Train *> &affected_vehicles, StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
 
{
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	int allowed_z = -1;
 
	uint invalid_dirs = 5 << axis;
 

	
 
	const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
 
	bool slope_cb = statspec != nullptr && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK);
 

	
 
	TILE_AREA_LOOP(tile_cur, tile_area) {
 
	for (TileIndex tile_cur : tile_area) {
 
		CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false);
 
		if (ret.Failed()) return ret;
 
		cost.AddCost(ret);
 

	
 
		if (slope_cb) {
 
			/* Do slope check if requested. */
 
			ret = PerformStationTileSlopeCheck(tile_area.tile, tile_cur, statspec, axis, plat_len, numtracks);
 
			if (ret.Failed()) return ret;
 
		}
 

	
 
		/* if station is set, then we have special handling to allow building on top of already existing stations.
 
		 * so station points to INVALID_STATION if we can build on any station.
 
@@ -945,25 +945,25 @@ static CommandCost CheckFlatLandRailStat
 
 * @param is_drive_through True if trying to build a drive-through station.
 
 * @param is_truck_stop True when building a truck stop, false otherwise.
 
 * @param axis Axis of a drive-through road stop.
 
 * @param station StationID to be queried and returned if available.
 
 * @param rt Road type to build.
 
 * @return The cost in case of success, or an error code if it failed.
 
 */
 
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadType rt)
 
{
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	int allowed_z = -1;
 

	
 
	TILE_AREA_LOOP(cur_tile, tile_area) {
 
	for (TileIndex cur_tile : tile_area) {
 
		CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through);
 
		if (ret.Failed()) return ret;
 
		cost.AddCost(ret);
 

	
 
		/* If station is set, then we have special handling to allow building on top of already existing stations.
 
		 * Station points to INVALID_STATION if we can build on any station.
 
		 * Or it points to a station if we're only allowed to build on exactly that station. */
 
		if (station != nullptr && IsTileType(cur_tile, MP_STATION)) {
 
			if (!IsRoadStop(cur_tile)) {
 
				return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
 
			} else {
 
				if (is_truck_stop != IsTruckStop(cur_tile) ||
 
@@ -1426,25 +1426,25 @@ CommandCost CmdBuildRailStation(TileInde
 
			/* Restore reservations of trains. */
 
			RestoreTrainReservation(affected_vehicles[i]);
 
		}
 

	
 
		/* Check whether we need to expand the reservation of trains already on the station. */
 
		TileArea update_reservation_area;
 
		if (axis == AXIS_X) {
 
			update_reservation_area = TileArea(tile_org, 1, numtracks_orig);
 
		} else {
 
			update_reservation_area = TileArea(tile_org, numtracks_orig, 1);
 
		}
 

	
 
		TILE_AREA_LOOP(tile, update_reservation_area) {
 
		for (TileIndex tile : update_reservation_area) {
 
			/* Don't even try to make eye candy parts reserved. */
 
			if (IsStationTileBlocked(tile)) continue;
 

	
 
			DiagDirection dir = AxisToDiagDir(axis);
 
			TileIndexDiff tile_offset = TileOffsByDiagDir(dir);
 
			TileIndex platform_begin = tile;
 
			TileIndex platform_end = tile;
 

	
 
			/* We can only account for tiles that are reachable from this tile, so ignore primarily blocked tiles while finding the platform begin and end. */
 
			for (TileIndex next_tile = platform_begin - tile_offset; IsCompatibleTrainStationTile(next_tile, platform_begin); next_tile -= tile_offset) {
 
				platform_begin = next_tile;
 
			}
 
@@ -1554,25 +1554,25 @@ static void MakeShipStationAreaSmaller(S
 
template <class T>
 
CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector<T *> &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
 
{
 
	/* Count of the number of tiles removed */
 
	int quantity = 0;
 
	CommandCost total_cost(EXPENSES_CONSTRUCTION);
 
	/* Accumulator for the errors seen during clearing. If no errors happen,
 
	 * and the quantity is 0 there is no station. Otherwise it will be one
 
	 * of the other error that got accumulated. */
 
	CommandCost error;
 

	
 
	/* Do the action for every tile into the area */
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		/* Make sure the specified tile is a rail station */
 
		if (!HasStationTileRail(tile)) continue;
 

	
 
		/* If there is a vehicle on ground, do not allow to remove (flood) the tile */
 
		CommandCost ret = EnsureNoVehicleOnGround(tile);
 
		error.AddCost(ret);
 
		if (ret.Failed()) continue;
 

	
 
		/* Check ownership of station */
 
		T *st = T::GetByTile(tile);
 
		if (st == nullptr) continue;
 

	
 
@@ -1720,25 +1720,25 @@ CommandCost RemoveRailStation(T *st, DoC
 
	if (_current_company != OWNER_WATER) {
 
		CommandCost ret = CheckOwnership(st->owner);
 
		if (ret.Failed()) return ret;
 
	}
 

	
 
	/* determine width and height of platforms */
 
	TileArea ta = st->train_station;
 

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

	
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	/* clear all areas of the station */
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		/* only remove tiles that are actually train station tiles */
 
		if (st->TileBelongsToRailStation(tile)) {
 
			std::vector<T*> affected_stations; // dummy
 
			CommandCost ret = RemoveFromRailBaseStation(TileArea(tile, 1, 1), affected_stations, flags, removal_cost, false);
 
			if (ret.Failed()) return ret;
 
			cost.AddCost(ret);
 
		}
 
	}
 

	
 
	return cost;
 
}
 

	
 
@@ -1885,25 +1885,25 @@ CommandCost CmdBuildRoadStop(TileIndex t
 
	Station *st = nullptr;
 
	ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 2), roadstop_area, &st);
 
	if (ret.Failed()) return ret;
 

	
 
	/* Check if this number of road stops can be allocated. */
 
	if (!RoadStop::CanAllocateItem(roadstop_area.w * roadstop_area.h)) return_cmd_error(type ? STR_ERROR_TOO_MANY_TRUCK_STOPS : STR_ERROR_TOO_MANY_BUS_STOPS);
 

	
 
	ret = BuildStationPart(&st, flags, reuse, roadstop_area, STATIONNAMING_ROAD);
 
	if (ret.Failed()) return ret;
 

	
 
	if (flags & DC_EXEC) {
 
		/* Check every tile in the area. */
 
		TILE_AREA_LOOP(cur_tile, roadstop_area) {
 
		for (TileIndex cur_tile : roadstop_area) {
 
			/* Get existing road types and owners before any tile clearing */
 
			RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE;
 
			RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE;
 
			Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company;
 
			Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company;
 

	
 
			if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
 
				RemoveRoadStop(cur_tile, flags);
 
			}
 

	
 
			RoadStop *road_stop = new RoadStop(cur_tile);
 
			/* Insert into linked list of RoadStops. */
 
@@ -2092,25 +2092,25 @@ CommandCost CmdRemoveRoadStop(TileIndex 
 
	if (width == 0 || height == 0) return CMD_ERROR;
 
	/* Check if the first tile and the last tile are valid */
 
	if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, height - 1) == INVALID_TILE) return CMD_ERROR;
 
	/* Bankrupting company is not supposed to remove roads, there may be road vehicles. */
 
	if (!keep_drive_through_roads && (flags & DC_BANKRUPT)) return CMD_ERROR;
 

	
 
	TileArea roadstop_area(tile, width, height);
 

	
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
 
	bool had_success = false;
 

	
 
	TILE_AREA_LOOP(cur_tile, roadstop_area) {
 
	for (TileIndex cur_tile : roadstop_area) {
 
		/* Make sure the specified tile is a road stop of the correct type */
 
		if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
 

	
 
		/* Save information on to-be-restored roads before the stop is removed. */
 
		RoadBits road_bits = ROAD_NONE;
 
		RoadType road_type[] = { INVALID_ROADTYPE, INVALID_ROADTYPE };
 
		Owner road_owner[] = { OWNER_NONE, OWNER_NONE };
 
		if (IsDriveThroughStopTile(cur_tile)) {
 
			for (RoadTramType rtt : _roadtramtypes) {
 
				road_type[rtt] = GetRoadType(cur_tile, rtt);
 
				if (road_type[rtt] == INVALID_ROADTYPE) continue;
 
				road_owner[rtt] = GetRoadOwner(cur_tile, rtt);
 
@@ -2400,25 +2400,25 @@ static CommandCost RemoveAirport(TileInd
 
		}
 

	
 
		const AirportSpec *as = st->airport.GetSpec();
 
		/* The noise level is the noise from the airport and reduce it to account for the distance to the town center.
 
		 * And as for construction, always remove it, even if the setting is not set, in order to avoid the
 
		 * need of recalculation */
 
		AirportTileIterator it(st);
 
		uint dist;
 
		Town *nearest = AirportGetNearestTown(as, it, dist);
 
		nearest->noise_reached -= GetAirportNoiseLevelForDistance(as, dist);
 
	}
 

	
 
	TILE_AREA_LOOP(tile_cur, st->airport) {
 
	for (TileIndex tile_cur : st->airport) {
 
		if (!st->TileBelongsToAirport(tile_cur)) continue;
 

	
 
		CommandCost ret = EnsureNoVehicleOnGround(tile_cur);
 
		if (ret.Failed()) return ret;
 

	
 
		cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
 

	
 
		if (flags & DC_EXEC) {
 
			DeleteAnimatedTile(tile_cur);
 
			DoClearSquare(tile_cur);
 
			DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
 
		}
 
@@ -4111,25 +4111,25 @@ void UpdateStationDockingTiles(Station *
 
	int x = TileX(area->tile);
 
	int y = TileY(area->tile);
 

	
 
	/* Expand the area by a tile on each side while
 
	 * making sure that we remain inside the map. */
 
	int x2 = std::min<int>(x + area->w + 1, MapSizeX());
 
	int x1 = std::max<int>(x - 1, 0);
 

	
 
	int y2 = std::min<int>(y + area->h + 1, MapSizeY());
 
	int y1 = std::max<int>(y - 1, 0);
 

	
 
	TileArea ta(TileXY(x1, y1), TileXY(x2 - 1, y2 - 1));
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		if (IsValidTile(tile) && IsPossibleDockingTile(tile)) CheckForDockingTile(tile);
 
	}
 
}
 

	
 
void BuildOilRig(TileIndex tile)
 
{
 
	if (!Station::CanAllocateItem()) {
 
		DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
 
		return;
 
	}
 

	
 
	Station *st = new Station(tile);
src/station_gui.cpp
Show inline comments
 
@@ -94,25 +94,25 @@ static void FindStationsAroundSelection(
 
	TileArea location(TileVirtXY(_thd.pos.x, _thd.pos.y), _thd.size.x / TILE_SIZE - 1, _thd.size.y / TILE_SIZE - 1);
 

	
 
	/* Extended area by one tile */
 
	uint x = TileX(location.tile);
 
	uint y = TileY(location.tile);
 

	
 
	int max_c = 1;
 
	TileArea ta(TileXY(std::max<int>(0, x - max_c), std::max<int>(0, y - max_c)), TileXY(std::min<int>(MapMaxX(), x + location.w + max_c), std::min<int>(MapMaxY(), y + location.h + max_c)));
 

	
 
	Station *adjacent = nullptr;
 

	
 
	/* Direct loop instead of ForAllStationsAroundTiles as we are not interested in catchment area */
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) {
 
			Station *st = Station::GetByTile(tile);
 
			if (st == nullptr) continue;
 
			if (adjacent != nullptr && st != adjacent) {
 
				/* Multiple nearby, distant join is required. */
 
				adjacent = nullptr;
 
				break;
 
			}
 
			adjacent = st;
 
		}
 
	}
 
	SetViewportCatchmentStation(adjacent, true);
 
@@ -2205,25 +2205,25 @@ static bool AddNearbyStation(TileIndex t
 
 *                     within station spread
 
 * @tparam T the type of station to look for
 
 */
 
template <class T>
 
static const T *FindStationsNearby(TileArea ta, bool distant_join)
 
{
 
	TileArea ctx = ta;
 

	
 
	_stations_nearby_list.clear();
 
	_deleted_stations_nearby.clear();
 

	
 
	/* Check the inside, to return, if we sit on another station */
 
	TILE_AREA_LOOP(t, ta) {
 
	for (TileIndex t : ta) {
 
		if (t < MapSize() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return T::GetByTile(t);
 
	}
 

	
 
	/* Look for deleted stations */
 
	for (const BaseStation *st : BaseStation::Iterate()) {
 
		if (T::IsExpected(st) && !st->IsInUse() && st->owner == _local_company) {
 
			/* Include only within station spread (yes, it is strictly less than) */
 
			if (std::max(DistanceMax(ta.tile, st->xy), DistanceMax(TILE_ADDXY(ta.tile, ta.w - 1, ta.h - 1), st->xy)) < _settings_game.station.station_spread) {
 
				_deleted_stations_nearby.push_back({st->xy, st->index});
 

	
 
				/* Add the station when it's within where we're going to build */
 
				if (IsInsideBS(TileX(st->xy), TileX(ctx.tile), ctx.w) &&
src/subsidy.cpp
Show inline comments
 
@@ -320,25 +320,25 @@ bool FindSubsidyTownCargoRoute()
 
{
 
	if (!Subsidy::CanAllocateItem()) return false;
 

	
 
	SourceType src_type = ST_TOWN;
 

	
 
	/* Select a random town. */
 
	const Town *src_town = Town::GetRandom();
 
	if (src_town->cache.population < SUBSIDY_CARGO_MIN_POPULATION) return false;
 

	
 
	/* Calculate the produced cargo of houses around town center. */
 
	CargoArray town_cargo_produced;
 
	TileArea ta = TileArea(src_town->xy, 1, 1).Expand(SUBSIDY_TOWN_CARGO_RADIUS);
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		if (IsTileType(tile, MP_HOUSE)) {
 
			AddProducedCargo(tile, town_cargo_produced);
 
		}
 
	}
 

	
 
	/* Passenger subsidies are not handled here. */
 
	town_cargo_produced[CT_PASSENGERS] = 0;
 

	
 
	uint8 cargo_count = 0;
 
	for (CargoID i = 0; i < NUM_CARGO; i++) {
 
		if (town_cargo_produced[i] > 0) cargo_count++;
 
	}
 
@@ -431,25 +431,25 @@ bool FindSubsidyCargoDestination(CargoID
 
	/* Choose a random destination. */
 
	SourceType dst_type = Chance16(1, 2) ? ST_TOWN : ST_INDUSTRY;
 

	
 
	SourceID dst;
 
	switch (dst_type) {
 
		case ST_TOWN: {
 
			/* Select a random town. */
 
			const Town *dst_town = Town::GetRandom();
 

	
 
			/* Calculate cargo acceptance of houses around town center. */
 
			CargoArray town_cargo_accepted;
 
			TileArea ta = TileArea(dst_town->xy, 1, 1).Expand(SUBSIDY_TOWN_CARGO_RADIUS);
 
			TILE_AREA_LOOP(tile, ta) {
 
			for (TileIndex tile : ta) {
 
				if (IsTileType(tile, MP_HOUSE)) {
 
					AddAcceptedCargo(tile, town_cargo_accepted, nullptr);
 
				}
 
			}
 

	
 
			/* Check if the town can accept this cargo. */
 
			if (town_cargo_accepted[cid] < 8) return false;
 

	
 
			dst = dst_town->index;
 
			break;
 
		}
 

	
src/terraform_gui.cpp
Show inline comments
 
@@ -48,42 +48,42 @@ void CcTerraform(const CommandCost &resu
 
	}
 
}
 

	
 

	
 
/** Scenario editor command that generates desert areas */
 
static void GenerateDesertArea(TileIndex end, TileIndex start)
 
{
 
	if (_game_mode != GM_EDITOR) return;
 

	
 
	_generating_world = true;
 

	
 
	TileArea ta(start, end);
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		SetTropicZone(tile, (_ctrl_pressed) ? TROPICZONE_NORMAL : TROPICZONE_DESERT);
 
		DoCommandP(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
 
		MarkTileDirtyByTile(tile);
 
	}
 
	_generating_world = false;
 
	InvalidateWindowClassesData(WC_TOWN_VIEW, 0);
 
}
 

	
 
/** Scenario editor command that generates rocky areas */
 
static void GenerateRockyArea(TileIndex end, TileIndex start)
 
{
 
	if (_game_mode != GM_EDITOR) return;
 

	
 
	bool success = false;
 
	TileArea ta(start, end);
 

	
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		switch (GetTileType(tile)) {
 
			case MP_TREES:
 
				if (GetTreeGround(tile) == TREE_GROUND_SHORE) continue;
 
				FALLTHROUGH;
 

	
 
			case MP_CLEAR:
 
				MakeClear(tile, CLEAR_ROCKS, 3);
 
				break;
 

	
 
			default:
 
				continue;
 
		}
 
@@ -399,36 +399,36 @@ static void CommonRaiseLowerBigLand(Tile
 
		assert(_terraform_size != 0);
 
		TileArea ta(tile, _terraform_size, _terraform_size);
 
		ta.ClampToMap();
 

	
 
		if (ta.w == 0 || ta.h == 0) return;
 

	
 
		if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
 

	
 
		uint h;
 
		if (mode != 0) {
 
			/* Raise land */
 
			h = MAX_TILE_HEIGHT;
 
			TILE_AREA_LOOP(tile2, ta) {
 
			for (TileIndex tile2 : ta) {
 
				h = std::min(h, TileHeight(tile2));
 
			}
 
		} else {
 
			/* Lower land */
 
			h = 0;
 
			TILE_AREA_LOOP(tile2, ta) {
 
			for (TileIndex tile2 : ta) {
 
				h = std::max(h, TileHeight(tile2));
 
			}
 
		}
 

	
 
		TILE_AREA_LOOP(tile2, ta) {
 
		for (TileIndex tile2 : ta) {
 
			if (TileHeight(tile2) == h) {
 
				DoCommandP(tile2, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND);
 
			}
 
		}
 
	}
 
}
 

	
 
static const int8 _multi_terraform_coords[][2] = {
 
	{  0, -2},
 
	{  4,  0}, { -4,  0}, {  0,  2},
 
	{ -8,  2}, { -4,  4}, {  0,  6}, {  4,  4}, {  8,  2},
 
	{-12,  0}, { -8, -2}, { -4, -4}, {  0, -6}, {  4, -4}, {  8, -2}, { 12,  0},
src/tilearea.cpp
Show inline comments
 
@@ -138,24 +138,42 @@ OrthogonalTileArea &OrthogonalTileArea::
 

	
 
/**
 
 * Clamp the tile area to map borders.
 
 */
 
void OrthogonalTileArea::ClampToMap()
 
{
 
	assert(this->tile < MapSize());
 
	this->w = std::min<int>(this->w, MapSizeX() - TileX(this->tile));
 
	this->h = std::min<int>(this->h, MapSizeY() - TileY(this->tile));
 
}
 

	
 
/**
 
 * Returns an iterator to the beginning of the tile area.
 
 * @return The OrthogonalTileIterator.
 
 */
 
OrthogonalTileIterator OrthogonalTileArea::begin() const
 
{
 
	return OrthogonalTileIterator(*this);
 
}
 

	
 
/**
 
 * Returns an iterator to the end of the tile area.
 
 * @return The OrthogonalTileIterator.
 
 */
 
OrthogonalTileIterator OrthogonalTileArea::end() const
 
{
 
	return OrthogonalTileIterator(OrthogonalTileArea());
 
}
 

	
 
/**
 
 * Create a diagonal tile area from two corners.
 
 * @param start First corner of the area.
 
 * @param end Second corner of the area.
 
 */
 
DiagonalTileArea::DiagonalTileArea(TileIndex start, TileIndex end) : tile(start)
 
{
 
	assert(start < MapSize());
 
	assert(end < MapSize());
 

	
 
	/* Unfortunately we can't find a new base and make all a and b positive because
 
	 * the new base might be a "flattened" corner where there actually is no single
 
	 * tile. If we try anyway the result is either inaccurate ("one off" half of the
src/tilearea_type.h
Show inline comments
 
@@ -3,24 +3,26 @@
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file tilearea_type.h Type for storing the 'area' of something uses on the map. */
 

	
 
#ifndef TILEAREA_TYPE_H
 
#define TILEAREA_TYPE_H
 

	
 
#include "map_func.h"
 

	
 
class OrthogonalTileIterator;
 

	
 
/** Represents the covered area of e.g. a rail station */
 
struct OrthogonalTileArea {
 
	TileIndex tile; ///< The base tile of the area
 
	uint16 w;       ///< The width of the area
 
	uint16 h;       ///< The height of the area
 

	
 
	/**
 
	 * Construct this tile area with some set values
 
	 * @param tile the base tile
 
	 * @param w the width
 
	 * @param h the height
 
	 */
 
@@ -49,24 +51,28 @@ struct OrthogonalTileArea {
 
	OrthogonalTileArea &Expand(int rad);
 

	
 
	void ClampToMap();
 

	
 
	/**
 
	 * Get the center tile.
 
	 * @return The tile at the center, or just north of it.
 
	 */
 
	TileIndex GetCenterTile() const
 
	{
 
		return TILE_ADDXY(this->tile, this->w / 2, this->h / 2);
 
	}
 

	
 
	OrthogonalTileIterator begin() const;
 

	
 
	OrthogonalTileIterator end() const;
 
};
 

	
 
/** Represents a diagonal tile area. */
 
struct DiagonalTileArea {
 

	
 
	TileIndex tile; ///< Base tile of the area
 
	int16 a;        ///< Extent in diagonal "x" direction (may be negative to signify the area stretches to the left)
 
	int16 b;        ///< Extent in diagonal "y" direction (may be negative to signify the area stretches upwards)
 

	
 
	/**
 
	 * Construct this tile area with some set values.
 
	 * @param tile The base tile.
 
@@ -115,24 +121,33 @@ public:
 
	}
 

	
 
	/**
 
	 * Get the tile we are currently at.
 
	 * @return The tile we are at, or INVALID_TILE when we're done.
 
	 */
 
	inline operator TileIndex () const
 
	{
 
		return this->tile;
 
	}
 

	
 
	/**
 
	 * Get the tile we are currently at.
 
	 * @return The tile we are at, or INVALID_TILE when we're done.
 
	 */
 
	inline TileIndex operator *() const
 
	{
 
		return this->tile;
 
	}
 

	
 
	/**
 
	 * Move ourselves to the next tile in the rectangle on the map.
 
	 */
 
	virtual TileIterator& operator ++() = 0;
 

	
 
	/**
 
	 * Allocate a new iterator that is a copy of this one.
 
	 */
 
	virtual TileIterator *Clone() const = 0;
 
};
 

	
 
/** Iterator to iterate over a tile area (rectangle) of the map. */
 
class OrthogonalTileIterator : public TileIterator {
 
@@ -214,21 +229,13 @@ public:
 
	{
 
		*this = DiagonalTileIterator(DiagonalTileArea(corner1, corner2));
 
	}
 

	
 
	TileIterator& operator ++();
 

	
 
	virtual TileIterator *Clone() const
 
	{
 
		return new DiagonalTileIterator(*this);
 
	}
 
};
 

	
 
/**
 
 * A loop which iterates over the tiles of a TileArea.
 
 * @param var The name of the variable which contains the current tile.
 
 *            This variable will be allocated in this \c for of this loop.
 
 * @param ta  The tile area to search over.
 
 */
 
#define TILE_AREA_LOOP(var, ta) for (OrthogonalTileIterator var(ta); var != INVALID_TILE; ++var)
 

	
 
#endif /* TILEAREA_TYPE_H */
src/tree_cmd.cpp
Show inline comments
 
@@ -383,25 +383,25 @@ CommandCost CmdPlantTree(TileIndex tile,
 
	StringID msg = INVALID_STRING_ID;
 
	CommandCost cost(EXPENSES_OTHER);
 
	const byte tree_to_plant = GB(p1, 0, 8); // We cannot use Extract as min and max are climate specific.
 

	
 
	if (p2 >= MapSize()) return CMD_ERROR;
 
	/* Check the tree type within the current climate */
 
	if (tree_to_plant != TREE_INVALID && !IsInsideBS(tree_to_plant, _tree_base_by_landscape[_settings_game.game_creation.landscape], _tree_count_by_landscape[_settings_game.game_creation.landscape])) return CMD_ERROR;
 

	
 
	Company *c = (_game_mode != GM_EDITOR) ? Company::GetIfValid(_current_company) : nullptr;
 
	int limit = (c == nullptr ? INT32_MAX : GB(c->tree_limit, 16, 16));
 

	
 
	TileArea ta(tile, p2);
 
	TILE_AREA_LOOP(tile, ta) {
 
	for (TileIndex tile : ta) {
 
		switch (GetTileType(tile)) {
 
			case MP_TREES:
 
				/* no more space for trees? */
 
				if (GetTreeCount(tile) == 4) {
 
					msg = STR_ERROR_TREE_ALREADY_HERE;
 
					continue;
 
				}
 

	
 
				/* Test tree limit. */
 
				if (--limit < 1) {
 
					msg = STR_ERROR_TREE_PLANT_LIMIT_REACHED;
 
					break;
src/water_cmd.cpp
Show inline comments
 
@@ -1035,25 +1035,25 @@ static Vehicle *FloodVehicleProc(Vehicle
 

	
 
/**
 
 * Finds a vehicle to flood.
 
 * It does not find vehicles that are already crashed on bridges, i.e. flooded.
 
 * @param tile the tile where to find a vehicle to flood
 
 */
 
static void FloodVehicles(TileIndex tile)
 
{
 
	int z = 0;
 

	
 
	if (IsAirportTile(tile)) {
 
		const Station *st = Station::GetByTile(tile);
 
		TILE_AREA_LOOP(tile, st->airport) {
 
		for (TileIndex tile : st->airport) {
 
			if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc);
 
		}
 

	
 
		/* No vehicle could be flooded on this airport anymore */
 
		return;
 
	}
 

	
 
	if (!IsBridgeTile(tile)) {
 
		FindVehicleOnPos(tile, &z, &FloodVehicleProc);
 
		return;
 
	}
 

	
0 comments (0 inline, 0 general)