src/road_cmd.cpp
branchNewGRF_ports
changeset 6720 35756db7e577
parent 6719 4cc327ad39d5
child 6725 23339968083f
equal deleted inserted replaced
6719:4cc327ad39d5 6720:35756db7e577
    11 #include "road_map.h"
    11 #include "road_map.h"
    12 #include "sprite.h"
    12 #include "sprite.h"
    13 #include "table/sprites.h"
    13 #include "table/sprites.h"
    14 #include "table/strings.h"
    14 #include "table/strings.h"
    15 #include "functions.h"
    15 #include "functions.h"
       
    16 #include "window.h"
    16 #include "map.h"
    17 #include "map.h"
    17 #include "landscape.h"
    18 #include "landscape.h"
    18 #include "tile.h"
    19 #include "tile.h"
    19 #include "town_map.h"
    20 #include "town_map.h"
    20 #include "vehicle.h"
    21 #include "vehicle.h"
    97 /** Delete a piece of road.
    98 /** Delete a piece of road.
    98  * @param tile tile where to remove road from
    99  * @param tile tile where to remove road from
    99  * @param flags operation to perform
   100  * @param flags operation to perform
   100  * @param p1 bit 0..3 road pieces to remove (RoadBits)
   101  * @param p1 bit 0..3 road pieces to remove (RoadBits)
   101  *           bit 4..5 road type
   102  *           bit 4..5 road type
       
   103  *           bit    6 ignore the fact that the tram track has not been removed
       
   104  *                    yet when removing the road bits when not actually doing
       
   105  *                    it. Makes it possible to test whether the road bits can
       
   106  *                    be removed from a level crossing without physically
       
   107  *                    removing the tram bits before the test.
   102  * @param p2 unused
   108  * @param p2 unused
   103  */
   109  */
   104 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   110 CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   105 {
   111 {
   106 	/* cost for removing inner/edge -roads */
   112 	/* cost for removing inner/edge -roads */
   107 	static const uint16 road_remove_cost[2] = {50, 18};
   113 	static const uint16 road_remove_cost[2] = {50, 18};
   108 
   114 
   109 	Town *t;
       
   110 	/* true if the roadpiece was always removeable,
   115 	/* true if the roadpiece was always removeable,
   111 	 * false if it was a center piece. Affects town ratings drop */
   116 	 * false if it was a center piece. Affects town ratings drop */
   112 	bool edge_road;
   117 	bool edge_road;
   113 
   118 
   114 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   119 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   115 
   120 
   116 	RoadType rt = (RoadType)GB(p1, 4, 2);
   121 	RoadType rt = (RoadType)GB(p1, 4, 2);
   117 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   122 	if (!IsValidRoadType(rt)) return CMD_ERROR;
   118 
   123 
   119 	Owner owner;
   124 	Town *t = NULL;
   120 	switch (GetTileType(tile)) {
   125 	switch (GetTileType(tile)) {
   121 		case MP_STREET:
   126 		case MP_STREET:
   122 			owner = GetRoadOwner(tile, rt);
   127 			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
   123 			break;
   128 			break;
   124 
   129 
   125 		case MP_STATION:
   130 		case MP_STATION:
   126 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   131 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   127 			owner = GetTileOwner(tile);
       
   128 			break;
   132 			break;
   129 
   133 
   130 		case MP_TUNNELBRIDGE:
   134 		case MP_TUNNELBRIDGE:
   131 			if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) ||
   135 			if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) ||
   132 					(IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR;
   136 					(IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR;
   133 			owner = GetTileOwner(tile);
       
   134 			break;
   137 			break;
   135 
   138 
   136 		default:
   139 		default:
   137 			return CMD_ERROR;
   140 			return CMD_ERROR;
   138 	}
       
   139 
       
   140 	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
       
   141 		t = GetTownByTile(tile);
       
   142 	} else {
       
   143 		t = NULL;
       
   144 	}
   141 	}
   145 
   142 
   146 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   143 	RoadBits pieces = Extract<RoadBits, 0>(p1);
   147 	RoadTypes rts = GetRoadTypes(tile);
   144 	RoadTypes rts = GetRoadTypes(tile);
   148 	/* The tile doesn't have the given road type */
   145 	/* The tile doesn't have the given road type */
   158 
   155 
   159 	if (!IsTileType(tile, MP_STREET)) {
   156 	if (!IsTileType(tile, MP_STREET)) {
   160 		/* If it's the last roadtype, just clear the whole tile */
   157 		/* If it's the last roadtype, just clear the whole tile */
   161 		if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   158 		if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   162 
   159 
   163 		int32 cost;
   160 		CommandCost cost;
   164 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   161 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   165 			TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
   162 			TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
   166 			/* Pay for *every* tile of the bridge or tunnel */
   163 			/* Pay for *every* tile of the bridge or tunnel */
   167 			cost = (DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road;
   164 			cost.AddCost((DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road);
   168 			if (flags & DC_EXEC) {
   165 			if (flags & DC_EXEC) {
   169 				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
   166 				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
   170 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
   167 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
   171 
   168 
   172 				/* Mark tiles diry that have been repaved */
   169 				/* Mark tiles diry that have been repaved */
   177 
   174 
   178 					for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t);
   175 					for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t);
   179 				}
   176 				}
   180 			}
   177 			}
   181 		} else {
   178 		} else {
   182 			cost = _price.remove_road;
   179 			cost.AddCost(_price.remove_road);
   183 			if (flags & DC_EXEC) {
   180 			if (flags & DC_EXEC) {
   184 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
   181 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
   185 				MarkTileDirtyByTile(tile);
   182 				MarkTileDirtyByTile(tile);
   186 			}
   183 			}
   187 		}
   184 		}
   188 		return cost;
   185 		return CommandCost(cost);
   189 	}
   186 	}
   190 
   187 
   191 	switch (GetRoadTileType(tile)) {
   188 	switch (GetRoadTileType(tile)) {
   192 		case ROAD_TILE_NORMAL: {
   189 		case ROAD_TILE_NORMAL: {
   193 			RoadBits present = GetRoadBits(tile, rt);
   190 			RoadBits present = GetRoadBits(tile, rt);
   224 					if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE);
   221 					if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE);
   225 					SetRoadBits(tile, present, rt);
   222 					SetRoadBits(tile, present, rt);
   226 					MarkTileDirtyByTile(tile);
   223 					MarkTileDirtyByTile(tile);
   227 				}
   224 				}
   228 			}
   225 			}
   229 			return CountRoadBits(c) * _price.remove_road;
   226 			return CommandCost(CountRoadBits(c) * _price.remove_road);
   230 		}
   227 		}
   231 
   228 
   232 		case ROAD_TILE_CROSSING: {
   229 		case ROAD_TILE_CROSSING: {
   233 			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
   230 			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
   234 				return CMD_ERROR;
   231 				return CMD_ERROR;
   235 			}
   232 			}
   236 
   233 
   237 			/* Don't allow road to be removed from the crossing when there is tram;
   234 			/* Don't allow road to be removed from the crossing when there is tram;
   238 			 * we can't draw the crossing without trambits ;) */
   235 			 * we can't draw the crossing without trambits ;) */
   239 			if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM)) return CMD_ERROR;
   236 			if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HASBIT(p1, 6))) return CMD_ERROR;
   240 
   237 
   241 			if (flags & DC_EXEC) {
   238 			if (flags & DC_EXEC) {
   242 				if (rt == ROADTYPE_ROAD) {
   239 				if (rt == ROADTYPE_ROAD) {
   243 					ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   240 					ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   244 				}
   241 				}
   250 					SetRoadTypes(tile, rts);
   247 					SetRoadTypes(tile, rts);
   251 				}
   248 				}
   252 				MarkTileDirtyByTile(tile);
   249 				MarkTileDirtyByTile(tile);
   253 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   250 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   254 			}
   251 			}
   255 			return _price.remove_road * 2;
   252 			return CommandCost(_price.remove_road * 2);
   256 		}
   253 		}
   257 
   254 
   258 		default:
   255 		default:
   259 		case ROAD_TILE_DEPOT:
   256 		case ROAD_TILE_DEPOT:
   260 			return CMD_ERROR;
   257 			return CMD_ERROR;
   293 		ROAD_ALL
   290 		ROAD_ALL
   294 	},
   291 	},
   295 };
   292 };
   296 
   293 
   297 
   294 
   298 static uint32 CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing)
   295 static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing)
   299 {
   296 {
   300 	RoadBits road_bits;
   297 	RoadBits road_bits;
   301 
   298 
   302 	if (IsSteepSlope(tileh)) {
   299 	if (IsSteepSlope(tileh)) {
   303 		if (existing == 0) {
   300 		if (existing == 0) {
   312 
   309 
   313 	/* no special foundation */
   310 	/* no special foundation */
   314 	if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) {
   311 	if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) {
   315 		/* force that all bits are set when we have slopes */
   312 		/* force that all bits are set when we have slopes */
   316 		if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh];
   313 		if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh];
   317 		return 0; // no extra cost
   314 		return CommandCost(); // no extra cost
   318 	}
   315 	}
   319 
   316 
   320 	/* foundation is used. Whole tile is leveled up */
   317 	/* foundation is used. Whole tile is leveled up */
   321 	if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) {
   318 	if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) {
   322 		return existing != 0 ? 0 : _price.terraform;
   319 		return CommandCost(existing != 0 ? 0 : _price.terraform);
   323 	}
   320 	}
   324 
   321 
   325 	/* partly leveled up tile, only if there's no road on that tile */
   322 	/* partly leveled up tile, only if there's no road on that tile */
   326 	if (existing == 0 && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) {
   323 	if (existing == 0 && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) {
   327 		/* force full pieces. */
   324 		/* force full pieces. */
   338  * @param p1 bit 0..3 road pieces to build (RoadBits)
   335  * @param p1 bit 0..3 road pieces to build (RoadBits)
   339  *           bit 4..5 road type
   336  *           bit 4..5 road type
   340  *           bit 6..7 disallowed directions to toggle
   337  *           bit 6..7 disallowed directions to toggle
   341  * @param p2 the town that is building the road (0 if not applicable)
   338  * @param p2 the town that is building the road (0 if not applicable)
   342  */
   339  */
   343 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   340 CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   344 {
   341 {
   345 	int32 cost = 0;
   342 	CommandCost cost;
   346 	int32 ret;
   343 	CommandCost ret;
   347 	RoadBits existing = ROAD_NONE;
   344 	RoadBits existing = ROAD_NONE;
   348 	RoadBits all_bits = ROAD_NONE;
   345 	RoadBits all_bits = ROAD_NONE;
   349 	Slope tileh;
   346 	Slope tileh;
   350 
   347 
   351 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   348 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   388 							/* Ignore half built tiles */
   385 							/* Ignore half built tiles */
   389 							if (flags & DC_EXEC && rt != ROADTYPE_TRAM && (existing == ROAD_X || existing == ROAD_Y)) {
   386 							if (flags & DC_EXEC && rt != ROADTYPE_TRAM && (existing == ROAD_X || existing == ROAD_Y)) {
   390 								SetDisallowedRoadDirections(tile, GetDisallowedRoadDirections(tile) ^ toggle_drd);
   387 								SetDisallowedRoadDirections(tile, GetDisallowedRoadDirections(tile) ^ toggle_drd);
   391 								MarkTileDirtyByTile(tile);
   388 								MarkTileDirtyByTile(tile);
   392 							}
   389 							}
   393 							return 0;
   390 							return CommandCost();
   394 						}
   391 						}
   395 						return_cmd_error(STR_1007_ALREADY_BUILT);
   392 						return_cmd_error(STR_1007_ALREADY_BUILT);
   396 					}
   393 					}
   397 				} break;
   394 				} break;
   398 
   395 
   443 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   440 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
   444 				/* Always add road to the roadtypes (can't draw without it) */
   441 				/* Always add road to the roadtypes (can't draw without it) */
   445 				MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2);
   442 				MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2);
   446 				MarkTileDirtyByTile(tile);
   443 				MarkTileDirtyByTile(tile);
   447 			}
   444 			}
   448 			return _price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4);
   445 			return CommandCost(_price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4));
   449 		}
   446 		}
   450 
   447 
   451 		case MP_STATION:
   448 		case MP_STATION:
   452 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   449 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   453 			if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   450 			if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   465 
   462 
   466 		default:
   463 		default:
   467 do_clear:;
   464 do_clear:;
   468 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   465 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   469 			if (CmdFailed(ret)) return ret;
   466 			if (CmdFailed(ret)) return ret;
   470 			cost += ret;
   467 			cost.AddCost(ret);
   471 	}
   468 	}
   472 
   469 
   473 	if (all_bits != pieces) {
   470 	if (all_bits != pieces) {
   474 		/* Check the foundation/slopes when adding road/tram bits */
   471 		/* Check the foundation/slopes when adding road/tram bits */
   475 		ret = CheckRoadSlope(tileh, &pieces, all_bits | existing);
   472 		ret = CheckRoadSlope(tileh, &pieces, all_bits | existing);
   476 		/* Return an error if we need to build a foundation (ret != 0) but the
   473 		/* Return an error if we need to build a foundation (ret != 0) but the
   477 		 * current patch-setting is turned off (or stupid AI@work) */
   474 		 * current patch-setting is turned off (or stupid AI@work) */
   478 		if (CmdFailed(ret) || (ret != 0 && (!_patches.build_on_slopes || _is_old_ai_player))) {
   475 		if (CmdFailed(ret) || (ret.GetCost() != 0 && (!_patches.build_on_slopes || _is_old_ai_player))) {
   479 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   476 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   480 		}
   477 		}
   481 		cost += ret;
   478 		cost.AddCost(ret);
   482 	}
   479 	}
   483 
   480 
   484 	if (IsTileType(tile, MP_STREET)) {
   481 	if (IsTileType(tile, MP_STREET)) {
   485 		/* Don't put the pieces that already exist */
   482 		/* Don't put the pieces that already exist */
   486 		pieces &= ComplementRoadBits(existing);
   483 		pieces &= ComplementRoadBits(existing);
   487 	}
   484 	}
   488 
   485 
   489 	cost += CountRoadBits(pieces) * _price.build_road;
   486 	cost.AddCost(CountRoadBits(pieces) * _price.build_road);
   490 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   487 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   491 		/* Pay for *every* tile of the bridge or tunnel */
   488 		/* Pay for *every* tile of the bridge or tunnel */
   492 		cost *= DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile);
   489 		cost.MultiplyCost(DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile));
   493 	}
   490 	}
   494 
   491 
   495 	if (flags & DC_EXEC) {
   492 	if (flags & DC_EXEC) {
   496 		switch (GetTileType(tile)) {
   493 		switch (GetTileType(tile)) {
   497 			case MP_STREET: {
   494 			case MP_STREET: {
   498 				RoadTileType rtt = GetRoadTileType(tile);
   495 				RoadTileType rtt = GetRoadTileType(tile);
   499 				if (existing == ROAD_NONE || rtt == ROAD_TILE_CROSSING) {
   496 				if (existing == ROAD_NONE || rtt == ROAD_TILE_CROSSING) {
   500 					SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
   497 					SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
   501 					SetRoadOwner(tile, rt, _current_player);
   498 					SetRoadOwner(tile, rt, _current_player);
       
   499 					if (_current_player == OWNER_TOWN && rt == ROADTYPE_ROAD) SetTownIndex(tile, p2);
   502 				}
   500 				}
   503 				if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt);
   501 				if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt);
   504 			} break;
   502 			} break;
   505 
   503 
   506 			case MP_TUNNELBRIDGE: {
   504 			case MP_TUNNELBRIDGE: {
   545  * @param totype      The railtype we want to convert to
   543  * @param totype      The railtype we want to convert to
   546  * @param exec        Switches between test and execute mode
   544  * @param exec        Switches between test and execute mode
   547  * @return            The cost and state of the operation
   545  * @return            The cost and state of the operation
   548  * @retval CMD_ERROR  An error occured during the operation.
   546  * @retval CMD_ERROR  An error occured during the operation.
   549  */
   547  */
   550 int32 DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
   548 CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
   551 {
   549 {
   552 	/* not a railroad crossing? */
   550 	/* not a railroad crossing? */
   553 	if (!IsLevelCrossing(tile)) return CMD_ERROR;
   551 	if (!IsLevelCrossing(tile)) return CMD_ERROR;
   554 
   552 
   555 	/* not owned by me? */
   553 	/* not owned by me? */
   564 		SetRailType(tile, totype);
   562 		SetRailType(tile, totype);
   565 		MarkTileDirtyByTile(tile);
   563 		MarkTileDirtyByTile(tile);
   566 		YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile)));
   564 		YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile)));
   567 	}
   565 	}
   568 
   566 
   569 	return _price.build_rail / 2;
   567 	return CommandCost(_price.build_rail / 2);
   570 }
   568 }
   571 
   569 
   572 
   570 
   573 /** Build a long piece of road.
   571 /** Build a long piece of road.
   574  * @param end_tile end tile of drag
   572  * @param end_tile end tile of drag
   579  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   577  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   580  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   578  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   581  * - p2 = (bit 3 + 4) - road type
   579  * - p2 = (bit 3 + 4) - road type
   582  * - p2 = (bit 5) - set road direction
   580  * - p2 = (bit 5) - set road direction
   583  */
   581  */
   584 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   582 CommandCost CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   585 {
   583 {
   586 	TileIndex start_tile, tile;
   584 	TileIndex start_tile, tile;
   587 	int32 cost, ret;
   585 	CommandCost cost, ret;
   588 	bool had_bridge = false;
   586 	bool had_bridge = false;
   589 	bool had_success = false;
   587 	bool had_success = false;
   590 	DisallowedRoadDirections drd = DRD_NORTHBOUND;
   588 	DisallowedRoadDirections drd = DRD_NORTHBOUND;
   591 
   589 
   592 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   590 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   615 	 * when you just 'click' on one tile to build them. */
   613 	 * when you just 'click' on one tile to build them. */
   616 	if (HASBIT(p2, 2) == (start_tile == end_tile)) drd ^= DRD_BOTH;
   614 	if (HASBIT(p2, 2) == (start_tile == end_tile)) drd ^= DRD_BOTH;
   617 	/* No disallowed direction bits have to be toggled */
   615 	/* No disallowed direction bits have to be toggled */
   618 	if (!HASBIT(p2, 5)) drd = DRD_NONE;
   616 	if (!HASBIT(p2, 5)) drd = DRD_NONE;
   619 
   617 
   620 	cost = 0;
       
   621 	tile = start_tile;
   618 	tile = start_tile;
   622 	/* Start tile is the small number. */
   619 	/* Start tile is the small number. */
   623 	for (;;) {
   620 	for (;;) {
   624 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   621 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   625 
   622 
   633 		} else {
   630 		} else {
   634 			had_success = true;
   631 			had_success = true;
   635 			/* Only pay for the upgrade on one side of the bridge */
   632 			/* Only pay for the upgrade on one side of the bridge */
   636 			if (IsBridgeTile(tile)) {
   633 			if (IsBridgeTile(tile)) {
   637 				if ((!had_bridge || GetBridgeRampDirection(tile) == DIAGDIR_SE || GetBridgeRampDirection(tile) == DIAGDIR_SW)) {
   634 				if ((!had_bridge || GetBridgeRampDirection(tile) == DIAGDIR_SE || GetBridgeRampDirection(tile) == DIAGDIR_SW)) {
   638 					cost += ret;
   635 					cost.AddCost(ret);
   639 				}
   636 				}
   640 				had_bridge = true;
   637 				had_bridge = true;
   641 			} else {
   638 			} else {
   642 				cost += ret;
   639 				cost.AddCost(ret);
   643 			}
   640 			}
   644 		}
   641 		}
   645 
   642 
   646 		if (tile == end_tile) break;
   643 		if (tile == end_tile) break;
   647 
   644 
   659  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   656  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
   660  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   657  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
   661  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   658  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
   662  * - p2 = (bit 3 + 4) - road type
   659  * - p2 = (bit 3 + 4) - road type
   663  */
   660  */
   664 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   661 CommandCost CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   665 {
   662 {
   666 	TileIndex start_tile, tile;
   663 	TileIndex start_tile, tile;
   667 	int32 cost, ret;
   664 	CommandCost cost, ret;
   668 
   665 
   669 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   666 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   670 
   667 
   671 	if (p1 >= MapSize()) return CMD_ERROR;
   668 	if (p1 >= MapSize()) return CMD_ERROR;
   672 
   669 
   684 		start_tile = end_tile;
   681 		start_tile = end_tile;
   685 		end_tile = t;
   682 		end_tile = t;
   686 		p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0;
   683 		p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0;
   687 	}
   684 	}
   688 
   685 
   689 	cost = 0;
       
   690 	tile = start_tile;
   686 	tile = start_tile;
   691 	/* Start tile is the small number. */
   687 	/* Start tile is the small number. */
   692 	for (;;) {
   688 	for (;;) {
   693 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   689 		RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X;
   694 
   690 
   696 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   692 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   697 
   693 
   698 		/* try to remove the halves. */
   694 		/* try to remove the halves. */
   699 		if (bits != 0) {
   695 		if (bits != 0) {
   700 			ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
   696 			ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
   701 			if (!CmdFailed(ret)) cost += ret;
   697 			if (CmdSucceeded(ret)) cost.AddCost(ret);
   702 		}
   698 		}
   703 
   699 
   704 		if (tile == end_tile) break;
   700 		if (tile == end_tile) break;
   705 
   701 
   706 		tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
   702 		tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
   707 	}
   703 	}
   708 
   704 
   709 	return (cost == 0) ? CMD_ERROR : cost;
   705 	return (cost.GetCost() == 0) ? CMD_ERROR : cost;
   710 }
   706 }
   711 
   707 
   712 /** Build a road depot.
   708 /** Build a road depot.
   713  * @param tile tile where to build the depot
   709  * @param tile tile where to build the depot
   714  * @param flags operation to perform
   710  * @param flags operation to perform
   717  * @param p2 unused
   713  * @param p2 unused
   718  *
   714  *
   719  * @todo When checking for the tile slope,
   715  * @todo When checking for the tile slope,
   720  * distingush between "Flat land required" and "land sloped in wrong direction"
   716  * distingush between "Flat land required" and "land sloped in wrong direction"
   721  */
   717  */
   722 int32 CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   718 CommandCost CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   723 {
   719 {
   724 	int32 cost;
   720 	CommandCost cost;
   725 	Depot *dep;
   721 	Depot *dep;
   726 	Slope tileh;
   722 	Slope tileh;
   727 
   723 
   728 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   724 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   729 
   725 
   754 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   750 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
   755 
   751 
   756 		MakeRoadDepot(tile, _current_player, dir, rt);
   752 		MakeRoadDepot(tile, _current_player, dir, rt);
   757 		MarkTileDirtyByTile(tile);
   753 		MarkTileDirtyByTile(tile);
   758 	}
   754 	}
   759 	return cost + _price.build_road_depot;
   755 	return cost.AddCost(_price.build_road_depot);
   760 }
   756 }
   761 
   757 
   762 static int32 RemoveRoadDepot(TileIndex tile, uint32 flags)
   758 static CommandCost RemoveRoadDepot(TileIndex tile, uint32 flags)
   763 {
   759 {
   764 	if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
   760 	if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
   765 		return CMD_ERROR;
   761 		return CMD_ERROR;
   766 
   762 
   767 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   763 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   768 
   764 
   769 	if (flags & DC_EXEC) DeleteDepot(GetDepotByTile(tile));
   765 	if (flags & DC_EXEC) DeleteDepot(GetDepotByTile(tile));
   770 
   766 
   771 	return _price.remove_road_depot;
   767 	return CommandCost(_price.remove_road_depot);
   772 }
   768 }
   773 
   769 
   774 static int32 ClearTile_Road(TileIndex tile, byte flags)
   770 static CommandCost ClearTile_Road(TileIndex tile, byte flags)
   775 {
   771 {
   776 	switch (GetRoadTileType(tile)) {
   772 	switch (GetRoadTileType(tile)) {
   777 		case ROAD_TILE_NORMAL: {
   773 		case ROAD_TILE_NORMAL: {
   778 			RoadBits b = GetAllRoadBits(tile);
   774 			RoadBits b = GetAllRoadBits(tile);
   779 
   775 
   783 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) ||
   779 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) ||
   784 			    ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) ||
   780 			    ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) ||
   785 			    !(flags & DC_AUTO)
   781 			    !(flags & DC_AUTO)
   786 				) {
   782 				) {
   787 				RoadTypes rts = GetRoadTypes(tile);
   783 				RoadTypes rts = GetRoadTypes(tile);
   788 				int32 ret = 0;
   784 				CommandCost ret;
   789 				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
   785 				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
   790 					if (HASBIT(rts, rt)) {
   786 					if (HASBIT(rts, rt)) {
   791 						int32 tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
   787 						CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
   792 						if (CmdFailed(tmp_ret)) return tmp_ret;
   788 						if (CmdFailed(tmp_ret)) return tmp_ret;
   793 						ret += tmp_ret;
   789 						ret.AddCost(tmp_ret);
   794 					}
   790 					}
   795 				}
   791 				}
   796 				return ret;
   792 				return ret;
   797 			}
   793 			}
   798 			return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
   794 			return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
   799 		}
   795 		}
   800 #undef M
   796 #undef M
   801 
   797 
   802 		case ROAD_TILE_CROSSING: {
   798 		case ROAD_TILE_CROSSING: {
   803 			int32 ret;
   799 			RoadTypes rts = GetRoadTypes(tile);
       
   800 			CommandCost ret;
   804 
   801 
   805 			if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
   802 			if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
   806 
   803 
   807 			ret = DoCommand(tile, GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD);
   804 			/* Must iterate over the roadtypes in a reverse manner because
   808 			if (CmdFailed(ret)) return CMD_ERROR;
   805 			 * tram tracks must be removed before the road bits. */
       
   806 			for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) {
       
   807 				if (HASBIT(rts, rt)) {
       
   808 					CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD);
       
   809 					if (CmdFailed(tmp_ret)) return tmp_ret;
       
   810 					ret.AddCost(tmp_ret);
       
   811 				}
       
   812 			}
   809 
   813 
   810 			if (flags & DC_EXEC) {
   814 			if (flags & DC_EXEC) {
   811 				DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   815 				DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   812 			}
   816 			}
   813 			return ret;
   817 			return ret;
   978 		}
   982 		}
   979 	}
   983 	}
   980 
   984 
   981 	DrawGroundSprite(image, pal);
   985 	DrawGroundSprite(image, pal);
   982 
   986 
   983 	if (road != ROAD_NONE) {
       
   984 		DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
       
   985 		if (drd != DRD_NONE) {
       
   986 			DrawRoadDetail(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), ti, 8, 8, 0);
       
   987 		}
       
   988 	}
       
   989 
       
   990 	/* For tram we overlay the road graphics with either tram tracks only
   987 	/* For tram we overlay the road graphics with either tram tracks only
   991 	 * (when there is actual road beneath the trams) or with tram tracks
   988 	 * (when there is actual road beneath the trams) or with tram tracks
   992 	 * and some dirts which hides the road graphics */
   989 	 * and some dirts which hides the road graphics */
   993 	if (tram != ROAD_NONE) {
   990 	if (tram != ROAD_NONE) {
   994 		if (ti->tileh != SLOPE_FLAT) {
   991 		if (ti->tileh != SLOPE_FLAT) {
   996 		} else {
   993 		} else {
   997 			image = _road_tile_sprites_1[tram] - SPR_ROAD_Y;
   994 			image = _road_tile_sprites_1[tram] - SPR_ROAD_Y;
   998 		}
   995 		}
   999 		image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY;
   996 		image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY;
  1000 		DrawGroundSprite(image, pal);
   997 		DrawGroundSprite(image, pal);
       
   998 	}
       
   999 
       
  1000 	if (road != ROAD_NONE) {
       
  1001 		DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
       
  1002 		if (drd != DRD_NONE) {
       
  1003 			DrawRoadDetail(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), ti, 8, 8, 0);
       
  1004 		}
  1001 	}
  1005 	}
  1002 
  1006 
  1003 	if (HasRoadWorks(ti->tile)) {
  1007 	if (HasRoadWorks(ti->tile)) {
  1004 		/* Road works */
  1008 		/* Road works */
  1005 		DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
  1009 		DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
  1344 
  1348 
  1345 		case ROAD_TILE_DEPOT:
  1349 		case ROAD_TILE_DEPOT:
  1346 			if (v->type == VEH_ROAD &&
  1350 			if (v->type == VEH_ROAD &&
  1347 					v->u.road.frame == 11 &&
  1351 					v->u.road.frame == 11 &&
  1348 					_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) {
  1352 					_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) {
  1349 				VehicleEnterDepot(v);
  1353 				v->u.road.state = RVSB_IN_DEPOT;
       
  1354 				v->vehstatus |= VS_HIDDEN;
       
  1355 				v->direction = ReverseDir(v->direction);
       
  1356 				if (v->next == NULL) VehicleEnterDepot(v);
       
  1357 				v->tile = tile;
       
  1358 
       
  1359 				InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
  1350 				return VETSB_ENTERED_WORMHOLE;
  1360 				return VETSB_ENTERED_WORMHOLE;
  1351 			}
  1361 			}
  1352 			break;
  1362 			break;
  1353 
  1363 
  1354 		default: break;
  1364 		default: break;