src/station_cmd.cpp
branchnoai
changeset 9694 e72987579514
parent 9686 d3c195c226f9
child 9701 d1ac22c62f64
equal deleted inserted replaced
9693:31fcaa5375a1 9694:e72987579514
    41 #include "misc/autoptr.hpp"
    41 #include "misc/autoptr.hpp"
    42 #include "road.h"
    42 #include "road.h"
    43 #include "cargotype.h"
    43 #include "cargotype.h"
    44 #include "strings.h"
    44 #include "strings.h"
    45 
    45 
       
    46 DEFINE_OLD_POOL_GENERIC(Station, Station)
       
    47 DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop)
       
    48 
       
    49 
    46 /**
    50 /**
    47  * Called if a new block is added to the station-pool
    51  * Check whether the given tile is a hangar.
       
    52  * @param t the tile to of whether it is a hangar.
       
    53  * @pre IsTileType(t, MP_STATION)
       
    54  * @return true if and only if the tile is a hangar.
    48  */
    55  */
    49 static void StationPoolNewBlock(uint start_item)
    56 bool IsHangar(TileIndex t)
    50 {
    57 {
    51 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
    58 	assert(IsTileType(t, MP_STATION));
    52 	 *  TODO - This is just a temporary stage, this will be removed. */
    59 
    53 	for (Station *st = GetStation(start_item); st != NULL; st = (st->index + 1U < GetStationPoolSize()) ? GetStation(st->index + 1U) : NULL) st->index = start_item++;
    60 	const Station *st = GetStationByTile(t);
    54 }
    61 	const AirportFTAClass *apc = st->Airport();
    55 
    62 
    56 static void StationPoolCleanBlock(uint start_item, uint end_item)
    63 	for (uint i = 0; i < apc->nof_depots; i++) {
    57 {
    64 		if (st->airport_tile + ToTileIndexDiff(apc->airport_depots[i]) == t) return true;
    58 	for (uint i = start_item; i <= end_item; i++) {
    65 	}
    59 		Station *st = GetStation(i);
    66 
    60 		if (st->IsValid()) st->~Station();
    67 	return false;
    61 	}
    68 }
    62 }
       
    63 
       
    64 /**
       
    65  * Called if a new block is added to the roadstop-pool
       
    66  */
       
    67 static void RoadStopPoolNewBlock(uint start_item)
       
    68 {
       
    69 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
       
    70 	 * TODO - This is just a temporary stage, this will be removed. */
       
    71 	for (RoadStop *rs = GetRoadStop(start_item); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
       
    72 		rs->xy    = INVALID_TILE;
       
    73 		rs->index = start_item++;
       
    74 	}
       
    75 }
       
    76 
       
    77 DEFINE_OLD_POOL(Station, Station, StationPoolNewBlock, StationPoolCleanBlock)
       
    78 DEFINE_OLD_POOL(RoadStop, RoadStop, RoadStopPoolNewBlock, NULL)
       
    79 
       
    80 
    69 
    81 RoadStop* GetRoadStopByTile(TileIndex tile, RoadStop::Type type)
    70 RoadStop* GetRoadStopByTile(TileIndex tile, RoadStop::Type type)
    82 {
    71 {
    83 	const Station* st = GetStationByTile(tile);
    72 	const Station* st = GetStationByTile(tile);
    84 
    73 
   135 		}
   124 		}
   136 	END_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TileDiffXY(1, 1))
   125 	END_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TileDiffXY(1, 1))
   137 	return (closest_station == INVALID_STATION) ? NULL : GetStation(closest_station);
   126 	return (closest_station == INVALID_STATION) ? NULL : GetStation(closest_station);
   138 }
   127 }
   139 
   128 
       
   129 /**
       
   130  * Function to check whether the given tile matches some criterion.
       
   131  * @param tile the tile to check
       
   132  * @return true if it matches, false otherwise
       
   133  */
       
   134 typedef bool (*CMSAMatcher)(TileIndex tile);
   140 
   135 
   141 /**
   136 /**
   142  * Counts the numbers of tiles matching a specific type in the area around
   137  * Counts the numbers of tiles matching a specific type in the area around
   143  * @param tile the center tile of the 'count area'
   138  * @param tile the center tile of the 'count area'
   144  * @param type the type of tile searched for
   139  * @param type the type of tile searched for
   145  * @param industry when type == MP_INDUSTRY, the type of the industry,
   140  * @param industry when type == MP_INDUSTRY, the type of the industry,
   146  *                 in all other cases this parameter is ignored
   141  *                 in all other cases this parameter is ignored
   147  * @return the result the noumber of matching tiles around
   142  * @return the result the noumber of matching tiles around
   148  */
   143  */
   149 static int CountMapSquareAround(TileIndex tile, TileType type, IndustryType industry)
   144 static int CountMapSquareAround(TileIndex tile, CMSAMatcher cmp)
   150 {
   145 {
   151 	int num = 0;
   146 	int num = 0;
   152 
   147 
   153 	for (int dx = -3; dx <= 3; dx++) {
   148 	for (int dx = -3; dx <= 3; dx++) {
   154 		for (int dy = -3; dy <= 3; dy++) {
   149 		for (int dy = -3; dy <= 3; dy++) {
   155 			TileIndex cur_tile = TILE_MASK(tile + TileDiffXY(dx, dy));
   150 			if (cmp(TILE_MASK(tile + TileDiffXY(dx, dy)))) num++;
   156 
       
   157 			if (IsTileType(cur_tile, type)) {
       
   158 				switch (type) {
       
   159 					case MP_INDUSTRY:
       
   160 						if (GetIndustryType(cur_tile) == industry)
       
   161 							num++;
       
   162 						break;
       
   163 
       
   164 					case MP_WATER:
       
   165 						if (!IsWater(cur_tile))
       
   166 							break;
       
   167 						/* FALL THROUGH WHEN WATER TILE */
       
   168 					case MP_TREES:
       
   169 						num++;
       
   170 						break;
       
   171 
       
   172 					default:
       
   173 						break;
       
   174 				}
       
   175 			}
       
   176 		}
   151 		}
   177 	}
   152 	}
   178 
   153 
   179 	return num;
   154 	return num;
       
   155 }
       
   156 
       
   157 /**
       
   158  * Check whether the tile is a mine.
       
   159  * @param tile the tile to investigate.
       
   160  * @return true if and only if the tile is a mine
       
   161  */
       
   162 static bool CMSAMine(TileIndex tile)
       
   163 {
       
   164 	/* No industry */
       
   165 	if (!IsTileType(tile, MP_INDUSTRY)) return false;
       
   166 
       
   167 	const IndustrySpec *indsp = GetIndustrySpec(GetIndustryByTile(tile)->type);
       
   168 
       
   169 	/* No extractive industry */
       
   170 	if ((indsp->life_type & INDUSTRYLIFE_EXTRACTIVE) == 0) return false;
       
   171 
       
   172 	for (uint i = 0; i < lengthof(indsp->produced_cargo); i++) {
       
   173 		/* The industry extracts something non-liquid, i.e. no oil or plastic, so it is a mine */
       
   174 		if (indsp->produced_cargo[i] != CT_INVALID && (GetCargo(indsp->produced_cargo[i])->classes & CC_LIQUID) == 0) return true;
       
   175 	}
       
   176 
       
   177 	return false;
       
   178 }
       
   179 
       
   180 /**
       
   181  * Check whether the tile is water.
       
   182  * @param tile the tile to investigate.
       
   183  * @return true if and only if the tile is a mine
       
   184  */
       
   185 static bool CMSAWater(TileIndex tile)
       
   186 {
       
   187 	return IsTileType(tile, MP_WATER) && IsWater(tile);
       
   188 }
       
   189 
       
   190 /**
       
   191  * Check whether the tile is a tree.
       
   192  * @param tile the tile to investigate.
       
   193  * @return true if and only if the tile is a mine
       
   194  */
       
   195 static bool CMSATree(TileIndex tile)
       
   196 {
       
   197 	return IsTileType(tile, MP_TREES);
       
   198 }
       
   199 
       
   200 /**
       
   201  * Check whether the tile is a forest.
       
   202  * @param tile the tile to investigate.
       
   203  * @return true if and only if the tile is a mine
       
   204  */
       
   205 static bool CMSAForest(TileIndex tile)
       
   206 {
       
   207 	/* No industry */
       
   208 	if (!IsTileType(tile, MP_INDUSTRY)) return false;
       
   209 
       
   210 	const IndustrySpec *indsp = GetIndustrySpec(GetIndustryByTile(tile)->type);
       
   211 
       
   212 	/* No extractive industry */
       
   213 	if ((indsp->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
       
   214 
       
   215 	for (uint i = 0; i < lengthof(indsp->produced_cargo); i++) {
       
   216 		/* The industry produces wood. */
       
   217 		if (indsp->produced_cargo[i] != CT_INVALID && GetCargo(indsp->produced_cargo[i])->label == 'WOOD') return true;
       
   218 	}
       
   219 
       
   220 	return false;
   180 }
   221 }
   181 
   222 
   182 #define M(x) ((x) - STR_SV_STNAME)
   223 #define M(x) ((x) - STR_SV_STNAME)
   183 
   224 
   184 static bool GenerateStationName(Station *st, TileIndex tile, int flag)
   225 static bool GenerateStationName(Station *st, TileIndex tile, int flag)
   219 		goto done;
   260 		goto done;
   220 	}
   261 	}
   221 
   262 
   222 	/* check mine? */
   263 	/* check mine? */
   223 	if (HASBIT(free_names, M(STR_SV_STNAME_MINES))) {
   264 	if (HASBIT(free_names, M(STR_SV_STNAME_MINES))) {
   224 		if (CountMapSquareAround(tile, MP_INDUSTRY, IT_COAL_MINE) >= 2 ||
   265 		if (CountMapSquareAround(tile, CMSAMine) >= 2) {
   225 				CountMapSquareAround(tile, MP_INDUSTRY, IT_IRON_MINE) >= 2 ||
       
   226 				CountMapSquareAround(tile, MP_INDUSTRY, IT_COPPER_MINE) >= 2 ||
       
   227 				CountMapSquareAround(tile, MP_INDUSTRY, IT_GOLD_MINE) >= 2 ||
       
   228 				CountMapSquareAround(tile, MP_INDUSTRY, IT_DIAMOND_MINE) >= 2) {
       
   229 			found = M(STR_SV_STNAME_MINES);
   266 			found = M(STR_SV_STNAME_MINES);
   230 			goto done;
   267 			goto done;
   231 		}
   268 		}
   232 	}
   269 	}
   233 
   270 
   241 	}
   278 	}
   242 
   279 
   243 	/* Check lakeside */
   280 	/* Check lakeside */
   244 	if (HASBIT(free_names, M(STR_SV_STNAME_LAKESIDE)) &&
   281 	if (HASBIT(free_names, M(STR_SV_STNAME_LAKESIDE)) &&
   245 			DistanceFromEdge(tile) < 20 &&
   282 			DistanceFromEdge(tile) < 20 &&
   246 			CountMapSquareAround(tile, MP_WATER, 0) >= 5) {
   283 			CountMapSquareAround(tile, CMSAWater) >= 5) {
   247 		found = M(STR_SV_STNAME_LAKESIDE);
   284 		found = M(STR_SV_STNAME_LAKESIDE);
   248 		goto done;
   285 		goto done;
   249 	}
   286 	}
   250 
   287 
   251 	/* Check woods */
   288 	/* Check woods */
   252 	if (HASBIT(free_names, M(STR_SV_STNAME_WOODS)) && (
   289 	if (HASBIT(free_names, M(STR_SV_STNAME_WOODS)) && (
   253 				CountMapSquareAround(tile, MP_TREES, 0) >= 8 ||
   290 				CountMapSquareAround(tile, CMSATree) >= 8 ||
   254 				CountMapSquareAround(tile, MP_INDUSTRY, IT_FOREST) >= 2)
   291 				CountMapSquareAround(tile, CMSAForest) >= 2)
   255 			) {
   292 			) {
   256 		found = _opt.landscape == LT_TROPIC ?
   293 		found = _opt.landscape == LT_TROPIC ?
   257 			M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS);
   294 			M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS);
   258 		goto done;
   295 		goto done;
   259 	}
   296 	}
   888 		//XXX can't we pack this in the "else" part of the if above?
   925 		//XXX can't we pack this in the "else" part of the if above?
   889 		if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR;
   926 		if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR;
   890 	} else {
   927 	} else {
   891 		/* allocate and initialize new station */
   928 		/* allocate and initialize new station */
   892 		st = new Station(tile_org);
   929 		st = new Station(tile_org);
   893 		if (st == NULL) return CMD_ERROR;
   930 		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
   894 
   931 
   895 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
   932 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
   896 		st_auto_delete = st;
   933 		st_auto_delete = st;
   897 
   934 
   898 		st->town = ClosestTownFromTile(tile_org, (uint)-1);
   935 		st->town = ClosestTownFromTile(tile_org, (uint)-1);
   980 		UpdateStationVirtCoordDirty(st);
  1017 		UpdateStationVirtCoordDirty(st);
   981 		UpdateStationAcceptance(st, false);
  1018 		UpdateStationAcceptance(st, false);
   982 		RebuildStationLists();
  1019 		RebuildStationLists();
   983 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1020 		InvalidateWindow(WC_STATION_LIST, st->owner);
   984 		/* success, so don't delete the new station */
  1021 		/* success, so don't delete the new station */
   985 		st_auto_delete.Release();
  1022 		st_auto_delete.Detach();
   986 	}
  1023 	}
   987 
  1024 
   988 	return cost;
  1025 	return cost;
   989 }
  1026 }
   990 
  1027 
  1242  */
  1279  */
  1243 CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1280 CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1244 {
  1281 {
  1245 	bool type = HASBIT(p2, 0);
  1282 	bool type = HASBIT(p2, 0);
  1246 	bool is_drive_through = HASBIT(p2, 1);
  1283 	bool is_drive_through = HASBIT(p2, 1);
  1247 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
  1284 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
  1248 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
  1285 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
  1249 	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
  1286 	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
  1250 
  1287 
  1251 	if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR;
  1288 	if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR;
  1252 
  1289 
  1319 
  1356 
  1320 		if (!st->rect.BeforeAddTile(tile, StationRect::ADD_TEST)) return CMD_ERROR;
  1357 		if (!st->rect.BeforeAddTile(tile, StationRect::ADD_TEST)) return CMD_ERROR;
  1321 	} else {
  1358 	} else {
  1322 		/* allocate and initialize new station */
  1359 		/* allocate and initialize new station */
  1323 		st = new Station(tile);
  1360 		st = new Station(tile);
  1324 		if (st == NULL) return CMD_ERROR;
  1361 		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1325 
  1362 
  1326 		/* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */
  1363 		/* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */
  1327 		st_auto_delete = st;
  1364 		st_auto_delete = st;
  1328 
  1365 
  1329 
  1366 
  1359 		UpdateStationVirtCoordDirty(st);
  1396 		UpdateStationVirtCoordDirty(st);
  1360 		UpdateStationAcceptance(st, false);
  1397 		UpdateStationAcceptance(st, false);
  1361 		RebuildStationLists();
  1398 		RebuildStationLists();
  1362 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1399 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1363 		/* success, so don't delete the new station and the new road stop */
  1400 		/* success, so don't delete the new station and the new road stop */
  1364 		st_auto_delete.Release();
  1401 		st_auto_delete.Detach();
  1365 		rs_auto_delete.Release();
  1402 		rs_auto_delete.Detach();
  1366 	}
  1403 	}
  1367 	return cost;
  1404 	return cost;
  1368 }
  1405 }
  1369 
  1406 
  1370 // Remove a bus station
  1407 // Remove a bus station
  1613 	} else {
  1650 	} else {
  1614 		airport_upgrade = false;
  1651 		airport_upgrade = false;
  1615 
  1652 
  1616 		/* allocate and initialize new station */
  1653 		/* allocate and initialize new station */
  1617 		st = new Station(tile);
  1654 		st = new Station(tile);
  1618 		if (st == NULL) return CMD_ERROR;
  1655 		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1619 
  1656 
  1620 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1657 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1621 		st_auto_delete = st;
  1658 		st_auto_delete = st;
  1622 
  1659 
  1623 		st->town = t;
  1660 		st->town = t;
  1666 		UpdateStationVirtCoordDirty(st);
  1703 		UpdateStationVirtCoordDirty(st);
  1667 		UpdateStationAcceptance(st, false);
  1704 		UpdateStationAcceptance(st, false);
  1668 		RebuildStationLists();
  1705 		RebuildStationLists();
  1669 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1706 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1670 		/* success, so don't delete the new station */
  1707 		/* success, so don't delete the new station */
  1671 		st_auto_delete.Release();
  1708 		st_auto_delete.Detach();
  1672 	}
  1709 	}
  1673 
  1710 
  1674 	return cost;
  1711 	return cost;
  1675 }
  1712 }
  1676 
  1713 
  1735 	if (!IsClearWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1772 	if (!IsClearWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1736 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
  1773 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
  1737 
  1774 
  1738 	/* allocate and initialize new station */
  1775 	/* allocate and initialize new station */
  1739 	Station *st = new Station(tile);
  1776 	Station *st = new Station(tile);
  1740 	if (st == NULL) return CMD_ERROR;
  1777 	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1741 
  1778 
  1742 	/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1779 	/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1743 	AutoPtrT<Station> st_auto_delete(st);
  1780 	AutoPtrT<Station> st_auto_delete(st);
  1744 
  1781 
  1745 	st->town = ClosestTownFromTile(tile, (uint)-1);
  1782 	st->town = ClosestTownFromTile(tile, (uint)-1);
  1762 		UpdateStationVirtCoordDirty(st);
  1799 		UpdateStationVirtCoordDirty(st);
  1763 		UpdateStationAcceptance(st, false);
  1800 		UpdateStationAcceptance(st, false);
  1764 		RebuildStationLists();
  1801 		RebuildStationLists();
  1765 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1802 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1766 		/* success, so don't delete the new station */
  1803 		/* success, so don't delete the new station */
  1767 		st_auto_delete.Release();
  1804 		st_auto_delete.Detach();
  1768 	}
  1805 	}
  1769 
  1806 
  1770 	return CommandCost(_price.build_dock);
  1807 	return CommandCost(_price.build_dock);
  1771 }
  1808 }
  1772 
  1809 
  1900 
  1937 
  1901 		if (st->dock_tile != 0) return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK);
  1938 		if (st->dock_tile != 0) return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK);
  1902 	} else {
  1939 	} else {
  1903 		/* allocate and initialize new station */
  1940 		/* allocate and initialize new station */
  1904 		st = new Station(tile);
  1941 		st = new Station(tile);
  1905 		if (st == NULL) return CMD_ERROR;
  1942 		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1906 
  1943 
  1907 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1944 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1908 		st_auto_delete = st;
  1945 		st_auto_delete = st;
  1909 
  1946 
  1910 		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
  1947 		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
  1929 		UpdateStationVirtCoordDirty(st);
  1966 		UpdateStationVirtCoordDirty(st);
  1930 		UpdateStationAcceptance(st, false);
  1967 		UpdateStationAcceptance(st, false);
  1931 		RebuildStationLists();
  1968 		RebuildStationLists();
  1932 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1969 		InvalidateWindow(WC_STATION_LIST, st->owner);
  1933 		/* success, so don't delete the new station */
  1970 		/* success, so don't delete the new station */
  1934 		st_auto_delete.Release();
  1971 		st_auto_delete.Detach();
  1935 	}
  1972 	}
  1936 	return CommandCost(_price.build_dock);
  1973 	return CommandCost(_price.build_dock);
  1937 }
  1974 }
  1938 
  1975 
  1939 static CommandCost RemoveDock(Station *st, uint32 flags)
  1976 static CommandCost RemoveDock(Station *st, uint32 flags)
  2001 		palette = PALETTE_TO_GREY;
  2038 		palette = PALETTE_TO_GREY;
  2002 	}
  2039 	}
  2003 
  2040 
  2004 	// don't show foundation for docks
  2041 	// don't show foundation for docks
  2005 	if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile))
  2042 	if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile))
  2006 		DrawFoundation(ti, ti->tileh);
  2043 		DrawFoundation(ti, FOUNDATION_LEVELED);
  2007 
  2044 
  2008 	if (IsCustomStationSpecIndex(ti->tile)) {
  2045 	if (IsCustomStationSpecIndex(ti->tile)) {
  2009 		// look for customization
  2046 		// look for customization
  2010 		st = GetStationByTile(ti->tile);
  2047 		st = GetStationByTile(ti->tile);
  2011 		statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
  2048 		statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
  2061 		} else {
  2098 		} else {
  2062 			image += relocation;
  2099 			image += relocation;
  2063 		}
  2100 		}
  2064 
  2101 
  2065 		SpriteID pal;
  2102 		SpriteID pal;
  2066 		if (HASBIT(_transparent_opt, TO_BUILDINGS)) {
  2103 		if (!HASBIT(_transparent_opt, TO_BUILDINGS) && HASBIT(image, PALETTE_MODIFIER_COLOR)) {
  2067 			SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
       
  2068 			pal = PALETTE_TO_TRANSPARENT;
       
  2069 		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
       
  2070 			pal = palette;
  2104 			pal = palette;
  2071 		} else {
  2105 		} else {
  2072 			pal = dtss->pal;
  2106 			pal = dtss->pal;
  2073 		}
  2107 		}
  2074 
  2108 
  2075 		if ((byte)dtss->delta_z != 0x80) {
  2109 		if ((byte)dtss->delta_z != 0x80) {
  2076 			AddSortableSpriteToDraw(
  2110 			AddSortableSpriteToDraw(
  2077 				image, pal,
  2111 				image, pal,
  2078 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
  2112 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
  2079 				dtss->size_x, dtss->size_y,
  2113 				dtss->size_x, dtss->size_y,
  2080 				dtss->size_z, ti->z + dtss->delta_z
  2114 				dtss->size_z, ti->z + dtss->delta_z,
       
  2115 				HASBIT(_transparent_opt, TO_BUILDINGS)
  2081 			);
  2116 			);
  2082 		} else {
  2117 		} else {
  2083 			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
  2118 			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
  2084 		}
  2119 		}
  2085 	}
  2120 	}
  2108 static uint GetSlopeZ_Station(TileIndex tile, uint x, uint y)
  2143 static uint GetSlopeZ_Station(TileIndex tile, uint x, uint y)
  2109 {
  2144 {
  2110 	return GetTileMaxZ(tile);
  2145 	return GetTileMaxZ(tile);
  2111 }
  2146 }
  2112 
  2147 
  2113 static Slope GetSlopeTileh_Station(TileIndex tile, Slope tileh)
  2148 static Foundation GetFoundation_Station(TileIndex tile, Slope tileh)
  2114 {
  2149 {
  2115 	return SLOPE_FLAT;
  2150 	return FlatteningFoundation(tileh);
  2116 }
  2151 }
  2117 
  2152 
  2118 static void GetAcceptedCargo_Station(TileIndex tile, AcceptedCargo ac)
  2153 static void GetAcceptedCargo_Station(TileIndex tile, AcceptedCargo ac)
  2119 {
  2154 {
  2120 	/* not used */
  2155 	/* not used */
  2812 }
  2847 }
  2813 
  2848 
  2814 void InitializeStations()
  2849 void InitializeStations()
  2815 {
  2850 {
  2816 	/* Clean the station pool and create 1 block in it */
  2851 	/* Clean the station pool and create 1 block in it */
  2817 	CleanPool(&_Station_pool);
  2852 	_Station_pool.CleanPool();
  2818 	AddBlockToPool(&_Station_pool);
  2853 	_Station_pool.AddBlockToPool();
  2819 
  2854 
  2820 	/* Clean the roadstop pool and create 1 block in it */
  2855 	/* Clean the roadstop pool and create 1 block in it */
  2821 	CleanPool(&_RoadStop_pool);
  2856 	_RoadStop_pool.CleanPool();
  2822 	AddBlockToPool(&_RoadStop_pool);
  2857 	_RoadStop_pool.AddBlockToPool();
  2823 
  2858 
  2824 	_station_tick_ctr = 0;
  2859 	_station_tick_ctr = 0;
  2825 
  2860 
  2826 }
  2861 }
  2827 
  2862 
  2853 	AnimateTile_Station,        /* animate_tile_proc */
  2888 	AnimateTile_Station,        /* animate_tile_proc */
  2854 	TileLoop_Station,           /* tile_loop_clear */
  2889 	TileLoop_Station,           /* tile_loop_clear */
  2855 	ChangeTileOwner_Station,    /* change_tile_owner_clear */
  2890 	ChangeTileOwner_Station,    /* change_tile_owner_clear */
  2856 	NULL,                       /* get_produced_cargo_proc */
  2891 	NULL,                       /* get_produced_cargo_proc */
  2857 	VehicleEnter_Station,       /* vehicle_enter_tile_proc */
  2892 	VehicleEnter_Station,       /* vehicle_enter_tile_proc */
  2858 	GetSlopeTileh_Station,      /* get_slope_tileh_proc */
  2893 	GetFoundation_Station,      /* get_foundation_proc */
  2859 };
  2894 };
  2860 
  2895 
  2861 static const SaveLoad _roadstop_desc[] = {
  2896 static const SaveLoad _roadstop_desc[] = {
  2862 	SLE_VAR(RoadStop,xy,           SLE_UINT32),
  2897 	SLE_VAR(RoadStop,xy,           SLE_UINT32),
  2863 	SLE_CONDNULL(1, 0, 44),
  2898 	SLE_CONDNULL(1, 0, 44),