77 * 11uuuudd => rail depot |
77 * 11uuuudd => rail depot |
78 */ |
78 */ |
79 |
79 |
80 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags) |
80 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags) |
81 { |
81 { |
82 TrackBits current; /* The current track layout */ |
82 TrackBits current; // The current track layout |
83 TrackBits future; /* The track layout we want to build */ |
83 TrackBits future; // The track layout we want to build |
84 _error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION; |
84 _error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION; |
85 |
85 |
86 if (!IsPlainRailTile(tile)) return false; |
86 if (!IsPlainRailTile(tile)) return false; |
87 |
87 |
88 /* So, we have a tile with tracks on it (and possibly signals). Let's see |
88 /* So, we have a tile with tracks on it (and possibly signals). Let's see |
197 if (valid & rail_bits) return _price.terraform; |
197 if (valid & rail_bits) return _price.terraform; |
198 } |
198 } |
199 } else { |
199 } else { |
200 rail_bits |= existing; |
200 rail_bits |= existing; |
201 |
201 |
202 // don't allow building on the lower side of a coast |
202 /* don't allow building on the lower side of a coast */ |
203 if (IsTileType(tile, MP_WATER) && |
203 if (IsTileType(tile, MP_WATER) && |
204 ~_valid_tileh_slopes[1][tileh] & rail_bits) { |
204 ~_valid_tileh_slopes[1][tileh] & rail_bits) { |
205 return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
205 return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
206 } |
206 } |
207 |
207 |
208 // no special foundation |
208 /* no special foundation */ |
209 if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0) |
209 if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0) |
210 return 0; |
210 return 0; |
211 |
211 |
212 if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up |
212 if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up |
213 (rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) && |
213 (rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) && |
257 !EnsureNoVehicleOnGround(tile)) { |
257 !EnsureNoVehicleOnGround(tile)) { |
258 return CMD_ERROR; |
258 return CMD_ERROR; |
259 } |
259 } |
260 if (!IsTileOwner(tile, _current_player) || |
260 if (!IsTileOwner(tile, _current_player) || |
261 !IsCompatibleRail(GetRailType(tile), railtype)) { |
261 !IsCompatibleRail(GetRailType(tile), railtype)) { |
262 // Get detailed error message |
262 /* Get detailed error message */ |
263 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
263 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
264 } |
264 } |
265 |
265 |
266 ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile); |
266 ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile); |
267 if (CmdFailed(ret)) return ret; |
267 if (CmdFailed(ret)) return ret; |
432 int ey = TileY(end); |
432 int ey = TileY(end); |
433 int dx, dy, trdx, trdy; |
433 int dx, dy, trdx, trdy; |
434 |
434 |
435 if (!ValParamTrackOrientation(TrackdirToTrack(*trackdir))) return CMD_ERROR; |
435 if (!ValParamTrackOrientation(TrackdirToTrack(*trackdir))) return CMD_ERROR; |
436 |
436 |
437 // calculate delta x,y from start to end tile |
437 /* calculate delta x,y from start to end tile */ |
438 dx = ex - x; |
438 dx = ex - x; |
439 dy = ey - y; |
439 dy = ey - y; |
440 |
440 |
441 // calculate delta x,y for the first direction |
441 /* calculate delta x,y for the first direction */ |
442 trdx = _trackdelta[*trackdir].x; |
442 trdx = _trackdelta[*trackdir].x; |
443 trdy = _trackdelta[*trackdir].y; |
443 trdy = _trackdelta[*trackdir].y; |
444 |
444 |
445 if (!IsDiagonalTrackdir(*trackdir)) { |
445 if (!IsDiagonalTrackdir(*trackdir)) { |
446 trdx += _trackdelta[*trackdir ^ 1].x; |
446 trdx += _trackdelta[*trackdir ^ 1].x; |
447 trdy += _trackdelta[*trackdir ^ 1].y; |
447 trdy += _trackdelta[*trackdir ^ 1].y; |
448 } |
448 } |
449 |
449 |
450 // validate the direction |
450 /* validate the direction */ |
451 while ( |
451 while ( |
452 (trdx <= 0 && dx > 0) || |
452 (trdx <= 0 && dx > 0) || |
453 (trdx >= 0 && dx < 0) || |
453 (trdx >= 0 && dx < 0) || |
454 (trdy <= 0 && dy > 0) || |
454 (trdy <= 0 && dy > 0) || |
455 (trdy >= 0 && dy < 0) |
455 (trdy >= 0 && dy < 0) |
461 } else { // other direction is invalid too, invalid drag |
461 } else { // other direction is invalid too, invalid drag |
462 return CMD_ERROR; |
462 return CMD_ERROR; |
463 } |
463 } |
464 } |
464 } |
465 |
465 |
466 // (for diagonal tracks, this is already made sure of by above test), but: |
466 /* (for diagonal tracks, this is already made sure of by above test), but: |
467 // for non-diagonal tracks, check if the start and end tile are on 1 line |
467 * for non-diagonal tracks, check if the start and end tile are on 1 line */ |
468 if (!IsDiagonalTrackdir(*trackdir)) { |
468 if (!IsDiagonalTrackdir(*trackdir)) { |
469 trdx = _trackdelta[*trackdir].x; |
469 trdx = _trackdelta[*trackdir].x; |
470 trdy = _trackdelta[*trackdir].y; |
470 trdy = _trackdelta[*trackdir].y; |
471 if (abs(dx) != abs(dy) && abs(dx) + abs(trdy) != abs(dy) + abs(trdx)) |
471 if (abs(dx) != abs(dy) && abs(dx) + abs(trdy) != abs(dy) + abs(trdx)) |
472 return CMD_ERROR; |
472 return CMD_ERROR; |
515 |
515 |
516 if (tile == end_tile) break; |
516 if (tile == end_tile) break; |
517 |
517 |
518 tile += ToTileIndexDiff(_trackdelta[trackdir]); |
518 tile += ToTileIndexDiff(_trackdelta[trackdir]); |
519 |
519 |
520 // toggle railbit for the non-diagonal tracks |
520 /* toggle railbit for the non-diagonal tracks */ |
521 if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0); |
521 if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0); |
522 } |
522 } |
523 |
523 |
524 return (total_cost == 0) ? CMD_ERROR : total_cost; |
524 return (total_cost == 0) ? CMD_ERROR : total_cost; |
525 } |
525 } |
647 } |
647 } |
648 |
648 |
649 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
649 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
650 |
650 |
651 if (!HasSignalOnTrack(tile, track)) { |
651 if (!HasSignalOnTrack(tile, track)) { |
652 // build new signals |
652 /* build new signals */ |
653 cost = _price.build_signals; |
653 cost = _price.build_signals; |
654 } else { |
654 } else { |
655 if (p2 != 0 && sigvar != GetSignalVariant(tile)) { |
655 if (p2 != 0 && sigvar != GetSignalVariant(tile)) { |
656 // convert signals <-> semaphores |
656 /* convert signals <-> semaphores */ |
657 cost = _price.build_signals + _price.remove_signals; |
657 cost = _price.build_signals + _price.remove_signals; |
658 } else { |
658 } else { |
659 // it is free to change orientation/pre-exit-combo signals |
659 // it is free to change orientation/pre-exit-combo signals |
660 cost = 0; |
660 cost = 0; |
661 } |
661 } |
662 } |
662 } |
663 |
663 |
664 if (flags & DC_EXEC) { |
664 if (flags & DC_EXEC) { |
665 if (!HasSignals(tile)) { |
665 if (!HasSignals(tile)) { |
666 // there are no signals at all on this tile yet |
666 /* there are no signals at all on this tile yet */ |
667 SetHasSignals(tile, true); |
667 SetHasSignals(tile, true); |
668 _m[tile].m2 |= 0xF0; // all signals are on |
668 _m[tile].m2 |= 0xF0; // all signals are on |
669 _m[tile].m3 &= ~0xF0; // no signals built by default |
669 _m[tile].m3 &= ~0xF0; // no signals built by default |
670 SetSignalType(tile, SIGTYPE_NORMAL); |
670 SetSignalType(tile, SIGTYPE_NORMAL); |
671 SetSignalVariant(tile, sigvar); |
671 SetSignalVariant(tile, sigvar); |
672 } |
672 } |
673 |
673 |
674 if (p2 == 0) { |
674 if (p2 == 0) { |
675 if (!HasSignalOnTrack(tile, track)) { |
675 if (!HasSignalOnTrack(tile, track)) { |
676 // build new signals |
676 /* build new signals */ |
677 _m[tile].m3 |= SignalOnTrack(track); |
677 _m[tile].m3 |= SignalOnTrack(track); |
678 } else { |
678 } else { |
679 if (pre_signal) { |
679 if (pre_signal) { |
680 // cycle between normal -> pre -> exit -> combo -> ... |
680 /* cycle between normal -> pre -> exit -> combo -> ... */ |
681 SignalType type = GetSignalType(tile); |
681 SignalType type = GetSignalType(tile); |
682 |
682 |
683 SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1)); |
683 SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1)); |
684 } else { |
684 } else { |
685 CycleSignalSide(tile, track); |
685 CycleSignalSide(tile, track); |
744 // copy the signal-style of the first rail-piece if existing |
744 // copy the signal-style of the first rail-piece if existing |
745 if (HasSignals(tile)) { |
745 if (HasSignals(tile)) { |
746 signals = _m[tile].m3 & SignalOnTrack(track); |
746 signals = _m[tile].m3 & SignalOnTrack(track); |
747 if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */ |
747 if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */ |
748 |
748 |
749 // copy signal/semaphores style (independent of CTRL) |
749 /* copy signal/semaphores style (independent of CTRL) */ |
750 semaphores = GetSignalVariant(tile) != SIG_ELECTRIC; |
750 semaphores = GetSignalVariant(tile) != SIG_ELECTRIC; |
751 } else { // no signals exist, drag a two-way signal stretch |
751 } else { // no signals exist, drag a two-way signal stretch |
752 signals = SignalOnTrack(track); |
752 signals = SignalOnTrack(track); |
753 } |
753 } |
754 |
754 |
760 * signals - is there a signal/semaphore on the first tile, copy its style (two-way/single-way) |
760 * signals - is there a signal/semaphore on the first tile, copy its style (two-way/single-way) |
761 * and convert all others to semaphore/signal |
761 * and convert all others to semaphore/signal |
762 * remove - 1 remove signals, 0 build signals */ |
762 * remove - 1 remove signals, 0 build signals */ |
763 signal_ctr = total_cost = 0; |
763 signal_ctr = total_cost = 0; |
764 for (;;) { |
764 for (;;) { |
765 // only build/remove signals with the specified density |
765 /* only build/remove signals with the specified density */ |
766 if (signal_ctr % signal_density == 0) { |
766 if (signal_ctr % signal_density == 0) { |
767 uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3); |
767 uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3); |
768 SB(p1, 3, 1, mode); |
768 SB(p1, 3, 1, mode); |
769 SB(p1, 4, 1, semaphores); |
769 SB(p1, 4, 1, semaphores); |
770 ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); |
770 ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); |
779 if (tile == end_tile) break; |
779 if (tile == end_tile) break; |
780 |
780 |
781 tile += ToTileIndexDiff(_trackdelta[trackdir]); |
781 tile += ToTileIndexDiff(_trackdelta[trackdir]); |
782 signal_ctr++; |
782 signal_ctr++; |
783 |
783 |
784 // toggle railbit for the non-diagonal tracks (|, -- tracks) |
784 /* toggle railbit for the non-diagonal tracks (|, -- tracks) */ |
785 if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0); |
785 if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0); |
786 } |
786 } |
787 |
787 |
788 return error ? CMD_ERROR : total_cost; |
788 return error ? CMD_ERROR : total_cost; |
789 } |
789 } |
867 |
867 |
868 if (GetRailType(tile) == totype) return CMD_ERROR; |
868 if (GetRailType(tile) == totype) return CMD_ERROR; |
869 |
869 |
870 if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR; |
870 if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR; |
871 |
871 |
872 // 'hidden' elrails can't be downgraded to normal rail when elrails are disabled |
872 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
873 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
873 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
874 |
874 |
875 // change type. |
875 /* change type. */ |
876 if (exec) { |
876 if (exec) { |
877 SetRailType(tile, totype); |
877 SetRailType(tile, totype); |
878 MarkTileDirtyByTile(tile); |
878 MarkTileDirtyByTile(tile); |
879 |
879 |
880 // notify YAPF about the track layout change |
880 /* notify YAPF about the track layout change */ |
881 TrackBits tracks = GetTrackBits(tile); |
881 TrackBits tracks = GetTrackBits(tile); |
882 while (tracks != TRACK_BIT_NONE) { |
882 while (tracks != TRACK_BIT_NONE) { |
883 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks)); |
883 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks)); |
884 } |
884 } |
885 |
885 |
921 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
921 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
922 |
922 |
923 if (!ValParamRailtype(p2)) return CMD_ERROR; |
923 if (!ValParamRailtype(p2)) return CMD_ERROR; |
924 if (p1 >= MapSize()) return CMD_ERROR; |
924 if (p1 >= MapSize()) return CMD_ERROR; |
925 |
925 |
926 // make sure sx,sy are smaller than ex,ey |
926 /* make sure sx,sy are smaller than ex,ey */ |
927 ex = TileX(tile); |
927 ex = TileX(tile); |
928 ey = TileY(tile); |
928 ey = TileY(tile); |
929 sx = TileX(p1); |
929 sx = TileX(p1); |
930 sy = TileY(p1); |
930 sy = TileY(p1); |
931 if (ex < sx) Swap(ex, sx); |
931 if (ex < sx) Swap(ex, sx); |
1186 const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); |
1186 const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); |
1187 SpriteID image; |
1187 SpriteID image; |
1188 SpriteID pal = PAL_NONE; |
1188 SpriteID pal = PAL_NONE; |
1189 bool junction = false; |
1189 bool junction = false; |
1190 |
1190 |
1191 // Select the sprite to use. |
1191 /* Select the sprite to use. */ |
1192 (image = rti->base_sprites.track_y, track == TRACK_BIT_Y) || |
1192 (image = rti->base_sprites.track_y, track == TRACK_BIT_Y) || |
1193 (image++, track == TRACK_BIT_X) || |
1193 (image++, track == TRACK_BIT_X) || |
1194 (image++, track == TRACK_BIT_UPPER) || |
1194 (image++, track == TRACK_BIT_UPPER) || |
1195 (image++, track == TRACK_BIT_LOWER) || |
1195 (image++, track == TRACK_BIT_LOWER) || |
1196 (image++, track == TRACK_BIT_RIGHT) || |
1196 (image++, track == TRACK_BIT_RIGHT) || |
1210 if (ti->tileh != SLOPE_FLAT) { |
1210 if (ti->tileh != SLOPE_FLAT) { |
1211 uint foundation = GetRailFoundation(ti->tileh, track); |
1211 uint foundation = GetRailFoundation(ti->tileh, track); |
1212 |
1212 |
1213 if (foundation != 0) DrawFoundation(ti, foundation); |
1213 if (foundation != 0) DrawFoundation(ti, foundation); |
1214 |
1214 |
1215 // DrawFoundation() modifies ti. |
1215 /* DrawFoundation() modifies it. |
1216 // Default sloped sprites.. |
1216 * Default sloped sprites.. */ |
1217 if (ti->tileh != SLOPE_FLAT) |
1217 if (ti->tileh != SLOPE_FLAT) |
1218 image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y; |
1218 image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y; |
1219 } |
1219 } |
1220 |
1220 |
1221 switch (GetRailGroundType(ti->tile)) { |
1221 switch (GetRailGroundType(ti->tile)) { |
1224 default: break; |
1224 default: break; |
1225 } |
1225 } |
1226 |
1226 |
1227 DrawGroundSprite(image, pal); |
1227 DrawGroundSprite(image, pal); |
1228 |
1228 |
1229 // Draw track pieces individually for junction tiles |
1229 /* Draw track pieces individually for junction tiles */ |
1230 if (junction) { |
1230 if (junction) { |
1231 if (track & TRACK_BIT_X) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE); |
1231 if (track & TRACK_BIT_X) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE); |
1232 if (track & TRACK_BIT_Y) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE); |
1232 if (track & TRACK_BIT_Y) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE); |
1233 if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE); |
1233 if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE); |
1234 if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE); |
1234 if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE); |
1286 |
1286 |
1287 if (_display_opt & DO_FULL_DETAIL) DrawTrackDetails(ti); |
1287 if (_display_opt & DO_FULL_DETAIL) DrawTrackDetails(ti); |
1288 |
1288 |
1289 if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails); |
1289 if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails); |
1290 } else { |
1290 } else { |
1291 // draw depot/waypoint |
1291 /* draw depot/waypoint */ |
1292 const DrawTileSprites* dts; |
1292 const DrawTileSprites* dts; |
1293 const DrawTileSeqStruct* dtss; |
1293 const DrawTileSeqStruct* dtss; |
1294 uint32 relocation; |
1294 uint32 relocation; |
1295 |
1295 |
1296 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh); |
1296 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh); |
1301 relocation = rti->total_offset; |
1301 relocation = rti->total_offset; |
1302 |
1302 |
1303 image = dts->ground_sprite; |
1303 image = dts->ground_sprite; |
1304 if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset; |
1304 if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset; |
1305 |
1305 |
1306 // adjust ground tile for desert |
1306 /* adjust ground tile for desert |
1307 // don't adjust for snow, because snow in depots looks weird |
1307 * don't adjust for snow, because snow in depots looks weird */ |
1308 if (IsSnowRailGround(ti->tile) && _opt.landscape == LT_TROPIC) { |
1308 if (IsSnowRailGround(ti->tile) && _opt.landscape == LT_TROPIC) { |
1309 if (image != SPR_FLAT_GRASS_TILE) { |
1309 if (image != SPR_FLAT_GRASS_TILE) { |
1310 image += rti->snow_offset; // tile with tracks |
1310 image += rti->snow_offset; // tile with tracks |
1311 } else { |
1311 } else { |
1312 image = SPR_FLAT_SNOWY_TILE; // flat ground |
1312 image = SPR_FLAT_SNOWY_TILE; // flat ground |
1313 } |
1313 } |
1314 } |
1314 } |
1315 } else { |
1315 } else { |
1316 // look for customization |
1316 /* look for customization */ |
1317 byte stat_id = GetWaypointByTile(ti->tile)->stat_id; |
1317 byte stat_id = GetWaypointByTile(ti->tile)->stat_id; |
1318 const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, stat_id); |
1318 const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, stat_id); |
1319 |
1319 |
1320 if (statspec != NULL) { |
1320 if (statspec != NULL) { |
1321 // emulate station tile - open with building |
1321 /* emulate station tile - open with building */ |
1322 const Station* st = ComposeWaypointStation(ti->tile); |
1322 const Station* st = ComposeWaypointStation(ti->tile); |
1323 uint gfx = 2; |
1323 uint gfx = 2; |
1324 |
1324 |
1325 if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) { |
1325 if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) { |
1326 uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile); |
1326 uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile); |
1346 } else { |
1346 } else { |
1347 goto default_waypoint; |
1347 goto default_waypoint; |
1348 } |
1348 } |
1349 } else { |
1349 } else { |
1350 default_waypoint: |
1350 default_waypoint: |
1351 // There is no custom layout, fall back to the default graphics |
1351 /* There is no custom layout, fall back to the default graphics */ |
1352 dts = &_waypoint_gfx_table[GetWaypointAxis(ti->tile)]; |
1352 dts = &_waypoint_gfx_table[GetWaypointAxis(ti->tile)]; |
1353 relocation = 0; |
1353 relocation = 0; |
1354 image = dts->ground_sprite + rti->total_offset; |
1354 image = dts->ground_sprite + rti->total_offset; |
1355 if (IsSnowRailGround(ti->tile)) image += rti->snow_offset; |
1355 if (IsSnowRailGround(ti->tile)) image += rti->snow_offset; |
1356 } |
1356 } |
1433 int cur; |
1433 int cur; |
1434 int cur_stack; |
1434 int cur_stack; |
1435 bool stop; |
1435 bool stop; |
1436 bool has_presignal; |
1436 bool has_presignal; |
1437 |
1437 |
1438 // presignal info |
1438 /* presignal info */ |
1439 int presignal_exits; |
1439 int presignal_exits; |
1440 int presignal_exits_free; |
1440 int presignal_exits_free; |
1441 |
1441 |
1442 // these are used to keep track of the signals that change. |
1442 /* these are used to keep track of the signals that change. */ |
1443 TrackdirByte bit[NUM_SSD_ENTRY]; |
1443 TrackdirByte bit[NUM_SSD_ENTRY]; |
1444 TileIndex tile[NUM_SSD_ENTRY]; |
1444 TileIndex tile[NUM_SSD_ENTRY]; |
1445 |
1445 |
1446 // these are used to keep track of the stack that modifies presignals recursively |
1446 /* these are used to keep track of the stack that modifies presignals recursively */ |
1447 TileIndex next_tile[NUM_SSD_STACK]; |
1447 TileIndex next_tile[NUM_SSD_STACK]; |
1448 DiagDirectionByte next_dir[NUM_SSD_STACK]; |
1448 DiagDirectionByte next_dir[NUM_SSD_STACK]; |
1449 |
1449 |
1450 }; |
1450 }; |
1451 |
1451 |
1453 { |
1453 { |
1454 SetSignalsData* ssd = (SetSignalsData*)data; |
1454 SetSignalsData* ssd = (SetSignalsData*)data; |
1455 |
1455 |
1456 if (!IsTileType(tile, MP_RAILWAY)) return false; |
1456 if (!IsTileType(tile, MP_RAILWAY)) return false; |
1457 |
1457 |
1458 // the tile has signals? |
1458 /* the tile has signals? */ |
1459 if (HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) { |
1459 if (HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) { |
1460 if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) { |
1460 if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) { |
1461 // yes, add the signal to the list of signals |
1461 /* yes, add the signal to the list of signals */ |
1462 if (ssd->cur != NUM_SSD_ENTRY) { |
1462 if (ssd->cur != NUM_SSD_ENTRY) { |
1463 ssd->tile[ssd->cur] = tile; // remember the tile index |
1463 ssd->tile[ssd->cur] = tile; // remember the tile index |
1464 ssd->bit[ssd->cur] = trackdir; // and the controlling bit number |
1464 ssd->bit[ssd->cur] = trackdir; // and the controlling bit number |
1465 ssd->cur++; |
1465 ssd->cur++; |
1466 } |
1466 } |
1467 |
1467 |
1468 // remember if this block has a presignal. |
1468 /* remember if this block has a presignal. */ |
1469 ssd->has_presignal |= IsPresignalEntry(tile); |
1469 ssd->has_presignal |= IsPresignalEntry(tile); |
1470 } |
1470 } |
1471 |
1471 |
1472 if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile)) { |
1472 if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile)) { |
1473 // this is an exit signal that points out from the segment |
1473 /* this is an exit signal that points out from the segment */ |
1474 ssd->presignal_exits++; |
1474 ssd->presignal_exits++; |
1475 if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED) |
1475 if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED) |
1476 ssd->presignal_exits_free++; |
1476 ssd->presignal_exits_free++; |
1477 } |
1477 } |
1478 |
1478 |
1526 direction = GetBridgeRampDirection(tile); |
1526 direction = GetBridgeRampDirection(tile); |
1527 } |
1527 } |
1528 |
1528 |
1529 dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible) |
1529 dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible) |
1530 |
1530 |
1531 // check for a vehicle with that trackdir on the start tile of the tunnel |
1531 /* check for a vehicle with that trackdir on the start tile of the tunnel */ |
1532 if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true; |
1532 if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true; |
1533 |
1533 |
1534 // check for a vehicle with that trackdir on the end tile of the tunnel |
1534 /* check for a vehicle with that trackdir on the end tile of the tunnel */ |
1535 if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true; |
1535 if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true; |
1536 |
1536 |
1537 // now check all tiles from start to end for a warping vehicle |
1537 /* now check all tiles from start to end for a warping vehicle |
1538 // NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile? |
1538 * NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile? */ |
1539 dest.track = 0x40; //Vehicle inside a tunnel or on a bridge |
1539 dest.track = 0x40; //Vehicle inside a tunnel or on a bridge |
1540 for (; tile != end; tile += TileOffsByDiagDir(direction)) { |
1540 for (; tile != end; tile += TileOffsByDiagDir(direction)) { |
1541 if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) |
1541 if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) |
1542 return true; |
1542 return true; |
1543 } |
1543 } |
1544 |
1544 |
1545 // no vehicle found |
1545 /* no vehicle found */ |
1546 return false; |
1546 return false; |
1547 } |
1547 } |
1548 |
1548 |
1549 return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL; |
1549 return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL; |
1550 } |
1550 } |
1595 |
1595 |
1596 static void ChangeSignalStates(SetSignalsData *ssd) |
1596 static void ChangeSignalStates(SetSignalsData *ssd) |
1597 { |
1597 { |
1598 int i; |
1598 int i; |
1599 |
1599 |
1600 // thinking about presignals... |
1600 /* thinking about presignals... |
1601 // the presignal is green if, |
1601 * the presignal is green if, |
1602 // if no train is in the segment AND |
1602 * if no train is in the segment AND |
1603 // there is at least one green exit signal OR |
1603 * there is at least one green exit signal OR |
1604 // there are no exit signals in the segment |
1604 * there are no exit signals in the segment */ |
1605 |
1605 |
1606 // then mark the signals in the segment accordingly |
1606 /* then mark the signals in the segment accordingly */ |
1607 for (i = 0; i != ssd->cur; i++) { |
1607 for (i = 0; i != ssd->cur; i++) { |
1608 TileIndex tile = ssd->tile[i]; |
1608 TileIndex tile = ssd->tile[i]; |
1609 byte bit = SignalAgainstTrackdir(ssd->bit[i]); |
1609 byte bit = SignalAgainstTrackdir(ssd->bit[i]); |
1610 uint16 m2 = _m[tile].m2; |
1610 uint16 m2 = _m[tile].m2; |
1611 |
1611 |
1612 // presignals don't turn green if there is at least one presignal exit and none are free |
1612 /* presignals don't turn green if there is at least one presignal exit and none are free */ |
1613 if (IsPresignalEntry(tile)) { |
1613 if (IsPresignalEntry(tile)) { |
1614 int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free; |
1614 int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free; |
1615 |
1615 |
1616 // subtract for dual combo signals so they don't count themselves |
1616 /* subtract for dual combo signals so they don't count themselves */ |
1617 if (IsPresignalExit(tile) && HasSignalOnTrackdir(tile, ssd->bit[i])) { |
1617 if (IsPresignalExit(tile) && HasSignalOnTrackdir(tile, ssd->bit[i])) { |
1618 ex--; |
1618 ex--; |
1619 if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--; |
1619 if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--; |
1620 } |
1620 } |
1621 |
1621 |
1622 // if we have exits and none are free, make red. |
1622 /* if we have exits and none are free, make red. */ |
1623 if (ex && !exfree) goto make_red; |
1623 if (ex && !exfree) goto make_red; |
1624 } |
1624 } |
1625 |
1625 |
1626 // check if the signal is unaffected. |
1626 /* check if the signal is unaffected. */ |
1627 if (ssd->stop) { |
1627 if (ssd->stop) { |
1628 make_red: |
1628 make_red: |
1629 // turn red |
1629 /* turn red */ |
1630 if ((bit & m2) == 0) continue; |
1630 if ((bit & m2) == 0) continue; |
1631 } else { |
1631 } else { |
1632 // turn green |
1632 /* turn green */ |
1633 if ((bit & m2) != 0) continue; |
1633 if ((bit & m2) != 0) continue; |
1634 } |
1634 } |
1635 |
1635 |
1636 /* Update signals on the other side of this exit-combo signal; it changed. */ |
1636 /* Update signals on the other side of this exit-combo signal; it changed. */ |
1637 if (IsPresignalExit(tile)) { |
1637 if (IsPresignalExit(tile)) { |
1657 int result = -1; |
1657 int result = -1; |
1658 |
1658 |
1659 ssd.cur_stack = 0; |
1659 ssd.cur_stack = 0; |
1660 |
1660 |
1661 for (;;) { |
1661 for (;;) { |
1662 // go through one segment and update all signals pointing into that segment. |
1662 /* go through one segment and update all signals pointing into that segment. */ |
1663 ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0; |
1663 ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0; |
1664 ssd.has_presignal = false; |
1664 ssd.has_presignal = false; |
1665 |
1665 |
1666 FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd); |
1666 FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd); |
1667 ChangeSignalStates(&ssd); |
1667 ChangeSignalStates(&ssd); |
1668 |
1668 |
1669 // remember the result only for the first iteration. |
1669 /* remember the result only for the first iteration. */ |
1670 if (result < 0) { |
1670 if (result < 0) { |
1671 // stay in depot while segment is occupied or while all presignal exits are blocked |
1671 /* stay in depot while segment is occupied or while all presignal exits are blocked */ |
1672 result = ssd.stop || (ssd.presignal_exits > 0 && ssd.presignal_exits_free == 0); |
1672 result = ssd.stop || (ssd.presignal_exits > 0 && ssd.presignal_exits_free == 0); |
1673 } |
1673 } |
1674 |
1674 |
1675 // if any exit signals were changed, we need to keep going to modify the stuff behind those. |
1675 /* if any exit signals were changed, we need to keep going to modify the stuff behind those. */ |
1676 if (ssd.cur_stack == 0) break; |
1676 if (ssd.cur_stack == 0) break; |
1677 |
1677 |
1678 // one or more exit signals were changed, so we need to update another segment too. |
1678 /* one or more exit signals were changed, so we need to update another segment too. */ |
1679 tile = ssd.next_tile[--ssd.cur_stack]; |
1679 tile = ssd.next_tile[--ssd.cur_stack]; |
1680 direction = ssd.next_dir[ssd.cur_stack]; |
1680 direction = ssd.next_dir[ssd.cur_stack]; |
1681 } |
1681 } |
1682 |
1682 |
1683 return result != 0; |
1683 return result != 0; |
1766 |
1766 |
1767 if (!IsPlainRailTile(tile)) return; |
1767 if (!IsPlainRailTile(tile)) return; |
1768 |
1768 |
1769 new_ground = RAIL_GROUND_GRASS; |
1769 new_ground = RAIL_GROUND_GRASS; |
1770 |
1770 |
1771 if (old_ground != RAIL_GROUND_BARREN) { /* wait until bottom is green */ |
1771 if (old_ground != RAIL_GROUND_BARREN) { // wait until bottom is green |
1772 /* determine direction of fence */ |
1772 /* determine direction of fence */ |
1773 TrackBits rail = GetTrackBits(tile); |
1773 TrackBits rail = GetTrackBits(tile); |
1774 |
1774 |
1775 switch (rail) { |
1775 switch (rail) { |
1776 case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break; |
1776 case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break; |
1960 byte fract_coord; |
1960 byte fract_coord; |
1961 byte fract_coord_leave; |
1961 byte fract_coord_leave; |
1962 DiagDirection dir; |
1962 DiagDirection dir; |
1963 int length; |
1963 int length; |
1964 |
1964 |
1965 // this routine applies only to trains in depot tiles |
1965 /* this routine applies only to trains in depot tiles */ |
1966 if (v->type != VEH_TRAIN || !IsTileDepotType(tile, TRANSPORT_RAIL)) return VETSB_CONTINUE; |
1966 if (v->type != VEH_TRAIN || !IsTileDepotType(tile, TRANSPORT_RAIL)) return VETSB_CONTINUE; |
1967 |
1967 |
1968 /* depot direction */ |
1968 /* depot direction */ |
1969 dir = GetRailDepotDirection(tile); |
1969 dir = GetRailDepotDirection(tile); |
1970 |
1970 |