src/road_cmd.cpp
branchNewGRF_ports
changeset 6720 35756db7e577
parent 6719 4cc327ad39d5
child 6725 23339968083f
--- a/src/road_cmd.cpp	Sat Jun 02 19:59:29 2007 +0000
+++ b/src/road_cmd.cpp	Sat Jul 14 19:42:58 2007 +0000
@@ -13,6 +13,7 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 #include "functions.h"
+#include "window.h"
 #include "map.h"
 #include "landscape.h"
 #include "tile.h"
@@ -99,14 +100,18 @@
  * @param flags operation to perform
  * @param p1 bit 0..3 road pieces to remove (RoadBits)
  *           bit 4..5 road type
+ *           bit    6 ignore the fact that the tram track has not been removed
+ *                    yet when removing the road bits when not actually doing
+ *                    it. Makes it possible to test whether the road bits can
+ *                    be removed from a level crossing without physically
+ *                    removing the tram bits before the test.
  * @param p2 unused
  */
-int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	/* cost for removing inner/edge -roads */
 	static const uint16 road_remove_cost[2] = {50, 18};
 
-	Town *t;
 	/* true if the roadpiece was always removeable,
 	 * false if it was a center piece. Affects town ratings drop */
 	bool edge_road;
@@ -116,33 +121,25 @@
 	RoadType rt = (RoadType)GB(p1, 4, 2);
 	if (!IsValidRoadType(rt)) return CMD_ERROR;
 
-	Owner owner;
+	Town *t = NULL;
 	switch (GetTileType(tile)) {
 		case MP_STREET:
-			owner = GetRoadOwner(tile, rt);
+			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
 			break;
 
 		case MP_STATION:
 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
-			owner = GetTileOwner(tile);
 			break;
 
 		case MP_TUNNELBRIDGE:
 			if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) ||
 					(IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR;
-			owner = GetTileOwner(tile);
 			break;
 
 		default:
 			return CMD_ERROR;
 	}
 
-	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
-		t = GetTownByTile(tile);
-	} else {
-		t = NULL;
-	}
-
 	RoadBits pieces = Extract<RoadBits, 0>(p1);
 	RoadTypes rts = GetRoadTypes(tile);
 	/* The tile doesn't have the given road type */
@@ -160,11 +157,11 @@
 		/* If it's the last roadtype, just clear the whole tile */
 		if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
-		int32 cost;
+		CommandCost cost;
 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 			TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
 			/* Pay for *every* tile of the bridge or tunnel */
-			cost = (DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road;
+			cost.AddCost((DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road);
 			if (flags & DC_EXEC) {
 				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
@@ -179,13 +176,13 @@
 				}
 			}
 		} else {
-			cost = _price.remove_road;
+			cost.AddCost(_price.remove_road);
 			if (flags & DC_EXEC) {
 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
 				MarkTileDirtyByTile(tile);
 			}
 		}
-		return cost;
+		return CommandCost(cost);
 	}
 
 	switch (GetRoadTileType(tile)) {
@@ -226,7 +223,7 @@
 					MarkTileDirtyByTile(tile);
 				}
 			}
-			return CountRoadBits(c) * _price.remove_road;
+			return CommandCost(CountRoadBits(c) * _price.remove_road);
 		}
 
 		case ROAD_TILE_CROSSING: {
@@ -236,7 +233,7 @@
 
 			/* Don't allow road to be removed from the crossing when there is tram;
 			 * we can't draw the crossing without trambits ;) */
-			if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM)) return CMD_ERROR;
+			if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HASBIT(p1, 6))) return CMD_ERROR;
 
 			if (flags & DC_EXEC) {
 				if (rt == ROADTYPE_ROAD) {
@@ -252,7 +249,7 @@
 				MarkTileDirtyByTile(tile);
 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
 			}
-			return _price.remove_road * 2;
+			return CommandCost(_price.remove_road * 2);
 		}
 
 		default:
@@ -295,7 +292,7 @@
 };
 
 
-static uint32 CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing)
+static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing)
 {
 	RoadBits road_bits;
 
@@ -314,12 +311,12 @@
 	if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) {
 		/* force that all bits are set when we have slopes */
 		if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh];
-		return 0; // no extra cost
+		return CommandCost(); // no extra cost
 	}
 
 	/* foundation is used. Whole tile is leveled up */
 	if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) {
-		return existing != 0 ? 0 : _price.terraform;
+		return CommandCost(existing != 0 ? 0 : _price.terraform);
 	}
 
 	/* partly leveled up tile, only if there's no road on that tile */
