branch | NewGRF_ports |
changeset 6872 | 1c4a4a609f85 |
parent 6871 | 5a9dc001e1ad |
child 6877 | 889301acc299 |
6871:5a9dc001e1ad | 6872:1c4a4a609f85 |
---|---|
6 #include "openttd.h" |
6 #include "openttd.h" |
7 #include "bridge_map.h" |
7 #include "bridge_map.h" |
8 #include "bridge.h" |
8 #include "bridge.h" |
9 #include "cmd_helper.h" |
9 #include "cmd_helper.h" |
10 #include "debug.h" |
10 #include "debug.h" |
11 #include "functions.h" |
11 #include "tile_cmd.h" |
12 #include "rail_map.h" |
12 #include "rail_map.h" |
13 #include "road_map.h" |
13 #include "road_map.h" |
14 #include "table/sprites.h" |
|
15 #include "table/strings.h" |
|
16 #include "map.h" |
|
17 #include "landscape.h" |
14 #include "landscape.h" |
18 #include "tile.h" |
|
19 #include "town_map.h" |
15 #include "town_map.h" |
20 #include "tunnel_map.h" |
16 #include "tunnel_map.h" |
21 #include "vehicle.h" |
17 #include "viewport_func.h" |
22 #include "viewport.h" |
18 #include "command_func.h" |
23 #include "command.h" |
|
24 #include "pathfind.h" |
19 #include "pathfind.h" |
25 #include "engine.h" |
20 #include "engine.h" |
26 #include "town.h" |
21 #include "town.h" |
27 #include "sound.h" |
|
28 #include "station.h" |
22 #include "station.h" |
29 #include "sprite.h" |
23 #include "sprite.h" |
30 #include "depot.h" |
24 #include "depot.h" |
31 #include "waypoint.h" |
25 #include "waypoint.h" |
32 #include "window.h" |
|
33 #include "rail.h" |
26 #include "rail.h" |
34 #include "railtypes.h" // include table for railtypes |
|
35 #include "newgrf.h" |
27 #include "newgrf.h" |
36 #include "yapf/yapf.h" |
28 #include "yapf/yapf.h" |
37 #include "newgrf_engine.h" |
29 #include "newgrf_engine.h" |
38 #include "newgrf_callbacks.h" |
30 #include "newgrf_callbacks.h" |
39 #include "newgrf_station.h" |
31 #include "newgrf_station.h" |
40 #include "train.h" |
32 #include "train.h" |
41 #include "misc/autoptr.hpp" |
33 #include "misc/autoptr.hpp" |
34 #include "variables.h" |
|
42 #include "autoslope.h" |
35 #include "autoslope.h" |
43 #include "transparency.h" |
36 #include "transparency.h" |
44 #include "water.h" |
37 #include "water.h" |
38 #include "tunnelbridge_map.h" |
|
39 #include "window_func.h" |
|
40 #include "vehicle_func.h" |
|
41 #include "sound_func.h" |
|
42 #include "signal_func.h" |
|
43 |
|
44 #include "table/sprites.h" |
|
45 #include "table/strings.h" |
|
46 #include "table/railtypes.h" |
|
45 |
47 |
46 const byte _track_sloped_sprites[14] = { |
48 const byte _track_sloped_sprites[14] = { |
47 14, 15, 22, 13, |
49 14, 15, 22, 13, |
48 0, 21, 17, 12, |
50 0, 21, 17, 12, |
49 23, 0, 18, 20, |
51 23, 0, 18, 20, |
80 * 01abcdef => rail w/ signals |
82 * 01abcdef => rail w/ signals |
81 * 10uuuuuu => unused |
83 * 10uuuuuu => unused |
82 * 11uuuudd => rail depot |
84 * 11uuuudd => rail depot |
83 */ |
85 */ |
84 |
86 |
85 /** Struct used in EnsureNoTrainOnTrack() */ |
87 |
86 struct TrainOnTrackData { |
88 void *EnsureNoTrainOnTrackProc(Vehicle *v, void *data) |
87 TileIndex tile; ///< tile to check |
89 { |
88 uint z; ///< tile max Z |
90 TrackBits rail_bits = *(TrackBits *)data; |
89 TrackBits rail_bits; ///< trackbits of interest |
91 |
90 }; |
92 if (v->type != VEH_TRAIN) return NULL; |
91 |
93 |
92 static void *EnsureNoTrainOnTrackProc(Vehicle *v, void *data) |
94 if ((v->u.rail.track != rail_bits) && !TracksOverlap(v->u.rail.track | rail_bits)) return NULL; |
93 { |
|
94 const TrainOnTrackData *info = (const TrainOnTrackData *)data; |
|
95 |
|
96 if (v->tile != info->tile || v->type != VEH_TRAIN) return NULL; |
|
97 if (v->z_pos > info->z) return NULL; |
|
98 |
|
99 if ((v->u.rail.track != info->rail_bits) && !TracksOverlap(v->u.rail.track | info->rail_bits)) return NULL; |
|
100 |
95 |
101 _error_message = VehicleInTheWayErrMsg(v); |
96 _error_message = VehicleInTheWayErrMsg(v); |
102 return v; |
97 return v; |
103 } |
98 } |
104 |
99 |
109 * @param tile The tile. |
104 * @param tile The tile. |
110 * @param track The track. |
105 * @param track The track. |
111 */ |
106 */ |
112 static bool EnsureNoTrainOnTrack(TileIndex tile, Track track) |
107 static bool EnsureNoTrainOnTrack(TileIndex tile, Track track) |
113 { |
108 { |
114 TrainOnTrackData info; |
109 TrackBits rail_bits = TrackToTrackBits(track); |
115 |
110 |
116 info.tile = tile; |
111 return VehicleFromPos(tile, &rail_bits, &EnsureNoTrainOnTrackProc) == NULL; |
117 info.z = GetTileMaxZ(tile); |
|
118 info.rail_bits = TrackToTrackBits(track); |
|
119 |
|
120 return VehicleFromPos(tile, &info, EnsureNoTrainOnTrackProc) == NULL; |
|
121 } |
112 } |
122 |
113 |
123 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags) |
114 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags) |
124 { |
115 { |
125 TrackBits current; // The current track layout |
116 TrackBits current; // The current track layout |
296 if ((f_new == FOUNDATION_INVALID) || |
287 if ((f_new == FOUNDATION_INVALID) || |
297 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player)) |
288 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player)) |
298 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
289 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
299 |
290 |
300 Foundation f_old = GetRailFoundation(tileh, existing); |
291 Foundation f_old = GetRailFoundation(tileh, existing); |
301 return CommandCost(f_new != f_old ? _price.terraform : (Money)0); |
292 return CommandCost(EXPENSES_CONSTRUCTION, f_new != f_old ? _price.terraform : (Money)0); |
302 } |
293 } |
303 |
294 |
304 /* Validate functions for rail building */ |
295 /* Validate functions for rail building */ |
305 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
296 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
306 |
297 |
311 * @param p2 rail track to build |
302 * @param p2 rail track to build |
312 */ |
303 */ |
313 CommandCost CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
304 CommandCost CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
314 { |
305 { |
315 Slope tileh; |
306 Slope tileh; |
316 RailType railtype; |
307 RailType railtype = (RailType)p1; |
317 Track track; |
308 Track track = (Track)p2; |
318 TrackBits trackbit; |
309 TrackBits trackbit; |
319 CommandCost cost; |
310 CommandCost cost(EXPENSES_CONSTRUCTION); |
320 CommandCost ret; |
311 CommandCost ret; |
321 |
312 |
322 if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
313 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
323 railtype = (RailType)p1; |
|
324 track = (Track)p2; |
|
325 |
314 |
326 tileh = GetTileSlope(tile, NULL); |
315 tileh = GetTileSlope(tile, NULL); |
327 trackbit = TrackToTrackBits(track); |
316 trackbit = TrackToTrackBits(track); |
328 |
|
329 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
330 |
317 |
331 switch (GetTileType(tile)) { |
318 switch (GetTileType(tile)) { |
332 case MP_RAILWAY: |
319 case MP_RAILWAY: |
333 if (!CheckTrackCombination(tile, trackbit, flags) || |
320 if (!CheckTrackCombination(tile, trackbit, flags) || |
334 !EnsureNoTrainOnTrack(tile, track)) { |
321 !EnsureNoTrainOnTrack(tile, track)) { |
394 |
381 |
395 if ((track == TRACK_X && road == ROAD_Y) || |
382 if ((track == TRACK_X && road == ROAD_Y) || |
396 (track == TRACK_Y && road == ROAD_X)) { |
383 (track == TRACK_Y && road == ROAD_X)) { |
397 if (flags & DC_EXEC) { |
384 if (flags & DC_EXEC) { |
398 MakeRoadCrossing(tile, GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile)); |
385 MakeRoadCrossing(tile, GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile)); |
386 UpdateLevelCrossing(tile, false); |
|
399 } |
387 } |
400 break; |
388 break; |
401 } |
389 } |
402 } |
390 } |
403 |
391 |
429 break; |
417 break; |
430 } |
418 } |
431 |
419 |
432 if (flags & DC_EXEC) { |
420 if (flags & DC_EXEC) { |
433 MarkTileDirtyByTile(tile); |
421 MarkTileDirtyByTile(tile); |
434 SetSignalsOnBothDir(tile, track); |
422 AddTrackToSignalBuffer(tile, track, _current_player); |
435 YapfNotifyTrackLayoutChange(tile, track); |
423 YapfNotifyTrackLayoutChange(tile, track); |
436 } |
424 } |
437 |
425 |
438 return cost.AddCost(RailBuildCost(railtype)); |
426 return cost.AddCost(RailBuildCost(railtype)); |
439 } |
427 } |
446 */ |
434 */ |
447 CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
435 CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
448 { |
436 { |
449 Track track = (Track)p2; |
437 Track track = (Track)p2; |
450 TrackBits trackbit; |
438 TrackBits trackbit; |
451 CommandCost cost(_price.remove_rail); |
439 CommandCost cost(EXPENSES_CONSTRUCTION, _price.remove_rail ); |
452 bool crossing = false; |
440 bool crossing = false; |
453 |
441 |
454 if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
442 if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
455 trackbit = TrackToTrackBits(track); |
443 trackbit = TrackToTrackBits(track); |
456 |
444 |
457 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
445 /* Need to read tile owner now because it may change when the rail is removed |
446 * Also, in case of floods, _current_player != owner |
|
447 * There may be invalid tiletype even in exec run (when removing long track), |
|
448 * so do not call GetTileOwner(tile) in any case here */ |
|
449 Owner owner = INVALID_OWNER; |
|
458 |
450 |
459 switch (GetTileType(tile)) { |
451 switch (GetTileType(tile)) { |
460 case MP_ROAD: { |
452 case MP_ROAD: { |
461 if (!IsLevelCrossing(tile) || |
453 if (!IsLevelCrossing(tile) || |
462 GetCrossingRailBits(tile) != trackbit || |
454 GetCrossingRailBits(tile) != trackbit || |
464 !EnsureNoVehicleOnGround(tile)) { |
456 !EnsureNoVehicleOnGround(tile)) { |
465 return CMD_ERROR; |
457 return CMD_ERROR; |
466 } |
458 } |
467 |
459 |
468 if (flags & DC_EXEC) { |
460 if (flags & DC_EXEC) { |
461 owner = GetTileOwner(tile); |
|
469 MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY)); |
462 MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY)); |
470 } |
463 } |
471 break; |
464 break; |
472 } |
465 } |
473 |
466 |
487 /* Charge extra to remove signals on the track, if they are there */ |
480 /* Charge extra to remove signals on the track, if they are there */ |
488 if (HasSignalOnTrack(tile, track)) |
481 if (HasSignalOnTrack(tile, track)) |
489 cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS)); |
482 cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS)); |
490 |
483 |
491 if (flags & DC_EXEC) { |
484 if (flags & DC_EXEC) { |
485 owner = GetTileOwner(tile); |
|
492 present ^= trackbit; |
486 present ^= trackbit; |
493 if (present == 0) { |
487 if (present == 0) { |
494 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) { |
488 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) { |
495 MakeShore(tile); |
489 MakeShore(tile); |
496 } else { |
490 } else { |
505 |
499 |
506 default: return CMD_ERROR; |
500 default: return CMD_ERROR; |
507 } |
501 } |
508 |
502 |
509 if (flags & DC_EXEC) { |
503 if (flags & DC_EXEC) { |
504 /* if we got that far, 'owner' variable is set correctly */ |
|
505 assert(IsValidPlayer(owner)); |
|
506 |
|
510 MarkTileDirtyByTile(tile); |
507 MarkTileDirtyByTile(tile); |
511 if (crossing) { |
508 if (crossing) { |
512 /* crossing is set when only TRACK_BIT_X and TRACK_BIT_Y are set. As we |
509 /* crossing is set when only TRACK_BIT_X and TRACK_BIT_Y are set. As we |
513 * are removing one of these pieces, we'll need to update signals for |
510 * are removing one of these pieces, we'll need to update signals for |
514 * both directions explicitly, as after the track is removed it won't |
511 * both directions explicitly, as after the track is removed it won't |
515 * 'connect' with the other piece. */ |
512 * 'connect' with the other piece. */ |
516 SetSignalsOnBothDir(tile, TRACK_X); |
513 AddTrackToSignalBuffer(tile, TRACK_X, owner); |
517 SetSignalsOnBothDir(tile, TRACK_Y); |
514 AddTrackToSignalBuffer(tile, TRACK_Y, owner); |
518 YapfNotifyTrackLayoutChange(tile, TRACK_X); |
515 YapfNotifyTrackLayoutChange(tile, TRACK_X); |
519 YapfNotifyTrackLayoutChange(tile, TRACK_Y); |
516 YapfNotifyTrackLayoutChange(tile, TRACK_Y); |
520 } else { |
517 } else { |
521 SetSignalsOnBothDir(tile, track); |
518 AddTrackToSignalBuffer(tile, track, owner); |
522 YapfNotifyTrackLayoutChange(tile, track); |
519 YapfNotifyTrackLayoutChange(tile, track); |
523 } |
520 } |
524 } |
521 } |
525 |
522 |
526 return cost; |
523 return cost; |
530 /** |
527 /** |
531 * Called from water_cmd if a non-flat rail-tile gets flooded and should be converted to shore. |
528 * Called from water_cmd if a non-flat rail-tile gets flooded and should be converted to shore. |
532 * The function floods the lower halftile, if the tile has a halftile foundation. |
529 * The function floods the lower halftile, if the tile has a halftile foundation. |
533 * |
530 * |
534 * @param t The tile to flood. |
531 * @param t The tile to flood. |
535 */ |
532 * @return true if something was flooded. |
536 void FloodHalftile(TileIndex t) |
533 */ |
537 { |
534 bool FloodHalftile(TileIndex t) |
538 if (GetRailGroundType(t) == RAIL_GROUND_WATER) return; |
535 { |
536 bool flooded = false; |
|
537 if (GetRailGroundType(t) == RAIL_GROUND_WATER) return flooded; |
|
539 |
538 |
540 Slope tileh = GetTileSlope(t, NULL); |
539 Slope tileh = GetTileSlope(t, NULL); |
541 TrackBits rail_bits = GetTrackBits(t); |
540 TrackBits rail_bits = GetTrackBits(t); |
542 |
541 |
543 if (!IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh)) { |
542 if (!IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh)) { |
544 TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh))); |
543 TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh))); |
545 |
544 |
546 TrackBits to_remove = lower_track & rail_bits; |
545 TrackBits to_remove = lower_track & rail_bits; |
547 if (to_remove != 0) { |
546 if (to_remove != 0) { |
548 _current_player = OWNER_WATER; |
547 _current_player = OWNER_WATER; |
549 if (CmdFailed(DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL))) return; // not yet floodable |
548 if (CmdFailed(DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL))) return flooded; // not yet floodable |
549 flooded = true; |
|
550 rail_bits = rail_bits & ~to_remove; |
550 rail_bits = rail_bits & ~to_remove; |
551 if (rail_bits == 0) { |
551 if (rail_bits == 0) { |
552 MakeShore(t); |
552 MakeShore(t); |
553 MarkTileDirtyByTile(t); |
553 MarkTileDirtyByTile(t); |
554 return; |
554 return flooded; |
555 } |
555 } |
556 } |
556 } |
557 |
557 |
558 if (IsNonContinuousFoundation(GetRailFoundation(tileh, rail_bits))) { |
558 if (IsNonContinuousFoundation(GetRailFoundation(tileh, rail_bits))) { |
559 flooded = true; |
|
559 SetRailGroundType(t, RAIL_GROUND_WATER); |
560 SetRailGroundType(t, RAIL_GROUND_WATER); |
560 MarkTileDirtyByTile(t); |
561 MarkTileDirtyByTile(t); |
561 } |
562 } |
562 } |
563 } |
564 return flooded; |
|
563 } |
565 } |
564 |
566 |
565 static const TileIndexDiffC _trackdelta[] = { |
567 static const TileIndexDiffC _trackdelta[] = { |
566 { -1, 0 }, { 0, 1 }, { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, 1 }, |
568 { -1, 0 }, { 0, 1 }, { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, 1 }, |
567 { 0, 0 }, |
569 { 0, 0 }, |
632 * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) |
634 * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) |
633 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
635 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
634 */ |
636 */ |
635 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
637 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
636 { |
638 { |
637 CommandCost ret, total_cost; |
639 CommandCost ret, total_cost(EXPENSES_CONSTRUCTION); |
638 Track track = (Track)GB(p2, 4, 3); |
640 Track track = (Track)GB(p2, 4, 3); |
639 Trackdir trackdir; |
641 Trackdir trackdir; |
640 byte mode = HasBit(p2, 7); |
642 byte mode = HasBit(p2, 7); |
641 RailType railtype = (RailType)GB(p2, 0, 4); |
643 RailType railtype = (RailType)GB(p2, 0, 4); |
642 TileIndex end_tile; |
644 TileIndex end_tile; |
643 |
645 |
644 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
646 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
645 if (p1 >= MapSize()) return CMD_ERROR; |
647 if (p1 >= MapSize()) return CMD_ERROR; |
646 end_tile = p1; |
648 end_tile = p1; |
647 trackdir = TrackToTrackdir(track); |
649 trackdir = TrackToTrackdir(track); |
648 |
|
649 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
650 |
650 |
651 if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR; |
651 if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR; |
652 |
652 |
653 if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile); |
653 if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile); |
654 |
654 |
714 * @todo When checking for the tile slope, |
714 * @todo When checking for the tile slope, |
715 * distingush between "Flat land required" and "land sloped in wrong direction" |
715 * distingush between "Flat land required" and "land sloped in wrong direction" |
716 */ |
716 */ |
717 CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
717 CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
718 { |
718 { |
719 CommandCost cost; |
|
720 Slope tileh; |
719 Slope tileh; |
721 |
720 |
722 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
723 |
|
724 /* check railtype and valid direction for depot (0 through 3), 4 in total */ |
721 /* check railtype and valid direction for depot (0 through 3), 4 in total */ |
725 if (!ValParamRailtype(p1)) return CMD_ERROR; |
722 if (!ValParamRailtype((RailType)p1)) return CMD_ERROR; |
726 |
723 |
727 tileh = GetTileSlope(tile, NULL); |
724 tileh = GetTileSlope(tile, NULL); |
728 |
725 |
729 DiagDirection dir = Extract<DiagDirection, 0>(p2); |
726 DiagDirection dir = Extract<DiagDirection, 0>(p2); |
730 |
727 |
743 !CanBuildDepotByTileh(dir, tileh) |
740 !CanBuildDepotByTileh(dir, tileh) |
744 )) { |
741 )) { |
745 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
742 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
746 } |
743 } |
747 |
744 |
748 cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
745 CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
749 if (CmdFailed(cost)) return CMD_ERROR; |
746 if (CmdFailed(cost)) return CMD_ERROR; |
750 |
747 |
751 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
748 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
752 |
749 |
753 Depot *d = new Depot(tile); |
750 Depot *d = new Depot(tile); |
759 MakeRailDepot(tile, _current_player, dir, (RailType)p1); |
756 MakeRailDepot(tile, _current_player, dir, (RailType)p1); |
760 MarkTileDirtyByTile(tile); |
757 MarkTileDirtyByTile(tile); |
761 |
758 |
762 d->town_index = ClosestTownFromTile(tile, (uint)-1)->index; |
759 d->town_index = ClosestTownFromTile(tile, (uint)-1)->index; |
763 |
760 |
764 UpdateSignalsOnSegment(tile, dir); |
761 AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_player); |
765 YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); |
762 YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); |
766 d_auto_delete.Detach(); |
763 d_auto_delete.Detach(); |
767 } |
764 } |
768 |
765 |
769 return cost.AddCost(_price.build_train_depot); |
766 return cost.AddCost(_price.build_train_depot); |
814 } |
811 } |
815 |
812 |
816 /* you can not convert a signal if no signal is on track */ |
813 /* you can not convert a signal if no signal is on track */ |
817 if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR; |
814 if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR; |
818 |
815 |
819 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
820 |
|
821 if (!HasSignalOnTrack(tile, track)) { |
816 if (!HasSignalOnTrack(tile, track)) { |
822 /* build new signals */ |
817 /* build new signals */ |
823 cost = CommandCost(_price.build_signals); |
818 cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals); |
824 } else { |
819 } else { |
825 if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) { |
820 if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) { |
826 /* convert signals <-> semaphores */ |
821 /* convert signals <-> semaphores */ |
827 cost = CommandCost(_price.build_signals + _price.remove_signals); |
822 cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals); |
828 |
823 |
829 } else if (convert_signal) { |
824 } else if (convert_signal) { |
830 /* convert button pressed */ |
825 /* convert button pressed */ |
831 if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) { |
826 if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) { |
832 /* convert electric <-> semaphore */ |
827 /* convert electric <-> semaphore */ |
833 cost = CommandCost(_price.build_signals + _price.remove_signals); |
828 cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals); |
834 } else { |
829 } else { |
835 /* it is free to change signal type: normal-pre-exit-combo */ |
830 /* it is free to change signal type: normal-pre-exit-combo */ |
836 cost = CommandCost(); |
831 cost = CommandCost(); |
837 } |
832 } |
838 |
833 |
887 SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | (p2 & SignalOnTrack(track))); |
882 SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | (p2 & SignalOnTrack(track))); |
888 SetSignalVariant(tile, track, sigvar); |
883 SetSignalVariant(tile, track, sigvar); |
889 } |
884 } |
890 |
885 |
891 MarkTileDirtyByTile(tile); |
886 MarkTileDirtyByTile(tile); |
892 SetSignalsOnBothDir(tile, track); |
887 AddTrackToSignalBuffer(tile, track, _current_player); |
893 YapfNotifyTrackLayoutChange(tile, track); |
888 YapfNotifyTrackLayoutChange(tile, track); |
894 } |
889 } |
895 |
890 |
896 return cost; |
891 return cost; |
897 } |
892 } |
933 if (!IsLevelCrossing(tile)) return false; |
928 if (!IsLevelCrossing(tile)) return false; |
934 signal_ctr += 2; |
929 signal_ctr += 2; |
935 return true; |
930 return true; |
936 |
931 |
937 case MP_TUNNELBRIDGE: { |
932 case MP_TUNNELBRIDGE: { |
938 TileIndex orig_tile = tile; |
933 TileIndex orig_tile = tile; // backup old value |
939 /* Skip to end of tunnel or bridge */ |
934 |
940 if (IsBridge(tile)) { |
935 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return false; |
941 if (GetBridgeTransportType(tile) != TRANSPORT_RAIL) return false; |
936 if (GetTunnelBridgeDirection(tile) != TrackdirToExitdir(trackdir)) return false; |
942 if (GetBridgeRampDirection(tile) != TrackdirToExitdir(trackdir)) return false; |
937 |
943 tile = GetOtherBridgeEnd(tile); |
938 /* Skip to end of tunnel or bridge |
944 } else { |
939 * note that tile is a parameter by reference, so it must be updated */ |
945 if (GetTunnelTransportType(tile) != TRANSPORT_RAIL) return false; |
940 tile = GetOtherTunnelBridgeEnd(tile); |
946 if (GetTunnelDirection(tile) != TrackdirToExitdir(trackdir)) return false; |
941 |
947 tile = GetOtherTunnelEnd(tile); |
|
948 } |
|
949 signal_ctr += 2 + DistanceMax(orig_tile, tile) * 2; |
942 signal_ctr += 2 + DistanceMax(orig_tile, tile) * 2; |
950 return true; |
943 return true; |
951 } |
944 } |
952 |
945 |
953 default: return false; |
946 default: return false; |
966 * - p2 = (bit 6) - 0 = selected stretch, 1 = auto fill |
959 * - p2 = (bit 6) - 0 = selected stretch, 1 = auto fill |
967 * - p2 = (bit 24-31) - user defined signals_density |
960 * - p2 = (bit 24-31) - user defined signals_density |
968 */ |
961 */ |
969 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
962 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
970 { |
963 { |
971 CommandCost ret, total_cost; |
964 CommandCost ret, total_cost(EXPENSES_CONSTRUCTION); |
972 int signal_ctr; |
965 int signal_ctr; |
973 byte signals; |
966 byte signals; |
974 bool error = true; |
967 bool error = true; |
975 TileIndex end_tile; |
968 TileIndex end_tile; |
976 TileIndex start_tile = tile; |
969 TileIndex start_tile = tile; |
986 if (p1 >= MapSize()) return CMD_ERROR; |
979 if (p1 >= MapSize()) return CMD_ERROR; |
987 end_tile = p1; |
980 end_tile = p1; |
988 if (signal_density == 0 || signal_density > 20) return CMD_ERROR; |
981 if (signal_density == 0 || signal_density > 20) return CMD_ERROR; |
989 |
982 |
990 if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR; |
983 if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR; |
991 |
|
992 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
993 |
984 |
994 /* for vertical/horizontal tracks, double the given signals density |
985 /* for vertical/horizontal tracks, double the given signals density |
995 * since the original amount will be too dense (shorter tracks) */ |
986 * since the original amount will be too dense (shorter tracks) */ |
996 signal_density *= 2; |
987 signal_density *= 2; |
997 |
988 |
1111 } |
1102 } |
1112 |
1103 |
1113 /* Only water can remove signals from anyone */ |
1104 /* Only water can remove signals from anyone */ |
1114 if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR; |
1105 if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR; |
1115 |
1106 |
1116 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
1117 |
|
1118 /* Do it? */ |
1107 /* Do it? */ |
1119 if (flags & DC_EXEC) { |
1108 if (flags & DC_EXEC) { |
1120 SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track)); |
1109 SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track)); |
1121 |
1110 |
1122 /* removed last signal from tile? */ |
1111 /* removed last signal from tile? */ |
1124 SetSignalStates(tile, 0); |
1113 SetSignalStates(tile, 0); |
1125 SetHasSignals(tile, false); |
1114 SetHasSignals(tile, false); |
1126 SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores |
1115 SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores |
1127 } |
1116 } |
1128 |
1117 |
1129 SetSignalsOnBothDir(tile, track); |
1118 AddTrackToSignalBuffer(tile, track, GetTileOwner(tile)); |
1130 YapfNotifyTrackLayoutChange(tile, track); |
1119 YapfNotifyTrackLayoutChange(tile, track); |
1131 |
1120 |
1132 MarkTileDirtyByTile(tile); |
1121 MarkTileDirtyByTile(tile); |
1133 } |
1122 } |
1134 |
1123 |
1135 return CommandCost(_price.remove_signals); |
1124 return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_signals); |
1136 } |
1125 } |
1137 |
1126 |
1138 /** Remove signals on a stretch of track. |
1127 /** Remove signals on a stretch of track. |
1139 * Stub for the unified signal builder/remover |
1128 * Stub for the unified signal builder/remover |
1140 * @param tile start tile of drag |
1129 * @param tile start tile of drag |
1152 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1141 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1153 { |
1142 { |
1154 return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5)); // bit 5 is remove bit |
1143 return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5)); // bit 5 is remove bit |
1155 } |
1144 } |
1156 |
1145 |
1157 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec); |
1146 /** Update power of train under which is the railtype being converted */ |
1158 |
|
1159 void *UpdateTrainPowerProc(Vehicle *v, void *data) |
1147 void *UpdateTrainPowerProc(Vehicle *v, void *data) |
1160 { |
1148 { |
1161 /* Similiar checks as in TrainPowerChanged() */ |
1149 /* Similiar checks as in TrainPowerChanged() */ |
1162 |
1150 |
1163 if (v->type == VEH_TRAIN && v->tile == *(TileIndex*)data && !IsArticulatedPart(v)) { |
1151 if (v->type == VEH_TRAIN && !IsArticulatedPart(v)) { |
1164 const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); |
1152 const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); |
1165 if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First()); |
1153 if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First()); |
1166 } |
1154 } |
1167 |
1155 |
1168 return NULL; |
1156 return NULL; |
1169 } |
1157 } |
1170 |
|
1171 /** |
|
1172 * Switches the rail type. |
|
1173 * Railtypes are stored on a per-tile basis, not on a per-track basis, so |
|
1174 * all the tracks in the given tile will be converted. |
|
1175 * @param tile The tile on which the railtype is to be convert. |
|
1176 * @param totype The railtype we want to convert to |
|
1177 * @param exec Switches between test and execute mode |
|
1178 * @return The cost and state of the operation |
|
1179 * @retval CMD_ERROR An error occured during the operation. |
|
1180 */ |
|
1181 static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec) |
|
1182 { |
|
1183 /* change type. */ |
|
1184 if (exec) { |
|
1185 SetRailType(tile, totype); |
|
1186 MarkTileDirtyByTile(tile); |
|
1187 |
|
1188 /* notify YAPF about the track layout change */ |
|
1189 TrackBits tracks = GetTrackBits(tile); |
|
1190 while (tracks != TRACK_BIT_NONE) { |
|
1191 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks)); |
|
1192 } |
|
1193 |
|
1194 if (IsTileDepotType(tile, TRANSPORT_RAIL)) { |
|
1195 /* Update build vehicle window related to this depot */ |
|
1196 InvalidateWindowData(WC_VEHICLE_DEPOT, tile); |
|
1197 InvalidateWindowData(WC_BUILD_VEHICLE, tile); |
|
1198 } |
|
1199 |
|
1200 /* update power of train engines on this tile */ |
|
1201 VehicleFromPos(tile, &tile, UpdateTrainPowerProc); |
|
1202 } |
|
1203 |
|
1204 return CommandCost(RailBuildCost(totype) / 2); |
|
1205 } |
|
1206 |
|
1207 extern CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec); |
|
1208 extern CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec); |
|
1209 extern CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec); |
|
1210 |
1158 |
1211 /** Convert one rail type to the other. You can convert normal rail to |
1159 /** Convert one rail type to the other. You can convert normal rail to |
1212 * monorail/maglev easily or vice-versa. |
1160 * monorail/maglev easily or vice-versa. |
1213 * @param tile end tile of rail conversion drag |
1161 * @param tile end tile of rail conversion drag |
1214 * @param flags operation to perform |
1162 * @param flags operation to perform |
1215 * @param p1 start tile of drag |
1163 * @param p1 start tile of drag |
1216 * @param p2 new railtype to convert to |
1164 * @param p2 new railtype to convert to |
1217 */ |
1165 */ |
1218 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1166 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1219 { |
1167 { |
1220 CommandCost ret, cost; |
1168 CommandCost cost(EXPENSES_CONSTRUCTION); |
1221 Money money; |
1169 RailType totype = (RailType)p2; |
1222 int ex; |
1170 |
1223 int ey; |
1171 if (!ValParamRailtype(totype)) return CMD_ERROR; |
1224 int sx, sy, x, y; |
|
1225 |
|
1226 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
1227 |
|
1228 if (!ValParamRailtype(p2)) return CMD_ERROR; |
|
1229 if (p1 >= MapSize()) return CMD_ERROR; |
1172 if (p1 >= MapSize()) return CMD_ERROR; |
1230 |
1173 |
1174 uint ex = TileX(tile); |
|
1175 uint ey = TileY(tile); |
|
1176 uint sx = TileX(p1); |
|
1177 uint sy = TileY(p1); |
|
1178 |
|
1231 /* make sure sx,sy are smaller than ex,ey */ |
1179 /* make sure sx,sy are smaller than ex,ey */ |
1232 ex = TileX(tile); |
|
1233 ey = TileY(tile); |
|
1234 sx = TileX(p1); |
|
1235 sy = TileY(p1); |
|
1236 if (ex < sx) Swap(ex, sx); |
1180 if (ex < sx) Swap(ex, sx); |
1237 if (ey < sy) Swap(ey, sy); |
1181 if (ey < sy) Swap(ey, sy); |
1238 |
1182 |
1239 money = GetAvailableMoneyForCommand(); |
1183 _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert |
1240 |
1184 |
1241 for (x = sx; x <= ex; ++x) { |
1185 for (uint x = sx; x <= ex; ++x) { |
1242 for (y = sy; y <= ey; ++y) { |
1186 for (uint y = sy; y <= ey; ++y) { |
1243 TileIndex tile = TileXY(x, y); |
1187 TileIndex tile = TileXY(x, y); |
1244 DoConvertRailProc *proc; |
1188 TileType tt = GetTileType(tile); |
1245 RailType totype = (RailType)p2; |
1189 |
1246 |
1190 /* Check if there is any track on tile */ |
1247 switch (GetTileType(tile)) { |
1191 switch (tt) { |
1248 case MP_RAILWAY: proc = DoConvertRail; break; |
1192 case MP_RAILWAY: |
1249 case MP_STATION: proc = DoConvertStationRail; break; |
1193 break; |
1250 case MP_ROAD: proc = DoConvertStreetRail; break; |
1194 case MP_STATION: |
1251 case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break; |
1195 if (!IsRailwayStation(tile)) continue; |
1196 break; |
|
1197 case MP_ROAD: |
|
1198 if (!IsLevelCrossing(tile)) continue; |
|
1199 break; |
|
1200 case MP_TUNNELBRIDGE: |
|
1201 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue; |
|
1202 break; |
|
1252 default: continue; |
1203 default: continue; |
1253 } |
1204 } |
1254 |
1205 |
1255 /* It is possible that 'type' is invalid when there is no rail on the tile, |
1206 /* Original railtype we are converting from */ |
1256 * but this situation will be detected in proc() |
|
1257 */ |
|
1258 RailType type = GetRailType(tile); |
1207 RailType type = GetRailType(tile); |
1259 |
1208 |
1260 /* Not own tile or track is already converted */ |
1209 /* Converting to the same type or converting 'hidden' elrail -> rail */ |
1261 if ((!CheckTileOwnership(tile) || type == totype) || |
1210 if (type == totype || (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue; |
1262 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
1211 |
1263 (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC) || |
1212 /* Trying to convert other's rail */ |
1264 /* Vehicle on a tile while not converting Rail <-> ElRail */ |
1213 if (!CheckTileOwnership(tile)) continue; |
1265 (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile))) { |
1214 |
1266 ret = CMD_ERROR; |
1215 /* Vehicle on the tile when not converting Rail <-> ElRail |
1267 continue; |
1216 * Tunnels and bridges have special check later */ |
1268 } |
1217 if (tt != MP_TUNNELBRIDGE) { |
1269 |
1218 if (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile)) continue; |
1270 ret = proc(tile, totype, false); |
1219 if (flags & DC_EXEC) { // we can safely convert, too |
1271 if (CmdFailed(ret)) continue; |
1220 SetRailType(tile, totype); |
1272 |
1221 MarkTileDirtyByTile(tile); |
1273 if (flags & DC_EXEC) { |
1222 /* update power of train engines on this tile */ |
1274 money -= ret.GetCost(); |
1223 VehicleFromPos(tile, NULL, &UpdateTrainPowerProc); |
1275 if (money < 0) { |
|
1276 _additional_cash_required = ret.GetCost(); |
|
1277 return cost; |
|
1278 } |
1224 } |
1279 proc(tile, totype, true); |
1225 } |
1280 } |
1226 |
1281 cost.AddCost(ret); |
1227 switch (tt) { |
1282 } |
1228 case MP_RAILWAY: |
1283 } |
1229 switch (GetRailTileType(tile)) { |
1284 |
1230 case RAIL_TILE_WAYPOINT: |
1285 return (cost.GetCost() == 0) ? ret : cost; |
1231 if (flags & DC_EXEC) { |
1232 /* notify YAPF about the track layout change */ |
|
1233 YapfNotifyTrackLayoutChange(tile, AxisToTrack(GetWaypointAxis(tile))); |
|
1234 } |
|
1235 cost.AddCost(RailConvertCost(type, totype)); |
|
1236 break; |
|
1237 |
|
1238 case RAIL_TILE_DEPOT: |
|
1239 if (flags & DC_EXEC) { |
|
1240 /* notify YAPF about the track layout change */ |
|
1241 YapfNotifyTrackLayoutChange(tile, AxisToTrack(DiagDirToAxis(GetRailDepotDirection(tile)))); |
|
1242 |
|
1243 /* Update build vehicle window related to this depot */ |
|
1244 InvalidateWindowData(WC_VEHICLE_DEPOT, tile); |
|
1245 InvalidateWindowData(WC_BUILD_VEHICLE, tile); |
|
1246 } |
|
1247 cost.AddCost(RailConvertCost(type, totype)); |
|
1248 break; |
|
1249 |
|
1250 default: // RAIL_TILE_NORMAL, RAIL_TILE_SIGNALS |
|
1251 if (flags & DC_EXEC) { |
|
1252 /* notify YAPF about the track layout change */ |
|
1253 TrackBits tracks = GetTrackBits(tile); |
|
1254 while (tracks != TRACK_BIT_NONE) { |
|
1255 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks)); |
|
1256 } |
|
1257 } |
|
1258 cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile))); |
|
1259 break; |
|
1260 } |
|
1261 break; |
|
1262 |
|
1263 case MP_TUNNELBRIDGE: { |
|
1264 TileIndex endtile = GetOtherTunnelBridgeEnd(tile); |
|
1265 |
|
1266 /* If both ends of tunnel/bridge are in the range, do not try to convert twice - |
|
1267 * it would cause assert because of different test and exec runs */ |
|
1268 if (endtile < tile && TileX(endtile) >= sx && TileX(endtile) <= ex && |
|
1269 TileY(endtile) >= sy && TileY(endtile) <= ey) continue; |
|
1270 |
|
1271 /* When not coverting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */ |
|
1272 if (!IsCompatibleRail(GetRailType(tile), totype) && |
|
1273 GetVehicleTunnelBridge(tile, endtile) != NULL) continue; |
|
1274 |
|
1275 if (flags & DC_EXEC) { |
|
1276 SetRailType(tile, totype); |
|
1277 SetRailType(endtile, totype); |
|
1278 |
|
1279 VehicleFromPos(tile, NULL, &UpdateTrainPowerProc); |
|
1280 VehicleFromPos(endtile, NULL, &UpdateTrainPowerProc); |
|
1281 |
|
1282 Track track = AxisToTrack(DiagDirToAxis(GetTunnelBridgeDirection(tile))); |
|
1283 |
|
1284 YapfNotifyTrackLayoutChange(tile, track); |
|
1285 YapfNotifyTrackLayoutChange(endtile, track); |
|
1286 |
|
1287 MarkTileDirtyByTile(tile); |
|
1288 MarkTileDirtyByTile(endtile); |
|
1289 |
|
1290 if (IsBridge(tile)) { |
|
1291 TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile)); |
|
1292 TileIndex t = tile + delta; |
|
1293 for (; t != endtile; t += delta) MarkTileDirtyByTile(t); // TODO encapsulate this into a function |
|
1294 } |
|
1295 } |
|
1296 |
|
1297 cost.AddCost((DistanceManhattan(tile, endtile) + 1) * RailConvertCost(type, totype)); |
|
1298 } break; |
|
1299 |
|
1300 default: // MP_STATION, MP_ROAD |
|
1301 if (flags & DC_EXEC) { |
|
1302 Track track = (tt == MP_STATION) ? GetRailStationTrack(tile) : AxisToTrack(OtherAxis(GetCrossingRoadAxis(tile))); |
|
1303 YapfNotifyTrackLayoutChange(tile, track); |
|
1304 } |
|
1305 |
|
1306 cost.AddCost(RailConvertCost(type, totype)); |
|
1307 break; |
|
1308 } |
|
1309 } |
|
1310 } |
|
1311 |
|
1312 return (cost.GetCost() == 0) ? CMD_ERROR : cost; |
|
1286 } |
1313 } |
1287 |
1314 |
1288 static CommandCost RemoveTrainDepot(TileIndex tile, uint32 flags) |
1315 static CommandCost RemoveTrainDepot(TileIndex tile, uint32 flags) |
1289 { |
1316 { |
1290 if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) |
1317 if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) |
1292 |
1319 |
1293 if (!EnsureNoVehicleOnGround(tile)) |
1320 if (!EnsureNoVehicleOnGround(tile)) |
1294 return CMD_ERROR; |
1321 return CMD_ERROR; |
1295 |
1322 |
1296 if (flags & DC_EXEC) { |
1323 if (flags & DC_EXEC) { |
1324 /* read variables before the depot is removed */ |
|
1297 DiagDirection dir = GetRailDepotDirection(tile); |
1325 DiagDirection dir = GetRailDepotDirection(tile); |
1326 Owner owner = GetTileOwner(tile); |
|
1298 |
1327 |
1299 DoClearSquare(tile); |
1328 DoClearSquare(tile); |
1300 delete GetDepotByTile(tile); |
1329 delete GetDepotByTile(tile); |
1301 UpdateSignalsOnSegment(tile, dir); |
1330 AddSideToSignalBuffer(tile, dir, owner); |
1302 YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); |
1331 YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); |
1303 } |
1332 } |
1304 |
1333 |
1305 return CommandCost(_price.remove_train_depot); |
1334 return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot); |
1306 } |
1335 } |
1307 |
1336 |
1308 static CommandCost ClearTile_Track(TileIndex tile, byte flags) |
1337 static CommandCost ClearTile_Track(TileIndex tile, byte flags) |
1309 { |
1338 { |
1310 CommandCost cost; |
1339 CommandCost cost(EXPENSES_CONSTRUCTION); |
1311 CommandCost ret; |
1340 CommandCost ret; |
1312 |
1341 |
1313 if (flags & DC_AUTO) { |
1342 if (flags & DC_AUTO) { |
1314 if (!IsTileOwner(tile, _current_player)) |
1343 if (!IsTileOwner(tile, _current_player)) |
1315 return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER); |
1344 return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER); |
1781 image += rti->total_offset; |
1810 image += rti->total_offset; |
1782 } else { |
1811 } else { |
1783 image += relocation; |
1812 image += relocation; |
1784 } |
1813 } |
1785 |
1814 |
1786 if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) { |
1815 if (!(!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)) && HasBit(image, PALETTE_MODIFIER_COLOR)) { |
1787 pal = _drawtile_track_palette; |
1816 pal = _drawtile_track_palette; |
1788 } else { |
1817 } else { |
1789 pal = dtss->pal; |
1818 pal = dtss->pal; |
1790 } |
1819 } |
1791 |
1820 |
1793 AddSortableSpriteToDraw( |
1822 AddSortableSpriteToDraw( |
1794 image, pal, |
1823 image, pal, |
1795 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
1824 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
1796 dtss->size_x, dtss->size_y, |
1825 dtss->size_x, dtss->size_y, |
1797 dtss->size_z, ti->z + dtss->delta_z, |
1826 dtss->size_z, ti->z + dtss->delta_z, |
1798 IsTransparencySet(TO_BUILDINGS) |
1827 !HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS) |
1799 ); |
1828 ); |
1800 } else { |
1829 } else { |
1801 AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); |
1830 AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); |
1802 } |
1831 } |
1803 } |
1832 } |
1833 { |
1862 { |
1834 uint32 offset = GetRailTypeInfo(railtype)->total_offset; |
1863 uint32 offset = GetRailTypeInfo(railtype)->total_offset; |
1835 const DrawTileSprites* dts = &_waypoint_gfx_table[AXIS_X]; |
1864 const DrawTileSprites* dts = &_waypoint_gfx_table[AXIS_X]; |
1836 |
1865 |
1837 DrawTileSequence(x, y, dts->ground_sprite + offset, dts->seq, 0); |
1866 DrawTileSequence(x, y, dts->ground_sprite + offset, dts->seq, 0); |
1838 } |
|
1839 |
|
1840 struct SetSignalsData { |
|
1841 int cur; |
|
1842 int cur_stack; |
|
1843 bool stop; |
|
1844 bool has_presignal; |
|
1845 |
|
1846 /* presignal info */ |
|
1847 int presignal_exits; |
|
1848 int presignal_exits_free; |
|
1849 |
|
1850 /* these are used to keep track of the signals that change. */ |
|
1851 TrackdirByte bit[NUM_SSD_ENTRY]; |
|
1852 TileIndex tile[NUM_SSD_ENTRY]; |
|
1853 |
|
1854 /* these are used to keep track of the stack that modifies presignals recursively */ |
|
1855 TileIndex next_tile[NUM_SSD_STACK]; |
|
1856 DiagDirectionByte next_dir[NUM_SSD_STACK]; |
|
1857 |
|
1858 }; |
|
1859 |
|
1860 static bool SetSignalsEnumProc(TileIndex tile, void* data, Trackdir trackdir, uint length, byte* state) |
|
1861 { |
|
1862 SetSignalsData* ssd = (SetSignalsData*)data; |
|
1863 Track track = TrackdirToTrack(trackdir); |
|
1864 |
|
1865 if (!IsTileType(tile, MP_RAILWAY)) return false; |
|
1866 |
|
1867 /* the tile has signals? */ |
|
1868 if (HasSignalOnTrack(tile, track)) { |
|
1869 if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) { |
|
1870 /* yes, add the signal to the list of signals */ |
|
1871 if (ssd->cur != NUM_SSD_ENTRY) { |
|
1872 ssd->tile[ssd->cur] = tile; // remember the tile index |
|
1873 ssd->bit[ssd->cur] = trackdir; // and the controlling bit number |
|
1874 ssd->cur++; |
|
1875 } |
|
1876 |
|
1877 /* remember if this block has a presignal. */ |
|
1878 ssd->has_presignal |= IsPresignalEntry(tile, track); |
|
1879 } |
|
1880 |
|
1881 if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile, track)) { |
|
1882 /* this is an exit signal that points out from the segment */ |
|
1883 ssd->presignal_exits++; |
|
1884 if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED) |
|
1885 ssd->presignal_exits_free++; |
|
1886 } |
|
1887 |
|
1888 return true; |
|
1889 } else if (IsTileDepotType(tile, TRANSPORT_RAIL)) { |
|
1890 return true; // don't look further if the tile is a depot |
|
1891 } |
|
1892 |
|
1893 return false; |
|
1894 } |
|
1895 |
|
1896 /* Struct to parse data from VehicleFromPos to SignalVehicleCheckProc */ |
|
1897 struct SignalVehicleCheckStruct { |
|
1898 TileIndex tile; |
|
1899 uint track; |
|
1900 }; |
|
1901 |
|
1902 static void *SignalVehicleCheckProc(Vehicle *v, void *data) |
|
1903 { |
|
1904 const SignalVehicleCheckStruct* dest = (SignalVehicleCheckStruct*)data; |
|
1905 |
|
1906 if (v->type != VEH_TRAIN) return NULL; |
|
1907 |
|
1908 /* Wrong tile, or no train? Not a match */ |
|
1909 if (v->tile != dest->tile) return NULL; |
|
1910 |
|
1911 /* Are we on the same piece of track? */ |
|
1912 if (dest->track & v->u.rail.track * 0x101) return v; |
|
1913 |
|
1914 return NULL; |
|
1915 } |
|
1916 |
|
1917 /* Special check for SetSignalsAfterProc, to see if there is a vehicle on this tile */ |
|
1918 static bool SignalVehicleCheck(TileIndex tile, uint track) |
|
1919 { |
|
1920 SignalVehicleCheckStruct dest; |
|
1921 |
|
1922 dest.tile = tile; |
|
1923 dest.track = track; |
|
1924 |
|
1925 /* Locate vehicles in tunnels or on bridges */ |
|
1926 if (IsTunnelTile(tile) || IsBridgeTile(tile)) { |
|
1927 TileIndex end; |
|
1928 DiagDirection direction; |
|
1929 |
|
1930 if (IsTunnelTile(tile)) { |
|
1931 end = GetOtherTunnelEnd(tile); |
|
1932 direction = GetTunnelDirection(tile); |
|
1933 } else { |
|
1934 end = GetOtherBridgeEnd(tile); |
|
1935 direction = GetBridgeRampDirection(tile); |
|
1936 } |
|
1937 |
|
1938 dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible) |
|
1939 |
|
1940 /* check for a vehicle with that trackdir on the start tile of the tunnel */ |
|
1941 if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true; |
|
1942 |
|
1943 /* check for a vehicle with that trackdir on the end tile of the tunnel */ |
|
1944 if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true; |
|
1945 |
|
1946 /* now check all tiles from start to end for a warping vehicle */ |
|
1947 dest.track = 0x40; //Vehicle inside a tunnel or on a bridge |
|
1948 if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true; |
|
1949 if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true; |
|
1950 |
|
1951 /* no vehicle found */ |
|
1952 return false; |
|
1953 } |
|
1954 |
|
1955 return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL; |
|
1956 } |
|
1957 |
|
1958 static void SetSignalsAfterProc(TrackPathFinder *tpf) |
|
1959 { |
|
1960 SetSignalsData *ssd = (SetSignalsData*)tpf->userdata; |
|
1961 const TrackPathFinderLink* link; |
|
1962 uint offs; |
|
1963 uint i; |
|
1964 |
|
1965 ssd->stop = false; |
|
1966 |
|
1967 /* Go through all the PF tiles */ |
|
1968 for (i = 0; i < lengthof(tpf->hash_head); i++) { |
|
1969 /* Empty hash item */ |
|
1970 if (tpf->hash_head[i] == 0) continue; |
|
1971 |
|
1972 /* If 0x8000 is not set, there is only 1 item */ |
|
1973 if (!(tpf->hash_head[i] & 0x8000)) { |
|
1974 /* Check if there is a vehicle on this tile */ |
|
1975 if (SignalVehicleCheck(tpf->hash_tile[i], tpf->hash_head[i])) { |
|
1976 ssd->stop = true; |
|
1977 return; |
|
1978 } |
|
1979 } else { |
|
1980 /* There are multiple items, where hash_tile points to the first item in the list */ |
|
1981 offs = tpf->hash_tile[i]; |
|
1982 do { |
|
1983 /* Find the next item */ |
|
1984 link = PATHFIND_GET_LINK_PTR(tpf, offs); |
|
1985 /* Check if there is a vehicle on this tile */ |
|
1986 if (SignalVehicleCheck(link->tile, link->flags)) { |
|
1987 ssd->stop = true; |
|
1988 return; |
|
1989 } |
|
1990 /* Goto the next item */ |
|
1991 } while ((offs = link->next) != 0xFFFF); |
|
1992 } |
|
1993 } |
|
1994 } |
|
1995 |
|
1996 static void ChangeSignalStates(SetSignalsData *ssd) |
|
1997 { |
|
1998 int i; |
|
1999 |
|
2000 /* thinking about presignals... |
|
2001 * the presignal is green if, |
|
2002 * if no train is in the segment AND |
|
2003 * there is at least one green exit signal OR |
|
2004 * there are no exit signals in the segment */ |
|
2005 |
|
2006 /* then mark the signals in the segment accordingly */ |
|
2007 for (i = 0; i != ssd->cur; i++) { |
|
2008 TileIndex tile = ssd->tile[i]; |
|
2009 byte bit = SignalAgainstTrackdir(ssd->bit[i]); |
|
2010 uint signals = GetSignalStates(tile); |
|
2011 Track track = TrackdirToTrack(ssd->bit[i]); |
|
2012 |
|
2013 /* presignals don't turn green if there is at least one presignal exit and none are free */ |
|
2014 if (IsPresignalEntry(tile, track)) { |
|
2015 int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free; |
|
2016 |
|
2017 /* subtract for dual combo signals so they don't count themselves */ |
|
2018 if (IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, ssd->bit[i])) { |
|
2019 ex--; |
|
2020 if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--; |
|
2021 } |
|
2022 |
|
2023 /* if we have exits and none are free, make red. */ |
|
2024 if (ex && !exfree) goto make_red; |
|
2025 } |
|
2026 |
|
2027 /* check if the signal is unaffected. */ |
|
2028 if (ssd->stop) { |
|
2029 make_red: |
|
2030 /* turn red */ |
|
2031 if ((bit & signals) == 0) continue; |
|
2032 } else { |
|
2033 /* turn green */ |
|
2034 if ((bit & signals) != 0) continue; |
|
2035 } |
|
2036 |
|
2037 /* Update signals on the other side of this exit-combo signal; it changed. */ |
|
2038 if (IsPresignalExit(tile, track)) { |
|
2039 if (ssd->cur_stack != NUM_SSD_STACK) { |
|
2040 ssd->next_tile[ssd->cur_stack] = tile; |
|
2041 ssd->next_dir[ssd->cur_stack] = TrackdirToExitdir(ssd->bit[i]); |
|
2042 ssd->cur_stack++; |
|
2043 } else { |
|
2044 DEBUG(misc, 0, "NUM_SSD_STACK too small"); /// @todo WTF is this??? |
|
2045 } |
|
2046 } |
|
2047 |
|
2048 /* it changed, so toggle it */ |
|
2049 SetSignalStates(tile, signals ^ bit); |
|
2050 MarkTileDirtyByTile(tile); |
|
2051 } |
|
2052 } |
|
2053 |
|
2054 |
|
2055 bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction) |
|
2056 { |
|
2057 SetSignalsData ssd; |
|
2058 int result = -1; |
|
2059 |
|
2060 ssd.cur_stack = 0; |
|
2061 |
|
2062 for (;;) { |
|
2063 /* go through one segment and update all signals pointing into that segment. */ |
|
2064 ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0; |
|
2065 ssd.has_presignal = false; |
|
2066 |
|
2067 FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, 0, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd); |
|
2068 ChangeSignalStates(&ssd); |
|
2069 |
|
2070 /* remember the result only for the first iteration. */ |
|
2071 if (result < 0) { |
|
2072 /* stay in depot while segment is occupied or while all presignal exits are blocked */ |
|
2073 result = ssd.stop || (ssd.presignal_exits > 0 && ssd.presignal_exits_free == 0); |
|
2074 } |
|
2075 |
|
2076 /* if any exit signals were changed, we need to keep going to modify the stuff behind those. */ |
|
2077 if (ssd.cur_stack == 0) break; |
|
2078 |
|
2079 /* one or more exit signals were changed, so we need to update another segment too. */ |
|
2080 tile = ssd.next_tile[--ssd.cur_stack]; |
|
2081 direction = ssd.next_dir[ssd.cur_stack]; |
|
2082 } |
|
2083 |
|
2084 return result != 0; |
|
2085 } |
|
2086 |
|
2087 void SetSignalsOnBothDir(TileIndex tile, byte track) |
|
2088 { |
|
2089 static const DiagDirection _search_dir_1[] = { |
|
2090 DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE |
|
2091 }; |
|
2092 static const DiagDirection _search_dir_2[] = { |
|
2093 DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE |
|
2094 }; |
|
2095 |
|
2096 UpdateSignalsOnSegment(tile, _search_dir_1[track]); |
|
2097 UpdateSignalsOnSegment(tile, _search_dir_2[track]); |
|
2098 } |
1867 } |
2099 |
1868 |
2100 static uint GetSlopeZ_Track(TileIndex tile, uint x, uint y) |
1869 static uint GetSlopeZ_Track(TileIndex tile, uint x, uint y) |
2101 { |
1870 { |
2102 uint z; |
1871 uint z; |
2358 static const signed char _deltacoord_leaveoffset[8] = { |
2127 static const signed char _deltacoord_leaveoffset[8] = { |
2359 -1, 0, 1, 0, /* x */ |
2128 -1, 0, 1, 0, /* x */ |
2360 0, 1, 0, -1 /* y */ |
2129 0, 1, 0, -1 /* y */ |
2361 }; |
2130 }; |
2362 |
2131 |
2363 static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y) |
2132 static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y) |
2364 { |
2133 { |
2365 byte fract_coord; |
2134 byte fract_coord; |
2366 byte fract_coord_leave; |
2135 byte fract_coord_leave; |
2367 DiagDirection dir; |
2136 DiagDirection dir; |
2368 int length; |
2137 int length; |
2441 case TRACK_BIT_LOWER: track_corner = CORNER_S; break; |
2210 case TRACK_BIT_LOWER: track_corner = CORNER_S; break; |
2442 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; |
2211 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; |
2443 case TRACK_BIT_UPPER: track_corner = CORNER_N; break; |
2212 case TRACK_BIT_UPPER: track_corner = CORNER_N; break; |
2444 |
2213 |
2445 /* Surface slope must not be changed */ |
2214 /* Surface slope must not be changed */ |
2446 default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform); |
2215 default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : CommandCost(EXPENSES_CONSTRUCTION, _price.terraform)); |
2447 } |
2216 } |
2448 |
2217 |
2449 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */ |
2218 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */ |
2450 z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner); |
2219 z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner); |
2451 z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner); |
2220 z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner); |
2452 if (z_old != z_new) return CMD_ERROR; |
2221 if (z_old != z_new) return CMD_ERROR; |
2453 |
2222 |
2454 CommandCost cost = CommandCost(_price.terraform); |
2223 CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
2455 /* Make the ground dirty, if surface slope has changed */ |
2224 /* Make the ground dirty, if surface slope has changed */ |
2456 if (tileh_old != tileh_new) { |
2225 if (tileh_old != tileh_new) { |
2457 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water); |
2226 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water); |
2458 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2227 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2459 } |
2228 } |
2496 |
2265 |
2497 /* Make the ground dirty */ |
2266 /* Make the ground dirty */ |
2498 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2267 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2499 |
2268 |
2500 /* allow terraforming */ |
2269 /* allow terraforming */ |
2501 return (was_water ? CommandCost(_price.clear_water) : CommandCost()); |
2270 return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0); |
2502 } else { |
2271 } else { |
2503 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
2272 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
2504 switch (GetRailTileType(tile)) { |
2273 switch (GetRailTileType(tile)) { |
2505 case RAIL_TILE_WAYPOINT: { |
2274 case RAIL_TILE_WAYPOINT: { |
2506 CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); |
2275 CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); |
2507 if (!CmdFailed(cost)) return cost; // allow autoslope |
2276 if (!CmdFailed(cost)) return cost; // allow autoslope |
2508 break; |
2277 break; |
2509 } |
2278 } |
2510 |
2279 |
2511 case RAIL_TILE_DEPOT: |
2280 case RAIL_TILE_DEPOT: |
2512 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return _price.terraform; |
2281 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
2513 break; |
2282 break; |
2514 |
2283 |
2515 default: NOT_REACHED(); |
2284 default: NOT_REACHED(); |
2516 } |
2285 } |
2517 } |
2286 } |