src/rail_cmd.cpp
changeset 8230 64f28fe2d5c8
parent 8228 a25986306665
child 8236 8a5dd0b42e47
equal deleted inserted replaced
8229:00e7467ceeee 8230:64f28fe2d5c8
   286 	if ((f_new == FOUNDATION_INVALID) ||
   286 	if ((f_new == FOUNDATION_INVALID) ||
   287 	    ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player))
   287 	    ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player))
   288 	   ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   288 	   ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   289 
   289 
   290 	Foundation f_old = GetRailFoundation(tileh, existing);
   290 	Foundation f_old = GetRailFoundation(tileh, existing);
   291 	return CommandCost(f_new != f_old ? _price.terraform : (Money)0);
   291 	return CommandCost(EXPENSES_CONSTRUCTION, f_new != f_old ? _price.terraform : (Money)0);
   292 }
   292 }
   293 
   293 
   294 /* Validate functions for rail building */
   294 /* Validate functions for rail building */
   295 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);}
   295 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);}
   296 
   296 
   304 {
   304 {
   305 	Slope tileh;
   305 	Slope tileh;
   306 	RailType railtype;
   306 	RailType railtype;
   307 	Track track;
   307 	Track track;
   308 	TrackBits trackbit;
   308 	TrackBits trackbit;
   309 	CommandCost cost;
   309 	CommandCost cost(EXPENSES_CONSTRUCTION);
   310 	CommandCost ret;
   310 	CommandCost ret;
   311 
   311 
   312 	if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
   312 	if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
   313 	railtype = (RailType)p1;
   313 	railtype = (RailType)p1;
   314 	track = (Track)p2;
   314 	track = (Track)p2;
   315 
   315 
   316 	tileh = GetTileSlope(tile, NULL);
   316 	tileh = GetTileSlope(tile, NULL);
   317 	trackbit = TrackToTrackBits(track);
   317 	trackbit = TrackToTrackBits(track);
   318 
       
   319 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   320 
   318 
   321 	switch (GetTileType(tile)) {
   319 	switch (GetTileType(tile)) {
   322 		case MP_RAILWAY:
   320 		case MP_RAILWAY:
   323 			if (!CheckTrackCombination(tile, trackbit, flags) ||
   321 			if (!CheckTrackCombination(tile, trackbit, flags) ||
   324 					!EnsureNoTrainOnTrack(tile, track)) {
   322 					!EnsureNoTrainOnTrack(tile, track)) {
   436  */
   434  */
   437 CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   435 CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   438 {
   436 {
   439 	Track track = (Track)p2;
   437 	Track track = (Track)p2;
   440 	TrackBits trackbit;
   438 	TrackBits trackbit;
   441 	CommandCost cost(_price.remove_rail);
   439 	CommandCost cost(EXPENSES_CONSTRUCTION, _price.remove_rail );
   442 	bool crossing = false;
   440 	bool crossing = false;
   443 
   441 
   444 	if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
   442 	if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
   445 	trackbit = TrackToTrackBits(track);
   443 	trackbit = TrackToTrackBits(track);
   446 
       
   447 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   448 
   444 
   449 	switch (GetTileType(tile)) {
   445 	switch (GetTileType(tile)) {
   450 		case MP_ROAD: {
   446 		case MP_ROAD: {
   451 			if (!IsLevelCrossing(tile) ||
   447 			if (!IsLevelCrossing(tile) ||
   452 					GetCrossingRailBits(tile) != trackbit ||
   448 					GetCrossingRailBits(tile) != trackbit ||
   622  * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum)
   618  * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum)
   623  * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
   619  * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
   624  */
   620  */
   625 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   621 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   626 {
   622 {
   627 	CommandCost ret, total_cost;
   623 	CommandCost ret, total_cost(EXPENSES_CONSTRUCTION);
   628 	Track track = (Track)GB(p2, 4, 3);
   624 	Track track = (Track)GB(p2, 4, 3);
   629 	Trackdir trackdir;
   625 	Trackdir trackdir;
   630 	byte mode = HasBit(p2, 7);
   626 	byte mode = HasBit(p2, 7);
   631 	RailType railtype = (RailType)GB(p2, 0, 4);
   627 	RailType railtype = (RailType)GB(p2, 0, 4);
   632 	TileIndex end_tile;
   628 	TileIndex end_tile;
   633 
   629 
   634 	if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
   630 	if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
   635 	if (p1 >= MapSize()) return CMD_ERROR;
   631 	if (p1 >= MapSize()) return CMD_ERROR;
   636 	end_tile = p1;
   632 	end_tile = p1;
   637 	trackdir = TrackToTrackdir(track);
   633 	trackdir = TrackToTrackdir(track);
   638 
       
   639 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   640 
   634 
   641 	if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
   635 	if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
   642 
   636 
   643 	if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile);
   637 	if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile);
   644 
   638 
   704  * @todo When checking for the tile slope,
   698  * @todo When checking for the tile slope,
   705  * distingush between "Flat land required" and "land sloped in wrong direction"
   699  * distingush between "Flat land required" and "land sloped in wrong direction"
   706  */
   700  */
   707 CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   701 CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   708 {
   702 {
   709 	CommandCost cost;
       
   710 	Slope tileh;
   703 	Slope tileh;
   711 
       
   712 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   713 
   704 
   714 	/* check railtype and valid direction for depot (0 through 3), 4 in total */
   705 	/* check railtype and valid direction for depot (0 through 3), 4 in total */
   715 	if (!ValParamRailtype(p1)) return CMD_ERROR;
   706 	if (!ValParamRailtype(p1)) return CMD_ERROR;
   716 
   707 
   717 	tileh = GetTileSlope(tile, NULL);
   708 	tileh = GetTileSlope(tile, NULL);
   733 				!CanBuildDepotByTileh(dir, tileh)
   724 				!CanBuildDepotByTileh(dir, tileh)
   734 			)) {
   725 			)) {
   735 		return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   726 		return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   736 	}
   727 	}
   737 
   728 
   738 	cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   729 	CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   739 	if (CmdFailed(cost)) return CMD_ERROR;
   730 	if (CmdFailed(cost)) return CMD_ERROR;
   740 
   731 
   741 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   732 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   742 
   733 
   743 	Depot *d = new Depot(tile);
   734 	Depot *d = new Depot(tile);
   804 	}
   795 	}
   805 
   796 
   806 	/* you can not convert a signal if no signal is on track */
   797 	/* you can not convert a signal if no signal is on track */
   807 	if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR;
   798 	if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR;
   808 
   799 
   809 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   810 
       
   811 	if (!HasSignalOnTrack(tile, track)) {
   800 	if (!HasSignalOnTrack(tile, track)) {
   812 		/* build new signals */
   801 		/* build new signals */
   813 		cost = CommandCost(_price.build_signals);
   802 		cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals);
   814 	} else {
   803 	} else {
   815 		if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) {
   804 		if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) {
   816 			/* convert signals <-> semaphores */
   805 			/* convert signals <-> semaphores */
   817 			cost = CommandCost(_price.build_signals + _price.remove_signals);
   806 			cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals);
   818 
   807 
   819 		} else if (convert_signal) {
   808 		} else if (convert_signal) {
   820 			/* convert button pressed */
   809 			/* convert button pressed */
   821 			if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) {
   810 			if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) {
   822 				/* convert electric <-> semaphore */
   811 				/* convert electric <-> semaphore */
   823 				cost = CommandCost(_price.build_signals + _price.remove_signals);
   812 				cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals);
   824 			} else {
   813 			} else {
   825 				/* it is free to change signal type: normal-pre-exit-combo */
   814 				/* it is free to change signal type: normal-pre-exit-combo */
   826 				cost = CommandCost();
   815 				cost = CommandCost();
   827 			}
   816 			}
   828 
   817 
   954  * - p2 = (bit  6)    - 0 = selected stretch, 1 = auto fill
   943  * - p2 = (bit  6)    - 0 = selected stretch, 1 = auto fill
   955  * - p2 = (bit 24-31) - user defined signals_density
   944  * - p2 = (bit 24-31) - user defined signals_density
   956  */
   945  */
   957 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   946 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   958 {
   947 {
   959 	CommandCost ret, total_cost;
   948 	CommandCost ret, total_cost(EXPENSES_CONSTRUCTION);
   960 	int signal_ctr;
   949 	int signal_ctr;
   961 	byte signals;
   950 	byte signals;
   962 	bool error = true;
   951 	bool error = true;
   963 	TileIndex end_tile;
   952 	TileIndex end_tile;
   964 	TileIndex start_tile = tile;
   953 	TileIndex start_tile = tile;
   974 	if (p1 >= MapSize()) return CMD_ERROR;
   963 	if (p1 >= MapSize()) return CMD_ERROR;
   975 	end_tile = p1;
   964 	end_tile = p1;
   976 	if (signal_density == 0 || signal_density > 20) return CMD_ERROR;
   965 	if (signal_density == 0 || signal_density > 20) return CMD_ERROR;
   977 
   966 
   978 	if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR;
   967 	if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR;
   979 
       
   980 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   981 
   968 
   982 	/* for vertical/horizontal tracks, double the given signals density
   969 	/* for vertical/horizontal tracks, double the given signals density
   983 	 * since the original amount will be too dense (shorter tracks) */
   970 	 * since the original amount will be too dense (shorter tracks) */
   984 	signal_density *= 2;
   971 	signal_density *= 2;
   985 
   972 
  1099 	}
  1086 	}
  1100 
  1087 
  1101 	/* Only water can remove signals from anyone */
  1088 	/* Only water can remove signals from anyone */
  1102 	if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR;
  1089 	if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR;
  1103 
  1090 
  1104 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
  1105 
       
  1106 	/* Do it? */
  1091 	/* Do it? */
  1107 	if (flags & DC_EXEC) {
  1092 	if (flags & DC_EXEC) {
  1108 		SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
  1093 		SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
  1109 
  1094 
  1110 		/* removed last signal from tile? */
  1095 		/* removed last signal from tile? */
  1118 		YapfNotifyTrackLayoutChange(tile, track);
  1103 		YapfNotifyTrackLayoutChange(tile, track);
  1119 
  1104 
  1120 		MarkTileDirtyByTile(tile);
  1105 		MarkTileDirtyByTile(tile);
  1121 	}
  1106 	}
  1122 
  1107 
  1123 	return CommandCost(_price.remove_signals);
  1108 	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_signals);
  1124 }
  1109 }
  1125 
  1110 
  1126 /** Remove signals on a stretch of track.
  1111 /** Remove signals on a stretch of track.
  1127  * Stub for the unified signal builder/remover
  1112  * Stub for the unified signal builder/remover
  1128  * @param tile start tile of drag
  1113  * @param tile start tile of drag
  1162  * @param p1 start tile of drag
  1147  * @param p1 start tile of drag
  1163  * @param p2 new railtype to convert to
  1148  * @param p2 new railtype to convert to
  1164  */
  1149  */
  1165 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1150 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1166 {
  1151 {
  1167 	CommandCost cost;
  1152 	CommandCost cost(EXPENSES_CONSTRUCTION);
  1168 
  1153 
  1169 	if (!ValParamRailtype(p2)) return CMD_ERROR;
  1154 	if (!ValParamRailtype(p2)) return CMD_ERROR;
  1170 	if (p1 >= MapSize()) return CMD_ERROR;
  1155 	if (p1 >= MapSize()) return CMD_ERROR;
  1171 
  1156 
  1172 	RailType totype = (RailType)p2;
  1157 	RailType totype = (RailType)p2;
  1177 	uint sy = TileY(p1);
  1162 	uint sy = TileY(p1);
  1178 
  1163 
  1179 	/* make sure sx,sy are smaller than ex,ey */
  1164 	/* make sure sx,sy are smaller than ex,ey */
  1180 	if (ex < sx) Swap(ex, sx);
  1165 	if (ex < sx) Swap(ex, sx);
  1181 	if (ey < sy) Swap(ey, sy);
  1166 	if (ey < sy) Swap(ey, sy);
  1182 
       
  1183 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
  1184 
  1167 
  1185 	_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert
  1168 	_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert
  1186 
  1169 
  1187 	for (uint x = sx; x <= ex; ++x) {
  1170 	for (uint x = sx; x <= ex; ++x) {
  1188 		for (uint y = sy; y <= ey; ++y) {
  1171 		for (uint y = sy; y <= ey; ++y) {
  1329 		delete GetDepotByTile(tile);
  1312 		delete GetDepotByTile(tile);
  1330 		UpdateSignalsOnSegment(tile, dir);
  1313 		UpdateSignalsOnSegment(tile, dir);
  1331 		YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
  1314 		YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
  1332 	}
  1315 	}
  1333 
  1316 
  1334 	return CommandCost(_price.remove_train_depot);
  1317 	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot);
  1335 }
  1318 }
  1336 
  1319 
  1337 static CommandCost ClearTile_Track(TileIndex tile, byte flags)
  1320 static CommandCost ClearTile_Track(TileIndex tile, byte flags)
  1338 {
  1321 {
  1339 	CommandCost cost;
  1322 	CommandCost cost(EXPENSES_CONSTRUCTION);
  1340 	CommandCost ret;
  1323 	CommandCost ret;
  1341 
  1324 
  1342 	if (flags & DC_AUTO) {
  1325 	if (flags & DC_AUTO) {
  1343 		if (!IsTileOwner(tile, _current_player))
  1326 		if (!IsTileOwner(tile, _current_player))
  1344 			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
  1327 			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
  2431 		case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
  2414 		case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
  2432 		case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
  2415 		case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
  2433 		case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
  2416 		case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
  2434 
  2417 
  2435 		/* Surface slope must not be changed */
  2418 		/* Surface slope must not be changed */
  2436 		default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform);
  2419 		default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : CommandCost(EXPENSES_CONSTRUCTION, _price.terraform));
  2437 	}
  2420 	}
  2438 
  2421 
  2439 	/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
  2422 	/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
  2440 	z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner);
  2423 	z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner);
  2441 	z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner);
  2424 	z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner);
  2442 	if (z_old != z_new) return CMD_ERROR;
  2425 	if (z_old != z_new) return CMD_ERROR;
  2443 
  2426 
  2444 	CommandCost cost = CommandCost(_price.terraform);
  2427 	CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
  2445 	/* Make the ground dirty, if surface slope has changed */
  2428 	/* Make the ground dirty, if surface slope has changed */
  2446 	if (tileh_old != tileh_new) {
  2429 	if (tileh_old != tileh_new) {
  2447 		if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water);
  2430 		if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water);
  2448 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2431 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2449 	}
  2432 	}
  2486 
  2469 
  2487 		/* Make the ground dirty */
  2470 		/* Make the ground dirty */
  2488 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2471 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2489 
  2472 
  2490 		/* allow terraforming */
  2473 		/* allow terraforming */
  2491 		return (was_water ? CommandCost(_price.clear_water) : CommandCost());
  2474 		return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0);
  2492 	} else {
  2475 	} else {
  2493 		if (_patches.build_on_slopes && AutoslopeEnabled()) {
  2476 		if (_patches.build_on_slopes && AutoslopeEnabled()) {
  2494 			switch (GetRailTileType(tile)) {
  2477 			switch (GetRailTileType(tile)) {
  2495 				case RAIL_TILE_WAYPOINT: {
  2478 				case RAIL_TILE_WAYPOINT: {
  2496 					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
  2479 					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
  2497 					if (!CmdFailed(cost)) return cost; // allow autoslope
  2480 					if (!CmdFailed(cost)) return cost; // allow autoslope
  2498 					break;
  2481 					break;
  2499 				}
  2482 				}
  2500 
  2483 
  2501 				case RAIL_TILE_DEPOT:
  2484 				case RAIL_TILE_DEPOT:
  2502 					if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return _price.terraform;
  2485 					if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
  2503 					break;
  2486 					break;
  2504 
  2487 
  2505 				default: NOT_REACHED();
  2488 				default: NOT_REACHED();
  2506 			}
  2489 			}
  2507 		}
  2490 		}