branch | noai |
changeset 9722 | ebf0ece7d8f6 |
parent 9718 | f82a4facea8b |
child 9723 | eee46cb39750 |
9721:9a27928bcd5e | 9722:ebf0ece7d8f6 |
---|---|
38 #include "newgrf_callbacks.h" |
38 #include "newgrf_callbacks.h" |
39 #include "newgrf_station.h" |
39 #include "newgrf_station.h" |
40 #include "train.h" |
40 #include "train.h" |
41 #include "misc/autoptr.hpp" |
41 #include "misc/autoptr.hpp" |
42 #include "autoslope.h" |
42 #include "autoslope.h" |
43 #include "transparency.h" |
|
43 |
44 |
44 const byte _track_sloped_sprites[14] = { |
45 const byte _track_sloped_sprites[14] = { |
45 14, 15, 22, 13, |
46 14, 15, 22, 13, |
46 0, 21, 17, 12, |
47 0, 21, 17, 12, |
47 23, 0, 18, 20, |
48 23, 0, 18, 20, |
213 /* Get higher track */ |
214 /* Get higher track */ |
214 Corner highest_corner = GetHighestSlopeCorner(tileh); |
215 Corner highest_corner = GetHighestSlopeCorner(tileh); |
215 TrackBits higher_track = CornerToTrackBits(highest_corner); |
216 TrackBits higher_track = CornerToTrackBits(highest_corner); |
216 |
217 |
217 /* Only higher track? */ |
218 /* Only higher track? */ |
218 if (bits == higher_track) return FOUNDATION_STEEP_HIGHER; |
219 if (bits == higher_track) return HalftileFoundation(highest_corner); |
219 |
220 |
220 /* Overlap with higher track? */ |
221 /* Overlap with higher track? */ |
221 if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID; |
222 if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID; |
222 |
223 |
223 /* either lower track or both higher and lower track */ |
224 /* either lower track or both higher and lower track */ |
224 return ((bits & higher_track) != 0 ? FOUNDATION_INVALID : FOUNDATION_STEEP_LOWER); |
225 return ((bits & higher_track) != 0 ? FOUNDATION_STEEP_BOTH : FOUNDATION_STEEP_LOWER); |
225 } else { |
226 } else { |
226 if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE; |
227 if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE; |
227 |
228 |
228 bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0); |
229 bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0); |
229 |
230 |
231 Corner track_corner; |
|
230 switch (bits) { |
232 switch (bits) { |
233 case TRACK_BIT_LEFT: track_corner = CORNER_W; break; |
|
234 case TRACK_BIT_LOWER: track_corner = CORNER_S; break; |
|
235 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; |
|
236 case TRACK_BIT_UPPER: track_corner = CORNER_N; break; |
|
237 |
|
238 case TRACK_BIT_HORZ: |
|
239 if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N); |
|
240 if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S); |
|
241 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
|
242 |
|
243 case TRACK_BIT_VERT: |
|
244 if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W); |
|
245 if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E); |
|
246 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
|
247 |
|
231 case TRACK_BIT_X: |
248 case TRACK_BIT_X: |
232 if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X; |
249 if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X; |
233 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
250 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
234 |
251 |
235 case TRACK_BIT_Y: |
252 case TRACK_BIT_Y: |
237 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
254 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
238 |
255 |
239 default: |
256 default: |
240 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
257 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
241 } |
258 } |
259 /* Single diagonal track */ |
|
260 |
|
261 /* Track must be at least valid on leveled foundation */ |
|
262 if (!valid_on_leveled) return FOUNDATION_INVALID; |
|
263 |
|
264 /* If slope has three raised corners, build leveled foundation */ |
|
265 if (HasSlopeHighestCorner(ComplementSlope(tileh))) return FOUNDATION_LEVELED; |
|
266 |
|
267 /* If neighboured corners of track_corner are lowered, build halftile foundation */ |
|
268 if ((tileh & SlopeWithThreeCornersRaised(OppositeCorner(track_corner))) == SlopeWithOneCornerRaised(track_corner)) return HalftileFoundation(track_corner); |
|
269 |
|
270 /* else special anti-zig-zag foundation */ |
|
271 return SpecialRailFoundation(track_corner); |
|
242 } |
272 } |
243 } |
273 } |
244 |
274 |
245 |
275 |
246 /** |
276 /** |
253 * @return Error message or cost for foundation building. |
283 * @return Error message or cost for foundation building. |
254 */ |
284 */ |
255 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile) |
285 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile) |
256 { |
286 { |
257 /* don't allow building on the lower side of a coast */ |
287 /* don't allow building on the lower side of a coast */ |
258 if (IsTileType(tile, MP_WATER)) { |
288 if (IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_RAILWAY) && (GetRailGroundType(tile) == RAIL_GROUND_WATER))) { |
259 if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
289 if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
260 } |
290 } |
261 |
291 |
262 Foundation f_new = GetRailFoundation(tileh, rail_bits | existing); |
292 Foundation f_new = GetRailFoundation(tileh, rail_bits | existing); |
263 |
293 |
265 if ((f_new == FOUNDATION_INVALID) || |
295 if ((f_new == FOUNDATION_INVALID) || |
266 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes)) |
296 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes)) |
267 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
297 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
268 |
298 |
269 Foundation f_old = GetRailFoundation(tileh, existing); |
299 Foundation f_old = GetRailFoundation(tileh, existing); |
270 return CommandCost(f_new != f_old ? _price.terraform : 0); |
300 return CommandCost(f_new != f_old ? _price.terraform : (Money)0); |
271 } |
301 } |
272 |
302 |
273 /* Validate functions for rail building */ |
303 /* Validate functions for rail building */ |
274 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
304 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
275 |
305 |
328 break; |
358 break; |
329 |
359 |
330 case MP_ROAD: |
360 case MP_ROAD: |
331 #define M(x) (1 << (x)) |
361 #define M(x) (1 << (x)) |
332 /* Level crossings may only be built on these slopes */ |
362 /* Level crossings may only be built on these slopes */ |
333 if (!HASBIT(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) { |
363 if (!HasBit(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) { |
334 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
364 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
335 } |
365 } |
336 #undef M |
366 #undef M |
337 |
367 |
338 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
368 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
374 return_cmd_error(STR_1007_ALREADY_BUILT); |
404 return_cmd_error(STR_1007_ALREADY_BUILT); |
375 } |
405 } |
376 /* FALLTHROUGH */ |
406 /* FALLTHROUGH */ |
377 |
407 |
378 default: |
408 default: |
409 bool water_ground = IsTileType(tile, MP_WATER) && !IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh); |
|
410 |
|
379 ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile); |
411 ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile); |
380 if (CmdFailed(ret)) return ret; |
412 if (CmdFailed(ret)) return ret; |
381 cost.AddCost(ret); |
413 cost.AddCost(ret); |
382 |
414 |
383 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
415 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
384 if (CmdFailed(ret)) return ret; |
416 if (CmdFailed(ret)) return ret; |
385 cost.AddCost(ret); |
417 cost.AddCost(ret); |
386 |
418 |
387 if (flags & DC_EXEC) MakeRailNormal(tile, _current_player, trackbit, railtype); |
419 if (water_ground) { |
420 cost.AddCost(-_price.clear_water); |
|
421 cost.AddCost(_price.purchase_land); |
|
422 } |
|
423 |
|
424 if (flags & DC_EXEC) { |
|
425 MakeRailNormal(tile, _current_player, trackbit, railtype); |
|
426 if (water_ground) SetRailGroundType(tile, RAIL_GROUND_WATER); |
|
427 } |
|
388 break; |
428 break; |
389 } |
429 } |
390 |
430 |
391 if (flags & DC_EXEC) { |
431 if (flags & DC_EXEC) { |
392 MarkTileDirtyByTile(tile); |
432 MarkTileDirtyByTile(tile); |
448 cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS)); |
488 cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS)); |
449 |
489 |
450 if (flags & DC_EXEC) { |
490 if (flags & DC_EXEC) { |
451 present ^= trackbit; |
491 present ^= trackbit; |
452 if (present == 0) { |
492 if (present == 0) { |
453 DoClearSquare(tile); |
493 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) { |
494 MakeShore(tile); |
|
495 } else { |
|
496 DoClearSquare(tile); |
|
497 } |
|
454 } else { |
498 } else { |
455 SetTrackBits(tile, present); |
499 SetTrackBits(tile, present); |
456 } |
500 } |
457 } |
501 } |
458 break; |
502 break; |
480 |
524 |
481 return cost; |
525 return cost; |
482 } |
526 } |
483 |
527 |
484 |
528 |
529 /** |
|
530 * Called from water_cmd if a non-flat rail-tile gets flooded and should be converted to shore. |
|
531 * The function floods the lower halftile, if the tile has a halftile foundation. |
|
532 * |
|
533 * @param t The tile to flood. |
|
534 */ |
|
535 void FloodHalftile(TileIndex t) |
|
536 { |
|
537 if (GetRailGroundType(t) == RAIL_GROUND_WATER) return; |
|
538 |
|
539 Slope tileh = GetTileSlope(t, NULL); |
|
540 TrackBits rail_bits = GetTrackBits(t); |
|
541 |
|
542 if (!IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh)) { |
|
543 TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh))); |
|
544 |
|
545 TrackBits to_remove = lower_track & rail_bits; |
|
546 if (to_remove != 0) { |
|
547 _current_player = OWNER_WATER; |
|
548 if (CmdFailed(DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL))) return; // not yet floodable |
|
549 rail_bits = rail_bits & ~to_remove; |
|
550 if (rail_bits == 0) { |
|
551 MakeShore(t); |
|
552 MarkTileDirtyByTile(t); |
|
553 return; |
|
554 } |
|
555 } |
|
556 |
|
557 if (IsNonContinuousFoundation(GetRailFoundation(tileh, rail_bits))) { |
|
558 SetRailGroundType(t, RAIL_GROUND_WATER); |
|
559 MarkTileDirtyByTile(t); |
|
560 } |
|
561 } |
|
562 } |
|
563 |
|
485 static const TileIndexDiffC _trackdelta[] = { |
564 static const TileIndexDiffC _trackdelta[] = { |
486 { -1, 0 }, { 0, 1 }, { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, 1 }, |
565 { -1, 0 }, { 0, 1 }, { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, 1 }, |
487 { 0, 0 }, |
566 { 0, 0 }, |
488 { 0, 0 }, |
567 { 0, 0 }, |
489 { 1, 0 }, { 0, -1 }, { 0, -1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }, |
568 { 1, 0 }, { 0, -1 }, { 0, -1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }, |
520 (trdx <= 0 && dx > 0) || |
599 (trdx <= 0 && dx > 0) || |
521 (trdx >= 0 && dx < 0) || |
600 (trdx >= 0 && dx < 0) || |
522 (trdy <= 0 && dy > 0) || |
601 (trdy <= 0 && dy > 0) || |
523 (trdy >= 0 && dy < 0) |
602 (trdy >= 0 && dy < 0) |
524 ) { |
603 ) { |
525 if (!HASBIT(*trackdir, 3)) { // first direction is invalid, try the other |
604 if (!HasBit(*trackdir, 3)) { // first direction is invalid, try the other |
526 SetBitT(*trackdir, 3); // reverse the direction |
605 SetBit(*trackdir, 3); // reverse the direction |
527 trdx = -trdx; |
606 trdx = -trdx; |
528 trdy = -trdy; |
607 trdy = -trdy; |
529 } else { // other direction is invalid too, invalid drag |
608 } else { // other direction is invalid too, invalid drag |
530 return CMD_ERROR; |
609 return CMD_ERROR; |
531 } |
610 } |
555 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
634 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
556 { |
635 { |
557 CommandCost ret, total_cost; |
636 CommandCost ret, total_cost; |
558 Track track = (Track)GB(p2, 4, 3); |
637 Track track = (Track)GB(p2, 4, 3); |
559 Trackdir trackdir; |
638 Trackdir trackdir; |
560 byte mode = HASBIT(p2, 7); |
639 byte mode = HasBit(p2, 7); |
561 RailType railtype = (RailType)GB(p2, 0, 4); |
640 RailType railtype = (RailType)GB(p2, 0, 4); |
562 TileIndex end_tile; |
641 TileIndex end_tile; |
563 |
642 |
564 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
643 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
565 if (p1 >= MapSize()) return CMD_ERROR; |
644 if (p1 >= MapSize()) return CMD_ERROR; |
585 if (tile == end_tile) break; |
664 if (tile == end_tile) break; |
586 |
665 |
587 tile += ToTileIndexDiff(_trackdelta[trackdir]); |
666 tile += ToTileIndexDiff(_trackdelta[trackdir]); |
588 |
667 |
589 /* toggle railbit for the non-diagonal tracks */ |
668 /* toggle railbit for the non-diagonal tracks */ |
590 if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0); |
669 if (!IsDiagonalTrackdir(trackdir)) ToggleBit(trackdir, 0); |
591 } |
670 } |
592 |
671 |
593 return (total_cost.GetCost() == 0) ? CMD_ERROR : total_cost; |
672 return (total_cost.GetCost() == 0) ? CMD_ERROR : total_cost; |
594 } |
673 } |
595 |
674 |
604 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
683 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
605 * @see CmdRailTrackHelper |
684 * @see CmdRailTrackHelper |
606 */ |
685 */ |
607 CommandCost CmdBuildRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
686 CommandCost CmdBuildRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
608 { |
687 { |
609 return CmdRailTrackHelper(tile, flags, p1, CLRBIT(p2, 7)); |
688 return CmdRailTrackHelper(tile, flags, p1, ClrBit(p2, 7)); |
610 } |
689 } |
611 |
690 |
612 /** Build rail on a stretch of track. |
691 /** Build rail on a stretch of track. |
613 * Stub for the unified rail builder/remover |
692 * Stub for the unified rail builder/remover |
614 * @param tile start tile of drag |
693 * @param tile start tile of drag |
620 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
699 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
621 * @see CmdRailTrackHelper |
700 * @see CmdRailTrackHelper |
622 */ |
701 */ |
623 CommandCost CmdRemoveRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
702 CommandCost CmdRemoveRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
624 { |
703 { |
625 return CmdRailTrackHelper(tile, flags, p1, SETBIT(p2, 7)); |
704 return CmdRailTrackHelper(tile, flags, p1, SetBit(p2, 7)); |
626 } |
705 } |
627 |
706 |
628 /** Build a train depot |
707 /** Build a train depot |
629 * @param tile position of the train depot |
708 * @param tile position of the train depot |
630 * @param flags operation to perform |
709 * @param flags operation to perform |
701 * TODO: p2 should be replaced by two bits for "along" and "against" the track. |
780 * TODO: p2 should be replaced by two bits for "along" and "against" the track. |
702 */ |
781 */ |
703 CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
782 CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
704 { |
783 { |
705 Track track = (Track)GB(p1, 0, 3); |
784 Track track = (Track)GB(p1, 0, 3); |
706 bool pre_signal = HASBIT(p1, 3); |
785 bool pre_signal = HasBit(p1, 3); |
707 SignalVariant sigvar = (pre_signal ^ HASBIT(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; |
786 SignalVariant sigvar = (pre_signal ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; |
708 CommandCost cost; |
787 CommandCost cost; |
709 |
788 |
710 if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track)) |
789 if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track)) |
711 return CMD_ERROR; |
790 return CMD_ERROR; |
712 |
791 |
721 _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; |
800 _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; |
722 |
801 |
723 { |
802 { |
724 /* See if this is a valid track combination for signals, (ie, no overlap) */ |
803 /* See if this is a valid track combination for signals, (ie, no overlap) */ |
725 TrackBits trackbits = GetTrackBits(tile); |
804 TrackBits trackbits = GetTrackBits(tile); |
726 if (KILL_FIRST_BIT(trackbits) != 0 && /* More than one track present */ |
805 if (KillFirstBit(trackbits) != TRACK_BIT_NONE && /* More than one track present */ |
727 trackbits != TRACK_BIT_HORZ && |
806 trackbits != TRACK_BIT_HORZ && |
728 trackbits != TRACK_BIT_VERT) { |
807 trackbits != TRACK_BIT_VERT) { |
729 return CMD_ERROR; |
808 return CMD_ERROR; |
730 } |
809 } |
731 } |
810 } |
813 if (!remove && HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) return false; |
892 if (!remove && HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) return false; |
814 signal_ctr++; |
893 signal_ctr++; |
815 if (IsDiagonalTrackdir(trackdir)) { |
894 if (IsDiagonalTrackdir(trackdir)) { |
816 signal_ctr++; |
895 signal_ctr++; |
817 /* Ensure signal_ctr even so X and Y pieces get signals */ |
896 /* Ensure signal_ctr even so X and Y pieces get signals */ |
818 CLRBIT(signal_ctr, 0); |
897 ClrBit(signal_ctr, 0); |
819 } |
898 } |
820 return true; |
899 return true; |
821 |
900 |
822 case MP_ROAD: |
901 case MP_ROAD: |
823 if (!IsLevelCrossing(tile)) return false; |
902 if (!IsLevelCrossing(tile)) return false; |
864 bool error = true; |
943 bool error = true; |
865 TileIndex end_tile; |
944 TileIndex end_tile; |
866 TileIndex start_tile = tile; |
945 TileIndex start_tile = tile; |
867 |
946 |
868 Track track = (Track)GB(p2, 0, 3); |
947 Track track = (Track)GB(p2, 0, 3); |
869 bool mode = HASBIT(p2, 3); |
948 bool mode = HasBit(p2, 3); |
870 bool semaphores = HASBIT(p2, 4); |
949 bool semaphores = HasBit(p2, 4); |
871 bool remove = HASBIT(p2, 5); |
950 bool remove = HasBit(p2, 5); |
872 bool autofill = HASBIT(p2, 6); |
951 bool autofill = HasBit(p2, 6); |
873 Trackdir trackdir = TrackToTrackdir(track); |
952 Trackdir trackdir = TrackToTrackdir(track); |
874 byte signal_density = GB(p2, 24, 8); |
953 byte signal_density = GB(p2, 24, 8); |
875 |
954 |
876 if (p1 >= MapSize()) return CMD_ERROR; |
955 if (p1 >= MapSize()) return CMD_ERROR; |
877 end_tile = p1; |
956 end_tile = p1; |
903 } else { // no signals exist, drag a two-way signal stretch |
982 } else { // no signals exist, drag a two-way signal stretch |
904 signals = SignalOnTrack(track); |
983 signals = SignalOnTrack(track); |
905 } |
984 } |
906 |
985 |
907 byte signal_dir = 0; |
986 byte signal_dir = 0; |
908 if (signals & SignalAlongTrackdir(trackdir)) SETBIT(signal_dir, 0); |
987 if (signals & SignalAlongTrackdir(trackdir)) SetBit(signal_dir, 0); |
909 if (signals & SignalAgainstTrackdir(trackdir)) SETBIT(signal_dir, 1); |
988 if (signals & SignalAgainstTrackdir(trackdir)) SetBit(signal_dir, 1); |
910 |
989 |
911 /* signal_ctr - amount of tiles already processed |
990 /* signal_ctr - amount of tiles already processed |
912 * signals_density - patch setting to put signal on every Nth tile (double space on |, -- tracks) |
991 * signals_density - patch setting to put signal on every Nth tile (double space on |, -- tracks) |
913 ********** |
992 ********** |
914 * trackdir - trackdir to build with autorail |
993 * trackdir - trackdir to build with autorail |
924 SB(p1, 3, 1, mode); |
1003 SB(p1, 3, 1, mode); |
925 SB(p1, 4, 1, semaphores); |
1004 SB(p1, 4, 1, semaphores); |
926 |
1005 |
927 /* Pick the correct orientation for the track direction */ |
1006 /* Pick the correct orientation for the track direction */ |
928 signals = 0; |
1007 signals = 0; |
929 if (HASBIT(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir); |
1008 if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir); |
930 if (HASBIT(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir); |
1009 if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir); |
931 |
1010 |
932 ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); |
1011 ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); |
933 |
1012 |
934 /* Be user-friendly and try placing signals as much as possible */ |
1013 /* Be user-friendly and try placing signals as much as possible */ |
935 if (CmdSucceeded(ret)) { |
1014 if (CmdSucceeded(ret)) { |
951 |
1030 |
952 /* toggle railbit for the non-diagonal tracks (|, -- tracks) */ |
1031 /* toggle railbit for the non-diagonal tracks (|, -- tracks) */ |
953 if (IsDiagonalTrackdir(trackdir)) { |
1032 if (IsDiagonalTrackdir(trackdir)) { |
954 signal_ctr++; |
1033 signal_ctr++; |
955 } else { |
1034 } else { |
956 ToggleBitT(trackdir, 0); |
1035 ToggleBit(trackdir, 0); |
957 } |
1036 } |
958 } |
1037 } |
959 } |
1038 } |
960 |
1039 |
961 return error ? CMD_ERROR : total_cost; |
1040 return error ? CMD_ERROR : total_cost; |
1039 * - p2 = (bit 24-31) - user defined signals_density |
1118 * - p2 = (bit 24-31) - user defined signals_density |
1040 * @see CmdSignalTrackHelper |
1119 * @see CmdSignalTrackHelper |
1041 */ |
1120 */ |
1042 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1121 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1043 { |
1122 { |
1044 return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 5)); // bit 5 is remove bit |
1123 return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5)); // bit 5 is remove bit |
1045 } |
1124 } |
1046 |
1125 |
1047 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec); |
1126 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec); |
1048 |
1127 |
1049 void *UpdateTrainPowerProc(Vehicle *v, void *data) |
1128 void *UpdateTrainPowerProc(Vehicle *v, void *data) |
1212 } |
1291 } |
1213 |
1292 |
1214 switch (GetRailTileType(tile)) { |
1293 switch (GetRailTileType(tile)) { |
1215 case RAIL_TILE_SIGNALS: |
1294 case RAIL_TILE_SIGNALS: |
1216 case RAIL_TILE_NORMAL: { |
1295 case RAIL_TILE_NORMAL: { |
1296 bool water_ground = (GetRailGroundType(tile) == RAIL_GROUND_WATER); |
|
1297 |
|
1217 TrackBits tracks = GetTrackBits(tile); |
1298 TrackBits tracks = GetTrackBits(tile); |
1218 while (tracks != TRACK_BIT_NONE) { |
1299 while (tracks != TRACK_BIT_NONE) { |
1219 Track track = RemoveFirstTrack(&tracks); |
1300 Track track = RemoveFirstTrack(&tracks); |
1220 ret = DoCommand(tile, 0, track, flags, CMD_REMOVE_SINGLE_RAIL); |
1301 ret = DoCommand(tile, 0, track, flags, CMD_REMOVE_SINGLE_RAIL); |
1221 if (CmdFailed(ret)) return CMD_ERROR; |
1302 if (CmdFailed(ret)) return CMD_ERROR; |
1222 cost.AddCost(ret); |
1303 cost.AddCost(ret); |
1223 } |
1304 } |
1305 |
|
1306 if (water_ground) { |
|
1307 /* The track was removed, and left a coast tile. Now also clear the water. */ |
|
1308 if (flags & DC_EXEC) DoClearSquare(tile); |
|
1309 cost.AddCost(_price.clear_water); |
|
1310 } |
|
1311 |
|
1224 return cost; |
1312 return cost; |
1225 } |
1313 } |
1226 |
1314 |
1227 case RAIL_TILE_DEPOT: |
1315 case RAIL_TILE_DEPOT: |
1228 return RemoveTrainDepot(tile, flags); |
1316 return RemoveTrainDepot(tile, flags); |
1234 return CMD_ERROR; |
1322 return CMD_ERROR; |
1235 } |
1323 } |
1236 } |
1324 } |
1237 |
1325 |
1238 #include "table/track_land.h" |
1326 #include "table/track_land.h" |
1327 |
|
1328 /** |
|
1329 * Get surface height in point (x,y) |
|
1330 * On tiles with halftile foundations move (x,y) to a save point wrt. track |
|
1331 */ |
|
1332 static uint GetSaveSlopeZ(uint x, uint y, Track track) |
|
1333 { |
|
1334 switch (track) { |
|
1335 case TRACK_UPPER: x &= ~0xF; y &= ~0xF; break; |
|
1336 case TRACK_LOWER: x |= 0xF; y |= 0xF; break; |
|
1337 case TRACK_LEFT: x |= 0xF; y &= ~0xF; break; |
|
1338 case TRACK_RIGHT: x &= ~0xF; y |= 0xF; break; |
|
1339 default: break; |
|
1340 } |
|
1341 return GetSlopeZ(x, y); |
|
1342 } |
|
1239 |
1343 |
1240 static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos) |
1344 static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos) |
1241 { |
1345 { |
1242 bool side = (_opt.road_side != 0) && _patches.signal_side; |
1346 bool side = (_opt.road_side != 0) && _patches.signal_side; |
1243 static const Point SignalPositions[2][12] = { |
1347 static const Point SignalPositions[2][12] = { |
1269 uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x; |
1373 uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x; |
1270 uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y; |
1374 uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y; |
1271 |
1375 |
1272 SpriteID sprite; |
1376 SpriteID sprite; |
1273 |
1377 |
1274 /* _signal_base is set by our NewGRF Action 5 loader. If it is 0 then we |
1378 if (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC) { |
1275 * just draw the standard signals, else we get the offset from _signal_base |
|
1276 * and draw that sprite. All the signal sprites are loaded sequentially. */ |
|
1277 if (_signal_base == 0 || (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC)) { |
|
1278 sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition; |
1379 sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition; |
1279 } else { |
1380 } else { |
1280 sprite = _signal_base + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition; |
1381 sprite = SPR_SIGNALS_BASE + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition; |
1281 } |
1382 } |
1282 |
1383 |
1283 AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSlopeZ(x,y)); |
1384 AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); |
1284 } |
1385 } |
1285 |
1386 |
1286 static uint32 _drawtile_track_palette; |
1387 static uint32 _drawtile_track_palette; |
1287 |
1388 |
1288 |
1389 |
1335 */ |
1436 */ |
1336 static void DrawTrackFence_NS_1(const TileInfo *ti) |
1437 static void DrawTrackFence_NS_1(const TileInfo *ti) |
1337 { |
1438 { |
1338 int z = ti->z; |
1439 int z = ti->z; |
1339 if (ti->tileh & SLOPE_W) z += TILE_HEIGHT; |
1440 if (ti->tileh & SLOPE_W) z += TILE_HEIGHT; |
1441 if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT; |
|
1340 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette, |
1442 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette, |
1341 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1443 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1342 } |
1444 } |
1343 |
1445 |
1344 /** |
1446 /** |
1346 */ |
1448 */ |
1347 static void DrawTrackFence_NS_2(const TileInfo *ti) |
1449 static void DrawTrackFence_NS_2(const TileInfo *ti) |
1348 { |
1450 { |
1349 int z = ti->z; |
1451 int z = ti->z; |
1350 if (ti->tileh & SLOPE_E) z += TILE_HEIGHT; |
1452 if (ti->tileh & SLOPE_E) z += TILE_HEIGHT; |
1453 if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT; |
|
1351 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette, |
1454 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette, |
1352 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1455 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1353 } |
1456 } |
1354 |
1457 |
1355 /** |
1458 /** |
1357 */ |
1460 */ |
1358 static void DrawTrackFence_WE_1(const TileInfo *ti) |
1461 static void DrawTrackFence_WE_1(const TileInfo *ti) |
1359 { |
1462 { |
1360 int z = ti->z; |
1463 int z = ti->z; |
1361 if (ti->tileh & SLOPE_N) z += TILE_HEIGHT; |
1464 if (ti->tileh & SLOPE_N) z += TILE_HEIGHT; |
1465 if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT; |
|
1362 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette, |
1466 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette, |
1363 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1467 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1364 } |
1468 } |
1365 |
1469 |
1366 /** |
1470 /** |
1368 */ |
1472 */ |
1369 static void DrawTrackFence_WE_2(const TileInfo *ti) |
1473 static void DrawTrackFence_WE_2(const TileInfo *ti) |
1370 { |
1474 { |
1371 int z = ti->z; |
1475 int z = ti->z; |
1372 if (ti->tileh & SLOPE_S) z += TILE_HEIGHT; |
1476 if (ti->tileh & SLOPE_S) z += TILE_HEIGHT; |
1477 if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT; |
|
1373 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette, |
1478 AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette, |
1374 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1479 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); |
1375 } |
1480 } |
1376 |
1481 |
1377 |
1482 |
1386 case RAIL_GROUND_FENCE_NESW: DrawTrackFence_NE_SW(ti); break; |
1491 case RAIL_GROUND_FENCE_NESW: DrawTrackFence_NE_SW(ti); break; |
1387 case RAIL_GROUND_FENCE_VERT1: DrawTrackFence_NS_1(ti); break; |
1492 case RAIL_GROUND_FENCE_VERT1: DrawTrackFence_NS_1(ti); break; |
1388 case RAIL_GROUND_FENCE_VERT2: DrawTrackFence_NS_2(ti); break; |
1493 case RAIL_GROUND_FENCE_VERT2: DrawTrackFence_NS_2(ti); break; |
1389 case RAIL_GROUND_FENCE_HORIZ1: DrawTrackFence_WE_1(ti); break; |
1494 case RAIL_GROUND_FENCE_HORIZ1: DrawTrackFence_WE_1(ti); break; |
1390 case RAIL_GROUND_FENCE_HORIZ2: DrawTrackFence_WE_2(ti); break; |
1495 case RAIL_GROUND_FENCE_HORIZ2: DrawTrackFence_WE_2(ti); break; |
1496 case RAIL_GROUND_WATER: |
|
1497 switch (GetHalftileSlopeCorner(ti->tileh)) { |
|
1498 case CORNER_W: DrawTrackFence_NS_1(ti); break; |
|
1499 case CORNER_S: DrawTrackFence_WE_2(ti); break; |
|
1500 case CORNER_E: DrawTrackFence_NS_2(ti); break; |
|
1501 case CORNER_N: DrawTrackFence_WE_1(ti); break; |
|
1502 default: NOT_REACHED(); |
|
1503 } |
|
1504 break; |
|
1391 default: break; |
1505 default: break; |
1392 } |
1506 } |
1393 } |
1507 } |
1394 |
1508 |
1395 |
1509 |
1399 * @param track TrackBits to draw |
1513 * @param track TrackBits to draw |
1400 */ |
1514 */ |
1401 static void DrawTrackBits(TileInfo* ti, TrackBits track) |
1515 static void DrawTrackBits(TileInfo* ti, TrackBits track) |
1402 { |
1516 { |
1403 const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); |
1517 const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); |
1518 RailGroundType rgt = GetRailGroundType(ti->tile); |
|
1519 Foundation f = GetRailFoundation(ti->tileh, track); |
|
1520 Corner halftile_corner = CORNER_INVALID; |
|
1521 |
|
1522 if (IsNonContinuousFoundation(f)) { |
|
1523 /* Save halftile corner */ |
|
1524 halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f)); |
|
1525 /* Draw lower part first */ |
|
1526 track &= ~CornerToTrackBits(halftile_corner); |
|
1527 f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE); |
|
1528 } |
|
1529 |
|
1530 DrawFoundation(ti, f); |
|
1531 /* DrawFoundation modifies ti */ |
|
1532 |
|
1404 SpriteID image; |
1533 SpriteID image; |
1405 SpriteID pal = PAL_NONE; |
1534 SpriteID pal = PAL_NONE; |
1406 bool junction = false; |
1535 bool junction = false; |
1407 |
1536 |
1408 /* Select the sprite to use. */ |
1537 /* Select the sprite to use. */ |
1409 (image = rti->base_sprites.track_y, track == TRACK_BIT_Y) || |
1538 if (track == 0) { |
1410 (image++, track == TRACK_BIT_X) || |
1539 /* Clear ground (only track on halftile foundation) */ |
1411 (image++, track == TRACK_BIT_UPPER) || |
1540 if (rgt == RAIL_GROUND_WATER) { |
1412 (image++, track == TRACK_BIT_LOWER) || |
1541 image = SPR_FLAT_WATER_TILE; |
1413 (image++, track == TRACK_BIT_RIGHT) || |
1542 } else { |
1414 (image++, track == TRACK_BIT_LEFT) || |
1543 switch (rgt) { |
1415 (image++, track == TRACK_BIT_CROSS) || |
1544 case RAIL_GROUND_BARREN: image = SPR_FLAT_BARE_LAND; break; |
1416 |
1545 case RAIL_GROUND_ICE_DESERT: image = SPR_FLAT_SNOWY_TILE; break; |
1417 (image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) || |
1546 default: image = SPR_FLAT_GRASS_TILE; break; |
1418 (image++, track == TRACK_BIT_VERT) || |
1547 } |
1419 |
1548 image += _tileh_to_sprite[ti->tileh]; |
1420 (junction = true, false) || |
1549 } |
1421 (image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) || |
1550 } else { |
1422 (image++, (track & TRACK_BIT_3WAY_SW) == 0) || |
1551 if (ti->tileh != SLOPE_FLAT) { |
1423 (image++, (track & TRACK_BIT_3WAY_NW) == 0) || |
1552 /* track on non-flat ground */ |
1424 (image++, (track & TRACK_BIT_3WAY_SE) == 0) || |
1553 image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y; |
1425 (image++, true); |
1554 } else { |
1426 |
1555 /* track on flat ground */ |
1427 if (ti->tileh != SLOPE_FLAT) { |
1556 (image = rti->base_sprites.track_y, track == TRACK_BIT_Y) || |
1428 DrawFoundation(ti, GetRailFoundation(ti->tileh, track)); |
1557 (image++, track == TRACK_BIT_X) || |
1429 |
1558 (image++, track == TRACK_BIT_UPPER) || |
1430 /* DrawFoundation() modifies it. |
1559 (image++, track == TRACK_BIT_LOWER) || |
1431 * Default sloped sprites.. */ |
1560 (image++, track == TRACK_BIT_RIGHT) || |
1432 if (ti->tileh != SLOPE_FLAT) image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y; |
1561 (image++, track == TRACK_BIT_LEFT) || |
1433 } |
1562 (image++, track == TRACK_BIT_CROSS) || |
1434 |
1563 |
1435 switch (GetRailGroundType(ti->tile)) { |
1564 (image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) || |
1436 case RAIL_GROUND_BARREN: pal = PALETTE_TO_BARE_LAND; break; |
1565 (image++, track == TRACK_BIT_VERT) || |
1437 case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break; |
1566 |
1438 default: break; |
1567 (junction = true, false) || |
1568 (image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) || |
|
1569 (image++, (track & TRACK_BIT_3WAY_SW) == 0) || |
|
1570 (image++, (track & TRACK_BIT_3WAY_NW) == 0) || |
|
1571 (image++, (track & TRACK_BIT_3WAY_SE) == 0) || |
|
1572 (image++, true); |
|
1573 } |
|
1574 |
|
1575 switch (rgt) { |
|
1576 case RAIL_GROUND_BARREN: pal = PALETTE_TO_BARE_LAND; break; |
|
1577 case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break; |
|
1578 case RAIL_GROUND_WATER: NOT_REACHED(); |
|
1579 default: break; |
|
1580 } |
|
1439 } |
1581 } |
1440 |
1582 |
1441 DrawGroundSprite(image, pal); |
1583 DrawGroundSprite(image, pal); |
1442 |
1584 |
1443 /* Draw track pieces individually for junction tiles */ |
1585 /* Draw track pieces individually for junction tiles */ |
1447 if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE); |
1589 if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE); |
1448 if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE); |
1590 if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE); |
1449 if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE); |
1591 if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE); |
1450 if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE); |
1592 if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE); |
1451 } |
1593 } |
1594 |
|
1595 if (IsValidCorner(halftile_corner)) { |
|
1596 DrawFoundation(ti, HalftileFoundation(halftile_corner)); |
|
1597 |
|
1598 /* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */ |
|
1599 Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner)); |
|
1600 image = _track_sloped_sprites[fake_slope - 1] + rti->base_sprites.track_y; |
|
1601 pal = PAL_NONE; |
|
1602 switch (rgt) { |
|
1603 case RAIL_GROUND_BARREN: pal = PALETTE_TO_BARE_LAND; break; |
|
1604 case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break; |
|
1605 default: break; |
|
1606 } |
|
1607 |
|
1608 static const int INF = 1000; // big number compared to tilesprite size |
|
1609 static const SubSprite _halftile_sub_sprite[4] = { |
|
1610 { -INF , -INF , 32 - 33, INF }, // CORNER_W, clip 33 pixels from right |
|
1611 { -INF , 0 + 7, INF , INF }, // CORNER_S, clip 7 pixels from top |
|
1612 { -31 + 33, -INF , INF , INF }, // CORNER_E, clip 33 pixels from left |
|
1613 { -INF , -INF , INF , 30 - 23 } // CORNER_N, clip 23 pixels from bottom |
|
1614 }; |
|
1615 |
|
1616 DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner])); |
|
1617 } |
|
1452 } |
1618 } |
1453 |
1619 |
1454 static void DrawSignals(TileIndex tile, TrackBits rails) |
1620 static void DrawSignals(TileIndex tile, TrackBits rails) |
1455 { |
1621 { |
1456 #define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z) |
1622 #define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z) |
1493 if (IsPlainRailTile(ti->tile)) { |
1659 if (IsPlainRailTile(ti->tile)) { |
1494 TrackBits rails = GetTrackBits(ti->tile); |
1660 TrackBits rails = GetTrackBits(ti->tile); |
1495 |
1661 |
1496 DrawTrackBits(ti, rails); |
1662 DrawTrackBits(ti, rails); |
1497 |
1663 |
1498 if (HASBIT(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti); |
1664 if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti); |
1499 |
1665 |
1500 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
1666 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
1501 |
1667 |
1502 if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails); |
1668 if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails); |
1503 } else { |
1669 } else { |
1533 if (statspec != NULL) { |
1699 if (statspec != NULL) { |
1534 /* emulate station tile - open with building */ |
1700 /* emulate station tile - open with building */ |
1535 const Station* st = ComposeWaypointStation(ti->tile); |
1701 const Station* st = ComposeWaypointStation(ti->tile); |
1536 uint gfx = 2; |
1702 uint gfx = 2; |
1537 |
1703 |
1538 if (HASBIT(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) { |
1704 if (HasBit(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) { |
1539 uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile); |
1705 uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile); |
1540 if (callback != CALLBACK_FAILED) gfx = callback; |
1706 if (callback != CALLBACK_FAILED) gfx = callback; |
1541 } |
1707 } |
1542 |
1708 |
1543 if (statspec->renderdata == NULL) { |
1709 if (statspec->renderdata == NULL) { |
1548 |
1714 |
1549 if (dts != NULL && dts->seq != NULL) { |
1715 if (dts != NULL && dts->seq != NULL) { |
1550 relocation = GetCustomStationRelocation(statspec, st, ti->tile); |
1716 relocation = GetCustomStationRelocation(statspec, st, ti->tile); |
1551 |
1717 |
1552 image = dts->ground_sprite; |
1718 image = dts->ground_sprite; |
1553 if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) { |
1719 if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) { |
1554 image += GetCustomStationGroundRelocation(statspec, st, ti->tile); |
1720 image += GetCustomStationGroundRelocation(statspec, st, ti->tile); |
1555 image += rti->custom_ground_offset; |
1721 image += rti->custom_ground_offset; |
1556 } else { |
1722 } else { |
1557 image += rti->total_offset; |
1723 image += rti->total_offset; |
1558 } |
1724 } |
1578 SpriteID pal; |
1744 SpriteID pal; |
1579 |
1745 |
1580 /* Unlike stations, our default waypoint has no variation for |
1746 /* Unlike stations, our default waypoint has no variation for |
1581 * different railtype, so don't use the railtype offset if |
1747 * different railtype, so don't use the railtype offset if |
1582 * no relocation is set */ |
1748 * no relocation is set */ |
1583 if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) { |
1749 if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) { |
1584 image += rti->total_offset; |
1750 image += rti->total_offset; |
1585 } else { |
1751 } else { |
1586 image += relocation; |
1752 image += relocation; |
1587 } |
1753 } |
1588 |
1754 |
1589 if (!HASBIT(_transparent_opt, TO_BUILDINGS) && HASBIT(image, PALETTE_MODIFIER_COLOR)) { |
1755 if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) { |
1590 pal = _drawtile_track_palette; |
1756 pal = _drawtile_track_palette; |
1591 } else { |
1757 } else { |
1592 pal = dtss->pal; |
1758 pal = dtss->pal; |
1593 } |
1759 } |
1594 |
1760 |
1596 AddSortableSpriteToDraw( |
1762 AddSortableSpriteToDraw( |
1597 image, pal, |
1763 image, pal, |
1598 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
1764 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
1599 dtss->size_x, dtss->size_y, |
1765 dtss->size_x, dtss->size_y, |
1600 dtss->size_z, ti->z + dtss->delta_z, |
1766 dtss->size_z, ti->z + dtss->delta_z, |
1601 HASBIT(_transparent_opt, TO_BUILDINGS) |
1767 IsTransparencySet(TO_BUILDINGS) |
1602 ); |
1768 ); |
1603 } else { |
1769 } else { |
1604 AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); |
1770 AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y); |
1605 } |
1771 } |
1606 } |
1772 } |
1616 DrawSprite(ground, PAL_NONE, x, y); |
1782 DrawSprite(ground, PAL_NONE, x, y); |
1617 for (; dtss->image != 0; dtss++) { |
1783 for (; dtss->image != 0; dtss++) { |
1618 Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); |
1784 Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); |
1619 SpriteID image = dtss->image + offset; |
1785 SpriteID image = dtss->image + offset; |
1620 |
1786 |
1621 DrawSprite(image, HASBIT(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y); |
1787 DrawSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y); |
1622 } |
1788 } |
1623 } |
1789 } |
1624 |
1790 |
1625 void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype) |
1791 void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype) |
1626 { |
1792 { |
1931 |
2097 |
1932 static void TileLoop_Track(TileIndex tile) |
2098 static void TileLoop_Track(TileIndex tile) |
1933 { |
2099 { |
1934 RailGroundType old_ground = GetRailGroundType(tile); |
2100 RailGroundType old_ground = GetRailGroundType(tile); |
1935 RailGroundType new_ground; |
2101 RailGroundType new_ground; |
2102 |
|
2103 if (old_ground == RAIL_GROUND_WATER) { |
|
2104 TileLoop_Water(tile); |
|
2105 return; |
|
2106 } |
|
1936 |
2107 |
1937 switch (_opt.landscape) { |
2108 switch (_opt.landscape) { |
1938 case LT_ARCTIC: |
2109 case LT_ARCTIC: |
1939 if (GetTileZ(tile) > GetSnowLine()) { |
2110 if (GetTileZ(tile) > GetSnowLine()) { |
1940 new_ground = RAIL_GROUND_ICE_DESERT; |
2111 new_ground = RAIL_GROUND_ICE_DESERT; |
2231 |
2402 |
2232 /* Get the slopes on top of the foundations */ |
2403 /* Get the slopes on top of the foundations */ |
2233 z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), &tileh_old); |
2404 z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), &tileh_old); |
2234 z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), &tileh_new); |
2405 z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), &tileh_new); |
2235 |
2406 |
2236 Slope track_corner; |
2407 Corner track_corner; |
2237 switch (rail_bits) { |
2408 switch (rail_bits) { |
2238 case TRACK_BIT_LEFT: track_corner = SLOPE_W; break; |
2409 case TRACK_BIT_LEFT: track_corner = CORNER_W; break; |
2239 case TRACK_BIT_LOWER: track_corner = SLOPE_S; break; |
2410 case TRACK_BIT_LOWER: track_corner = CORNER_S; break; |
2240 case TRACK_BIT_RIGHT: track_corner = SLOPE_E; break; |
2411 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; |
2241 case TRACK_BIT_UPPER: track_corner = SLOPE_N; break; |
2412 case TRACK_BIT_UPPER: track_corner = CORNER_N; break; |
2242 |
2413 |
2243 /* Surface slope must not be changed */ |
2414 /* Surface slope must not be changed */ |
2244 default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform); |
2415 default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform); |
2245 } |
2416 } |
2246 |
2417 |
2247 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */ |
2418 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */ |
2248 if ((tileh_old & track_corner) != 0) z_old += TILE_HEIGHT; |
2419 z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner); |
2249 if ((tileh_new & track_corner) != 0) z_new += TILE_HEIGHT; |
2420 z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner); |
2250 if (z_old != z_new) return CMD_ERROR; |
2421 if (z_old != z_new) return CMD_ERROR; |
2251 |
2422 |
2423 CommandCost cost = CommandCost(_price.terraform); |
|
2252 /* Make the ground dirty, if surface slope has changed */ |
2424 /* Make the ground dirty, if surface slope has changed */ |
2253 if ((tileh_old != tileh_new) && ((flags & DC_EXEC) != 0)) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2425 if (tileh_old != tileh_new) { |
2254 |
2426 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water); |
2255 return _price.terraform; |
2427 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2428 } |
|
2429 return cost; |
|
2256 } |
2430 } |
2257 |
2431 |
2258 static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
2432 static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
2259 { |
2433 { |
2260 uint z_old; |
2434 uint z_old; |
2261 Slope tileh_old = GetTileSlope(tile, &z_old); |
2435 Slope tileh_old = GetTileSlope(tile, &z_old); |
2262 if (IsPlainRailTile(tile)) { |
2436 if (IsPlainRailTile(tile)) { |
2263 TrackBits rail_bits = GetTrackBits(tile); |
2437 TrackBits rail_bits = GetTrackBits(tile); |
2438 bool was_water = GetRailGroundType(tile) == RAIL_GROUND_WATER; |
|
2264 |
2439 |
2265 _error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK; |
2440 _error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK; |
2266 |
2441 |
2267 /* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */ |
2442 /* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */ |
2268 CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits); |
2443 CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits); |
2269 |
2444 |
2270 /* When there is only a single horizontal/vertical track, one corner can be terraformed. */ |
2445 /* When there is only a single horizontal/vertical track, one corner can be terraformed. */ |
2271 Slope allowed_corner; |
2446 Corner allowed_corner; |
2272 switch (rail_bits) { |
2447 switch (rail_bits) { |
2273 case TRACK_BIT_RIGHT: allowed_corner = SLOPE_W; break; |
2448 case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break; |
2274 case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break; |
2449 case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break; |
2275 case TRACK_BIT_LEFT: allowed_corner = SLOPE_E; break; |
2450 case TRACK_BIT_LEFT: allowed_corner = CORNER_E; break; |
2276 case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break; |
2451 case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break; |
2277 default: return autoslope_result; |
2452 default: return autoslope_result; |
2278 } |
2453 } |
2279 |
2454 |
2280 Slope track_corners = ComplementSlope(allowed_corner); |
|
2281 |
|
2282 Foundation f_old = GetRailFoundation(tileh_old, rail_bits); |
2455 Foundation f_old = GetRailFoundation(tileh_old, rail_bits); |
2283 switch (f_old) { |
2456 |
2284 case FOUNDATION_NONE: |
2457 /* Do not allow terraforming if allowed_corner is part of anti-zig-zag foundations */ |
2285 /* Everything is valid, which only changes allowed_corner */ |
2458 if (tileh_old != SLOPE_NS && tileh_old != SLOPE_EW && IsSpecialRailFoundation(f_old)) return autoslope_result; |
2286 |
2459 |
2287 /* Compute height of track */ |
2460 /* Everything is valid, which only changes allowed_corner */ |
2288 if (tileh_old == track_corners) z_old += TILE_HEIGHT; |
2461 for (Corner corner = (Corner)0; corner < CORNER_END; corner = (Corner)(corner + 1)) { |
2289 if (tileh_new == track_corners) { |
2462 if (allowed_corner == corner) continue; |
2290 z_new += TILE_HEIGHT; |
2463 if (z_old + GetSlopeZInCorner(tileh_old, corner) != z_new + GetSlopeZInCorner(tileh_new, corner)) return autoslope_result; |
2291 } else { |
|
2292 /* do not build a foundation */ |
|
2293 if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return autoslope_result; |
|
2294 } |
|
2295 |
|
2296 /* Track height must remain unchanged */ |
|
2297 if (z_old != z_new) return autoslope_result; |
|
2298 break; |
|
2299 |
|
2300 case FOUNDATION_LEVELED: |
|
2301 /* Is allowed_corner covered by the foundation? */ |
|
2302 if ((tileh_old & allowed_corner) == 0) return autoslope_result; |
|
2303 |
|
2304 /* allowed_corner may only be raised -> steep slope */ |
|
2305 if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return autoslope_result; |
|
2306 break; |
|
2307 |
|
2308 case FOUNDATION_STEEP_LOWER: |
|
2309 /* Only allow to lower highest corner */ |
|
2310 if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return autoslope_result; |
|
2311 break; |
|
2312 |
|
2313 case FOUNDATION_STEEP_HIGHER: |
|
2314 return autoslope_result; |
|
2315 |
|
2316 default: NOT_REACHED(); |
|
2317 } |
2464 } |
2318 |
2465 |
2319 /* Make the ground dirty */ |
2466 /* Make the ground dirty */ |
2320 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2467 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2321 |
2468 |
2322 /* allow terraforming, no extra costs */ |
2469 /* allow terraforming */ |
2323 return CommandCost(); |
2470 return (was_water ? CommandCost(_price.clear_water) : CommandCost()); |
2324 } else { |
2471 } else { |
2325 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
2472 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
2326 switch (GetRailTileType(tile)) { |
2473 switch (GetRailTileType(tile)) { |
2327 case RAIL_TILE_WAYPOINT: { |
2474 case RAIL_TILE_WAYPOINT: { |
2328 CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); |
2475 CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); |