@@ -340,10 +337,10 @@
  *           bit 6..7 disallowed directions to toggle
  * @param p2 the town that is building the road (0 if not applicable)
  */
-int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	int32 cost = 0;
-	int32 ret;
+	CommandCost cost;
+	CommandCost ret;
 	RoadBits existing = ROAD_NONE;
 	RoadBits all_bits = ROAD_NONE;
 	Slope tileh;
@@ -390,7 +387,7 @@
 								SetDisallowedRoadDirections(tile, GetDisallowedRoadDirections(tile) ^ toggle_drd);
 								MarkTileDirtyByTile(tile);
 							}
-							return 0;
+							return CommandCost();
 						}
 						return_cmd_error(STR_1007_ALREADY_BUILT);
 					}
@@ -445,7 +442,7 @@
 				MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2);
 				MarkTileDirtyByTile(tile);
 			}
-			return _price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4);
+			return CommandCost(_price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4));
 		}
 
 		case MP_STATION:
@@ -467,7 +464,7 @@
 do_clear:;
 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 			if (CmdFailed(ret)) return ret;
-			cost += ret;
+			cost.AddCost(ret);
 	}
 
 	if (all_bits != pieces) {
@@ -475,10 +472,10 @@
 		ret = CheckRoadSlope(tileh, &pieces, all_bits | existing);
 		/* Return an error if we need to build a foundation (ret != 0) but the
 		 * current patch-setting is turned off (or stupid AI@work) */
-		if (CmdFailed(ret) || (ret != 0 && (!_patches.build_on_slopes || _is_old_ai_player))) {
+		if (CmdFailed(ret) || (ret.GetCost() != 0 && (!_patches.build_on_slopes || _is_old_ai_player))) {
 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 		}
-		cost += ret;
+		cost.AddCost(ret);
 	}
 
 	if (IsTileType(tile, MP_STREET)) {
@@ -486,10 +483,10 @@
 		pieces &= ComplementRoadBits(existing);
 	}
 
-	cost += CountRoadBits(pieces) * _price.build_road;
+	cost.AddCost(CountRoadBits(pieces) * _price.build_road);
 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 		/* Pay for *every* tile of the bridge or tunnel */
-		cost *= DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile);
+		cost.MultiplyCost(DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile));
 	}
 
 	if (flags & DC_EXEC) {
@@ -499,6 +496,7 @@
 				if (existing == ROAD_NONE || rtt == ROAD_TILE_CROSSING) {
 					SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
 					SetRoadOwner(tile, rt, _current_player);
+					if (_current_player == OWNER_TOWN && rt == ROADTYPE_ROAD) SetTownIndex(tile, p2);
 				}
 				if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt);
 			} break;
@@ -547,7 +545,7 @@
  * @return            The cost and state of the operation
  * @retval CMD_ERROR  An error occured during the operation.
  */
-int32 DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
+CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
 {
 	/* not a railroad crossing? */
 	if (!IsLevelCrossing(tile)) return CMD_ERROR;
@@ -566,7 +564,7 @@
 		YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile)));
 	}
 
-	return _price.build_rail / 2;
+	return CommandCost(_price.build_rail / 2);
 }
 
 
@@ -581,10 +579,10 @@
  * - p2 = (bit 3 + 4) - road type
  * - p2 = (bit 5) - set road direction
  */
-int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileIndex start_tile, tile;
-	int32 cost, ret;
+	CommandCost cost, ret;
 	bool had_bridge = false;
 	bool had_success = false;
 	DisallowedRoadDirections drd = DRD_NORTHBOUND;
@@ -617,7 +615,6 @@
 	/* No disallowed direction bits have to be toggled */
 	if (!HASBIT(p2, 5)) drd = DRD_NONE;
 
-	cost = 0;
 	tile = start_tile;
 	/* Start tile is the small number. */
 	for (;;) {
@@ -635,11 +632,11 @@
 			/* Only pay for the upgrade on one side of the bridge */
 			if (IsBridgeTile(tile)) {
 				if ((!had_bridge || GetBridgeRampDirection(tile) == DIAGDIR_SE || GetBridgeRampDirection(tile) == DIAGDIR_SW)) {
-					cost += ret;
+					cost.AddCost(ret);
 				}
 				had_bridge = true;
 			} else {
-				cost += ret;
+				cost.AddCost(ret);
 			}
 		}
 
@@ -661,10 +658,10 @@
  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
  * - p2 = (bit 3 + 4) - road type
  */
-int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileIndex start_tile, tile;
-	int32 cost, ret;
+	CommandCost cost, ret;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
@@ -686,7 +683,6 @@
 		p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0;
 	}
 
