src/road_cmd.cpp
changeset 6661 1716fce5ad29
parent 6626 207875b9069a
child 6662 ea30b3497d9a
equal deleted inserted replaced
6660:b892af29d891 6661:1716fce5ad29
    39 	if (r & ROAD_NE) ++count;
    39 	if (r & ROAD_NE) ++count;
    40 	return count;
    40 	return count;
    41 }
    41 }
    42 
    42 
    43 
    43 
    44 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road)
    44 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
    45 {
    45 {
    46 	RoadBits present;
    46 	RoadBits present;
    47 	RoadBits n;
    47 	RoadBits n;
    48 	*edge_road = true;
    48 	*edge_road = true;
    49 
    49 
    50 	if (_game_mode == GM_EDITOR) return true;
    50 	if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true;
    51 
    51 
    52 	/* Only do the special processing for actual players. */
    52 	/* Only do the special processing for actual players. */
    53 	if (!IsValidPlayer(_current_player)) return true;
    53 	if (!IsValidPlayer(_current_player)) return true;
    54 
    54 
    55 	/* Only do the special processing if the road is owned
    55 	/* Only do the special processing if the road is owned
    58 
    58 
    59 	if (_cheats.magic_bulldozer.value) return true;
    59 	if (_cheats.magic_bulldozer.value) return true;
    60 
    60 
    61 	/* Get a bitmask of which neighbouring roads has a tile */
    61 	/* Get a bitmask of which neighbouring roads has a tile */
    62 	n = ROAD_NONE;
    62 	n = ROAD_NONE;
    63 	present = GetAnyRoadBits(tile);
    63 	present = GetAnyRoadBits(tile, rt);
    64 	if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0)) & ROAD_SW) n |= ROAD_NE;
    64 	if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1,  0), rt) & ROAD_SW) n |= ROAD_NE;
    65 	if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1)) & ROAD_NW) n |= ROAD_SE;
    65 	if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile,  0,  1), rt) & ROAD_NW) n |= ROAD_SE;
    66 	if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0)) & ROAD_NE) n |= ROAD_SW;
    66 	if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile,  1,  0), rt) & ROAD_NE) n |= ROAD_SW;
    67 	if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1)) & ROAD_SE) n |= ROAD_NW;
    67 	if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile,  0, -1), rt) & ROAD_SE) n |= ROAD_NW;
    68 
    68 
    69 	/* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
    69 	/* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
    70 	 * then allow it */
    70 	 * then allow it */
    71 	if ((n & (n - 1)) != 0 && (n & remove) != 0) {
    71 	if ((n & (n - 1)) != 0 && (n & remove) != 0) {
    72 		Town *t;
    72 		Town *t;
    82 	}
    82 	}
    83 
    83 
    84 	return true;
    84 	return true;
    85 }
    85 }
    86 
    86 
    87 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road)
    87 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
    88 {
    88 {
    89 	return CheckAllowRemoveRoad(tile, remove, IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile), edge_road);
    89 	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
    90 }
    90 }
    91 
    91 
    92 /** Delete a piece of road.
    92 /** Delete a piece of road.
    93  * @param tile tile where to remove road from
    93  * @param tile tile where to remove road from
    94  * @param flags operation to perform
    94  * @param flags operation to perform
    95  * @param p1 bit 0..3 road pieces to remove (RoadBits)
    95  * @param p1 bit 0..3 road pieces to remove (RoadBits)
       
    96  *           bit 4..5 road type
    96  * @param p2 unused
    97  * @param p2 unused
    97  */
    98  */
    98 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    99 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    99 {
   100 {
   100 	/* cost for removing inner/edge -roads */
   101 	/* cost for removing inner/edge -roads */
   101 	static const uint16 road_remove_cost[2] = {50, 18};
   102 	static const uint16 road_remove_cost[2] = {50, 18};
   102 
   103 
   103 	Owner owner;
       
   104 	Town *t;
   104 	Town *t;
   105 	/* true if the roadpiece was always removeable,
   105 	/* true if the roadpiece was always removeable,
   106 	 * false if it was a center piece. Affects town ratings drop */
   106 	 * false if it was a center piece. Affects town ratings drop */
   107 	bool edge_road;
   107 	bool edge_road;
   108 
   108 
   109 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   109 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   110 
   110 
   111 	if (!IsTileType(tile, MP_STREET)) return CMD_ERROR;
   111 	RoadType rt = (RoadType)GB(p1, 4, 2);
   112 
   112 	if (!IsTileType(tile, MP_STREET) || !IsValidRoadType(rt)) return CMD_ERROR;
   113 	owner = IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile);
   113 
       
   114 	Owner owner = GetRoadOwner(tile, rt);
   114 
   115 
   115 	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
   116 	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
   116 		t = GetTownByTile(tile);
   117 		t = GetTownByTile(tile);
   117 	} else {
   118 	} else {
   118 		t = NULL;
   119 		t = NULL;
   119 	}
   120 	}
   120 
   121 
   121 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   122 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   122 
   123 	RoadTypes rts = GetRoadTypes(tile);
   123 	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road)) return CMD_ERROR;
   124 	/* The tile doesn't have the given road type */
       
   125 	if (!HASBIT(rts, rt)) return CMD_ERROR;
       
   126 
       
   127 	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
   124 
   128 
   125 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   129 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   126 
   130 
   127 	/* check if you're allowed to remove the street owned by a town
   131 	/* check if you're allowed to remove the street owned by a town
   128 	 * removal allowance depends on difficulty setting */
   132 	 * removal allowance depends on difficulty setting */
   129 	if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
   133 	if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
   130 
   134 
   131 	switch (GetRoadTileType(tile)) {
   135 	switch (GetRoadTileType(tile)) {
   132 		case ROAD_TILE_NORMAL: {
   136 		case ROAD_TILE_NORMAL: {
   133 			RoadBits present = GetRoadBits(tile);
   137 			RoadBits present = GetRoadBits(tile, rt);
   134 			RoadBits c = pieces;
   138 			RoadBits c = pieces;
   135 
   139 
   136 			if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   140 			if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   137 
   141 
   138 			if (GetTileSlope(tile, NULL) != SLOPE_FLAT  &&
   142 			if (GetTileSlope(tile, NULL) != SLOPE_FLAT  &&
   148 			if (flags & DC_EXEC) {
   152 			if (flags & DC_EXEC) {
   149 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   153 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   150 
   154 
   151 				present ^= c;
   155 				present ^= c;
   152 				if (present == 0) {
   156 				if (present == 0) {
   153 					DoClearSquare(tile);
   157 					RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
       
   158 					if (rts == ROADTYPES_NONE) {
       
   159 						DoClearSquare(tile);
       
   160 					} else {
       
   161 						SetRoadTypes(tile, rts);
       
   162 					}
   154 				} else {
   163 				} else {
   155 					SetRoadBits(tile, present);
   164 					SetRoadBits(tile, present, rt);
   156 					MarkTileDirtyByTile(tile);
   165 					MarkTileDirtyByTile(tile);
   157 				}
   166 				}
   158 			}
   167 			}
   159 			return CountRoadBits(c) * _price.remove_road;
   168 			return CountRoadBits(c) * _price.remove_road;
   160 		}
   169 		}
   163 			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
   172 			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
   164 				return CMD_ERROR;
   173 				return CMD_ERROR;
   165 			}
   174 			}
   166 
   175 
   167 			if (flags & DC_EXEC) {
   176 			if (flags & DC_EXEC) {
   168 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   177 				if (rt == ROADTYPE_ROAD) {
   169 
   178 					ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   170 				MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
   179 				}
       
   180 
       
   181 				RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
       
   182 				if (rts == ROADTYPES_NONE) {
       
   183 					MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
       
   184 				} else {
       
   185 					SetRoadTypes(tile, rts);
       
   186 				}
   171 				MarkTileDirtyByTile(tile);
   187 				MarkTileDirtyByTile(tile);
   172 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   188 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   173 			}
   189 			}
   174 			return _price.remove_road * 2;
   190 			return _price.remove_road * 2;
   175 		}
   191 		}
   253 
   269 
   254 /** Build a piece of road.
   270 /** Build a piece of road.
   255  * @param tile tile where to build road
   271  * @param tile tile where to build road
   256  * @param flags operation to perform
   272  * @param flags operation to perform
   257  * @param p1 bit 0..3 road pieces to build (RoadBits)
   273  * @param p1 bit 0..3 road pieces to build (RoadBits)
       
   274  *           bit 4..5 road type
   258  * @param p2 the town that is building the road (0 if not applicable)
   275  * @param p2 the town that is building the road (0 if not applicable)
   259  */
   276  */
   260 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   277 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   261 {
   278 {
   262 	int32 cost = 0;
   279 	int32 cost = 0;
   269 	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
   286 	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
   270 	 * if a non-player is building the road */
   287 	 * if a non-player is building the road */
   271 	if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR;
   288 	if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR;
   272 
   289 
   273 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   290 	RoadBits pieces = Extract<RoadBits, 0>(p1);
       
   291 
       
   292 	RoadType rt = (RoadType)GB(p1, 4, 2);
       
   293 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   274 
   294 
   275 	tileh = GetTileSlope(tile, NULL);
   295 	tileh = GetTileSlope(tile, NULL);
   276 
   296 
   277 	switch (GetTileType(tile)) {
   297 	switch (GetTileType(tile)) {
   278 		case MP_STREET:
   298 		case MP_STREET:
   279 			switch (GetRoadTileType(tile)) {
   299 			switch (GetRoadTileType(tile)) {
   280 				case ROAD_TILE_NORMAL:
   300 				case ROAD_TILE_NORMAL:
   281 					if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   301 					if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   282 
   302 
   283 					existing = GetRoadBits(tile);
   303 					existing = GetRoadBits(tile, rt);
   284 					if ((existing & pieces) == pieces) {
   304 					if ((existing & pieces) == pieces) {
   285 						return_cmd_error(STR_1007_ALREADY_BUILT);
   305 						return_cmd_error(STR_1007_ALREADY_BUILT);
   286 					}
   306 					}
   287 					if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   307 					if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   288 					break;
   308 					break;
   289 
   309 
   290 				case ROAD_TILE_CROSSING:
   310 				case ROAD_TILE_CROSSING:
   291 					if (pieces != GetCrossingRoadBits(tile)) { // XXX is this correct?
   311 					if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   292 						return_cmd_error(STR_1007_ALREADY_BUILT);
   312 					if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) goto do_clear;
   293 					}
   313 					break;
   294 					goto do_clear;
       
   295 
   314 
   296 				default:
   315 				default:
   297 				case ROAD_TILE_DEPOT:
   316 				case ROAD_TILE_DEPOT:
   298 					goto do_clear;
   317 					goto do_clear;
   299 			}
   318 			}
   330 
   349 
   331 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   350 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   332 
   351 
   333 			if (flags & DC_EXEC) {
   352 			if (flags & DC_EXEC) {
   334 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   353 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   335 				MakeRoadCrossing(tile, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), p2);
   354 				MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt), p2);
   336 				MarkTileDirtyByTile(tile);
   355 				MarkTileDirtyByTile(tile);
   337 			}
   356 			}
   338 			return _price.build_road * 2;
   357 			return _price.build_road * 2;
   339 		}
   358 		}
   340 
   359 
   360 
   379 
   361 	cost += CountRoadBits(pieces) * _price.build_road;
   380 	cost += CountRoadBits(pieces) * _price.build_road;
   362 
   381 
   363 	if (flags & DC_EXEC) {
   382 	if (flags & DC_EXEC) {
   364 		if (IsTileType(tile, MP_STREET)) {
   383 		if (IsTileType(tile, MP_STREET)) {
   365 			SetRoadBits(tile, existing | pieces);
   384 			if (existing == 0) {
       
   385 				SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
       
   386 				SetRoadOwner(tile, rt, _current_player);
       
   387 			}
       
   388 			SetRoadBits(tile, existing | pieces, rt);
   366 		} else {
   389 		} else {
   367 			MakeRoadNormal(tile, _current_player, pieces, p2);
   390 			MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_player, _current_player, _current_player);
   368 		}
   391 		}
   369 
   392 
   370 		MarkTileDirtyByTile(tile);
   393 		MarkTileDirtyByTile(tile);
   371 	}
   394 	}
   372 	return cost;
   395 	return cost;
   409  * @param p1 start tile of drag
   432  * @param p1 start tile of drag
   410  * @param p2 various bitstuffed elements
   433  * @param p2 various bitstuffed elements
   411  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   434  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   412  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   435  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   413  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   436  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
       
   437  * - p2 = (bit 3) - road type
   414  */
   438  */
   415 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   439 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   416 {
   440 {
   417 	TileIndex start_tile, tile;
   441 	TileIndex start_tile, tile;
   418 	int32 cost, ret;
   442 	int32 cost, ret;
   420 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   444 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   421 
   445 
   422 	if (p1 >= MapSize()) return CMD_ERROR;
   446 	if (p1 >= MapSize()) return CMD_ERROR;
   423 
   447 
   424 	start_tile = p1;
   448 	start_tile = p1;
       
   449 	RoadType rt = (RoadType)HASBIT(p2, 3);
   425 
   450 
   426 	/* Only drag in X or Y direction dictated by the direction variable */
   451 	/* Only drag in X or Y direction dictated by the direction variable */
   427 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   452 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   428 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   453 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   429 
   454 
   442 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   467 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   443 
   468 
   444 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   469 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   445 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   470 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   446 
   471 
   447 		ret = DoCommand(tile, bits, 0, flags, CMD_BUILD_ROAD);
   472 		ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
   448 		if (CmdFailed(ret)) {
   473 		if (CmdFailed(ret)) {
   449 			if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
   474 			if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
   450 			_error_message = INVALID_STRING_ID;
   475 			_error_message = INVALID_STRING_ID;
   451 		} else {
   476 		} else {
   452 			cost += ret;
   477 			cost += ret;
   466  * @param p1 start tile of drag
   491  * @param p1 start tile of drag
   467  * @param p2 various bitstuffed elements
   492  * @param p2 various bitstuffed elements
   468  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   493  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   469  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   494  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   470  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   495  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
       
   496  * - p2 = (bit 3) - road type
   471  */
   497  */
   472 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   498 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   473 {
   499 {
   474 	TileIndex start_tile, tile;
   500 	TileIndex start_tile, tile;
   475 	int32 cost, ret;
   501 	int32 cost, ret;
   477 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   503 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   478 
   504 
   479 	if (p1 >= MapSize()) return CMD_ERROR;
   505 	if (p1 >= MapSize()) return CMD_ERROR;
   480 
   506 
   481 	start_tile = p1;
   507 	start_tile = p1;
       
   508 	RoadType rt = (RoadType)HASBIT(p2, 3);
   482 
   509 
   483 	/* Only drag in X or Y direction dictated by the direction variable */
   510 	/* Only drag in X or Y direction dictated by the direction variable */
   484 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   511 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   485 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   512 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   486 
   513 
   501 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   528 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   502 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   529 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   503 
   530 
   504 		/* try to remove the halves. */
   531 		/* try to remove the halves. */
   505 		if (bits != 0) {
   532 		if (bits != 0) {
   506 			ret = DoCommand(tile, bits, 0, flags, CMD_REMOVE_ROAD);
   533 			ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
   507 			if (!CmdFailed(ret)) cost += ret;
   534 			if (!CmdFailed(ret)) cost += ret;
   508 		}
   535 		}
   509 
   536 
   510 		if (tile == end_tile) break;
   537 		if (tile == end_tile) break;
   511 
   538 
   517 
   544 
   518 /** Build a road depot.
   545 /** Build a road depot.
   519  * @param tile tile where to build the depot
   546  * @param tile tile where to build the depot
   520  * @param flags operation to perform
   547  * @param flags operation to perform
   521  * @param p1 bit 0..1 entrance direction (DiagDirection)
   548  * @param p1 bit 0..1 entrance direction (DiagDirection)
       
   549  *           bit    2 road type
   522  * @param p2 unused
   550  * @param p2 unused
   523  *
   551  *
   524  * @todo When checking for the tile slope,
   552  * @todo When checking for the tile slope,
   525  * distingush between "Flat land required" and "land sloped in wrong direction"
   553  * distingush between "Flat land required" and "land sloped in wrong direction"
   526  */
   554  */
   531 	Slope tileh;
   559 	Slope tileh;
   532 
   560 
   533 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   561 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   534 
   562 
   535 	DiagDirection dir = Extract<DiagDirection, 0>(p1);
   563 	DiagDirection dir = Extract<DiagDirection, 0>(p1);
       
   564 	RoadType rt = (RoadType)HASBIT(p1, 2);
   536 
   565 
   537 	tileh = GetTileSlope(tile, NULL);
   566 	tileh = GetTileSlope(tile, NULL);
   538 	if (tileh != SLOPE_FLAT && (
   567 	if (tileh != SLOPE_FLAT && (
   539 				!_patches.build_on_slopes ||
   568 				!_patches.build_on_slopes ||
   540 				IsSteepSlope(tileh) ||
   569 				IsSteepSlope(tileh) ||
   553 
   582 
   554 	if (flags & DC_EXEC) {
   583 	if (flags & DC_EXEC) {
   555 		dep->xy = tile;
   584 		dep->xy = tile;
   556 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   585 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   557 
   586 
   558 		MakeRoadDepot(tile, _current_player, dir);
   587 		MakeRoadDepot(tile, _current_player, dir, rt);
   559 		MarkTileDirtyByTile(tile);
   588 		MarkTileDirtyByTile(tile);
   560 	}
   589 	}
   561 	return cost + _price.build_road_depot;
   590 	return cost + _price.build_road_depot;
   562 }
   591 }
   563 
   592 
   575 
   604 
   576 static int32 ClearTile_Road(TileIndex tile, byte flags)
   605 static int32 ClearTile_Road(TileIndex tile, byte flags)
   577 {
   606 {
   578 	switch (GetRoadTileType(tile)) {
   607 	switch (GetRoadTileType(tile)) {
   579 		case ROAD_TILE_NORMAL: {
   608 		case ROAD_TILE_NORMAL: {
   580 			RoadBits b = GetRoadBits(tile);
   609 			RoadBits b = GetAllRoadBits(tile);
   581 
   610 
   582 #define M(x) (1 << (x))
   611 #define M(x) (1 << (x))
   583 			/* Clear the road if only one piece is on the tile OR the AI tries
   612 			/* Clear the road if only one piece is on the tile OR the AI tries
   584 			 * to clear town road OR we are not using the DC_AUTO flag */
   613 			 * to clear town road OR we are not using the DC_AUTO flag */
   585 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) ||
   614 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) ||
   683  * Draw ground sprite and road pieces
   712  * Draw ground sprite and road pieces
   684  * @param ti TileInfo
   713  * @param ti TileInfo
   685  */
   714  */
   686 static void DrawRoadBits(TileInfo* ti)
   715 static void DrawRoadBits(TileInfo* ti)
   687 {
   716 {
   688 	RoadBits road = GetRoadBits(ti->tile);
   717 	RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
   689 	const DrawRoadTileStruct *drts;
   718 	const DrawRoadTileStruct *drts;
   690 	SpriteID image = 0;
   719 	SpriteID image = 0;
   691 	SpriteID pal = PAL_NONE;
   720 	SpriteID pal = PAL_NONE;
   692 	Roadside roadside;
   721 	Roadside roadside;
   693 
   722 
   834 	uint z;
   863 	uint z;
   835 	Slope tileh = GetTileSlope(tile, &z);
   864 	Slope tileh = GetTileSlope(tile, &z);
   836 
   865 
   837 	if (tileh == SLOPE_FLAT) return z;
   866 	if (tileh == SLOPE_FLAT) return z;
   838 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   867 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   839 		uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
   868 		uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
   840 
   869 
   841 		if (f != 0) {
   870 		if (f != 0) {
   842 			if (IsSteepSlope(tileh)) {
   871 			if (IsSteepSlope(tileh)) {
   843 				z += TILE_HEIGHT;
   872 				z += TILE_HEIGHT;
   844 			} else if (f < 15) {
   873 			} else if (f < 15) {
   854 
   883 
   855 static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh)
   884 static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh)
   856 {
   885 {
   857 	if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
   886 	if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
   858 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   887 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   859 		uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
   888 		uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
   860 
   889 
   861 		if (f == 0) return tileh;
   890 		if (f == 0) return tileh;
   862 		if (f < 15) return SLOPE_FLAT; // leveled foundation
   891 		if (f < 15) return SLOPE_FLAT; // leveled foundation
   863 		return _inclined_tileh[f - 15]; // inclined foundation
   892 		return _inclined_tileh[f - 15]; // inclined foundation
   864 	} else {
   893 	} else {
   922 			grp = GetTownRadiusGroup(t, tile);
   951 			grp = GetTownRadiusGroup(t, tile);
   923 
   952 
   924 			/* Show an animation to indicate road work */
   953 			/* Show an animation to indicate road work */
   925 			if (t->road_build_months != 0 &&
   954 			if (t->road_build_months != 0 &&
   926 					(DistanceManhattan(t->xy, tile) < 8 || grp != 0) &&
   955 					(DistanceManhattan(t->xy, tile) < 8 || grp != 0) &&
   927 					GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetRoadBits(tile) == ROAD_X || GetRoadBits(tile) == ROAD_Y)) {
   956 					GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) {
   928 				if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
   957 				if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
   929 					StartRoadWorks(tile);
   958 					StartRoadWorks(tile);
   930 
   959 
   931 					SndPlayTileFx(SND_21_JACKHAMMER, tile);
   960 					SndPlayTileFx(SND_21_JACKHAMMER, tile);
   932 					CreateEffectVehicleAbove(
   961 					CreateEffectVehicleAbove(
   976 	0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F,
  1005 	0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F,
   977 };
  1006 };
   978 
  1007 
   979 static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode)
  1008 static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode)
   980 {
  1009 {
       
  1010 	RoadType rt = ROADTYPE_ROAD;
       
  1011 
   981 	switch (mode) {
  1012 	switch (mode) {
   982 		case TRANSPORT_RAIL:
  1013 		case TRANSPORT_RAIL:
   983 			if (!IsLevelCrossing(tile)) return 0;
  1014 			if (!IsLevelCrossing(tile)) return 0;
   984 			return GetCrossingRailBits(tile) * 0x101;
  1015 			return GetCrossingRailBits(tile) * 0x101;
   985 
  1016 
   986 		case TRANSPORT_ROAD:
  1017 		case TRANSPORT_ROAD:
       
  1018 			if (!HASBIT(GetRoadTypes(tile), rt)) return 0;
   987 			switch (GetRoadTileType(tile)) {
  1019 			switch (GetRoadTileType(tile)) {
   988 				case ROAD_TILE_NORMAL:
  1020 				case ROAD_TILE_NORMAL:
   989 					return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile)] * 0x101;
  1021 					return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile, rt)] * 0x101;
   990 
  1022 
   991 				case ROAD_TILE_CROSSING: {
  1023 				case ROAD_TILE_CROSSING: {
   992 					uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101;
  1024 					uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101;
   993 
  1025 
   994 					if (IsCrossingBarred(tile)) r *= 0x10001;
  1026 					if (IsCrossingBarred(tile)) r *= 0x10001;
  1058 }
  1090 }
  1059 
  1091 
  1060 
  1092 
  1061 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1093 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1062 {
  1094 {
  1063 	if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) == old_player) {
  1095 	if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) {
  1064 		SetCrossingRoadOwner(tile, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
  1096 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
  1065 	}
  1097 		return;
  1066 
  1098 	}
  1067 	if (!IsTileOwner(tile, old_player)) return;
  1099 
  1068 
  1100 	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
  1069 	if (new_player != PLAYER_SPECTATOR) {
  1101 		if (!HASBIT(GetRoadTypes(tile), rt)) continue;
  1070 		SetTileOwner(tile, new_player);
  1102 
  1071 	} else {
  1103 		if (GetRoadOwner(tile, rt) == old_player) {
  1072 		switch (GetRoadTileType(tile)) {
  1104 			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
  1073 			case ROAD_TILE_NORMAL:
  1105 
  1074 				SetTileOwner(tile, OWNER_NONE);
  1106 			if (rt == ROADTYPE_TRAM) {
  1075 				break;
  1107 				DoCommand(tile, ROADTYPE_TRAM << 4 | GetRoadBits(tile, ROADTYPE_ROAD), 0, DC_EXEC, CMD_REMOVE_ROAD);
  1076 
  1108 			}
  1077 			case ROAD_TILE_CROSSING:
  1109 		}
  1078 				MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile));
  1110 	}
  1079 				break;
  1111 
  1080 
  1112 	if (IsLevelCrossing(tile)) {
  1081 			default:
  1113 		MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY));
  1082 			case ROAD_TILE_DEPOT:
       
  1083 				DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
       
  1084 				break;
       
  1085 		}
       
  1086 	}
  1114 	}
  1087 }
  1115 }
  1088 
  1116 
  1089 
  1117 
  1090 extern const TileTypeProcs _tile_type_road_procs = {
  1118 extern const TileTypeProcs _tile_type_road_procs = {