Changeset - r8814:8b2b17bb64fc
[Not reviewed]
master
0 4 0
smatz - 16 years ago 2008-04-04 14:53:06
smatz@openttd.org
(svn r12560) -Cleanup: town_cmd.cpp and header files - variable scope and a bit of coding style
4 files changed with 123 insertions and 152 deletions:
0 comments (0 inline, 0 general)
src/economy.cpp
Show inline comments
 
@@ -348,13 +348,13 @@ void ChangeOwnershipOfPlayerItems(Player
 
					t->ratings[new_player] = t->ratings[old_player];
 
				}
 
			}
 
		}
 

	
 
		/* Reset the ratings for the old player */
 
		t->ratings[old_player] = 500;
 
		t->ratings[old_player] = RATING_INITIAL;
 
		ClrBit(t->have_ratings, old_player);
 
	}
 

	
 
	{
 
		int num_train = 0;
 
		int num_road = 0;
src/town.h
Show inline comments
 
@@ -44,18 +44,23 @@ enum BuildingFlags {
 
	BUILDING_HAS_4_TILES = TILE_SIZE_2x2,
 
};
 

	
 
DECLARE_ENUM_AS_BIT_SET(BuildingFlags)
 

	
 
enum HouseZonesBits {
 
	HZB_BEGIN     = 0,
 
	HZB_TOWN_EDGE = 0,
 
	HZB_TOWN_OUTSKIRT,
 
	HZB_TOWN_OUTER_SUBURB,
 
	HZB_TOWN_INNER_SUBURB,
 
	HZB_TOWN_CENTRE,
 
	HZB_END,
 
};
 
assert_compile(HZB_END == 5);
 

	
 
DECLARE_POSTFIX_INCREMENT(HouseZonesBits)
 

	
 
enum HouseZones {                  ///< Bit  Value       Meaning
 
	HZ_NOZNS             = 0x0000,  ///<       0          This is just to get rid of zeros, meaning none
 
	HZ_ZON1              = 1U << HZB_TOWN_EDGE,    ///< 0..4 1,2,4,8,10  which town zones the building can be built in, Zone1 been the further suburb
 
	HZ_ZON2              = 1U << HZB_TOWN_OUTSKIRT,
 
	HZ_ZON3              = 1U << HZB_TOWN_OUTER_SUBURB,
 
@@ -155,13 +160,13 @@ struct Town : PoolItem<Town, TownID, &_T
 
	byte road_build_months;
 

	
 
	/* If this is a larger town, and should grow more quickly. */
 
	bool larger_town;
 

	
 
	/* NOSAVE: UpdateTownRadius updates this given the house count. */
 
	uint16 radius[5];
 
	uint16 radius[HZB_END];
 

	
 
	/* NOSAVE: The number of each type of building in the town. */
 
	BuildingCounts building_counts;
 

	
 
	/* NOSAVE: The town specific road layout */
 
	TownLayout layout;
src/town_cmd.cpp
Show inline comments
 
@@ -139,13 +139,13 @@ static bool BuildTownHouse(Town *t, Tile
 
static void TownDrawHouseLift(const TileInfo *ti)
 
{
 
	AddChildSpriteScreen(SPR_LIFT, PAL_NONE, 14, 60 - GetLiftPosition(ti->tile));
 
}
 

	
 
typedef void TownDrawTileProc(const TileInfo *ti);
 
static TownDrawTileProc * const _town_draw_tile_procs[1] = {
 
static TownDrawTileProc *const _town_draw_tile_procs[1] = {
 
	TownDrawHouseLift
 
};
 

	
 
/**
 
 * Return a random direction
 
 *
 
@@ -160,15 +160,12 @@ static inline DiagDirection RandomDiagDi
 
 * House Tile drawing handler.
 
 * Part of the tile loop process
 
 * @param ti TileInfo of the tile to draw
 
 */
 
static void DrawTile_Town(TileInfo *ti)
 
{
 
	const DrawBuildingsTileStruct *dcts;
 
	SpriteID image;
 
	SpriteID pal;
 
	HouseID house_id = GetHouseType(ti->tile);
 

	
 
	if (house_id >= NEW_HOUSE_OFFSET) {
 
		/* Houses don't necessarily need new graphics. If they don't have a
 
		 * spritegroup associated with them, then the sprite for the substitute
 
		 * house id is drawn instead. */
 
@@ -178,25 +175,23 @@ static void DrawTile_Town(TileInfo *ti)
 
		} else {
 
			house_id = GetHouseSpecs(house_id)->substitute_id;
 
		}
 
	}
 

	
 
	/* Retrieve pointer to the draw town tile struct */
 
	dcts = &_town_draw_tile_data[house_id << 4 | TileHash2Bit(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)];
 
	const DrawBuildingsTileStruct *dcts = &_town_draw_tile_data[house_id << 4 | TileHash2Bit(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)];
 

	
 
	if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
 

	
 
	image = dcts->ground.sprite;
 
	pal   = dcts->ground.pal;
 
	DrawGroundSprite(image, pal);
 
	DrawGroundSprite(dcts->ground.sprite, dcts->ground.pal);
 

	
 
	/* If houses are invisible, do not draw the upper part */
 
	if (IsInvisibilitySet(TO_HOUSES)) return;
 

	
 
	/* Add a house on top of the ground? */
 
	image = dcts->building.sprite;
 
	SpriteID image = dcts->building.sprite;
 
	if (image != 0) {
 
		AddSortableSpriteToDraw(image, dcts->building.pal,
 
			ti->x + dcts->subtile_x,
 
			ti->y + dcts->subtile_y,
 
			dcts->width,
 
			dcts->height,
 
@@ -230,14 +225,12 @@ static Foundation GetFoundation_Town(Til
 
 * Only certain houses can be animated
 
 * The newhouses animation superseeds regular ones
 
 * @param tile TileIndex of the house to animate
 
 */
 
static void AnimateTile_Town(TileIndex tile)
 
{
 
	int pos, dest;
 

	
 
	if (GetHouseType(tile) >= NEW_HOUSE_OFFSET) {
 
		AnimateNewHouseTile(tile);
 
		return;
 
	}
 

	
 
	if (_tick_counter & 3) return;
 
@@ -249,27 +242,27 @@ static void AnimateTile_Town(TileIndex t
 
	if (!(GetHouseSpecs(GetHouseType(tile))->building_flags & BUILDING_IS_ANIMATED)) {
 
		DeleteAnimatedTile(tile);
 
		return;
 
	}
 

	
 
	if (!LiftHasDestination(tile)) {
 
		int i;
 

	
 
		/*  Building has 6 floors, number 0 .. 6, where 1 is illegal.
 
		 *  This is due to the fact that the first floor is, in the graphics,
 
		uint i;
 

	
 
		/* Building has 6 floors, number 0 .. 6, where 1 is illegal.
 
		 * This is due to the fact that the first floor is, in the graphics,
 
		 *  the height of 2 'normal' floors.
 
		 *  Furthermore, there are 6 lift positions from floor N (incl) to floor N + 1 (excl) */
 
		 * Furthermore, there are 6 lift positions from floor N (incl) to floor N + 1 (excl) */
 
		do {
 
			i = (Random() & 7) - 1;
 
		} while (i < 0 || i == 1 || i * 6 == GetLiftPosition(tile));
 
			i = RandomRange(7);
 
		} while (i == 1 || i * 6 == GetLiftPosition(tile));
 

	
 
		SetLiftDestination(tile, i);
 
	}
 

	
 
	pos = GetLiftPosition(tile);
 
	dest = GetLiftDestination(tile) * 6;
 
	int pos = GetLiftPosition(tile);
 
	int dest = GetLiftDestination(tile) * 6;
 
	pos += (pos < dest) ? 1 : -1;
 
	SetLiftPosition(tile, pos);
 

	
 
	if (pos == dest) HaltLift(tile);
 

	
 
	MarkTileDirtyByTile(tile);
 
@@ -280,13 +273,13 @@ static void AnimateTile_Town(TileIndex t
 
 * @param tile TileIndex of the tile to query
 
 * @param dist maximum distance to be accepted
 
 * @returns true if the tile correspond to the distance criteria
 
 */
 
static bool IsCloseToTown(TileIndex tile, uint dist)
 
{
 
	const Town* t;
 
	const Town *t;
 

	
 
	FOR_ALL_TOWNS(t) {
 
		if (DistanceManhattan(tile, t->xy) < dist) return true;
 
	}
 
	return false;
 
}
 
@@ -313,16 +306,14 @@ static void MarkTownSignDirty(Town *t)
 
 * Resize the sign(label) of the town after changes in
 
 * population (creation or growth or else)
 
 * @param t Town to update
 
 */
 
void UpdateTownVirtCoord(Town *t)
 
{
 
	Point pt;
 

	
 
	MarkTownSignDirty(t);
 
	pt = RemapCoords2(TileX(t->xy) * TILE_SIZE, TileY(t->xy) * TILE_SIZE);
 
	Point pt = RemapCoords2(TileX(t->xy) * TILE_SIZE, TileY(t->xy) * TILE_SIZE);
 
	SetDParam(0, t->index);
 
	SetDParam(1, t->population);
 
	UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24,
 
		_patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL);
 
	MarkTownSignDirty(t);
 
}
 
@@ -354,16 +345,15 @@ static void ChangePopulation(Town *t, in
 
 * Determines the world population
 
 * Basically, count population of all towns, one by one
 
 * @return uint32 the calculated population of the world
 
 */
 
uint32 GetWorldPopulation()
 
{
 
	uint32 pop;
 
	const Town* t;
 

	
 
	pop = 0;
 
	uint32 pop = 0;
 
	const Town *t;
 

	
 
	FOR_ALL_TOWNS(t) pop += t->population;
 
	return pop;
 
}
 

	
 
/**
 
 * Helper function for house completion stages progression
 
@@ -409,37 +399,36 @@ static void MakeTownHouseBigger(TileInde
 
/**
 
 * Periodic tic handler for houses and town
 
 * @param tile been asked to do its stuff
 
 */
 
static void TileLoop_Town(TileIndex tile)
 
{
 
	Town *t;
 
	uint32 r;
 
	HouseID house_id = GetHouseType(tile);
 
	HouseSpec *hs = GetHouseSpecs(house_id);
 

	
 
	/* NewHouseTileLoop returns false if Callback 21 succeeded, i.e. the house
 
	 * doesn't exist any more, so don't continue here. */
 
	if (house_id >= NEW_HOUSE_OFFSET && !NewHouseTileLoop(tile)) return;
 

	
 
	if (!IsHouseCompleted(tile)) {
 
		/* Construction is not completed. See if we can go further in construction*/
 
		MakeTownHouseBigger(tile);
 
		return;
 
	}
 

	
 
	const HouseSpec *hs = GetHouseSpecs(house_id);
 

	
 
	/* If the lift has a destination, it is already an animated tile. */
 
	if ((hs->building_flags & BUILDING_IS_ANIMATED) &&
 
			house_id < NEW_HOUSE_OFFSET &&
 
			!LiftHasDestination(tile) &&
 
			Chance16(1, 2))
 
			Chance16(1, 2)) {
 
		AddAnimatedTile(tile);
 

	
 
	t = GetTownByTile(tile);
 

	
 
	r = Random();
 
	}
 

	
 
	Town *t = GetTownByTile(tile);
 
	uint32 r = Random();
 

	
 
	if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
 
		for (uint i = 0; i < 256; i++) {
 
			uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile);
 

	
 
			if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
 
@@ -466,28 +455,24 @@ static void TileLoop_Town(TileIndex tile
 
					break;
 
			}
 
		}
 
	} else {
 
		if (GB(r, 0, 8) < hs->population) {
 
			uint amt = GB(r, 0, 8) / 8 + 1;
 
			uint moved;
 

	
 
			if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
 
			t->new_max_pass += amt;
 
			moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
 
			t->new_act_pass += moved;
 
			t->new_act_pass += MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
 
		}
 

	
 
		if (GB(r, 8, 8) < hs->mail_generation) {
 
			uint amt = GB(r, 8, 8) / 8 + 1;
 
			uint moved;
 

	
 
			if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
 
			t->new_max_mail += amt;
 
			moved = MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt);
 
			t->new_act_mail += moved;
 
			t->new_act_mail += MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt);
 
		}
 
	}
 

	
 
	_current_player = OWNER_TOWN;
 

	
 
	if (hs->building_flags & BUILDING_HAS_1_TILE &&
 
@@ -514,25 +499,23 @@ static void ClickTile_Town(TileIndex til
 
{
 
	/* not used */
 
}
 

	
 
static CommandCost ClearTile_Town(TileIndex tile, byte flags)
 
{
 
	int rating;
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	Town *t;
 
	HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	if (flags&DC_AUTO && !(flags&DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
 
	if ((flags & DC_AUTO) && !(flags & DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
 
	if (!CanDeleteHouse(tile)) return CMD_ERROR;
 

	
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	cost.AddCost(_price.remove_house * hs->removal_cost >> 8);
 

	
 
	rating = hs->remove_rating_decrease;
 
	int rating = hs->remove_rating_decrease;
 
	_cleared_town_rating += rating;
 
	_cleared_town = t = GetTownByTile(tile);
 
	Town *t = _cleared_town = GetTownByTile(tile);
 

	
 
	if (IsValidPlayer(_current_player)) {
 
		if (rating > t->ratings[_current_player] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) {
 
			SetDParam(0, t->index);
 
			return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
 
		}
 
@@ -545,13 +528,13 @@ static CommandCost ClearTile_Town(TileIn
 

	
 
	return cost;
 
}
 

	
 
static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac)
 
{
 
	HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
	CargoID accepts[3];
 

	
 
	/* Set the initial accepted cargo types */
 
	for (uint8 i = 0; i < lengthof(accepts); i++) {
 
		accepts[i] = hs->accepts_cargo[i];
 
	}
 
@@ -769,31 +752,27 @@ no_slope:
 
		return true;
 
	}
 
}
 

	
 
static bool TerraformTownTile(TileIndex tile, int edges, int dir)
 
{
 
	CommandCost r;
 

	
 
	TILE_ASSERT(tile);
 

	
 
	r = DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
 
	CommandCost r = DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
 
	if (CmdFailed(r) || r.GetCost() >= 126 * 16) return false;
 
	DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_TERRAFORM_LAND);
 
	return true;
 
}
 

	
 
static void LevelTownLand(TileIndex tile)
 
{
 
	Slope tileh;
 

	
 
	TILE_ASSERT(tile);
 

	
 
	/* Don't terraform if land is plain or if there's a house there. */
 
	if (IsTileType(tile, MP_HOUSE)) return;
 
	tileh = GetTileSlope(tile, NULL);
 
	Slope tileh = GetTileSlope(tile, NULL);
 
	if (tileh == SLOPE_FLAT) return;
 

	
 
	/* First try up, then down */
 
	if (!TerraformTownTile(tile, ~tileh & SLOPE_ELEVATED, 1)) {
 
		TerraformTownTile(tile, tileh & SLOPE_ELEVATED, 0);
 
	}
 
@@ -1225,16 +1204,17 @@ static RoadBits GenRandomRoadBits()
 
	uint b = GB(r, 8, 2);
 
	if (a == b) b ^= 2;
 
	return (RoadBits)((ROAD_NW << a) + (ROAD_NW << b));
 
}
 

	
 
/** Grow the town
 
 * @Return true if a house was built, or no if the build failed. */
 
 * @param t town to grow
 
 * @return true iff a house was built
 
 */
 
static bool GrowTown(Town *t)
 
{
 

	
 
	/* Let the town be a ghost town
 
	 * The player wanted it in such a way. Thus there he has it. ;)
 
	 * Never reached in editor mode. */
 
	if (_patches.town_layout == TL_NO_ROADS && _generating_world) {
 
		return false;
 
	}
 
@@ -1251,21 +1231,21 @@ static bool GrowTown(Town *t)
 
		{-1, -1},
 
		{-2,  2},
 
		{ 2,  2},
 
		{ 2, -2},
 
		{ 0,  0}
 
	};
 
	const TileIndexDiffC *ptr;
 

	
 
	/* Current player is a town */
 
	PlayerID old_player = _current_player;
 
	_current_player = OWNER_TOWN;
 

	
 
	TileIndex tile = t->xy; // The tile we are working with ATM
 

	
 
	/* Find a road that we can base the construction on. */
 
	const TileIndexDiffC *ptr;
 
	for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
 
		if (GetTownRoadBits(tile) != ROAD_NONE) {
 
			int r = GrowTownAtRoad(t, tile);
 
			_current_player = old_player;
 
			return r != 0;
 
		}
 
@@ -1350,13 +1330,13 @@ static bool CreateTownName(uint32 *townn
 
	 * too much). */
 
	int tries = 1000;
 
	bool grf = (_opt.town_name >= _nb_orig_names);
 
	uint32 grfid = grf ? GetGRFTownNameId(_opt.town_name - _nb_orig_names) : 0;
 
	uint16 townnametype = grf ? GetGRFTownNameType(_opt.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _opt.town_name;
 

	
 
	assert(townnameparts);
 
	assert(townnameparts != NULL);
 

	
 
	for (;;) {
 
restart:
 
		r = Random();
 

	
 
		SetDParam(0, r);
 
@@ -1399,13 +1379,12 @@ void UpdateTownMaxPass(Town *t)
 
 * @param size_mode How the size should be determined
 
 * @param size Parameter for size determination
 
 */
 
static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSizeMode size_mode, uint size)
 
{
 
	extern int _nb_orig_names;
 
	int x, i;
 

	
 
	t->xy = tile;
 
	t->num_houses = 0;
 
	t->time_until_rebuild = 10;
 
	UpdateTownRadius(t);
 
	t->flags12 = 0;
 
@@ -1426,14 +1405,13 @@ static void DoCreateTown(Town *t, TileIn
 
	t->fund_buildings_months = 0;
 
	t->new_act_food = 0;
 
	t->new_act_water = 0;
 
	t->act_food = 0;
 
	t->act_water = 0;
 

	
 
	for (i = 0; i != MAX_PLAYERS; i++)
 
		t->ratings[i] = 500;
 
	for (uint i = 0; i != MAX_PLAYERS; i++) t->ratings[i] = RATING_INITIAL;
 

	
 
	t->have_ratings = 0;
 
	t->exclusivity = INVALID_PLAYER;
 
	t->exclusive_counter = 0;
 
	t->statues = 0;
 

	
 
@@ -1451,13 +1429,13 @@ static void DoCreateTown(Town *t, TileIn
 
	UpdateTownVirtCoord(t);
 
	_town_sort_dirty = true;
 

	
 
	t->InitializeLayout();
 

	
 
	/* Random town size. */
 
	x = (Random() & 0xF) + 8;
 
	int x = (Random() & 0xF) + 8;
 

	
 
	switch (size_mode) {
 
		default: NOT_REACHED();
 

	
 
		case TSM_RANDOM:
 
			t->larger_town = false;
 
@@ -1474,13 +1452,13 @@ static void DoCreateTown(Town *t, TileIn
 
			break;
 
	}
 

	
 
	t->num_houses += x;
 
	UpdateTownRadius(t);
 

	
 
	i = x * 4;
 
	int i = x * 4;
 
	do {
 
		GrowTown(t);
 
	} while (--i);
 

	
 
	t->num_houses -= x;
 
	UpdateTownRadius(t);
 
@@ -1494,14 +1472,12 @@ static void DoCreateTown(Town *t, TileIn
 
 * @param flags type of operation
 
 * @param p1 size of the town (0 = small, 1 = medium, 2 = large)
 
 * @param p2 size mode (@see TownSizeMode)
 
 */
 
CommandCost CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	uint32 townnameparts;
 

	
 
	/* Only in the scenario editor */
 
	if (_game_mode != GM_EDITOR) return CMD_ERROR;
 
	if (p2 > TSM_CITY) return CMD_ERROR;
 

	
 
	/* Check if too close to the edge of map */
 
	if (DistanceFromEdge(tile) < 12)
 
@@ -1513,12 +1489,14 @@ CommandCost CmdBuildTown(TileIndex tile,
 
	}
 

	
 
	/* Check distance to all other towns. */
 
	if (IsCloseToTown(tile, 20))
 
		return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN);
 

	
 
	uint32 townnameparts;
 

	
 
	/* Get a unique name for the town. */
 
	if (!CreateTownName(&townnameparts))
 
		return_cmd_error(STR_023A_TOO_MANY_TOWNS);
 

	
 
	/* Allocate town struct */
 
	Town *t = new Town(tile);
 
@@ -1534,37 +1512,36 @@ CommandCost CmdBuildTown(TileIndex tile,
 
	}
 
	return CommandCost();
 
}
 

	
 
Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size)
 
{
 
	TileIndex tile;
 
	Town *t;
 
	uint32 townnameparts;
 

	
 
	do {
 
		/* Generate a tile index not too close from the edge */
 
		tile = RandomTile();
 
		TileIndex tile = RandomTile();
 
		if (DistanceFromEdge(tile) < 20) continue;
 

	
 
		/* Make sure the tile is plain */
 
		if (!IsTileType(tile, MP_CLEAR) || GetTileSlope(tile, NULL) != SLOPE_FLAT) continue;
 

	
 
		/* Check not too close to a town */
 
		if (IsCloseToTown(tile, 20)) continue;
 

	
 
		uint32 townnameparts;
 

	
 
		/* Get a unique name for the town. */
 
		if (!CreateTownName(&townnameparts)) break;
 

	
 
		/* Allocate a town struct */
 
		t = new Town(tile);
 
		Town *t = new Town(tile);
 
		if (t == NULL) break;
 

	
 
		DoCreateTown(t, tile, townnameparts, mode, size);
 
		return t;
 
	} while (--attempts);
 
	} while (--attempts != 0);
 

	
 
	return NULL;
 
}
 

	
 
static const byte _num_initial_towns[4] = {5, 11, 23, 46};
 

	
 
bool GenerateTowns()
 
@@ -1599,23 +1576,21 @@ bool GenerateTowns()
 

	
 
/** Returns the bit corresponding to the town zone of the specified tile
 
 * @param t Town on which radius is to be found
 
 * @param tile TileIndex where radius needs to be found
 
 * @return the bit position of the given zone, as defined in HouseZones
 
 */
 
HouseZonesBits GetTownRadiusGroup(const Town* t, TileIndex tile)
 
HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile)
 
{
 
	uint dist = DistanceSquare(tile, t->xy);
 
	HouseZonesBits smallest;
 
	uint i;
 

	
 
	if (t->fund_buildings_months && dist <= 25) return HZB_TOWN_CENTRE;
 

	
 
	smallest = HZB_TOWN_EDGE;
 
	for (i = 0; i != lengthof(t->radius); i++) {
 
		if (dist < t->radius[i]) smallest = (HouseZonesBits)i;
 
	HouseZonesBits smallest = HZB_TOWN_EDGE;
 
	for (HouseZonesBits i = HZB_BEGIN; i < HZB_END; i++) {
 
		if (dist < t->radius[i]) smallest = i;
 
	}
 

	
 
	return smallest;
 
}
 

	
 
/**
 
@@ -1875,13 +1850,13 @@ static bool BuildTownHouse(Town *t, Tile
 
	uint num = 0;
 
	uint probs[HOUSE_MAX];
 
	uint probability_max = 0;
 

	
 
	/* Generate a list of all possible houses that can be built. */
 
	for (uint i = 0; i < HOUSE_MAX; i++) {
 
		HouseSpec *hs = GetHouseSpecs(i);
 
		const HouseSpec *hs = GetHouseSpecs(i);
 
		/* Verify that the candidate house spec matches the current tile status */
 
		if ((~hs->building_availability & bitmask) == 0 && hs->enabled) {
 
			/* Without NewHouses, all houses have probability '1' */
 
			uint cur_prob = (_loaded_newgrf_features.has_newhouses ? hs->probability : 1);
 
			probability_max += cur_prob;
 
			probs[num] = cur_prob;
 
@@ -1904,13 +1879,13 @@ static bool BuildTownHouse(Town *t, Tile
 

	
 
		/* remove tested house from the set */
 
		num--;
 
		houses[i] = houses[num];
 
		probs[i] = probs[num];
 

	
 
		HouseSpec *hs = GetHouseSpecs(house);
 
		const HouseSpec *hs = GetHouseSpecs(house);
 

	
 
		if (_loaded_newgrf_features.has_newhouses) {
 
			if (hs->override != 0) {
 
				house = hs->override;
 
				hs = GetHouseSpecs(house);
 
			}
 
@@ -1988,17 +1963,15 @@ static void DoClearTownHouseHelper(TileI
 
	DoClearSquare(tile);
 
	DeleteAnimatedTile(tile);
 
}
 

	
 
void ClearTownHouse(Town *t, TileIndex tile)
 
{
 
	assert(IsTileType(tile, MP_HOUSE));
 

	
 
	HouseID house = GetHouseType(tile);
 
	uint eflags;
 
	HouseSpec *hs;
 

	
 
	assert(IsTileType(tile, MP_HOUSE));
 

	
 
	/* need to align the tile to point to the upper left corner of the house */
 
	if (house >= 3) { // house id 0,1,2 MUST be single tile houses, or this code breaks.
 
		if (GetHouseSpecs(house-1)->building_flags & TILE_SIZE_2x1) {
 
			house--;
 
			tile += TileDiffXY(-1, 0);
 
@@ -2011,13 +1984,13 @@ void ClearTownHouse(Town *t, TileIndex t
 
		} else if (GetHouseSpecs(house-3)->building_flags & BUILDING_HAS_4_TILES) {
 
			house-=3;
 
			tile += TileDiffXY(-1, -1);
 
		}
 
	}
 

	
 
	hs = GetHouseSpecs(house);
 
	const HouseSpec *hs = GetHouseSpecs(house);
 

	
 
	/* Remove population from the town if the house is finished. */
 
	if (IsHouseCompleted(tile)) {
 
		ChangePopulation(t, -hs->population);
 
	}
 

	
 
@@ -2029,13 +2002,13 @@ void ClearTownHouse(Town *t, TileIndex t
 
		ClrBit(t->flags12, TOWN_HAS_CHURCH);
 
	} else if (hs->building_flags & BUILDING_IS_STADIUM) {
 
		ClrBit(t->flags12, TOWN_HAS_STADIUM);
 
	}
 

	
 
	/* Do the actual clearing of tiles */
 
	eflags = hs->building_flags;
 
	uint eflags = hs->building_flags;
 
	DoClearTownHouseHelper(tile);
 
	if (eflags & BUILDING_2_TILES_X)   DoClearTownHouseHelper(tile + TileDiffXY(1, 0));
 
	if (eflags & BUILDING_2_TILES_Y)   DoClearTownHouseHelper(tile + TileDiffXY(0, 1));
 
	if (eflags & BUILDING_HAS_4_TILES) DoClearTownHouseHelper(tile + TileDiffXY(1, 1));
 
}
 

	
 
@@ -2058,21 +2031,19 @@ static bool IsUniqueTownName(const char 
 
 * @param flags type of operation
 
 * @param p1 town ID to rename
 
 * @param p2 unused
 
 */
 
CommandCost CmdRenameTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Town *t;
 

	
 
	if (!IsValidTownID(p1) || StrEmpty(_cmd_text)) return CMD_ERROR;
 

	
 
	t = GetTown(p1);
 

	
 
	if (!IsUniqueTownName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
 

	
 
	if (flags & DC_EXEC) {
 
		Town *t = GetTown(p1);
 

	
 
		free(t->name);
 
		t->name = strdup(_cmd_text);
 

	
 
		UpdateTownVirtCoord(t);
 
		_town_sort_dirty = true;
 
		UpdateAllStationVirtCoord();
 
@@ -2082,22 +2053,20 @@ CommandCost CmdRenameTown(TileIndex tile
 
	return CommandCost();
 
}
 

	
 
/** Called from GUI */
 
void ExpandTown(Town *t)
 
{
 
	uint amount, n;
 

	
 
	_generating_world = true;
 

	
 
	/* The more houses, the faster we grow */
 
	amount = RandomRange(ClampToU16(t->num_houses / 10)) + 3;
 
	uint amount = RandomRange(ClampToU16(t->num_houses / 10)) + 3;
 
	t->num_houses += amount;
 
	UpdateTownRadius(t);
 

	
 
	n = amount * 10;
 
	uint n = amount * 10;
 
	do GrowTown(t); while (--n);
 

	
 
	t->num_houses -= amount;
 
	UpdateTownRadius(t);
 

	
 
	UpdateTownMaxPass(t);
 
@@ -2105,55 +2074,52 @@ void ExpandTown(Town *t)
 
}
 

	
 
extern const byte _town_action_costs[8] = {
 
	2, 4, 9, 35, 48, 53, 117, 175
 
};
 

	
 
static void TownActionAdvertiseSmall(Town* t)
 
static void TownActionAdvertiseSmall(Town *t)
 
{
 
	ModifyStationRatingAround(t->xy, _current_player, 0x40, 10);
 
}
 

	
 
static void TownActionAdvertiseMedium(Town* t)
 
static void TownActionAdvertiseMedium(Town *t)
 
{
 
	ModifyStationRatingAround(t->xy, _current_player, 0x70, 15);
 
}
 

	
 
static void TownActionAdvertiseLarge(Town* t)
 
static void TownActionAdvertiseLarge(Town *t)
 
{
 
	ModifyStationRatingAround(t->xy, _current_player, 0xA0, 20);
 
}
 

	
 
static void TownActionRoadRebuild(Town* t)
 
static void TownActionRoadRebuild(Town *t)
 
{
 
	t->road_build_months = 6;
 

	
 
	SetDParam(0, t->index);
 
	SetDParam(1, _current_player);
 

	
 
	AddNewsItem(STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING,
 
		NM_NORMAL, NF_TILE, NT_GENERAL, DNC_NONE, t->xy, 0);
 
}
 

	
 
static bool DoBuildStatueOfCompany(TileIndex tile, TownID town_id)
 
{
 
	PlayerID old;
 
	CommandCost r;
 

	
 
	/* Statues can be build on slopes, just like houses. Only the steep slopes is a no go. */
 
	if (IsSteepSlope(GetTileSlope(tile, NULL))) return false;
 

	
 
	if (!IsTileType(tile, MP_HOUSE) &&
 
			!IsTileType(tile, MP_CLEAR) &&
 
			!IsTileType(tile, MP_TREES)) {
 
		return false;
 
	}
 

	
 
	old = _current_player;
 
	PlayerID old = _current_player;
 
	_current_player = OWNER_NONE;
 
	r = DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
	CommandCost r = DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
	_current_player = old;
 

	
 
	if (CmdFailed(r)) return false;
 

	
 
	MakeStatue(tile, _current_player, town_id);
 
	MarkTileDirtyByTile(tile);
 
@@ -2174,50 +2140,50 @@ static bool SearchTileForStatue(TileInde
 

	
 
/**
 
 * Perform a 9x9 tiles circular search from the center of the town
 
 * in order to find a free tile to place a statue
 
 * @param t town to search in
 
 */
 
static void TownActionBuildStatue(Town* t)
 
static void TownActionBuildStatue(Town *t)
 
{
 
	TileIndex tile = t->xy;
 

	
 
	if (CircularTileSearch(tile, 9, SearchTileForStatue, t->index))
 
	if (CircularTileSearch(tile, 9, SearchTileForStatue, t->index)) {
 
		SetBit(t->statues, _current_player); // Once found and built, "inform" the Town
 
	}
 
}
 

	
 
static void TownActionFundBuildings(Town* t)
 
static void TownActionFundBuildings(Town *t)
 
{
 
	/* Build next tick */
 
	t->grow_counter = 1;
 
	/* If we were not already growing */
 
	SetBit(t->flags12, TOWN_IS_FUNDED);
 
	/* And grow for 3 months */
 
	t->fund_buildings_months = 3;
 
}
 

	
 
static void TownActionBuyRights(Town* t)
 
static void TownActionBuyRights(Town *t)
 
{
 
	/* Check if it's allowed to by the rights */
 
	if (!_patches.exclusive_rights) return;
 

	
 
	t->exclusive_counter = 12;
 
	t->exclusivity = _current_player;
 

	
 
	ModifyStationRatingAround(t->xy, _current_player, 130, 17);
 
}
 

	
 
static void TownActionBribe(Town* t)
 
static void TownActionBribe(Town *t)
 
{
 
	if (!RandomRange(15)) {
 
		Station *st;
 

	
 
	if (Chance16(1, 14)) {
 
		/* set as unwanted for 6 months */
 
		t->unwanted[_current_player] = 6;
 

	
 
		/* set all close by station ratings to 0 */
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (st->town == t && st->owner == _current_player) {
 
				for (CargoID i = 0; i < NUM_CARGO; i++) st->goods[i].rating = 0;
 
			}
 
		}
 

	
 
@@ -2234,14 +2200,14 @@ static void TownActionBribe(Town* t)
 
		}
 
	} else {
 
		ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM);
 
	}
 
}
 

	
 
typedef void TownActionProc(Town* t);
 
static TownActionProc * const _town_action_proc[] = {
 
typedef void TownActionProc(Town *t);
 
static TownActionProc *const _town_action_proc[] = {
 
	TownActionAdvertiseSmall,
 
	TownActionAdvertiseMedium,
 
	TownActionAdvertiseLarge,
 
	TownActionRoadRebuild,
 
	TownActionBuildStatue,
 
	TownActionFundBuildings,
 
@@ -2258,17 +2224,15 @@ extern uint GetMaskOfTownActions(int *nu
 
 * @param flags type of operation
 
 * @param p1 town to do the action at
 
 * @param p2 action to perform, @see _town_action_proc for the list of available actions
 
 */
 
CommandCost CmdDoTownAction(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Town *t;
 

	
 
	if (!IsValidTownID(p1) || p2 > lengthof(_town_action_proc)) return CMD_ERROR;
 

	
 
	t = GetTown(p1);
 
	Town *t = GetTown(p1);
 

	
 
	if (!HasBit(GetMaskOfTownActions(NULL, _current_player, t), p2)) return CMD_ERROR;
 

	
 
	CommandCost cost(EXPENSES_OTHER, (_price.build_industry >> 8) * _town_action_costs[p2]);
 

	
 
	if (flags & DC_EXEC) {
 
@@ -2278,34 +2242,34 @@ CommandCost CmdDoTownAction(TileIndex ti
 

	
 
	return cost;
 
}
 

	
 
static void UpdateTownGrowRate(Town *t)
 
{
 
	int n;
 
	Station *st;
 
	uint16 m;
 
	Player *p;
 

	
 
	/* Reset player ratings if they're low */
 
	/* Increase player ratings if they're low */
 
	const Player *p;
 
	FOR_ALL_PLAYERS(p) {
 
		if (p->is_active && t->ratings[p->index] <= 200) {
 
			t->ratings[p->index] += 5;
 
		if (p->is_active) {
 
			t->ratings[p->index] = min((int)RATING_GROWTH_MAXIMUM, t->ratings[p->index] + RATING_GROWTH_UP_STEP);
 
		}
 
	}
 

	
 
	n = 0;
 
	int n = 0;
 

	
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
		if (DistanceSquare(st->xy, t->xy) <= t->radius[0]) {
 
			if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
 
				n++;
 
				if (IsValidPlayer(st->owner) && t->ratings[st->owner] <= 1000-12)
 
					t->ratings[st->owner] += 12;
 
				if (IsValidPlayer(st->owner)) {
 
					t->ratings[st->owner] = min((int)RATING_MAXIMUM, t->ratings[st->owner] + RATING_STATION_UP_STEP);
 
				}
 
			} else {
 
				if (IsValidPlayer(st->owner) && t->ratings[st->owner] >= -1000+15)
 
					t->ratings[st->owner] -= 15;
 
				if (IsValidPlayer(st->owner)) {
 
					t->ratings[st->owner] = max((int)RATING_MINIMUM, t->ratings[st->owner] + RATING_STATION_DOWN_STEP);
 
				}
 
			}
 
		}
 
	}
 

	
 
	ClrBit(t->flags12, TOWN_IS_FUNDED);
 
	if (_patches.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
 
@@ -2314,12 +2278,14 @@ static void UpdateTownGrowRate(Town *t)
 
	 * number of times towns are processed before a new building is built. */
 
	static const uint16 _grow_count_values[2][6] = {
 
		{ 120, 120, 120, 100,  80,  60 }, // Fund new buildings has been activated
 
		{ 320, 420, 300, 220, 160, 100 }  // Normal values
 
	};
 

	
 
	uint16 m;
 

	
 
	if (t->fund_buildings_months != 0) {
 
		m = _grow_count_values[0][min(n, 5)];
 
		t->fund_buildings_months--;
 
	} else {
 
		m = _grow_count_values[1][min(n, 5)];
 
		if (n == 0 && !Chance16(1, 12)) return;
 
@@ -2364,45 +2330,43 @@ static void UpdateTownAmounts(Town *t)
 

	
 
	InvalidateWindow(WC_TOWN_VIEW, t->index);
 
}
 

	
 
static void UpdateTownUnwanted(Town *t)
 
{
 
	const Player* p;
 
	const Player *p;
 

	
 
	FOR_ALL_PLAYERS(p) {
 
		if (t->unwanted[p->index] > 0) t->unwanted[p->index]--;
 
	}
 
}
 

	
 
bool CheckIfAuthorityAllows(TileIndex tile)
 
{
 
	Town *t;
 

	
 
	if (!IsValidPlayer(_current_player)) return true;
 

	
 
	t = ClosestTownFromTile(tile, _patches.dist_local_authority);
 
	Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
 
	if (t == NULL) return true;
 

	
 
	if (t->ratings[_current_player] > -200) return true;
 
	if (t->ratings[_current_player] > RATING_VERYPOOR) return true;
 

	
 
	_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
 
	SetDParam(0, t->index);
 

	
 
	return false;
 
}
 

	
 

	
 
Town* CalcClosestTownFromTile(TileIndex tile, uint threshold)
 
Town *CalcClosestTownFromTile(TileIndex tile, uint threshold)
 
{
 
	Town *t;
 
	uint dist, best = threshold;
 
	uint best = threshold;
 
	Town *best_town = NULL;
 

	
 
	FOR_ALL_TOWNS(t) {
 
		dist = DistanceManhattan(tile, t->xy);
 
		uint dist = DistanceManhattan(tile, t->xy);
 
		if (dist < best) {
 
			best = dist;
 
			best_town = t;
 
		}
 
	}
 

	
 
@@ -2439,24 +2403,22 @@ void SetTownRatingTestMode(bool mode)
 
	}
 
	_town_rating_test = !(ref_count == 0);
 
}
 

	
 
void ChangeTownRating(Town *t, int add, int max)
 
{
 
	int rating;
 

	
 
	/* if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff */
 
	if (t == NULL ||
 
			!IsValidPlayer(_current_player) ||
 
			(_cheats.magic_bulldozer.value && add < 0)) {
 
		return;
 
	}
 

	
 
	SetBit(t->have_ratings, _current_player);
 

	
 
	rating = _town_rating_test ? t->test_rating : t->ratings[_current_player];
 
	int rating = _town_rating_test ? t->test_rating : t->ratings[_current_player];
 

	
 
	if (add < 0) {
 
		if (rating > max) {
 
			rating += add;
 
			if (rating < max) rating = max;
 
		}
 
@@ -2480,23 +2442,21 @@ static const int _default_rating_setting
 
	{ 48, 192, 480}, // Neutral
 
	{ 96, 384, 768}, // Hostile
 
};
 

	
 
bool CheckforTownRating(uint32 flags, Town *t, byte type)
 
{
 
	int modemod;
 

	
 
	/* if magic_bulldozer cheat is active, town doesn't restrict your destructive actions */
 
	if (t == NULL || !IsValidPlayer(_current_player) || _cheats.magic_bulldozer.value)
 
		return true;
 

	
 
	/* check if you're allowed to remove the street/bridge/tunnel/industry
 
	 * owned by a town no removal if rating is lower than ... depends now on
 
	 * difficulty setting. Minimum town rating selected by difficulty level
 
	 */
 
	modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type];
 
	int modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type];
 

	
 
	if ((_town_rating_test ? t->test_rating : t->ratings[_current_player]) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) {
 
		SetDParam(0, t->index);
 
		_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
 
		return false;
 
	}
 
@@ -2519,33 +2479,32 @@ void TownsMonthlyLoop()
 
		UpdateTownUnwanted(t);
 
	}
 
}
 

	
 
void InitializeTowns()
 
{
 
	Subsidy *s;
 

	
 
	/* Clean the town pool and create 1 block in it */
 
	_Town_pool.CleanPool();
 
	_Town_pool.AddBlockToPool();
 

	
 
	memset(_subsidies, 0, sizeof(_subsidies));
 
	for (s=_subsidies; s != endof(_subsidies); s++)
 
	for (Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
 
		s->cargo_type = CT_INVALID;
 
	}
 

	
 
	_cur_town_ctr = 0;
 
	_cur_town_iter = 0;
 
	_total_towns = 0;
 
	_town_sort_dirty = true;
 
}
 

	
 
static CommandCost TerraformTile_Town(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 
{
 
	if (AutoslopeEnabled()) {
 
		HouseID house = GetHouseType(tile);
 
		HouseSpec *hs = GetHouseSpecs(house);
 
		const HouseSpec *hs = GetHouseSpecs(house);
 

	
 
		/* Here we differ from TTDP by checking TILE_NOT_SLOPED */
 
		if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) &&
 
			(GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
	}
 

	
src/town_type.h
Show inline comments
 
@@ -32,18 +32,25 @@ enum {
 
	RATING_VERYGOOD    =   600,
 
	RATING_EXCELLENT   =   800,
 
	RATING_OUTSTANDING =  1000,         ///< OUTSTANDING
 

	
 
	RATING_MAXIMUM = RATING_OUTSTANDING,
 

	
 
	RATING_INITIAL = 500, ///< initial rating
 

	
 
	/* RATINGS AFFECTING NUMBERS */
 
	RATING_TREE_DOWN_STEP = -35,
 
	RATING_TREE_MINIMUM   = RATING_MINIMUM,
 
	RATING_TREE_UP_STEP   = 7,
 
	RATING_TREE_MAXIMUM   = 220,
 

	
 
	RATING_GROWTH_UP_STEP    =   5, ///< when a town grows, all players have rating increased a bit ...
 
	RATING_GROWTH_MAXIMUM    = RATING_MEDIOCRE, ///< ... up to RATING_MEDIOCRE
 
	RATING_STATION_UP_STEP   =  12, ///< when a town grows, player gains reputation for all well serviced stations ...
 
	RATING_STATION_DOWN_STEP = -15, ///< ... but loses for bad serviced stations
 

	
 
	RATING_TUNNEL_BRIDGE_DOWN_STEP = -250,
 
	RATING_TUNNEL_BRIDGE_MINIMUM   = 0,
 

	
 
	RATING_INDUSTRY_DOWN_STEP = -1500,
 
	RATING_INDUSTRY_MINIMUM   = RATING_MINIMUM,
 

	
0 comments (0 inline, 0 general)