-	cost = 0;
 	tile = start_tile;
 	/* Start tile is the small number. */
 	for (;;) {
@@ -698,7 +694,7 @@
 		/* try to remove the halves. */
 		if (bits != 0) {
 			ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
-			if (!CmdFailed(ret)) cost += ret;
+			if (CmdSucceeded(ret)) cost.AddCost(ret);
 		}
 
 		if (tile == end_tile) break;
@@ -706,7 +702,7 @@
 		tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
 	}
 
-	return (cost == 0) ? CMD_ERROR : cost;
+	return (cost.GetCost() == 0) ? CMD_ERROR : cost;
 }
 
 /** Build a road depot.
@@ -719,9 +715,9 @@
  * @todo When checking for the tile slope,
  * distingush between "Flat land required" and "land sloped in wrong direction"
  */
-int32 CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	int32 cost;
+	CommandCost cost;
 	Depot *dep;
 	Slope tileh;
 
@@ -756,10 +752,10 @@
 		MakeRoadDepot(tile, _current_player, dir, rt);
 		MarkTileDirtyByTile(tile);
 	}
-	return cost + _price.build_road_depot;
+	return cost.AddCost(_price.build_road_depot);
 }
 
-static int32 RemoveRoadDepot(TileIndex tile, uint32 flags)
+static CommandCost RemoveRoadDepot(TileIndex tile, uint32 flags)
 {
 	if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
 		return CMD_ERROR;
@@ -768,10 +764,10 @@
 
 	if (flags & DC_EXEC) DeleteDepot(GetDepotByTile(tile));
 
-	return _price.remove_road_depot;
+	return CommandCost(_price.remove_road_depot);
 }
 
-static int32 ClearTile_Road(TileIndex tile, byte flags)
+static CommandCost ClearTile_Road(TileIndex tile, byte flags)
 {
 	switch (GetRoadTileType(tile)) {
 		case ROAD_TILE_NORMAL: {
@@ -785,12 +781,12 @@
 			    !(flags & DC_AUTO)
 				) {
 				RoadTypes rts = GetRoadTypes(tile);
-				int32 ret = 0;
+				CommandCost ret;
 				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
 					if (HASBIT(rts, rt)) {
-						int32 tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
+						CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
 						if (CmdFailed(tmp_ret)) return tmp_ret;
-						ret += tmp_ret;
+						ret.AddCost(tmp_ret);
 					}
 				}
 				return ret;
@@ -800,12 +796,20 @@
 #undef M
 
 		case ROAD_TILE_CROSSING: {
-			int32 ret;
+			RoadTypes rts = GetRoadTypes(tile);
+			CommandCost ret;
 
 			if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
 
-			ret = DoCommand(tile, GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD);
-			if (CmdFailed(ret)) return CMD_ERROR;
+			/* Must iterate over the roadtypes in a reverse manner because
+			 * tram tracks must be removed before the road bits. */
+			for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) {
+				if (HASBIT(rts, rt)) {
+					CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD);
+					if (CmdFailed(tmp_ret)) return tmp_ret;
+					ret.AddCost(tmp_ret);
+				}
+			}
 
 			if (flags & DC_EXEC) {
 				DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
@@ -980,13 +984,6 @@
 
 	DrawGroundSprite(image, pal);
 
-	if (road != ROAD_NONE) {
-		DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
-		if (drd != DRD_NONE) {
-			DrawRoadDetail(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), ti, 8, 8, 0);
-		}
-	}
-
 	/* For tram we overlay the road graphics with either tram tracks only
 	 * (when there is actual road beneath the trams) or with tram tracks
 	 * and some dirts which hides the road graphics */
@@ -1000,6 +997,13 @@
 		DrawGroundSprite(image, pal);
 	}
 
+	if (road != ROAD_NONE) {
+		DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
+		if (drd != DRD_NONE) {
+			DrawRoadDetail(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), ti, 8, 8, 0);
+		}
+	}
+
 	if (HasRoadWorks(ti->tile)) {
 		/* Road works */
 		DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
@@ -1346,7 +1350,13 @@
 			if (v->type == VEH_ROAD &&
 					v->u.road.frame == 11 &&
 					_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) {
-				VehicleEnterDepot(v);
+				v->u.road.state = RVSB_IN_DEPOT;
+				v->vehstatus |= VS_HIDDEN;
+				v->direction = ReverseDir(v->direction);
+				if (v->next == NULL) VehicleEnterDepot(v);
+				v->tile = tile;
+
+				InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 				return VETSB_ENTERED_WORMHOLE;
 			}
 			break;