src/rail_cmd.cpp
changeset 8035 a0200ced6d9f
parent 7990 70039e33e893
child 8078 bdf94bf88568
equal deleted inserted replaced
8034:0f6a176ce1e9 8035:a0200ced6d9f
    32 #include "window.h"
    32 #include "window.h"
    33 #include "rail.h"
    33 #include "rail.h"
    34 #include "railtypes.h" // include table for railtypes
    34 #include "railtypes.h" // include table for railtypes
    35 #include "newgrf.h"
    35 #include "newgrf.h"
    36 #include "yapf/yapf.h"
    36 #include "yapf/yapf.h"
       
    37 #include "newgrf_engine.h"
    37 #include "newgrf_callbacks.h"
    38 #include "newgrf_callbacks.h"
    38 #include "newgrf_station.h"
    39 #include "newgrf_station.h"
    39 #include "train.h"
    40 #include "train.h"
    40 #include "misc/autoptr.hpp"
    41 #include "misc/autoptr.hpp"
    41 
    42 
  1022 	return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 5)); // bit 5 is remove bit
  1023 	return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 5)); // bit 5 is remove bit
  1023 }
  1024 }
  1024 
  1025 
  1025 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
  1026 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
  1026 
  1027 
       
  1028 void *UpdateTrainPowerProc(Vehicle *v, void *data)
       
  1029 {
       
  1030 	/* Similiar checks as in TrainPowerChanged() */
       
  1031 
       
  1032 	if (v->type == VEH_TRAIN && v->tile == *(TileIndex*)data && !IsArticulatedPart(v)) {
       
  1033 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
       
  1034 		if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First());
       
  1035 	}
       
  1036 
       
  1037 	return NULL;
       
  1038 }
       
  1039 
  1027 /**
  1040 /**
  1028  * Switches the rail type.
  1041  * Switches the rail type.
  1029  * Railtypes are stored on a per-tile basis, not on a per-track basis, so
  1042  * Railtypes are stored on a per-tile basis, not on a per-track basis, so
  1030  * all the tracks in the given tile will be converted.
  1043  * all the tracks in the given tile will be converted.
  1031  * @param tile        The tile on which the railtype is to be convert.
  1044  * @param tile        The tile on which the railtype is to be convert.
  1034  * @return            The cost and state of the operation
  1047  * @return            The cost and state of the operation
  1035  * @retval CMD_ERROR  An error occured during the operation.
  1048  * @retval CMD_ERROR  An error occured during the operation.
  1036  */
  1049  */
  1037 static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec)
  1050 static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec)
  1038 {
  1051 {
  1039 	if (!CheckTileOwnership(tile)) return CMD_ERROR;
       
  1040 
       
  1041 	if (GetRailType(tile) == totype) return CMD_ERROR;
       
  1042 
       
  1043 	if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR;
       
  1044 
       
  1045 	/* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */
       
  1046 	if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR;
       
  1047 
       
  1048 	/* change type. */
  1052 	/* change type. */
  1049 	if (exec) {
  1053 	if (exec) {
  1050 		SetRailType(tile, totype);
  1054 		SetRailType(tile, totype);
  1051 		MarkTileDirtyByTile(tile);
  1055 		MarkTileDirtyByTile(tile);
  1052 
  1056 
  1055 		while (tracks != TRACK_BIT_NONE) {
  1059 		while (tracks != TRACK_BIT_NONE) {
  1056 			YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
  1060 			YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
  1057 		}
  1061 		}
  1058 
  1062 
  1059 		if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
  1063 		if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
  1060 			Vehicle *v;
       
  1061 
       
  1062 			/* Update build vehicle window related to this depot */
  1064 			/* Update build vehicle window related to this depot */
  1063 			InvalidateWindowData(WC_BUILD_VEHICLE, tile);
  1065 			InvalidateWindowData(WC_BUILD_VEHICLE, tile);
  1064 
  1066 		}
  1065 			/* update power of trains in this depot */
  1067 
  1066 			FOR_ALL_VEHICLES(v) {
  1068 		/* update power of train engines on this tile */
  1067 				if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == tile && v->u.rail.track == 0x80) {
  1069 		VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
  1068 					TrainPowerChanged(v);
       
  1069 				}
       
  1070 			}
       
  1071 		}
       
  1072 	}
  1070 	}
  1073 
  1071 
  1074 	return CommandCost(_price.build_rail / 2);
  1072 	return CommandCost(_price.build_rail / 2);
  1075 }
  1073 }
  1076 
  1074 
  1109 	money = GetAvailableMoneyForCommand();
  1107 	money = GetAvailableMoneyForCommand();
  1110 
  1108 
  1111 	for (x = sx; x <= ex; ++x) {
  1109 	for (x = sx; x <= ex; ++x) {
  1112 		for (y = sy; y <= ey; ++y) {
  1110 		for (y = sy; y <= ey; ++y) {
  1113 			TileIndex tile = TileXY(x, y);
  1111 			TileIndex tile = TileXY(x, y);
  1114 			DoConvertRailProc* proc;
  1112 			DoConvertRailProc *proc;
       
  1113 			RailType totype = (RailType)p2;
  1115 
  1114 
  1116 			switch (GetTileType(tile)) {
  1115 			switch (GetTileType(tile)) {
  1117 				case MP_RAILWAY:      proc = DoConvertRail;             break;
  1116 				case MP_RAILWAY:      proc = DoConvertRail;             break;
  1118 				case MP_STATION:      proc = DoConvertStationRail;      break;
  1117 				case MP_STATION:      proc = DoConvertStationRail;      break;
  1119 				case MP_ROAD:         proc = DoConvertStreetRail;       break;
  1118 				case MP_ROAD:         proc = DoConvertStreetRail;       break;
  1120 				case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break;
  1119 				case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break;
  1121 				default: continue;
  1120 				default: continue;
  1122 			}
  1121 			}
  1123 
  1122 
  1124 			ret = proc(tile, (RailType)p2, false);
  1123 			/* It is possible that 'type' is invalid when there is no rail on the tile,
       
  1124 			 * but this situation will be detected in proc()
       
  1125 			 */
       
  1126 			RailType type = GetRailType(tile);
       
  1127 
       
  1128 			/* Not own tile or track is already converted */
       
  1129 			if ((!CheckTileOwnership(tile) || type == totype) ||
       
  1130 				/* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */
       
  1131 				(_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC) ||
       
  1132 				/* Vehicle on a tile while not converting Rail <-> ElRail */
       
  1133 				(!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile))) {
       
  1134 					ret = CMD_ERROR;
       
  1135 					continue;
       
  1136 			}
       
  1137 
       
  1138 			ret = proc(tile, totype, false);
  1125 			if (CmdFailed(ret)) continue;
  1139 			if (CmdFailed(ret)) continue;
  1126 
  1140 
  1127 			if (flags & DC_EXEC) {
  1141 			if (flags & DC_EXEC) {
  1128 				money -= ret.GetCost();
  1142 				money -= ret.GetCost();
  1129 				if (money < 0) {
  1143 				if (money < 0) {
  1130 					_additional_cash_required = ret.GetCost();
  1144 					_additional_cash_required = ret.GetCost();
  1131 					return cost;
  1145 					return cost;
  1132 				}
  1146 				}
  1133 				proc(tile, (RailType)p2, true);
  1147 				proc(tile, totype, true);
  1134 			}
  1148 			}
  1135 			cost.AddCost(ret);
  1149 			cost.AddCost(ret);
  1136 		}
  1150 		}
  1137 	}
  1151 	}
  1138 
  1152