|
@@ -43,27 +43,27 @@ MemoryPool _town_pool = { "Towns", TOWN_
|
|
|
* one town should get grown per tick. The other numbers of towns
|
|
|
* are then scaled based on that. */
|
|
|
#define TOWN_GROWTH_FREQUENCY 23
|
|
|
|
|
|
enum {
|
|
|
TOWN_HAS_CHURCH = 0x02,
|
|
|
TOWN_HAS_STADIUM = 0x04
|
|
|
};
|
|
|
|
|
|
// Local
|
|
|
static int _grow_town_result;
|
|
|
|
|
|
static bool BuildTownHouse(Town *t, uint tile);
|
|
|
static void ClearTownHouse(Town *t, uint tile);
|
|
|
static void DoBuildTownHouse(Town *t, uint tile);
|
|
|
static bool BuildTownHouse(Town *t, TileIndex tile);
|
|
|
static void ClearTownHouse(Town *t, TileIndex tile);
|
|
|
static void DoBuildTownHouse(Town *t, TileIndex tile);
|
|
|
|
|
|
typedef struct DrawTownTileStruct {
|
|
|
uint32 sprite_1;
|
|
|
uint32 sprite_2;
|
|
|
|
|
|
byte subtile_x:4;
|
|
|
byte subtile_y:4;
|
|
|
byte width:4;
|
|
|
byte height:4;
|
|
|
byte dz;
|
|
|
byte proc;
|
|
|
} DrawTownTileStruct;
|
|
@@ -141,25 +141,25 @@ static void DrawTile_Town(TileInfo *ti)
|
|
|
static uint GetSlopeZ_Town(TileInfo *ti)
|
|
|
{
|
|
|
uint z = GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z;
|
|
|
if (ti->tileh != 0) z = (z & ~7) + 4;
|
|
|
return (uint16) z;
|
|
|
}
|
|
|
|
|
|
static uint GetSlopeTileh_Town(TileInfo *ti)
|
|
|
{
|
|
|
return ti->tileh;
|
|
|
}
|
|
|
|
|
|
static void AnimateTile_Town(uint tile)
|
|
|
static void AnimateTile_Town(TileIndex tile)
|
|
|
{
|
|
|
int old;
|
|
|
int i;
|
|
|
int a,b;
|
|
|
|
|
|
if (_tick_counter & 3)
|
|
|
return;
|
|
|
|
|
|
if (_map3_hi[tile] != 4 && _map3_hi[tile] != 5)
|
|
|
return;
|
|
|
|
|
|
if (!((old=_map_owner[tile])&0x80)) {
|
|
@@ -179,25 +179,25 @@ static void AnimateTile_Town(uint tile)
|
|
|
|
|
|
if (a == b) {
|
|
|
_map5[tile] &= 0x40;
|
|
|
_map_owner[tile] &= 0x7F;
|
|
|
DeleteAnimatedTile(tile);
|
|
|
}
|
|
|
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
}
|
|
|
|
|
|
static void UpdateTownRadius(Town *t);
|
|
|
|
|
|
static bool IsCloseToTown(uint tile, uint dist)
|
|
|
static bool IsCloseToTown(TileIndex tile, uint dist)
|
|
|
{
|
|
|
Town *t;
|
|
|
|
|
|
FOR_ALL_TOWNS(t) {
|
|
|
if (t->xy != 0 && DistanceManhattan(tile, t->xy) < dist)
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
static void MarkTownSignDirty(Town *t)
|
|
|
{
|
|
@@ -233,57 +233,57 @@ static void ChangePopulation(Town *t, in
|
|
|
|
|
|
uint32 GetWorldPopulation(void)
|
|
|
{
|
|
|
uint32 pop;
|
|
|
Town *t;
|
|
|
pop = 0;
|
|
|
FOR_ALL_TOWNS(t) {
|
|
|
pop += t->population;
|
|
|
}
|
|
|
return pop;
|
|
|
}
|
|
|
|
|
|
static void MakeSingleHouseBigger(uint tile)
|
|
|
static void MakeSingleHouseBigger(TileIndex tile)
|
|
|
{
|
|
|
byte b;
|
|
|
|
|
|
assert(IsTileType(tile, MP_HOUSE));
|
|
|
|
|
|
b = _map5[tile];
|
|
|
if (b & 0x80)
|
|
|
return;
|
|
|
|
|
|
_map5[tile] = (b & 0xC0) | ((b+1)&7);
|
|
|
|
|
|
if ((_map5[tile]&7) != 0)
|
|
|
return;
|
|
|
|
|
|
_map3_lo[tile] = _map3_lo[tile] + 0x40;
|
|
|
|
|
|
if ( (_map3_lo[tile] & 0xC0) == 0xC0) {
|
|
|
ChangePopulation(GetTown(_map2[tile]), _housetype_population[_map3_hi[tile]]);
|
|
|
}
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
}
|
|
|
|
|
|
static void MakeTownHouseBigger(uint tile)
|
|
|
static void MakeTownHouseBigger(TileIndex tile)
|
|
|
{
|
|
|
uint flags = _house_more_flags[_map3_hi[tile]];
|
|
|
if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
|
|
|
if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
|
|
|
if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
|
|
|
if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
|
|
|
}
|
|
|
|
|
|
static void TileLoop_Town(uint tile)
|
|
|
static void TileLoop_Town(TileIndex tile)
|
|
|
{
|
|
|
int house;
|
|
|
Town *t;
|
|
|
uint32 r;
|
|
|
|
|
|
if ((_map3_lo[tile] & 0xC0) != 0xC0) {
|
|
|
MakeTownHouseBigger(tile);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
house = _map3_hi[tile];
|
|
|
if (_housetype_extra_flags[house] & 0x20 &&
|
|
@@ -321,30 +321,30 @@ static void TileLoop_Town(uint tile)
|
|
|
|
|
|
ClearTownHouse(t, tile);
|
|
|
|
|
|
// rebuild with another house?
|
|
|
if ( (byte) (r >> 8) >= 12) {
|
|
|
DoBuildTownHouse(t, tile);
|
|
|
}
|
|
|
|
|
|
_current_player = OWNER_NONE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void ClickTile_Town(uint tile)
|
|
|
static void ClickTile_Town(TileIndex tile)
|
|
|
{
|
|
|
/* not used */
|
|
|
}
|
|
|
|
|
|
static int32 ClearTile_Town(uint tile, byte flags)
|
|
|
static int32 ClearTile_Town(TileIndex tile, byte flags)
|
|
|
{
|
|
|
int house, rating;
|
|
|
int32 cost;
|
|
|
Town *t;
|
|
|
|
|
|
// safety checks
|
|
|
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
|
|
if (flags&DC_AUTO && !(flags&DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
|
|
|
|
|
|
house = _map3_hi[tile];
|
|
|
cost = _price.remove_house * _housetype_remove_cost[house] >> 8;
|
|
|
|
|
@@ -358,52 +358,52 @@ static int32 ClearTile_Town(uint tile, b
|
|
|
return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM);
|
|
|
ClearTownHouse(t, tile);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
static void GetAcceptedCargo_Town(uint tile, AcceptedCargo ac)
|
|
|
static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac)
|
|
|
{
|
|
|
int type = _map3_hi[tile];
|
|
|
|
|
|
ac[CT_PASSENGERS] = _housetype_cargo_passengers[type];
|
|
|
ac[CT_MAIL] = _housetype_cargo_mail[type];
|
|
|
ac[CT_GOODS] = _housetype_cargo_goods[type];
|
|
|
ac[CT_FOOD] = _housetype_cargo_food[type];
|
|
|
}
|
|
|
|
|
|
static void GetTileDesc_Town(uint tile, TileDesc *td)
|
|
|
static void GetTileDesc_Town(TileIndex tile, TileDesc *td)
|
|
|
{
|
|
|
td->str = _town_tile_names[_map3_hi[tile]];
|
|
|
if ((_map3_lo[tile] & 0xC0) != 0xC0) {
|
|
|
SetDParamX(td->dparam, 0, td->str);
|
|
|
td->str = STR_2058_UNDER_CONSTRUCTION;
|
|
|
}
|
|
|
|
|
|
td->owner = OWNER_TOWN;
|
|
|
}
|
|
|
|
|
|
static uint32 GetTileTrackStatus_Town(uint tile, TransportType mode)
|
|
|
static uint32 GetTileTrackStatus_Town(TileIndex tile, TransportType mode)
|
|
|
{
|
|
|
/* not used */
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static void ChangeTileOwner_Town(uint tile, byte old_player, byte new_player)
|
|
|
static void ChangeTileOwner_Town(TileIndex tile, byte old_player, byte new_player)
|
|
|
{
|
|
|
/* not used */
|
|
|
}
|
|
|
|
|
|
|
|
|
static const TileIndexDiffC _roadblock_tileadd[] = {
|
|
|
{ 0, -1},
|
|
|
{ 1, 0},
|
|
|
{ 0, 1},
|
|
|
{-1, 0},
|
|
|
|
|
|
// Store the first 3 elements again.
|
|
@@ -457,25 +457,25 @@ static byte GetTownRoadMask(TileIndex ti
|
|
|
{
|
|
|
byte b = GetRoadBitsByTile(tile);
|
|
|
byte r=0;
|
|
|
if (b&1) r|=10;
|
|
|
if (b&2) r|=5;
|
|
|
if (b&4) r|=9;
|
|
|
if (b&8) r|=6;
|
|
|
if (b&16) r|=3;
|
|
|
if (b&32) r|=12;
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
static bool IsRoadAllowedHere(uint tile, int dir)
|
|
|
static bool IsRoadAllowedHere(TileIndex tile, int dir)
|
|
|
{
|
|
|
uint k;
|
|
|
uint slope;
|
|
|
|
|
|
// If this assertion fails, it might be because the world contains
|
|
|
// land at the edges. This is not ok.
|
|
|
TILE_ASSERT(tile);
|
|
|
|
|
|
for(;;) {
|
|
|
// Check if there already is a road at this point?
|
|
|
if (GetRoadBitsByTile(tile) == 0) {
|
|
|
// No, try to build one in the direction.
|
|
@@ -519,65 +519,65 @@ no_slope:
|
|
|
// We can consider building on the slope, though.
|
|
|
goto no_slope;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/* Can somebody explain for what this is needed? :s */
|
|
|
// tile = TILE_ADD(tile, _roadblock_tileadd[dir]);
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static bool TerraformTownTile(uint tile, int edges, int dir)
|
|
|
static bool TerraformTownTile(TileIndex tile, int edges, int dir)
|
|
|
{
|
|
|
int32 r;
|
|
|
|
|
|
TILE_ASSERT(tile);
|
|
|
|
|
|
r = DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
|
|
|
if (r == CMD_ERROR || r >= 126*16)
|
|
|
return false;
|
|
|
DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_TERRAFORM_LAND);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static void LevelTownLand(uint tile)
|
|
|
static void LevelTownLand(TileIndex tile)
|
|
|
{
|
|
|
TileInfo ti;
|
|
|
|
|
|
TILE_ASSERT(tile);
|
|
|
|
|
|
// Don't terraform if land is plain or if there's a house there.
|
|
|
FindLandscapeHeightByTile(&ti, tile);
|
|
|
if (ti.tileh == 0 || ti.type == MP_HOUSE)
|
|
|
return;
|
|
|
|
|
|
// First try up, then down
|
|
|
if (!TerraformTownTile(tile, ~ti.tileh & 0xF, 1)) {
|
|
|
TerraformTownTile(tile, ti.tileh & 0xF, 0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#define IS_WATER_TILE(t) (IsTileType((t), MP_WATER) && _map5[(t)] == 0)
|
|
|
|
|
|
static void GrowTownInTile(uint *tile_ptr, uint mask, int block, Town *t1)
|
|
|
static void GrowTownInTile(TileIndex *tile_ptr, uint mask, int block, Town *t1)
|
|
|
{
|
|
|
uint16 r;
|
|
|
int a,b,rcmd;
|
|
|
uint tmptile;
|
|
|
TileIndex tmptile;
|
|
|
TileInfo ti;
|
|
|
int i;
|
|
|
int j;
|
|
|
uint tile = *tile_ptr;
|
|
|
TileIndex tile = *tile_ptr;
|
|
|
|
|
|
TILE_ASSERT(tile);
|
|
|
|
|
|
if (mask == 0) {
|
|
|
// Tile has no road. First reset the status counter
|
|
|
// to say that this is the last iteration.
|
|
|
_grow_town_result = 0;
|
|
|
|
|
|
// Remove hills etc
|
|
|
LevelTownLand(tile);
|
|
|
|
|
|
// Is a road allowed here?
|
|
@@ -702,25 +702,25 @@ build_road_and_exit:
|
|
|
_grow_town_result = -1;
|
|
|
|
|
|
// obviously, if building any bridge would fail, there is no need to try other bridge-types
|
|
|
return;
|
|
|
}
|
|
|
} while(--j != 0);
|
|
|
}
|
|
|
}
|
|
|
#undef IS_WATER_TILE
|
|
|
|
|
|
|
|
|
// Returns true if a house was built, or no if the build failed.
|
|
|
static int GrowTownAtRoad(Town *t, uint tile)
|
|
|
static int GrowTownAtRoad(Town *t, TileIndex tile)
|
|
|
{
|
|
|
uint mask;
|
|
|
int block = 5; // special case
|
|
|
|
|
|
TILE_ASSERT(tile);
|
|
|
|
|
|
// Number of times to search.
|
|
|
_grow_town_result = 10 + t->num_houses * 4 / 9;
|
|
|
|
|
|
do {
|
|
|
// Get a bitmask of the road blocks on a tile
|
|
|
mask = GetTownRoadMask(tile);
|
|
@@ -763,25 +763,25 @@ static int GrowTownAtRoad(Town *t, uint
|
|
|
static int GenRandomRoadBits(void)
|
|
|
{
|
|
|
uint32 r = Random();
|
|
|
int a = r&3, b = (r >> 8) & 3;
|
|
|
if (a == b) b ^= 2;
|
|
|
return (1<<a)+(1<<b);
|
|
|
}
|
|
|
|
|
|
// Grow the town
|
|
|
// Returns true if a house was built, or no if the build failed.
|
|
|
bool GrowTown(Town *t)
|
|
|
{
|
|
|
uint tile;
|
|
|
TileIndex tile;
|
|
|
const TileIndexDiffC *ptr;
|
|
|
TileInfo ti;
|
|
|
byte old_player;
|
|
|
|
|
|
static const TileIndexDiffC _town_coord_mod[] = {
|
|
|
{-1, 0},
|
|
|
{ 1, 1},
|
|
|
{ 1, -1},
|
|
|
{-1, -1},
|
|
|
{-1, 0},
|
|
|
{ 0, 2},
|
|
|
{ 2, 0},
|
|
@@ -1056,25 +1056,25 @@ int32 CmdBuildTown(int x, int y, uint32
|
|
|
|
|
|
// Create the town
|
|
|
if (flags & DC_EXEC) {
|
|
|
_generating_world = true;
|
|
|
DoCreateTown(t, tile, townnameparts);
|
|
|
_generating_world = false;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
Town *CreateRandomTown(uint attempts)
|
|
|
{
|
|
|
uint tile;
|
|
|
TileIndex tile;
|
|
|
TileInfo ti;
|
|
|
Town *t;
|
|
|
uint32 townnameparts;
|
|
|
|
|
|
do {
|
|
|
// Generate a tile index not too close from the edge
|
|
|
tile = TILE_MASK(Random());
|
|
|
if (DistanceFromEdge(tile) < 20)
|
|
|
continue;
|
|
|
|
|
|
// Make sure the tile is plain
|
|
|
FindLandscapeHeightByTile(&ti, tile);
|
|
@@ -1112,89 +1112,90 @@ void GenerateTowns(void)
|
|
|
|
|
|
do {
|
|
|
if (CreateRandomTown(20) != NULL) //try 20 times for the first loop
|
|
|
num++;
|
|
|
} while (--n);
|
|
|
|
|
|
if (num == 0 && CreateRandomTown(10000) == NULL) {
|
|
|
//XXX can we handle that more gracefully?
|
|
|
error("Could not generate any town");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static bool CheckBuildHouseMode(Town *t1, uint tile, uint tileh, int mode) {
|
|
|
static bool CheckBuildHouseMode(Town *t1, TileIndex tile, uint tileh, int mode)
|
|
|
{
|
|
|
int b;
|
|
|
uint slope;
|
|
|
|
|
|
static const byte _masks[8] = {
|
|
|
0xC,0x3,0x9,0x6,
|
|
|
0x3,0xC,0x6,0x9,
|
|
|
};
|
|
|
|
|
|
slope = GetTileSlope(tile, NULL);
|
|
|
if (slope & 0x10)
|
|
|
return false;
|
|
|
|
|
|
b = 0;
|
|
|
if ((slope & 0xF && ~slope & _masks[mode])) b = ~b;
|
|
|
if ((tileh & 0xF && ~tileh & _masks[mode+4])) b = ~b;
|
|
|
if (b)
|
|
|
return false;
|
|
|
|
|
|
return DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR) != CMD_ERROR;
|
|
|
}
|
|
|
|
|
|
int GetTownRadiusGroup(Town *t, uint tile)
|
|
|
int GetTownRadiusGroup(Town *t, TileIndex tile)
|
|
|
{
|
|
|
uint dist;
|
|
|
int i,smallest;
|
|
|
|
|
|
dist = DistanceSquare(tile, t->xy);
|
|
|
if (t->fund_buildings_months && dist <= 25)
|
|
|
return 4;
|
|
|
|
|
|
smallest = 0;
|
|
|
for(i=0; i!=lengthof(t->radius); i++) {
|
|
|
if (dist < t->radius[i])
|
|
|
smallest = i;
|
|
|
}
|
|
|
|
|
|
return smallest;
|
|
|
}
|
|
|
|
|
|
static bool CheckFree2x2Area(Town *t1, uint tile)
|
|
|
static bool CheckFree2x2Area(Town *t1, TileIndex tile)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
static const TileIndexDiffC _tile_add[] = {
|
|
|
{0 , 0 },
|
|
|
{0 - 0, 1 - 0},
|
|
|
{1 - 0, 0 - 1},
|
|
|
{1 - 1, 1 - 0}
|
|
|
};
|
|
|
|
|
|
for(i=0; i!=4; i++) {
|
|
|
tile += ToTileIndexDiff(_tile_add[i]);
|
|
|
|
|
|
if (GetTileSlope(tile, NULL))
|
|
|
return false;
|
|
|
|
|
|
if (DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_FORCETEST, CMD_LANDSCAPE_CLEAR) == CMD_ERROR)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static void DoBuildTownHouse(Town *t, uint tile)
|
|
|
static void DoBuildTownHouse(Town *t, TileIndex tile)
|
|
|
{
|
|
|
int i;
|
|
|
uint bitmask;
|
|
|
int house;
|
|
|
uint slope;
|
|
|
uint z;
|
|
|
uint oneof;
|
|
|
|
|
|
// Above snow?
|
|
|
slope = GetTileSlope(tile, &z);
|
|
|
|
|
|
// Get the town zone type
|
|
@@ -1349,48 +1350,49 @@ static void DoBuildTownHouse(Town *t, ui
|
|
|
t->index,
|
|
|
m3lo, /* map3_lo */
|
|
|
++house, /* map3_hi */
|
|
|
0, /* map_owner */
|
|
|
m5 /* map5 */
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ENDING
|
|
|
}
|
|
|
|
|
|
static bool BuildTownHouse(Town *t, uint tile)
|
|
|
static bool BuildTownHouse(Town *t, TileIndex tile)
|
|
|
{
|
|
|
int32 r;
|
|
|
|
|
|
// make sure it's possible
|
|
|
if (!EnsureNoVehicle(tile)) return false;
|
|
|
if (GetTileSlope(tile, NULL) & 0x10) return false;
|
|
|
|
|
|
r = DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
|
|
|
if (r == CMD_ERROR) return false;
|
|
|
|
|
|
DoBuildTownHouse(t, tile);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
|
|
|
static void DoClearTownHouseHelper(uint tile)
|
|
|
static void DoClearTownHouseHelper(TileIndex tile)
|
|
|
{
|
|
|
assert(IsTileType(tile, MP_HOUSE));
|
|
|
DoClearSquare(tile);
|
|
|
DeleteAnimatedTile(tile);
|
|
|
}
|
|
|
|
|
|
static void ClearTownHouse(Town *t, uint tile) {
|
|
|
static void ClearTownHouse(Town *t, TileIndex tile)
|
|
|
{
|
|
|
uint house = _map3_hi[tile];
|
|
|
uint eflags;
|
|
|
|
|
|
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 (_housetype_extra_flags[house-1] & 0x04) {
|
|
|
house--;
|
|
|
tile += TILE_XY(-1,0);
|
|
|
} else if (_housetype_extra_flags[house-1] & 0x18) {
|
|
|
house--;
|
|
@@ -1555,25 +1557,25 @@ static void TownActionRoadRebuild(Town *
|
|
|
t->road_build_months = 6;
|
|
|
|
|
|
SetDParam(0, t->index);
|
|
|
|
|
|
p = GetPlayer(_current_player);
|
|
|
SetDParam(1, p->name_1);
|
|
|
SetDParam(2, p->name_2);
|
|
|
|
|
|
AddNewsItem(STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING,
|
|
|
NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_GENERAL, 0), t->xy, 0);
|
|
|
}
|
|
|
|
|
|
static bool DoBuildStatueOfCompany(uint tile)
|
|
|
static bool DoBuildStatueOfCompany(TileIndex tile)
|
|
|
{
|
|
|
TileInfo ti;
|
|
|
byte old;
|
|
|
int32 r;
|
|
|
|
|
|
FindLandscapeHeightByTile(&ti, tile);
|
|
|
if (ti.tileh != 0)
|
|
|
return false;
|
|
|
|
|
|
if (ti.type != MP_HOUSE && ti.type != MP_CLEAR && ti.type != MP_TREES)
|
|
|
return false;
|
|
|
|
|
@@ -1607,25 +1609,25 @@ static void TownActionBuildStatue(Town *
|
|
|
{ 0,-1}, { 0,-1}, { 0,-1}, { 0,-1},
|
|
|
{-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0},
|
|
|
{ 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1},
|
|
|
{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0},
|
|
|
{ 0,-1}, { 0,-1}, { 0,-1}, { 0,-1}, { 0,-1}, { 0,-1},
|
|
|
{-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0},
|
|
|
{ 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1},
|
|
|
{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0},
|
|
|
{ 0,-1}, { 0,-1}, { 0,-1}, { 0,-1}, { 0,-1}, { 0,-1}, { 0,-1}, { 0,-1},
|
|
|
{-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0},
|
|
|
{ 0, 0}
|
|
|
};
|
|
|
uint tile = t->xy;
|
|
|
TileIndex tile = t->xy;
|
|
|
const TileIndexDiffC *p;
|
|
|
|
|
|
SETBIT(t->statues, _current_player);
|
|
|
|
|
|
for (p = _statue_tiles; p != endof(_statue_tiles); ++p) {
|
|
|
if (DoBuildStatueOfCompany(tile))
|
|
|
return;
|
|
|
tile = TILE_ADD(tile, ToTileIndexDiff(*p));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void TownActionFundBuildings(Town *t, int action)
|
|
@@ -1802,46 +1804,46 @@ static void UpdateTownAmounts(Town *t)
|
|
|
}
|
|
|
|
|
|
static void UpdateTownUnwanted(Town *t)
|
|
|
{
|
|
|
Player *p;
|
|
|
|
|
|
FOR_ALL_PLAYERS(p) {
|
|
|
if (t->unwanted[p->index] > 0)
|
|
|
t->unwanted[p->index]--;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool CheckIfAuthorityAllows(uint tile)
|
|
|
bool CheckIfAuthorityAllows(TileIndex tile)
|
|
|
{
|
|
|
Town *t;
|
|
|
|
|
|
if (_current_player >= MAX_PLAYERS)
|
|
|
return true;
|
|
|
|
|
|
t = ClosestTownFromTile(tile, _patches.dist_local_authority);
|
|
|
if (t == NULL)
|
|
|
return true;
|
|
|
|
|
|
if (t->ratings[_current_player] > -200)
|
|
|
return true;
|
|
|
|
|
|
_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
|
|
|
SetDParam(0, t->index);
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
|
|
|
Town *ClosestTownFromTile(uint tile, uint threshold)
|
|
|
Town *ClosestTownFromTile(TileIndex tile, uint threshold)
|
|
|
{
|
|
|
Town *t;
|
|
|
uint dist, best = threshold;
|
|
|
Town *best_town = NULL;
|
|
|
|
|
|
// XXX - Fix this so for a given tiletype the owner of the type is in the same variable
|
|
|
if (IsTileType(tile, MP_HOUSE) || (
|
|
|
IsTileType(tile, MP_STREET) &&
|
|
|
(IsLevelCrossing(tile) ? _map3_lo[tile] : GetTileOwner(tile)) == OWNER_TOWN
|
|
|
))
|
|
|
return GetTown(_map2[tile]);
|
|
|
|
|
@@ -1883,25 +1885,25 @@ void ChangeTownRating(Town *t, int add,
|
|
|
}
|
|
|
t->ratings[_current_player] = rating;
|
|
|
}
|
|
|
|
|
|
/* penalty for removing town-owned stuff */
|
|
|
static const int _default_rating_settings [3][3] = {
|
|
|
// ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE
|
|
|
{ 0, 128, 384}, // Permissive
|
|
|
{ 48, 192, 480}, // Neutral
|
|
|
{ 96, 384, 768}, // Hostile
|
|
|
};
|
|
|
|
|
|
bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type)
|
|
|
bool CheckforTownRating(TileIndex tile, uint32 flags, Town *t, byte type)
|
|
|
{
|
|
|
int modemod;
|
|
|
|
|
|
// if magic_bulldozer cheat is active, town doesn't restrict your destructive actions
|
|
|
if (t == NULL || _current_player >= MAX_PLAYERS || _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];
|