src/road_cmd.cpp
branchNewGRF_ports
changeset 6877 889301acc299
parent 6872 1c4a4a609f85
child 6878 7d1ff2f621c7
equal deleted inserted replaced
6876:2c40faeef7a5 6877:889301acc299
    31 #include "strings_func.h"
    31 #include "strings_func.h"
    32 #include "vehicle_func.h"
    32 #include "vehicle_func.h"
    33 #include "vehicle_base.h"
    33 #include "vehicle_base.h"
    34 #include "sound_func.h"
    34 #include "sound_func.h"
    35 #include "road_func.h"
    35 #include "road_func.h"
       
    36 #include "tunnelbridge.h"
    36 
    37 
    37 #include "table/sprites.h"
    38 #include "table/sprites.h"
    38 #include "table/strings.h"
    39 #include "table/strings.h"
    39 
    40 
    40 #define M(x) (1 << (x))
    41 #define M(x) (1 << (x))
    41 /* Level crossings may only be built on these slopes */
    42 /* Level crossings may only be built on these slopes */
    42 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT));
    43 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT));
    43 #undef M
    44 #undef M
       
    45 
       
    46 Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
    44 
    47 
    45 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
    48 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
    46 {
    49 {
    47 	RoadBits present;
    50 	RoadBits present;
    48 	RoadBits n;
    51 	RoadBits n;
    91 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
    94 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
    92 {
    95 {
    93 	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
    96 	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
    94 }
    97 }
    95 
    98 
       
    99 
    96 /** Delete a piece of road.
   100 /** Delete a piece of road.
    97  * @param tile tile where to remove road from
   101  * @param tile tile where to remove road from
    98  * @param flags operation to perform
   102  * @param flags operation to perform
    99  * @param p1 bit 0..3 road pieces to remove (RoadBits)
   103  * @param pieces roadbits to remove
   100  *           bit 4..5 road type
   104  * @param rt roadtype to remove
   101  *           bit    6 ignore the fact that the tram track has not been removed
   105  * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
   102  *                    yet when removing the road bits when not actually doing
       
   103  *                    it. Makes it possible to test whether the road bits can
       
   104  *                    be removed from a level crossing without physically
       
   105  *                    removing the tram bits before the test.
       
   106  * @param p2 unused
       
   107  */
   106  */
   108 CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   107 static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check)
   109 {
   108 {
   110 	/* cost for removing inner/edge -roads */
   109 	/* cost for removing inner/edge -roads */
   111 	static const uint16 road_remove_cost[2] = {50, 18};
   110 	static const uint16 road_remove_cost[2] = {50, 18};
   112 
   111 
   113 	/* true if the roadpiece was always removeable,
   112 	/* true if the roadpiece was always removeable,
   114 	 * false if it was a center piece. Affects town ratings drop */
   113 	 * false if it was a center piece. Affects town ratings drop */
   115 	bool edge_road;
   114 	bool edge_road;
   116 
       
   117 	RoadType rt = (RoadType)GB(p1, 4, 2);
       
   118 	if (!IsValidRoadType(rt)) return CMD_ERROR;
       
   119 
   115 
   120 	Town *t = NULL;
   116 	Town *t = NULL;
   121 	switch (GetTileType(tile)) {
   117 	switch (GetTileType(tile)) {
   122 		case MP_ROAD:
   118 		case MP_ROAD:
   123 			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
   119 			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
   128 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   124 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   129 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   125 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   130 			break;
   126 			break;
   131 
   127 
   132 		case MP_TUNNELBRIDGE:
   128 		case MP_TUNNELBRIDGE:
   133 			{
   129 			if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
   134 				if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
   130 			if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR;
   135 				if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR;
   131 			break;
   136 			} break;
       
   137 
   132 
   138 		default:
   133 		default:
   139 			return CMD_ERROR;
   134 			return CMD_ERROR;
   140 	}
   135 	}
   141 
   136 
   142 	RoadBits pieces = Extract<RoadBits, 0>(p1);
       
   143 	RoadTypes rts = GetRoadTypes(tile);
   137 	RoadTypes rts = GetRoadTypes(tile);
   144 	/* The tile doesn't have the given road type */
   138 	/* The tile doesn't have the given road type */
   145 	if (!HasBit(rts, rt)) return CMD_ERROR;
   139 	if (!HasBit(rts, rt)) return CMD_ERROR;
   146 
   140 
   147 	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
   141 	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
   156 
   150 
   157 		CommandCost cost(EXPENSES_CONSTRUCTION);
   151 		CommandCost cost(EXPENSES_CONSTRUCTION);
   158 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   152 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   159 			TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
   153 			TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
   160 			/* Pay for *every* tile of the bridge or tunnel */
   154 			/* Pay for *every* tile of the bridge or tunnel */
   161 			cost.AddCost((DistanceManhattan(other_end, tile) + 1) * _price.remove_road);
   155 			cost.AddCost((GetTunnelBridgeLength(other_end, tile) + 2) * _price.remove_road);
   162 			if (flags & DC_EXEC) {
   156 			if (flags & DC_EXEC) {
   163 				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
   157 				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
   164 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
   158 				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
   165 
   159 
   166 				/* Mark tiles diry that have been repaved */
   160 				/* Mark tiles diry that have been repaved */
   229 				return CMD_ERROR;
   223 				return CMD_ERROR;
   230 			}
   224 			}
   231 
   225 
   232 			/* Don't allow road to be removed from the crossing when there is tram;
   226 			/* Don't allow road to be removed from the crossing when there is tram;
   233 			 * we can't draw the crossing without trambits ;) */
   227 			 * we can't draw the crossing without trambits ;) */
   234 			if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HasBit(p1, 6))) return CMD_ERROR;
   228 			if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR;
   235 
   229 
   236 			if (rt == ROADTYPE_ROAD) {
   230 			if (rt == ROADTYPE_ROAD) {
   237 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   231 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
   238 			}
   232 			}
   239 
   233 
   252 
   246 
   253 		default:
   247 		default:
   254 		case ROAD_TILE_DEPOT:
   248 		case ROAD_TILE_DEPOT:
   255 			return CMD_ERROR;
   249 			return CMD_ERROR;
   256 	}
   250 	}
       
   251 }
       
   252 
       
   253 
       
   254 /** Delete a piece of road.
       
   255  * @param tile tile where to remove road from
       
   256  * @param flags operation to perform
       
   257  * @param p1 bit 0..3 road pieces to remove (RoadBits)
       
   258  *           bit 4..5 road type
       
   259  * @param p2 unused
       
   260  */
       
   261 CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
       
   262 {
       
   263 	RoadType rt = (RoadType)GB(p1, 4, 2);
       
   264 	if (!IsValidRoadType(rt)) return CMD_ERROR;
       
   265 
       
   266 	RoadBits pieces = Extract<RoadBits, 0>(p1);
       
   267 
       
   268 	return RemoveRoad(tile, flags, pieces, rt, true);
   257 }
   269 }
   258 
   270 
   259 
   271 
   260 static const RoadBits _valid_tileh_slopes_road[][15] = {
   272 static const RoadBits _valid_tileh_slopes_road[][15] = {
   261 	/* set of normal ones */
   273 	/* set of normal ones */
   372 
   384 
   373 	/* Force straight roads. */
   385 	/* Force straight roads. */
   374 	*pieces |= MirrorRoadBits(*pieces);
   386 	*pieces |= MirrorRoadBits(*pieces);
   375 
   387 
   376 	/* partly leveled up tile, only if there's no road on that tile */
   388 	/* partly leveled up tile, only if there's no road on that tile */
   377 	if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) {
   389 	if ((existing == ROAD_NONE || existing == *pieces) && IsSlopeWithOneCornerRaised(tileh)) {
   378 		if (*pieces == ROAD_X || *pieces == ROAD_Y) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
   390 		if (*pieces == ROAD_X || *pieces == ROAD_Y) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
   379 	}
   391 	}
   380 	return CMD_ERROR;
   392 	return CMD_ERROR;
   381 }
   393 }
   382 
   394 
   494 		}
   506 		}
   495 
   507 
   496 		case MP_STATION:
   508 		case MP_STATION:
   497 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   509 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
   498 			if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   510 			if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   499 			/* Don't allow "upgrading" the roadstop when vehicles are already driving on it */
   511 			/* Don't allow adding roadtype to the roadstop when vehicles are already driving on it */
   500 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   512 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   501 			break;
   513 			break;
   502 
   514 
   503 		case MP_TUNNELBRIDGE:
   515 		case MP_TUNNELBRIDGE:
   504 			{
   516 			if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
   505 				if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
   517 			if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   506 				if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   518 			/* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
   507 
   519 			if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR;
   508 				/* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */
   520 			break;
   509 				if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR;
       
   510 			} break;
       
   511 
   521 
   512 		default:
   522 		default:
   513 do_clear:;
   523 do_clear:;
   514 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   524 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   515 			if (CmdFailed(ret)) return ret;
   525 			if (CmdFailed(ret)) return ret;
   528 	}
   538 	}
   529 
   539 
   530 	if (IsTileType(tile, MP_ROAD)) {
   540 	if (IsTileType(tile, MP_ROAD)) {
   531 		/* Don't put the pieces that already exist */
   541 		/* Don't put the pieces that already exist */
   532 		pieces &= ComplementRoadBits(existing);
   542 		pieces &= ComplementRoadBits(existing);
       
   543 
       
   544 		/* Check if new road bits will have the same foundation as other existing road types */
       
   545 		if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
       
   546 			Slope slope = GetTileSlope(tile, NULL);
       
   547 			Foundation found_new = GetRoadFoundation(slope, pieces | existing);
       
   548 
       
   549 			/* Test if all other roadtypes can be built at that foundation */
       
   550 			for (RoadType rtest = ROADTYPE_ROAD; rtest < ROADTYPE_END; rtest++) {
       
   551 				if (rtest != rt) { // check only other road types
       
   552 					RoadBits bits = GetRoadBits(tile, rtest);
       
   553 					/* do not check if there are not road bits of given type */
       
   554 					if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) {
       
   555 						return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   556 					}
       
   557 				}
       
   558 			}
       
   559 		}
   533 	}
   560 	}
   534 
   561 
   535 	cost.AddCost(CountBits(pieces) * _price.build_road);
   562 	cost.AddCost(CountBits(pieces) * _price.build_road);
   536 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   563 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   537 		/* Pay for *every* tile of the bridge or tunnel */
   564 		/* Pay for *every* tile of the bridge or tunnel */
   538 		cost.MultiplyCost(DistanceManhattan(GetOtherTunnelBridgeEnd(tile), tile) + 1);
   565 		cost.MultiplyCost(GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2);
   539 	}
   566 	}
   540 
   567 
   541 	if (flags & DC_EXEC) {
   568 	if (flags & DC_EXEC) {
   542 		switch (GetTileType(tile)) {
   569 		switch (GetTileType(tile)) {
   543 			case MP_ROAD: {
   570 			case MP_ROAD: {
   651 				if (IsBridge(tile)) {
   678 				if (IsBridge(tile)) {
   652 					if ((!had_bridge || GetTunnelBridgeDirection(tile) == DIAGDIR_SE || GetTunnelBridgeDirection(tile) == DIAGDIR_SW)) {
   679 					if ((!had_bridge || GetTunnelBridgeDirection(tile) == DIAGDIR_SE || GetTunnelBridgeDirection(tile) == DIAGDIR_SW)) {
   653 						cost.AddCost(ret);
   680 						cost.AddCost(ret);
   654 					}
   681 					}
   655 					had_bridge = true;
   682 					had_bridge = true;
   656 				} else {
   683 				} else { // IsTunnel(tile)
   657 					if ((!had_tunnel || GetTunnelBridgeDirection(tile) == DIAGDIR_SE || GetTunnelBridgeDirection(tile) == DIAGDIR_SW)) {
   684 					if ((!had_tunnel || GetTunnelBridgeDirection(tile) == DIAGDIR_SE || GetTunnelBridgeDirection(tile) == DIAGDIR_SW)) {
   658 						cost.AddCost(ret);
   685 						cost.AddCost(ret);
   659 					}
   686 					}
   660 					had_tunnel = true;
   687 					had_tunnel = true;
   661 				}
   688 				}
   715 		if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   742 		if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
   716 		if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   743 		if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
   717 
   744 
   718 		/* try to remove the halves. */
   745 		/* try to remove the halves. */
   719 		if (bits != 0) {
   746 		if (bits != 0) {
   720 			ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD);
   747 			ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true);
   721 			if (CmdSucceeded(ret)) {
   748 			if (CmdSucceeded(ret)) {
   722 				if (flags & DC_EXEC) {
   749 				if (flags & DC_EXEC) {
   723 					money -= ret.GetCost();
   750 					money -= ret.GetCost();
   724 					if (money < 0) {
   751 					if (money < 0) {
   725 						_additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
   752 						_additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
   726 						return cost;
   753 						return cost;
   727 					}
   754 					}
   728 					DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
   755 					RemoveRoad(tile, flags, bits, rt, true);
   729 				}
   756 				}
   730 				cost.AddCost(ret);
   757 				cost.AddCost(ret);
   731 			}
   758 			}
   732 		}
   759 		}
   733 
   760 
   816 				) {
   843 				) {
   817 				RoadTypes rts = GetRoadTypes(tile);
   844 				RoadTypes rts = GetRoadTypes(tile);
   818 				CommandCost ret(EXPENSES_CONSTRUCTION);
   845 				CommandCost ret(EXPENSES_CONSTRUCTION);
   819 				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
   846 				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
   820 					if (HasBit(rts, rt)) {
   847 					if (HasBit(rts, rt)) {
   821 						CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
   848 						CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true);
   822 						if (CmdFailed(tmp_ret)) return tmp_ret;
   849 						if (CmdFailed(tmp_ret)) return tmp_ret;
   823 						ret.AddCost(tmp_ret);
   850 						ret.AddCost(tmp_ret);
   824 					}
   851 					}
   825 				}
   852 				}
   826 				return ret;
   853 				return ret;
   836 
   863 
   837 			/* Must iterate over the roadtypes in a reverse manner because
   864 			/* Must iterate over the roadtypes in a reverse manner because
   838 			 * tram tracks must be removed before the road bits. */
   865 			 * tram tracks must be removed before the road bits. */
   839 			for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) {
   866 			for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) {
   840 				if (HasBit(rts, rt)) {
   867 				if (HasBit(rts, rt)) {
   841 					CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD);
   868 					CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false);
   842 					if (CmdFailed(tmp_ret)) return tmp_ret;
   869 					if (CmdFailed(tmp_ret)) return tmp_ret;
   843 					ret.AddCost(tmp_ret);
   870 					ret.AddCost(tmp_ret);
   844 				}
   871 				}
   845 			}
   872 			}
   846 
   873 
  1257 			/* Generate a nicer town surface */
  1284 			/* Generate a nicer town surface */
  1258 			const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
  1285 			const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
  1259 			const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
  1286 			const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
  1260 
  1287 
  1261 			if (old_rb != new_rb) {
  1288 			if (old_rb != new_rb) {
  1262 				DoCommand(tile, (old_rb ^ new_rb), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_REMOVE_ROAD);
  1289 				RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true);
  1263 			}
  1290 			}
  1264 		}
  1291 		}
  1265 
  1292 
  1266 		MarkTileDirtyByTile(tile);
  1293 		MarkTileDirtyByTile(tile);
  1267 	}
  1294 	}