src/road_cmd.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9910 0b2aebc8283e
child 9912 1ac8aac92385
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
    24 #include "town.h"
    24 #include "town.h"
    25 #include "gfx.h"
    25 #include "gfx.h"
    26 #include "sound.h"
    26 #include "sound.h"
    27 #include "yapf/yapf.h"
    27 #include "yapf/yapf.h"
    28 #include "depot.h"
    28 #include "depot.h"
       
    29 #include "newgrf.h"
    29 
    30 
    30 
    31 
    31 static uint CountRoadBits(RoadBits r)
    32 static uint CountRoadBits(RoadBits r)
    32 {
    33 {
    33 	uint count = 0;
    34 	uint count = 0;
    38 	if (r & ROAD_NE) ++count;
    39 	if (r & ROAD_NE) ++count;
    39 	return count;
    40 	return count;
    40 }
    41 }
    41 
    42 
    42 
    43 
    43 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)
    44 {
    45 {
    45 	RoadBits present;
    46 	RoadBits present;
    46 	RoadBits n;
    47 	RoadBits n;
    47 	*edge_road = true;
    48 	*edge_road = true;
    48 
    49 
    49 	if (_game_mode == GM_EDITOR) return true;
    50 	if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true;
    50 
    51 
    51 	/* Only do the special processing for actual players. */
    52 	/* Only do the special processing for actual players. */
    52 	if (!IsValidPlayer(_current_player)) return true;
    53 	if (!IsValidPlayer(_current_player)) return true;
    53 
    54 
    54 	/* Only do the special processing if the road is owned
    55 	/* Only do the special processing if the road is owned
    57 
    58 
    58 	if (_cheats.magic_bulldozer.value) return true;
    59 	if (_cheats.magic_bulldozer.value) return true;
    59 
    60 
    60 	/* Get a bitmask of which neighbouring roads has a tile */
    61 	/* Get a bitmask of which neighbouring roads has a tile */
    61 	n = ROAD_NONE;
    62 	n = ROAD_NONE;
    62 	present = GetAnyRoadBits(tile);
    63 	present = GetAnyRoadBits(tile, rt);
    63 	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;
    64 	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;
    65 	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;
    66 	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;
    67 
    68 
    68 	/* 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,
    69 	 * then allow it */
    70 	 * then allow it */
    70 	if ((n & (n - 1)) != 0 && (n & remove) != 0) {
    71 	if ((n & (n - 1)) != 0 && (n & remove) != 0) {
    71 		Town *t;
    72 		Town *t;
    81 	}
    82 	}
    82 
    83 
    83 	return true;
    84 	return true;
    84 }
    85 }
    85 
    86 
    86 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road)
    87 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
    87 {
    88 {
    88 	return CheckAllowRemoveRoad(tile, remove, IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile), edge_road);
    89 	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
    89 }
    90 }
    90 
    91 
    91 /** Delete a piece of road.
    92 /** Delete a piece of road.
    92  * @param tile tile where to remove road from
    93  * @param tile tile where to remove road from
    93  * @param flags operation to perform
    94  * @param flags operation to perform
    94  * @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
    95  * @param p2 unused
    97  * @param p2 unused
    96  */
    98  */
    97 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    99 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    98 {
   100 {
    99 	/* cost for removing inner/edge -roads */
   101 	/* cost for removing inner/edge -roads */
   100 	static const uint16 road_remove_cost[2] = {50, 18};
   102 	static const uint16 road_remove_cost[2] = {50, 18};
   101 
   103 
   102 	Owner owner;
       
   103 	Town *t;
   104 	Town *t;
   104 	/* true if the roadpiece was always removeable,
   105 	/* true if the roadpiece was always removeable,
   105 	 * false if it was a center piece. Affects town ratings drop */
   106 	 * false if it was a center piece. Affects town ratings drop */
   106 	bool edge_road;
   107 	bool edge_road;
   107 
   108 
   108 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   109 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   109 
   110 
   110 	if (!IsTileType(tile, MP_STREET)) return CMD_ERROR;
   111 	RoadType rt = (RoadType)GB(p1, 4, 2);
   111 
   112 	if (!IsTileType(tile, MP_STREET) || !IsValidRoadType(rt)) return CMD_ERROR;
   112 	owner = IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile);
   113 
       
   114 	Owner owner = GetRoadOwner(tile, rt);
   113 
   115 
   114 	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
   116 	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
   115 		t = GetTownByTile(tile);
   117 		t = GetTownByTile(tile);
   116 	} else {
   118 	} else {
   117 		t = NULL;
   119 		t = NULL;
   118 	}
   120 	}
   119 
   121 
   120 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   122 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   121 
   123 	RoadTypes rts = GetRoadTypes(tile);
   122 	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;
   123 
   128 
   124 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   129 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   125 
   130 
   126 	/* 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
   127 	 * removal allowance depends on difficulty setting */
   132 	 * removal allowance depends on difficulty setting */
   128 	if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
   133 	if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
   129 
   134 
   130 	switch (GetRoadTileType(tile)) {
   135 	switch (GetRoadTileType(tile)) {
   131 		case ROAD_TILE_NORMAL: {
   136 		case ROAD_TILE_NORMAL: {
   132 			RoadBits present = GetRoadBits(tile);
   137 			RoadBits present = GetRoadBits(tile, rt);
   133 			RoadBits c = pieces;
   138 			RoadBits c = pieces;
   134 
   139 
   135 			if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   140 			if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   136 
   141 
   137 			if (GetTileSlope(tile, NULL) != SLOPE_FLAT  &&
   142 			if (GetTileSlope(tile, NULL) != SLOPE_FLAT  &&
   140 				c |= (RoadBits)((c & 0x3) << 2);
   145 				c |= (RoadBits)((c & 0x3) << 2);
   141 			}
   146 			}
   142 
   147 
   143 			/* limit the bits to delete to the existing bits. */
   148 			/* limit the bits to delete to the existing bits. */
   144 			c &= present;
   149 			c &= present;
   145 			if (c == 0) return CMD_ERROR;
   150 			if (c == ROAD_NONE) return CMD_ERROR;
   146 
   151 
   147 			present ^= c;
   152 			present ^= c;
   148 			if (flags & DC_EXEC) {
   153 			if (flags & DC_EXEC) {
   149 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   154 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   150 
   155 
   151 				if (present == 0) {
   156 				if (present == ROAD_NONE) {
   152 					DoClearSquare(tile);
   157 					RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
       
   158 					if (rts == ROADTYPES_NONE) {
       
   159 						DoClearSquare(tile);
       
   160 					} else {
       
   161 						SetRoadBits(tile, ROAD_NONE, rt);
       
   162 						SetRoadTypes(tile, rts);
       
   163 					}
   153 				} else {
   164 				} else {
   154 					SetRoadBits(tile, present);
   165 					SetRoadBits(tile, present, rt);
   155 					MarkTileDirtyByTile(tile);
   166 					MarkTileDirtyByTile(tile);
   156 				}
   167 				}
   157 			}
   168 			}
   158 			return CountRoadBits(c) * _eco->GetPrice(CEconomy::REMOVE_ROAD, tile, (present == 0));
   169 			return CountRoadBits(c) * _eco->GetPrice(CEconomy::REMOVE_ROAD, tile, (present == 0));
   159 		}
   170 		}
   162 			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
   173 			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
   163 				return CMD_ERROR;
   174 				return CMD_ERROR;
   164 			}
   175 			}
   165 
   176 
   166 			if (flags & DC_EXEC) {
   177 			if (flags & DC_EXEC) {
   167 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   178 				if (rt == ROADTYPE_ROAD) {
   168 
   179 					ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   169 				MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
   180 				}
       
   181 
       
   182 				RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
       
   183 				if (rts == ROADTYPES_NONE) {
       
   184 					MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
       
   185 				} else {
       
   186 					SetRoadTypes(tile, rts);
       
   187 				}
   170 				MarkTileDirtyByTile(tile);
   188 				MarkTileDirtyByTile(tile);
   171 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   189 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   172 			}
   190 			}
   173 			return _eco->GetPrice(CEconomy::REMOVE_ROAD) * 2;
   191 			return _eco->GetPrice(CEconomy::REMOVE_ROAD) * 2;
   174 		}
   192 		}
   252 
   270 
   253 /** Build a piece of road.
   271 /** Build a piece of road.
   254  * @param tile tile where to build road
   272  * @param tile tile where to build road
   255  * @param flags operation to perform
   273  * @param flags operation to perform
   256  * @param p1 bit 0..3 road pieces to build (RoadBits)
   274  * @param p1 bit 0..3 road pieces to build (RoadBits)
       
   275  *           bit 4..5 road type
   257  * @param p2 the town that is building the road (0 if not applicable)
   276  * @param p2 the town that is building the road (0 if not applicable)
   258  */
   277  */
   259 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   278 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   260 {
   279 {
   261 	int32 cost = 0;
   280 	int32 cost = 0;
   268 	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
   287 	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
   269 	 * if a non-player is building the road */
   288 	 * if a non-player is building the road */
   270 	if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR;
   289 	if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR;
   271 
   290 
   272 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   291 	RoadBits pieces = Extract<RoadBits, 0>(p1);
       
   292 
       
   293 	RoadType rt = (RoadType)GB(p1, 4, 2);
       
   294 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   273 
   295 
   274 	tileh = GetTileSlope(tile, NULL);
   296 	tileh = GetTileSlope(tile, NULL);
   275 
   297 
   276 	switch (GetTileType(tile)) {
   298 	switch (GetTileType(tile)) {
   277 		case MP_STREET:
   299 		case MP_STREET:
   278 			switch (GetRoadTileType(tile)) {
   300 			switch (GetRoadTileType(tile)) {
   279 				case ROAD_TILE_NORMAL:
   301 				case ROAD_TILE_NORMAL:
   280 					if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   302 					if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
   281 
   303 					if (!HASBIT(GetRoadTypes(tile), rt)) break;
   282 					existing = GetRoadBits(tile);
   304 
       
   305 					existing = GetRoadBits(tile, rt);
   283 					if ((existing & pieces) == pieces) {
   306 					if ((existing & pieces) == pieces) {
   284 						return_cmd_error(STR_1007_ALREADY_BUILT);
   307 						return_cmd_error(STR_1007_ALREADY_BUILT);
   285 					}
   308 					}
   286 					if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   309 					if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   287 					break;
   310 					break;
   288 
   311 
   289 				case ROAD_TILE_CROSSING:
   312 				case ROAD_TILE_CROSSING:
   290 					if (pieces != GetCrossingRoadBits(tile)) { // XXX is this correct?
   313 					if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   291 						return_cmd_error(STR_1007_ALREADY_BUILT);
   314 					if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) goto do_clear;
   292 					}
   315 					break;
   293 					goto do_clear;
       
   294 
   316 
   295 				default:
   317 				default:
   296 				case ROAD_TILE_DEPOT:
   318 				case ROAD_TILE_DEPOT:
   297 					goto do_clear;
   319 					goto do_clear;
   298 			}
   320 			}
   329 
   351 
   330 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   352 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   331 
   353 
   332 			if (flags & DC_EXEC) {
   354 			if (flags & DC_EXEC) {
   333 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   355 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   334 				MakeRoadCrossing(tile, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), p2);
   356 				MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt), p2);
   335 				MarkTileDirtyByTile(tile);
   357 				MarkTileDirtyByTile(tile);
   336 			}
   358 			}
   337 			/** @todo should be more expensive */
   359 			/** @todo should be more expensive */
   338 			return _eco->GetPrice(CEconomy::BUILD_ROAD) * 2;
   360 			return _eco->GetPrice(CEconomy::BUILD_ROAD) * 2;
   339 		}
   361 		}
   363 	}
   385 	}
   364 
   386 
   365 
   387 
   366 	if (flags & DC_EXEC) {
   388 	if (flags & DC_EXEC) {
   367 		if (IsTileType(tile, MP_STREET)) {
   389 		if (IsTileType(tile, MP_STREET)) {
   368 			SetRoadBits(tile, existing | pieces);
   390 			if (existing == ROAD_NONE) {
       
   391 				SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
       
   392 				SetRoadOwner(tile, rt, _current_player);
       
   393 			}
       
   394 			SetRoadBits(tile, existing | pieces, rt);
   369 		} else {
   395 		} else {
   370 			MakeRoadNormal(tile, _current_player, pieces, p2);
   396 			MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_player, _current_player, _current_player);
   371 		}
   397 		}
   372 
   398 
   373 		MarkTileDirtyByTile(tile);
   399 		MarkTileDirtyByTile(tile);
   374 	}
   400 	}
   375 	return cost;
   401 	return cost;
   412  * @param p1 start tile of drag
   438  * @param p1 start tile of drag
   413  * @param p2 various bitstuffed elements
   439  * @param p2 various bitstuffed elements
   414  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   440  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   415  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   441  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   416  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   442  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
       
   443  * - p2 = (bit 3 + 4) - road type
   417  */
   444  */
   418 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   445 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   419 {
   446 {
   420 	TileIndex start_tile, tile;
   447 	TileIndex start_tile, tile;
   421 	int32 cost, ret;
   448 	int32 cost, ret;
   423 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   450 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   424 
   451 
   425 	if (p1 >= MapSize()) return CMD_ERROR;
   452 	if (p1 >= MapSize()) return CMD_ERROR;
   426 
   453 
   427 	start_tile = p1;
   454 	start_tile = p1;
       
   455 	RoadType rt = (RoadType)GB(p2, 3, 2);
       
   456 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   428 
   457 
   429 	/* Only drag in X or Y direction dictated by the direction variable */
   458 	/* Only drag in X or Y direction dictated by the direction variable */
   430 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   459 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   431 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   460 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   432 
   461 
   445 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   474 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   446 
   475 
   447 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   476 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   448 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   477 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   449 
   478 
   450 		ret = DoCommand(tile, bits, 0, flags, CMD_BUILD_ROAD);
   479 		ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
   451 		if (CmdFailed(ret)) {
   480 		if (CmdFailed(ret)) {
   452 			if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
   481 			if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
   453 			_error_message = INVALID_STRING_ID;
   482 			_error_message = INVALID_STRING_ID;
   454 		} else {
   483 		} else {
   455 			cost += ret;
   484 			cost += ret;
   469  * @param p1 start tile of drag
   498  * @param p1 start tile of drag
   470  * @param p2 various bitstuffed elements
   499  * @param p2 various bitstuffed elements
   471  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   500  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   472  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   501  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   473  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   502  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
       
   503  * - p2 = (bit 3 + 4) - road type
   474  */
   504  */
   475 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   505 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   476 {
   506 {
   477 	TileIndex start_tile, tile;
   507 	TileIndex start_tile, tile;
   478 	int32 cost, ret;
   508 	int32 cost, ret;
   480 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   510 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   481 
   511 
   482 	if (p1 >= MapSize()) return CMD_ERROR;
   512 	if (p1 >= MapSize()) return CMD_ERROR;
   483 
   513 
   484 	start_tile = p1;
   514 	start_tile = p1;
       
   515 	RoadType rt = (RoadType)GB(p2, 3, 2);
       
   516 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   485 
   517 
   486 	/* Only drag in X or Y direction dictated by the direction variable */
   518 	/* Only drag in X or Y direction dictated by the direction variable */
   487 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   519 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
   488 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   520 	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
   489 
   521 
   504 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   536 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   505 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   537 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   506 
   538 
   507 		/* try to remove the halves. */
   539 		/* try to remove the halves. */
   508 		if (bits != 0) {
   540 		if (bits != 0) {
   509 			ret = DoCommand(tile, bits, 0, flags, CMD_REMOVE_ROAD);
   541 			ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
   510 			if (!CmdFailed(ret)) cost += ret;
   542 			if (!CmdFailed(ret)) cost += ret;
   511 		}
   543 		}
   512 
   544 
   513 		if (tile == end_tile) break;
   545 		if (tile == end_tile) break;
   514 
   546 
   520 
   552 
   521 /** Build a road depot.
   553 /** Build a road depot.
   522  * @param tile tile where to build the depot
   554  * @param tile tile where to build the depot
   523  * @param flags operation to perform
   555  * @param flags operation to perform
   524  * @param p1 bit 0..1 entrance direction (DiagDirection)
   556  * @param p1 bit 0..1 entrance direction (DiagDirection)
       
   557  *           bit 2..3 road type
   525  * @param p2 unused
   558  * @param p2 unused
   526  *
   559  *
   527  * @todo When checking for the tile slope,
   560  * @todo When checking for the tile slope,
   528  * distingush between "Flat land required" and "land sloped in wrong direction"
   561  * distingush between "Flat land required" and "land sloped in wrong direction"
   529  */
   562  */
   534 	Slope tileh;
   567 	Slope tileh;
   535 
   568 
   536 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   569 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   537 
   570 
   538 	DiagDirection dir = Extract<DiagDirection, 0>(p1);
   571 	DiagDirection dir = Extract<DiagDirection, 0>(p1);
       
   572 	RoadType rt = (RoadType)GB(p1, 2, 2);
       
   573 
       
   574 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   539 
   575 
   540 	tileh = GetTileSlope(tile, NULL);
   576 	tileh = GetTileSlope(tile, NULL);
   541 	if (tileh != SLOPE_FLAT && (
   577 	if (tileh != SLOPE_FLAT && (
   542 				!_patches.build_on_slopes ||
   578 				!_patches.build_on_slopes ||
   543 				IsSteepSlope(tileh) ||
   579 				IsSteepSlope(tileh) ||
   558 
   594 
   559 	if (flags & DC_EXEC) {
   595 	if (flags & DC_EXEC) {
   560 		dep->xy = tile;
   596 		dep->xy = tile;
   561 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   597 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   562 
   598 
   563 		MakeRoadDepot(tile, _current_player, dir);
   599 		MakeRoadDepot(tile, _current_player, dir, rt);
   564 		MarkTileDirtyByTile(tile);
   600 		MarkTileDirtyByTile(tile);
   565 	}
   601 	}
   566 	return cost;
   602 	return cost;
   567 }
   603 }
   568 
   604 
   580 
   616 
   581 static int32 ClearTile_Road(TileIndex tile, byte flags)
   617 static int32 ClearTile_Road(TileIndex tile, byte flags)
   582 {
   618 {
   583 	switch (GetRoadTileType(tile)) {
   619 	switch (GetRoadTileType(tile)) {
   584 		case ROAD_TILE_NORMAL: {
   620 		case ROAD_TILE_NORMAL: {
   585 			RoadBits b = GetRoadBits(tile);
   621 			RoadBits b = GetAllRoadBits(tile);
   586 
   622 
   587 #define M(x) (1 << (x))
   623 #define M(x) (1 << (x))
   588 			/* Clear the road if only one piece is on the tile OR the AI tries
   624 			/* Clear the road if only one piece is on the tile OR the AI tries
   589 			 * to clear town road OR we are not using the DC_AUTO flag */
   625 			 * to clear town road OR we are not using the DC_AUTO flag */
   590 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) ||
   626 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) ||
   666 	3,  0,  0,  0,
   702 	3,  0,  0,  0,
   667 	0,  0
   703 	0,  0
   668 };
   704 };
   669 
   705 
   670 /**
   706 /**
       
   707  * Whether to draw unpaved roads regardless of the town zone.
       
   708  * By default, OpenTTD always draws roads as unpaved if they are on a desert
       
   709  * tile or above the snowline. Newgrf files, however, can set a bit that allows
       
   710  * paved roads to be built on desert tiles as they would be on grassy tiles.
       
   711  *
       
   712  * @param tile The tile the road is on
       
   713  * @param roadside What sort of road this is
       
   714  * @return True if the road should be drawn unpaved regardless of the roadside.
       
   715  */
       
   716 static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside)
       
   717 {
       
   718 	return (IsOnSnow(tile) &&
       
   719 			!(_opt.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) &&
       
   720 				roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS));
       
   721 }
       
   722 
       
   723 /**
   671  * Draw ground sprite and road pieces
   724  * Draw ground sprite and road pieces
   672  * @param ti TileInfo
   725  * @param ti TileInfo
   673  */
   726  */
   674 static void DrawRoadBits(TileInfo* ti)
   727 static void DrawRoadBits(TileInfo* ti)
   675 {
   728 {
   676 	RoadBits road = GetRoadBits(ti->tile);
   729 	RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
   677 	const DrawRoadTileStruct *drts;
   730 	const DrawRoadTileStruct *drts;
   678 	SpriteID image = 0;
   731 	SpriteID image = 0;
   679 	SpriteID pal = PAL_NONE;
   732 	SpriteID pal = PAL_NONE;
   680 	Roadside roadside;
   733 	Roadside roadside;
   681 
   734 
   691 
   744 
   692 	if (image == 0) image = _road_tile_sprites_1[road];
   745 	if (image == 0) image = _road_tile_sprites_1[road];
   693 
   746 
   694 	roadside = GetRoadside(ti->tile);
   747 	roadside = GetRoadside(ti->tile);
   695 
   748 
   696 	if (IsOnSnow(ti->tile)) {
   749 	if (AlwaysDrawUnpavedRoads(ti->tile, roadside)) {
   697 		image += 19;
   750 		image += 19;
   698 	} else {
   751 	} else {
   699 		switch (roadside) {
   752 		switch (roadside) {
   700 			case ROADSIDE_BARREN:           pal = PALETTE_TO_BARE_LAND; break;
   753 			case ROADSIDE_BARREN:           pal = PALETTE_TO_BARE_LAND; break;
   701 			case ROADSIDE_GRASS:            break;
   754 			case ROADSIDE_GRASS:            break;
   711 		DrawGroundSprite(road & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
   764 		DrawGroundSprite(road & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
   712 		return;
   765 		return;
   713 	}
   766 	}
   714 
   767 
   715 	/* Return if full detail is disabled, or we are zoomed fully out. */
   768 	/* Return if full detail is disabled, or we are zoomed fully out. */
   716 	if (!(_display_opt & DO_FULL_DETAIL) || _cur_dpi->zoom == 2) return;
   769 	if (!HASBIT(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
   717 
   770 
   718 	/* Draw extra details. */
   771 	/* Draw extra details. */
   719 	for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) {
   772 	for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) {
   720 		int x = ti->x | drts->subcoord_x;
   773 		int x = ti->x | drts->subcoord_x;
   721 		int y = ti->y | drts->subcoord_y;
   774 		int y = ti->y | drts->subcoord_y;
   733 			break;
   786 			break;
   734 
   787 
   735 		case ROAD_TILE_CROSSING: {
   788 		case ROAD_TILE_CROSSING: {
   736 			SpriteID image;
   789 			SpriteID image;
   737 			SpriteID pal = PAL_NONE;
   790 			SpriteID pal = PAL_NONE;
       
   791 			Roadside roadside = GetRoadside(ti->tile);
   738 
   792 
   739 			if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
   793 			if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
   740 
   794 
   741 			image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.crossing;
   795 			image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.crossing;
   742 
   796 
   743 			if (GetCrossingRoadAxis(ti->tile) == AXIS_X) image++;
   797 			if (GetCrossingRoadAxis(ti->tile) == AXIS_X) image++;
   744 			if (IsCrossingBarred(ti->tile)) image += 2;
   798 			if (IsCrossingBarred(ti->tile)) image += 2;
   745 
   799 
   746 			if (IsOnSnow(ti->tile)) {
   800 			if (AlwaysDrawUnpavedRoads(ti->tile, roadside)) {
   747 				image += 8;
   801 				image += 8;
   748 			} else {
   802 			} else {
   749 				switch (GetRoadside(ti->tile)) {
   803 				switch (roadside) {
   750 					case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
   804 					case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
   751 					case ROADSIDE_GRASS:  break;
   805 					case ROADSIDE_GRASS:  break;
   752 					default:              image += 4; break; // Paved
   806 					default:              image += 4; break; // Paved
   753 				}
   807 				}
   754 			}
   808 			}
   795 		}
   849 		}
   796 	}
   850 	}
   797 	DrawBridgeMiddle(ti);
   851 	DrawBridgeMiddle(ti);
   798 }
   852 }
   799 
   853 
   800 void DrawRoadDepotSprite(int x, int y, DiagDirection dir)
   854 void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
   801 {
   855 {
   802 	SpriteID palette = PLAYER_SPRITE_COLOR(_local_player);
   856 	SpriteID palette = PLAYER_SPRITE_COLOR(_local_player);
   803 	const DrawTileSprites* dts =  &_road_depot[dir];
   857 	const DrawTileSprites* dts =  &_road_depot[dir];
   804 	const DrawTileSeqStruct* dtss;
   858 	const DrawTileSeqStruct* dtss;
   805 
   859 
   821 	uint z;
   875 	uint z;
   822 	Slope tileh = GetTileSlope(tile, &z);
   876 	Slope tileh = GetTileSlope(tile, &z);
   823 
   877 
   824 	if (tileh == SLOPE_FLAT) return z;
   878 	if (tileh == SLOPE_FLAT) return z;
   825 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   879 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   826 		uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
   880 		uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
   827 
   881 
   828 		if (f != 0) {
   882 		if (f != 0) {
   829 			if (IsSteepSlope(tileh)) {
   883 			if (IsSteepSlope(tileh)) {
   830 				z += TILE_HEIGHT;
   884 				z += TILE_HEIGHT;
   831 			} else if (f < 15) {
   885 			} else if (f < 15) {
   841 
   895 
   842 static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh)
   896 static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh)
   843 {
   897 {
   844 	if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
   898 	if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
   845 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   899 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
   846 		uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
   900 		uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
   847 
   901 
   848 		if (f == 0) return tileh;
   902 		if (f == 0) return tileh;
   849 		if (f < 15) return SLOPE_FLAT; // leveled foundation
   903 		if (f < 15) return SLOPE_FLAT; // leveled foundation
   850 		return _inclined_tileh[f - 15]; // inclined foundation
   904 		return _inclined_tileh[f - 15]; // inclined foundation
   851 	} else {
   905 	} else {
   909 			grp = t->GetRadiusGroup(tile);
   963 			grp = t->GetRadiusGroup(tile);
   910 
   964 
   911 			/* Show an animation to indicate road work */
   965 			/* Show an animation to indicate road work */
   912 			if (t->road_build_months != 0 &&
   966 			if (t->road_build_months != 0 &&
   913 					(DistanceManhattan(t->xy, tile) < 8 || grp != 0) &&
   967 					(DistanceManhattan(t->xy, tile) < 8 || grp != 0) &&
   914 					GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetRoadBits(tile) == ROAD_X || GetRoadBits(tile) == ROAD_Y)) {
   968 					GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) {
   915 				if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
   969 				if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
   916 					StartRoadWorks(tile);
   970 					StartRoadWorks(tile);
   917 
   971 
   918 					SndPlayTileFx(SND_21_JACKHAMMER, tile);
   972 					SndPlayTileFx(SND_21_JACKHAMMER, tile);
   919 					CreateEffectVehicleAbove(
   973 					CreateEffectVehicleAbove(
   963 	0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F,
  1017 	0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F,
   964 };
  1018 };
   965 
  1019 
   966 static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode)
  1020 static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode)
   967 {
  1021 {
       
  1022 	RoadType rt = ROADTYPE_ROAD;
       
  1023 
   968 	switch (mode) {
  1024 	switch (mode) {
   969 		case TRANSPORT_RAIL:
  1025 		case TRANSPORT_RAIL:
   970 			if (!IsLevelCrossing(tile)) return 0;
  1026 			if (!IsLevelCrossing(tile)) return 0;
   971 			return GetCrossingRailBits(tile) * 0x101;
  1027 			return GetCrossingRailBits(tile) * 0x101;
   972 
  1028 
   973 		case TRANSPORT_ROAD:
  1029 		case TRANSPORT_ROAD:
       
  1030 			if (!HASBIT(GetRoadTypes(tile), rt)) return 0;
   974 			switch (GetRoadTileType(tile)) {
  1031 			switch (GetRoadTileType(tile)) {
   975 				case ROAD_TILE_NORMAL:
  1032 				case ROAD_TILE_NORMAL:
   976 					return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile)] * 0x101;
  1033 					return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile, rt)] * 0x101;
   977 
  1034 
   978 				case ROAD_TILE_CROSSING: {
  1035 				case ROAD_TILE_CROSSING: {
   979 					uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101;
  1036 					uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101;
   980 
  1037 
   981 					if (IsCrossingBarred(tile)) r *= 0x10001;
  1038 					if (IsCrossingBarred(tile)) r *= 0x10001;
  1045 }
  1102 }
  1046 
  1103 
  1047 
  1104 
  1048 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1105 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1049 {
  1106 {
  1050 	if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) == old_player) {
  1107 	if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) {
  1051 		SetCrossingRoadOwner(tile, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
  1108 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
  1052 	}
  1109 		return;
  1053 
  1110 	}
  1054 	if (!IsTileOwner(tile, old_player)) return;
  1111 
  1055 
  1112 	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
  1056 	if (new_player != PLAYER_SPECTATOR) {
  1113 		if (!HASBIT(GetRoadTypes(tile), rt)) continue;
  1057 		SetTileOwner(tile, new_player);
  1114 
  1058 	} else {
  1115 		if (GetRoadOwner(tile, rt) == old_player) {
  1059 		switch (GetRoadTileType(tile)) {
  1116 			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
  1060 			case ROAD_TILE_NORMAL:
  1117 
  1061 				SetTileOwner(tile, OWNER_NONE);
  1118 			if (rt == ROADTYPE_TRAM) {
  1062 				break;
  1119 				DoCommand(tile, ROADTYPE_TRAM << 4 | GetRoadBits(tile, ROADTYPE_ROAD), 0, DC_EXEC, CMD_REMOVE_ROAD);
  1063 
  1120 			}
  1064 			case ROAD_TILE_CROSSING:
  1121 		}
  1065 				MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile));
  1122 	}
  1066 				break;
  1123 
  1067 
  1124 	if (IsLevelCrossing(tile)) {
  1068 			default:
  1125 		MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY));
  1069 			case ROAD_TILE_DEPOT:
       
  1070 				DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
       
  1071 				break;
       
  1072 		}
       
  1073 	}
  1126 	}
  1074 }
  1127 }
  1075 
  1128 
  1076 
  1129 
  1077 extern const TileTypeProcs _tile_type_road_procs = {
  1130 extern const TileTypeProcs _tile_type_road_procs = {