src/rail_cmd.cpp
branchNewGRF_ports
changeset 6868 7eb395287b3d
parent 6743 cabfaa4a0295
child 6870 ca3fd1fbe311
equal deleted inserted replaced
6867:a4ad48192617 6868:7eb395287b3d
    76  *               01abcdef => rail w/ signals
    76  *               01abcdef => rail w/ signals
    77  *               10uuuuuu => unused
    77  *               10uuuuuu => unused
    78  *               11uuuudd => rail depot
    78  *               11uuuudd => rail depot
    79  */
    79  */
    80 
    80 
       
    81 /** Struct used in EnsureNoTrainOnTrack() */
       
    82 struct TrainOnTrackData {
       
    83 	TileIndex tile;       ///< tile to check
       
    84 	uint z;               ///< tile max Z
       
    85 	TrackBits rail_bits;  ///< trackbits of interest
       
    86 };
       
    87 
       
    88 static void *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
       
    89 {
       
    90 	const TrainOnTrackData *info = (const TrainOnTrackData *)data;
       
    91 
       
    92 	if (v->tile != info->tile || v->type != VEH_TRAIN) return NULL;
       
    93 	if (v->z_pos > info->z) return NULL;
       
    94 
       
    95 	if ((v->u.rail.track != info->rail_bits) && !TracksOverlap(v->u.rail.track | info->rail_bits)) return NULL;
       
    96 
       
    97 	_error_message = VehicleInTheWayErrMsg(v);
       
    98 	return v;
       
    99 }
       
   100 
       
   101 /**
       
   102  * Tests if a vehicle interacts with the specified track.
       
   103  * All track bits interact except parallel TRACK_BIT_HORZ or TRACK_BIT_VERT.
       
   104  *
       
   105  * @param tile The tile.
       
   106  * @param track The track.
       
   107  */
       
   108 static bool EnsureNoTrainOnTrack(TileIndex tile, Track track)
       
   109 {
       
   110 	TrainOnTrackData info;
       
   111 
       
   112 	info.tile = tile;
       
   113 	info.z = GetTileMaxZ(tile);
       
   114 	info.rail_bits = TrackToTrackBits(track);
       
   115 
       
   116 	return VehicleFromPos(tile, &info, EnsureNoTrainOnTrackProc) == NULL;
       
   117 }
       
   118 
    81 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
   119 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
    82 {
   120 {
    83 	TrackBits current; // The current track layout
   121 	TrackBits current; // The current track layout
    84 	TrackBits future;  // The track layout we want to build
   122 	TrackBits future;  // The track layout we want to build
    85 	_error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION;
   123 	_error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION;
   237 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   275 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   238 
   276 
   239 	switch (GetTileType(tile)) {
   277 	switch (GetTileType(tile)) {
   240 		case MP_RAILWAY:
   278 		case MP_RAILWAY:
   241 			if (!CheckTrackCombination(tile, trackbit, flags) ||
   279 			if (!CheckTrackCombination(tile, trackbit, flags) ||
   242 					!EnsureNoVehicleOnGround(tile)) {
   280 					!EnsureNoTrainOnTrack(tile, track)) {
   243 				return CMD_ERROR;
   281 				return CMD_ERROR;
   244 			}
   282 			}
   245 			if (!IsTileOwner(tile, _current_player) ||
   283 			if (!IsTileOwner(tile, _current_player) ||
   246 					!IsCompatibleRail(GetRailType(tile), railtype)) {
   284 					!IsCompatibleRail(GetRailType(tile), railtype)) {
   247 				/* Get detailed error message */
   285 				/* Get detailed error message */
   372 		case MP_RAILWAY: {
   410 		case MP_RAILWAY: {
   373 			TrackBits present;
   411 			TrackBits present;
   374 
   412 
   375 			if (!IsPlainRailTile(tile) ||
   413 			if (!IsPlainRailTile(tile) ||
   376 					(_current_player != OWNER_WATER && !CheckTileOwnership(tile)) ||
   414 					(_current_player != OWNER_WATER && !CheckTileOwnership(tile)) ||
   377 					!EnsureNoVehicleOnGround(tile)) {
   415 					!EnsureNoTrainOnTrack(tile, track)) {
   378 				return CMD_ERROR;
   416 				return CMD_ERROR;
   379 			}
   417 			}
   380 
   418 
   381 			present = GetTrackBits(tile);
   419 			present = GetTrackBits(tile);
   382 			if ((present & trackbit) == 0) return CMD_ERROR;
   420 			if ((present & trackbit) == 0) return CMD_ERROR;
   645 	Track track = (Track)GB(p1, 0, 3);
   683 	Track track = (Track)GB(p1, 0, 3);
   646 	bool pre_signal = HASBIT(p1, 3);
   684 	bool pre_signal = HASBIT(p1, 3);
   647 	SignalVariant sigvar = (pre_signal ^ HASBIT(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC;
   685 	SignalVariant sigvar = (pre_signal ^ HASBIT(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC;
   648 	CommandCost cost;
   686 	CommandCost cost;
   649 
   687 
   650 	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoVehicleOnGround(tile))
   688 	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track))
   651 		return CMD_ERROR;
   689 		return CMD_ERROR;
   652 
   690 
   653 	/* Protect against invalid signal copying */
   691 	/* Protect against invalid signal copying */
   654 	if (p2 != 0 && (p2 & SignalOnTrack(track)) == 0) return CMD_ERROR;
   692 	if (p2 != 0 && (p2 & SignalOnTrack(track)) == 0) return CMD_ERROR;
   655 
   693 
   933 {
   971 {
   934 	Track track = (Track)GB(p1, 0, 3);
   972 	Track track = (Track)GB(p1, 0, 3);
   935 
   973 
   936 	if (!ValParamTrackOrientation(track) ||
   974 	if (!ValParamTrackOrientation(track) ||
   937 			!IsTileType(tile, MP_RAILWAY) ||
   975 			!IsTileType(tile, MP_RAILWAY) ||
   938 			!EnsureNoVehicleOnGround(tile) ||
   976 			!EnsureNoTrainOnTrack(tile, track) ||
   939 			!HasSignalOnTrack(tile, track)) {
   977 			!HasSignalOnTrack(tile, track)) {
   940 		return CMD_ERROR;
   978 		return CMD_ERROR;
   941 	}
   979 	}
   942 
   980 
   943 	/* Only water can remove signals from anyone */
   981 	/* Only water can remove signals from anyone */
  2116 		if (DiagDirToDir(ReverseDiagDir(dir)) == v->direction) {
  2154 		if (DiagDirToDir(ReverseDiagDir(dir)) == v->direction) {
  2117 			/* enter the depot */
  2155 			/* enter the depot */
  2118 			v->u.rail.track = TRACK_BIT_DEPOT,
  2156 			v->u.rail.track = TRACK_BIT_DEPOT,
  2119 			v->vehstatus |= VS_HIDDEN; /* hide it */
  2157 			v->vehstatus |= VS_HIDDEN; /* hide it */
  2120 			v->direction = ReverseDir(v->direction);
  2158 			v->direction = ReverseDir(v->direction);
  2121 			if (v->next == NULL) VehicleEnterDepot(v);
  2159 			if (v->Next() == NULL) VehicleEnterDepot(v);
  2122 			v->tile = tile;
  2160 			v->tile = tile;
  2123 
  2161 
  2124 			InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
  2162 			InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
  2125 			return VETSB_ENTERED_WORMHOLE;
  2163 			return VETSB_ENTERED_WORMHOLE;
  2126 		}
  2164 		}
  2127 	} else if (fract_coord_leave == fract_coord) {
  2165 	} else if (fract_coord_leave == fract_coord) {
  2128 		if (DiagDirToDir(dir) == v->direction) {
  2166 		if (DiagDirToDir(dir) == v->direction) {
  2129 			/* leave the depot? */
  2167 			/* leave the depot? */
  2130 			if ((v = v->next) != NULL) {
  2168 			if ((v = v->Next()) != NULL) {
  2131 				v->vehstatus &= ~VS_HIDDEN;
  2169 				v->vehstatus &= ~VS_HIDDEN;
  2132 				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
  2170 				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
  2133 			}
  2171 			}
  2134 		}
  2172 		}
  2135 	}
  2173 	}
  2136 
  2174 
  2137 	return VETSB_CONTINUE;
  2175 	return VETSB_CONTINUE;
       
  2176 }
       
  2177 
       
  2178 static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
       
  2179 {
       
  2180 	if (IsPlainRailTile(tile)) {
       
  2181 		uint z_old;
       
  2182 		Slope tileh_old = GetTileSlope(tile, &z_old);
       
  2183 		TrackBits rail_bits = GetTrackBits(tile);
       
  2184 
       
  2185 		_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
       
  2186 
       
  2187 		/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
       
  2188 		Slope allowed_corner;
       
  2189 		switch (rail_bits) {
       
  2190 			case TRACK_BIT_RIGHT: allowed_corner = SLOPE_W; break;
       
  2191 			case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
       
  2192 			case TRACK_BIT_LEFT:  allowed_corner = SLOPE_E; break;
       
  2193 			case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
       
  2194 			default: return CMD_ERROR;
       
  2195 		}
       
  2196 
       
  2197 		Slope track_corners = ComplementSlope(allowed_corner);
       
  2198 
       
  2199 		Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
       
  2200 		switch (f_old) {
       
  2201 			case FOUNDATION_NONE:
       
  2202 				/* Everything is valid, which only changes allowed_corner */
       
  2203 
       
  2204 				/* Compute height of track */
       
  2205 				if (tileh_old == track_corners) z_old += TILE_HEIGHT;
       
  2206 				if (tileh_new == track_corners) {
       
  2207 					z_new += TILE_HEIGHT;
       
  2208 				} else {
       
  2209 					/* do not build a foundation */
       
  2210 					if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return CMD_ERROR;
       
  2211 				}
       
  2212 
       
  2213 				/* Track height must remain unchanged */
       
  2214 				if (z_old != z_new) return CMD_ERROR;
       
  2215 				break;
       
  2216 
       
  2217 			case FOUNDATION_LEVELED:
       
  2218 				/* Is allowed_corner covered by the foundation? */
       
  2219 				if ((tileh_old & allowed_corner) == 0) return CMD_ERROR;
       
  2220 
       
  2221 				/* allowed_corner may only be raised -> steep slope */
       
  2222 				if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return CMD_ERROR;
       
  2223 				break;
       
  2224 
       
  2225 			case FOUNDATION_STEEP_LOWER:
       
  2226 				/* Only allow to lower highest corner */
       
  2227 				if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return CMD_ERROR;
       
  2228 				break;
       
  2229 
       
  2230 			case FOUNDATION_STEEP_HIGHER:
       
  2231 				return CMD_ERROR;
       
  2232 
       
  2233 			default: NOT_REACHED();
       
  2234 		}
       
  2235 
       
  2236 		/* Make the ground dirty */
       
  2237 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
       
  2238 
       
  2239 		/* allow terraforming, no extra costs */
       
  2240 		return CommandCost();
       
  2241 	}
       
  2242 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  2138 }
  2243 }
  2139 
  2244 
  2140 
  2245 
  2141 extern const TileTypeProcs _tile_type_rail_procs = {
  2246 extern const TileTypeProcs _tile_type_rail_procs = {
  2142 	DrawTile_Track,           /* draw_tile_proc */
  2247 	DrawTile_Track,           /* draw_tile_proc */
  2150 	TileLoop_Track,           /* tile_loop_clear */
  2255 	TileLoop_Track,           /* tile_loop_clear */
  2151 	ChangeTileOwner_Track,    /* change_tile_owner_clear */
  2256 	ChangeTileOwner_Track,    /* change_tile_owner_clear */
  2152 	NULL,                     /* get_produced_cargo_proc */
  2257 	NULL,                     /* get_produced_cargo_proc */
  2153 	VehicleEnter_Track,       /* vehicle_enter_tile_proc */
  2258 	VehicleEnter_Track,       /* vehicle_enter_tile_proc */
  2154 	GetFoundation_Track,      /* get_foundation_proc */
  2259 	GetFoundation_Track,      /* get_foundation_proc */
       
  2260 	TerraformTile_Track,      /* terraform_tile_proc */
  2155 };
  2261 };