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 */ |