317 } |
303 } |
318 MarkTileDirtyByTile(tile_start); |
304 MarkTileDirtyByTile(tile_start); |
319 MarkTileDirtyByTile(tile_end); |
305 MarkTileDirtyByTile(tile_end); |
320 } |
306 } |
321 |
307 |
|
308 // position of middle part of the odd bridge (larger than MAX(i) otherwise) |
|
309 odd_middle_part = (bridge_len % 2) ? (bridge_len / 2) : bridge_len; |
|
310 |
322 tile = tile_start; |
311 tile = tile_start; |
323 delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); |
312 delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); |
324 for (i = 0; i != bridge_len; i++) { |
313 for (i = 0; i != bridge_len; i++) { |
|
314 TransportType transport_under; |
|
315 Owner owner_under = OWNER_NONE; |
|
316 RailType rail_under = INVALID_RAILTYPE; |
325 uint z; |
317 uint z; |
326 |
318 |
327 tile += delta; |
319 tile += delta; |
328 |
320 |
329 if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
321 if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) { |
330 |
322 return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
331 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) { |
|
332 /* Disallow crossing bridges for the time being */ |
|
333 return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
|
334 } |
323 } |
335 |
324 |
336 switch (GetTileType(tile)) { |
325 switch (GetTileType(tile)) { |
337 case MP_WATER: |
326 case MP_WATER: |
338 if (!EnsureNoVehicle(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY); |
327 if (!EnsureNoVehicle(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY); |
339 if (!(IsWater(tile) || IsCoast(tile))) goto not_valid_below; |
328 if (!(IsWater(tile) || IsCoast(tile))) goto not_valid_below; |
|
329 transport_under = TRANSPORT_WATER; |
|
330 owner_under = GetTileOwner(tile); |
340 break; |
331 break; |
341 |
332 |
342 case MP_RAILWAY: |
333 case MP_RAILWAY: |
343 if (!IsPlainRailTile(tile)) goto not_valid_below; |
334 if (GetRailTileType(tile) != RAIL_TILE_NORMAL || |
|
335 GetTrackBits(tile) != (direction == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X)) { |
|
336 goto not_valid_below; |
|
337 } |
|
338 transport_under = TRANSPORT_RAIL; |
|
339 owner_under = GetTileOwner(tile); |
|
340 rail_under = GetRailType(tile); |
344 break; |
341 break; |
345 |
342 |
346 case MP_STREET: |
343 case MP_STREET: |
347 if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) goto not_valid_below; |
344 if (GetRoadTileType(tile) != ROAD_TILE_NORMAL || |
348 break; |
345 GetRoadBits(tile) != (direction == AXIS_X ? ROAD_Y : ROAD_X)) { |
349 |
346 goto not_valid_below; |
350 case MP_TUNNELBRIDGE: |
347 } |
351 if (IsTunnel(tile)) break; |
348 transport_under = TRANSPORT_ROAD; |
352 if (direction == DiagDirToAxis(GetBridgeRampDirection(tile))) goto not_valid_below; |
349 owner_under = GetTileOwner(tile); |
353 if (GetBridgeHeight(tile_start, direction) == GetBridgeHeight(tile, DiagDirToAxis(GetBridgeRampDirection(tile)))) goto not_valid_below; |
|
354 break; |
|
355 |
|
356 case MP_CLEAR: |
|
357 if (IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
|
358 break; |
350 break; |
359 |
351 |
360 default: |
352 default: |
361 not_valid_below:; |
353 not_valid_below:; |
362 /* try and clear the middle landscape */ |
354 /* try and clear the middle landscape */ |
363 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
355 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
364 if (CmdFailed(ret)) return ret; |
356 if (CmdFailed(ret)) return ret; |
365 cost += ret; |
357 cost += ret; |
|
358 transport_under = INVALID_TRANSPORT; |
366 break; |
359 break; |
367 } |
360 } |
368 |
361 |
369 if (flags & DC_EXEC) { |
362 if (flags & DC_EXEC) { |
370 SetBridgeMiddle(tile, direction); |
363 uint piece; |
|
364 |
|
365 //bridges pieces sequence (middle parts) |
|
366 // bridge len 1: 0 |
|
367 // bridge len 2: 0 1 |
|
368 // bridge len 3: 0 4 1 |
|
369 // bridge len 4: 0 2 3 1 |
|
370 // bridge len 5: 0 2 5 3 1 |
|
371 // bridge len 6: 0 2 3 2 3 1 |
|
372 // bridge len 7: 0 2 3 4 2 3 1 |
|
373 // #0 - always as first, #1 - always as last (if len>1) |
|
374 // #2,#3 are to pair in order |
|
375 // for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0) |
|
376 |
|
377 if (i == 0) { // first tile |
|
378 piece = 0; |
|
379 } else if (i == bridge_len - 1) { // last tile |
|
380 piece = 1; |
|
381 } else if (i == odd_middle_part) { // we are on the middle of odd bridge: #5 on even pos, #4 on odd |
|
382 piece = 5 - (i % 2); |
|
383 } else { |
|
384 // generate #2 and #3 in turns [i%2==0], after the middle of odd bridge |
|
385 // this sequence swaps [... XOR (i>odd_middle_part)], |
|
386 // for even bridges XOR does not apply as odd_middle_part==bridge_len |
|
387 piece = 2 + ((i % 2 == 0) ^ (i > odd_middle_part)); |
|
388 } |
|
389 |
|
390 if (transport == TRANSPORT_RAIL) { |
|
391 MakeRailBridgeMiddle(tile, bridge_type, piece, direction, railtype); |
|
392 } else { |
|
393 MakeRoadBridgeMiddle(tile, bridge_type, piece, direction); |
|
394 } |
|
395 switch (transport_under) { |
|
396 case TRANSPORT_RAIL: SetRailUnderBridge(tile, owner_under, rail_under); break; |
|
397 case TRANSPORT_ROAD: SetRoadUnderBridge(tile, owner_under); break; |
|
398 |
|
399 case TRANSPORT_WATER: |
|
400 if (owner_under == OWNER_WATER) { |
|
401 SetWaterUnderBridge(tile); |
|
402 } else { |
|
403 SetCanalUnderBridge(tile, owner_under); |
|
404 } |
|
405 break; |
|
406 |
|
407 default: SetClearUnderBridge(tile); break; |
|
408 } |
|
409 |
371 MarkTileDirtyByTile(tile); |
410 MarkTileDirtyByTile(tile); |
372 } |
411 } |
373 } |
412 } |
374 |
413 |
375 SetSignalsOnBothDir(tile_start, direction == AXIS_X ? TRACK_X : TRACK_Y); |
414 SetSignalsOnBothDir(tile_start, direction == AXIS_X ? TRACK_X : TRACK_Y); |
550 YapfNotifyTrackLayoutChange(endtile, DiagDirToAxis(dir) == AXIS_X ? TRACK_X : TRACK_Y); |
589 YapfNotifyTrackLayoutChange(endtile, DiagDirToAxis(dir) == AXIS_X ? TRACK_X : TRACK_Y); |
551 } |
590 } |
552 return _price.clear_tunnel * (length + 1); |
591 return _price.clear_tunnel * (length + 1); |
553 } |
592 } |
554 |
593 |
555 #if 0 |
594 |
556 static uint GetBridgeHeightRamp(TileIndex t) |
595 static uint GetBridgeHeightRamp(TileIndex t) |
557 { |
596 { |
558 /* Return the height there (the height of the NORTH CORNER) |
597 /* Return the height there (the height of the NORTH CORNER) |
559 * If the end of the bridge is on a tile with all corners except the north corner raised, |
598 * If the end of the bridge is on a tile with all corners except the north corner raised, |
560 * the z coordinate is 1 height level too low. Compensate for that */ |
599 * the z coordinate is 1 height level too low. Compensate for that */ |
561 return TilePixelHeight(t) + (GetTileSlope(t, NULL) == SLOPE_WSE ? TILE_HEIGHT : 0); |
600 return TilePixelHeight(t) + (GetTileSlope(t, NULL) == SLOPE_WSE ? TILE_HEIGHT : 0); |
562 } |
601 } |
563 #endif |
|
564 |
602 |
565 |
603 |
566 static int32 DoClearBridge(TileIndex tile, uint32 flags) |
604 static int32 DoClearBridge(TileIndex tile, uint32 flags) |
567 { |
605 { |
568 DiagDirection direction; |
606 DiagDirection direction; |
569 TileIndexDiff delta; |
607 TileIndexDiff delta; |
570 TileIndex endtile; |
608 TileIndex endtile; |
|
609 Vehicle *v; |
571 Town *t; |
610 Town *t; |
572 |
611 |
573 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
612 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
613 |
|
614 if (IsBridgeMiddle(tile)) { |
|
615 if (IsTransportUnderBridge(tile)) { |
|
616 /* delete transport route under the bridge */ |
|
617 int32 cost; |
|
618 |
|
619 // check if we own the tile below the bridge.. |
|
620 if (_current_player != OWNER_WATER && (!CheckTileOwnership(tile) || !EnsureNoVehicleOnGround(tile))) |
|
621 return CMD_ERROR; |
|
622 |
|
623 if (GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) { |
|
624 cost = _price.remove_rail; |
|
625 } else { |
|
626 cost = _price.remove_road * 2; |
|
627 } |
|
628 |
|
629 if (flags & DC_EXEC) { |
|
630 SetClearUnderBridge(tile); |
|
631 MarkTileDirtyByTile(tile); |
|
632 } |
|
633 return cost; |
|
634 } else if (IsWaterUnderBridge(tile) && TilePixelHeight(tile) != 0) { |
|
635 /* delete canal under bridge */ |
|
636 |
|
637 // check for vehicles under bridge |
|
638 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
|
639 |
|
640 if (flags & DC_EXEC) { |
|
641 SetClearUnderBridge(tile); |
|
642 MarkTileDirtyByTile(tile); |
|
643 } |
|
644 return _price.clear_water; |
|
645 } |
|
646 |
|
647 tile = GetSouthernBridgeEnd(tile); |
|
648 } |
574 |
649 |
575 // floods, scenario editor can always destroy bridges |
650 // floods, scenario editor can always destroy bridges |
576 if (_current_player != OWNER_WATER && _game_mode != GM_EDITOR && !CheckTileOwnership(tile)) { |
651 if (_current_player != OWNER_WATER && _game_mode != GM_EDITOR && !CheckTileOwnership(tile)) { |
577 if (!(_patches.extra_dynamite || _cheats.magic_bulldozer.value) || !IsTileOwner(tile, OWNER_TOWN)) |
652 if (!(_patches.extra_dynamite || _cheats.magic_bulldozer.value) || !IsTileOwner(tile, OWNER_TOWN)) |
578 return CMD_ERROR; |
653 return CMD_ERROR; |
676 } |
803 } |
677 |
804 |
678 if (GetRailType(tile) == totype) return CMD_ERROR; |
805 if (GetRailType(tile) == totype) return CMD_ERROR; |
679 |
806 |
680 if (exec) { |
807 if (exec) { |
681 TileIndexDiff delta; |
808 Track track, endtrack; |
682 |
|
683 SetRailType(tile, totype); |
809 SetRailType(tile, totype); |
684 SetRailType(endtile, totype); |
810 SetRailType(endtile, totype); |
685 MarkTileDirtyByTile(tile); |
811 MarkTileDirtyByTile(tile); |
686 MarkTileDirtyByTile(endtile); |
812 MarkTileDirtyByTile(endtile); |
687 |
813 |
688 delta = TileOffsByDir(GetBridgeRampDirection(tile)); |
814 // notify YAPF about the track layout change |
689 for (tile += delta; tile != endtile; tile += delta) { |
815 track = TrackdirToTrack(DiagdirToDiagTrackdir(GetBridgeRampDirection(tile))); |
690 MarkTileDirtyByTile(tile); // TODO encapsulate this into a function |
816 endtrack = TrackdirToTrack(DiagdirToDiagTrackdir(GetBridgeRampDirection(endtile))); |
691 } |
817 YapfNotifyTrackLayoutChange(tile, track); |
692 } |
818 YapfNotifyTrackLayoutChange(endtile, endtrack); |
693 |
819 } |
694 return (DistanceManhattan(tile, endtile) + 1) * (_price.build_rail >> 1); |
820 cost = 2 * (_price.build_rail >> 1); |
|
821 delta = TileOffsByDir(GetBridgeRampDirection(tile)); |
|
822 for (tile += delta; tile != endtile; tile += delta) { |
|
823 if (exec) { |
|
824 SetRailTypeOnBridge(tile, totype); |
|
825 MarkTileDirtyByTile(tile); |
|
826 } |
|
827 cost += _price.build_rail >> 1; |
|
828 } |
|
829 |
|
830 return cost; |
695 } else |
831 } else |
696 return CMD_ERROR; |
832 return CMD_ERROR; |
697 } |
833 } |
698 |
834 |
699 |
835 |
700 static void DrawBridgePillars(PalSpriteID image, const TileInfo* ti, Axis axis, uint type, int x, int y, int z) |
836 // fast routine for getting the height of a middle bridge tile. 'tile' MUST be a middle bridge tile. |
|
837 uint GetBridgeHeight(TileIndex t) |
|
838 { |
|
839 return GetBridgeHeightRamp(GetSouthernBridgeEnd(t)); |
|
840 } |
|
841 |
|
842 static const byte _bridge_foundations[2][16] = { |
|
843 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
844 {0,16,18,3,20,5,0,7,22,0,10,11,12,13,14}, |
|
845 {0,15,17,0,19,5,6,7,21,9,10,11, 0,13,14}, |
|
846 }; |
|
847 |
|
848 extern const byte _road_sloped_sprites[14]; |
|
849 |
|
850 static void DrawBridgePillars(PalSpriteID image, const TileInfo *ti, int x, int y, int z) |
701 { |
851 { |
702 if (image != 0) { |
852 if (image != 0) { |
703 bool drawfarpillar = !HASBIT(GetBridgeFlags(type), 0); |
853 Axis axis = GetBridgeAxis(ti->tile); |
|
854 bool drawfarpillar = !HASBIT(GetBridgeFlags(GetBridgeType(ti->tile)), 0); |
704 int back_height, front_height; |
855 int back_height, front_height; |
705 int i = z; |
856 int i = z; |
706 const byte *p; |
857 const byte *p; |
707 |
858 |
708 static const byte _tileh_bits[4][8] = { |
859 static const byte _tileh_bits[4][8] = { |
782 image += GetTunnelDirection(ti->tile) * 2; |
939 image += GetTunnelDirection(ti->tile) * 2; |
783 DrawGroundSprite(image); |
940 DrawGroundSprite(image); |
784 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
941 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
785 |
942 |
786 AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z); |
943 AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z); |
787 DrawBridgeMiddle(ti); |
|
788 } else if (IsBridge(ti->tile)) { // XXX is this necessary? |
944 } else if (IsBridge(ti->tile)) { // XXX is this necessary? |
789 int base_offset; |
945 int base_offset; |
790 |
946 |
791 if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) { |
947 if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) { |
792 base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset; |
948 RailType rt; |
|
949 |
|
950 if (IsBridgeRamp(ti->tile)) { |
|
951 rt = GetRailType(ti->tile); |
|
952 } else { |
|
953 rt = GetRailTypeOnBridge(ti->tile); |
|
954 } |
|
955 |
|
956 base_offset = GetRailTypeInfo(rt)->bridge_offset; |
793 assert(base_offset != 8); /* This one is used for roads */ |
957 assert(base_offset != 8); /* This one is used for roads */ |
794 } else { |
958 } else { |
795 base_offset = 8; |
959 base_offset = 8; |
796 } |
960 } |
797 |
961 |
798 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
962 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
799 assert( (base_offset & 0x07) == 0x00); |
963 assert( (base_offset & 0x07) == 0x00); |
800 |
964 |
801 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
965 if (IsBridgeRamp(ti->tile)) { |
802 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
966 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
803 if (f) DrawFoundation(ti, f); |
967 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
804 } |
968 if (f) DrawFoundation(ti, f); |
805 |
969 } |
806 // HACK Wizardry to convert the bridge ramp direction into a sprite offset |
970 |
807 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
971 // HACK Wizardry to convert the bridge ramp direction into a sprite offset |
808 |
972 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
809 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
973 |
810 |
974 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
811 /* Table number 6 always refers to the bridge heads for any bridge type */ |
975 |
812 image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset]; |
976 /* Table number 6 always refers to the bridge heads for any bridge type */ |
813 |
977 image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset]; |
814 if (!ice) { |
978 |
815 DrawClearLandTile(ti, 3); |
979 if (!ice) { |
|
980 DrawClearLandTile(ti, 3); |
|
981 } else { |
|
982 DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]); |
|
983 } |
|
984 |
|
985 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
|
986 |
|
987 // draw ramp |
|
988 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
|
989 AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 7, ti->z); |
816 } else { |
990 } else { |
817 DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]); |
991 // bridge middle part. |
818 } |
992 Axis axis = GetBridgeAxis(ti->tile); |
819 |
993 uint z; |
820 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
994 int x,y; |
821 |
995 |
822 // draw ramp |
996 if (IsTransportUnderBridge(ti->tile)) { |
823 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
997 uint f = _bridge_foundations[axis][ti->tileh]; |
824 AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 7, ti->z); |
998 |
825 |
999 if (f != 0) DrawFoundation(ti, f); |
826 DrawBridgeMiddle(ti); |
1000 |
827 } |
1001 if (GetTransportTypeUnderBridge(ti->tile) == TRANSPORT_RAIL) { |
828 } |
1002 const RailtypeInfo* rti = GetRailTypeInfo(GetRailType(ti->tile)); |
829 |
1003 |
830 |
1004 if (ti->tileh == SLOPE_FLAT) { |
831 //bridges pieces sequence (middle parts) |
1005 image = (axis == AXIS_X ? SPR_RAIL_TRACK_Y : SPR_RAIL_TRACK_X); |
832 // bridge len 1: 0 |
1006 } else { |
833 // bridge len 2: 0 1 |
1007 image = SPR_RAIL_TRACK_Y + _track_sloped_sprites[ti->tileh - 1]; |
834 // bridge len 3: 0 4 1 |
1008 } |
835 // bridge len 4: 0 2 3 1 |
1009 image += rti->total_offset; |
836 // bridge len 5: 0 2 5 3 1 |
1010 if (ice) image += rti->snow_offset; |
837 // bridge len 6: 0 2 3 2 3 1 |
1011 } else { |
838 // bridge len 7: 0 2 3 4 2 3 1 |
1012 if (ti->tileh == SLOPE_FLAT) { |
839 // #0 - always as first, #1 - always as last (if len>1) |
1013 image = (axis == AXIS_X ? SPR_ROAD_Y : SPR_ROAD_X); |
840 // #2,#3 are to pair in order |
1014 } else { |
841 // for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0) |
1015 image = _road_sloped_sprites[ti->tileh - 1] + 0x53F; |
842 static uint CalcBridgePiece(uint north, uint south) |
1016 } |
843 { |
1017 if (ice) image += 19; |
844 if (north == 1) { |
1018 } |
845 return 0; |
1019 DrawGroundSprite(image); |
846 } else if (south == 1) { |
1020 } else { |
847 return 1; |
1021 if (IsClearUnderBridge(ti->tile)) { |
848 } else if (north < south) { |
1022 image = (ice ? SPR_FLAT_SNOWY_TILE : SPR_FLAT_GRASS_TILE); |
849 return north & 1 ? 3 : 2; |
1023 DrawGroundSprite(image + _tileh_to_sprite[ti->tileh]); |
850 } else if (north > south) { |
1024 } else { |
851 return south & 1 ? 2 : 3; |
1025 if (ti->tileh == SLOPE_FLAT) { |
852 } else { |
1026 DrawGroundSprite(SPR_FLAT_WATER_TILE); |
853 return north & 1 ? 5 : 4; |
1027 if (ti->z != 0) DrawCanalWater(ti->tile); |
854 } |
1028 } else { |
855 } |
1029 DrawGroundSprite(_water_shore_sprites[ti->tileh]); |
856 |
1030 } |
857 void DrawBridgeMiddle(const TileInfo* ti) |
1031 } |
858 { |
1032 } |
859 const PalSpriteID* b; |
1033 |
860 PalSpriteID image; |
1034 if (axis != AXIS_X) base_offset += 4; |
861 uint base_offset; |
1035 |
862 TileIndex rampnorth; |
1036 /* base_offset needs to be 0 due to the structure of the sprite table see table/bridge_land.h */ |
863 TileIndex rampsouth; |
1037 assert( (base_offset & 0x03) == 0x00); |
864 Axis axis; |
1038 // get bridge sprites |
865 uint piece; |
1039 b = GetBridgeSpriteTable(GetBridgeType(ti->tile), GetBridgePiece(ti->tile)) + base_offset; |
866 uint type; |
1040 |
867 int x; |
1041 z = GetBridgeHeight(ti->tile) + 5; |
868 int y; |
1042 |
869 uint z; |
1043 // draw rail or road component |
870 |
1044 image = b[0]; |
871 if (!IsBridgeAbove(ti->tile)) return; |
|
872 |
|
873 rampnorth = GetNorthernBridgeEnd(ti->tile); |
|
874 rampsouth = GetSouthernBridgeEnd(ti->tile); |
|
875 |
|
876 axis = GetBridgeAxis(ti->tile); |
|
877 piece = CalcBridgePiece( |
|
878 DistanceManhattan(ti->tile, rampnorth), |
|
879 DistanceManhattan(ti->tile, rampsouth) |
|
880 ); |
|
881 type = GetBridgeType(rampsouth); |
|
882 |
|
883 if (GetBridgeTransportType(rampsouth) == TRANSPORT_RAIL) { |
|
884 base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset; |
|
885 } else { |
|
886 base_offset = 8; |
|
887 } |
|
888 |
|
889 b = base_offset + GetBridgeSpriteTable(type, piece); |
|
890 if (axis != AXIS_X) b += 4; |
|
891 |
|
892 x = ti->x; |
|
893 y = ti->y; |
|
894 z = GetBridgeHeight(rampsouth, axis) - 3; |
|
895 |
|
896 image = b[0]; |
|
897 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
|
898 if (axis == AXIS_X) { |
|
899 AddSortableSpriteToDraw(image, x, y, 16, 11, 1, z); |
|
900 } else { |
|
901 AddSortableSpriteToDraw(image, x, y, 11, 16, 1, z); |
|
902 } |
|
903 |
|
904 image = b[1]; |
|
905 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
|
906 |
|
907 // draw roof, the component of the bridge which is logically between the vehicle and the camera |
|
908 if (axis == AXIS_X) { |
|
909 y += 12; |
|
910 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 16, 1, 0x28, z); |
|
911 } else { |
|
912 x += 12; |
|
913 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 1, 16, 0x28, z); |
|
914 } |
|
915 |
|
916 if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
|
917 |
|
918 if (ti->z + 5 == z) { |
|
919 // draw poles below for small bridges |
|
920 image = b[2]; |
|
921 if (image != 0) { |
|
922 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
1045 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
923 DrawGroundSpriteAt(image, x, y, z); |
1046 if (axis == AXIS_X) { |
924 } |
1047 AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 11, 1, z); |
925 } else if (_patches.bridge_pillars) { |
1048 } else { |
926 // draw pillars below for high bridges |
1049 AddSortableSpriteToDraw(image, ti->x, ti->y, 11, 16, 1, z); |
927 DrawBridgePillars(b[2], ti, axis, type, x, y, z); |
1050 } |
928 } |
1051 |
929 } |
1052 x = ti->x; |
930 |
1053 y = ti->y; |
931 |
1054 image = b[1]; |
932 uint SetSpeedLimitOnBridge(Vehicle *v) |
1055 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
933 { |
1056 |
934 uint bridge_speed; |
1057 // draw roof, the component of the bridge which is logically between the vehicle and the camera |
935 if (v->vehstatus & VS_HIDDEN) return v->max_speed; /* in tunnel */ |
1058 if (axis == AXIS_X) { |
936 |
1059 y += 12; |
937 bridge_speed = _bridge[GetBridgeType(v->tile)].speed; |
1060 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 16, 1, 0x28, z); |
938 |
1061 } else { |
939 if (v->type == VEH_Road) bridge_speed *= 2; /* XXX give vehicles proper speeds */ |
1062 x += 12; |
940 |
1063 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 1, 16, 0x28, z); |
941 if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed; |
1064 } |
942 return bridge_speed; |
1065 |
943 } |
1066 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC || GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
944 |
1067 |
945 |
1068 if (ti->z + 5 == z) { |
|
1069 // draw poles below for small bridges |
|
1070 image = b[2]; |
|
1071 if (image != 0) { |
|
1072 if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); |
|
1073 DrawGroundSpriteAt(image, x, y, z); |
|
1074 } |
|
1075 } else if (_patches.bridge_pillars) { |
|
1076 // draw pillars below for high bridges |
|
1077 DrawBridgePillars(b[2], ti, x, y, z); |
|
1078 } |
|
1079 } |
|
1080 } |
|
1081 } |
946 |
1082 |
947 static uint GetSlopeZ_TunnelBridge(const TileInfo* ti) |
1083 static uint GetSlopeZ_TunnelBridge(const TileInfo* ti) |
948 { |
1084 { |
949 TileIndex tile = ti->tile; |
1085 TileIndex tile = ti->tile; |
950 uint z = ti->z; |
1086 uint z = ti->z; |
956 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1092 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
957 |
1093 |
958 // In the tunnel entrance? |
1094 // In the tunnel entrance? |
959 if (5 <= pos && pos <= 10) return z; |
1095 if (5 <= pos && pos <= 10) return z; |
960 } else { |
1096 } else { |
961 DiagDirection dir = GetBridgeRampDirection(tile); |
1097 if (IsBridgeRamp(tile)) { |
962 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x); |
1098 DiagDirection dir = GetBridgeRampDirection(tile); |
963 |
1099 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x); |
964 // On the bridge ramp? |
1100 |
965 if (5 <= pos && pos <= 10) { |
1101 // On the bridge ramp? |
966 uint delta; |
1102 if (5 <= pos && pos <= 10) { |
967 |
1103 uint delta; |
968 if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT; |
1104 |
969 |
1105 if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT; |
970 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT; |
1106 |
971 switch (dir) { |
1107 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT; |
972 default: |
1108 switch (dir) { |
973 case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break; |
1109 default: |
974 case DIAGDIR_SE: delta = y / 2; break; |
1110 case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break; |
975 case DIAGDIR_SW: delta = x / 2; break; |
1111 case DIAGDIR_SE: delta = y / 2; break; |
976 case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break; |
1112 case DIAGDIR_SW: delta = x / 2; break; |
977 } |
1113 case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break; |
978 return z + 1 + delta; |
1114 } |
|
1115 return z + 1 + delta; |
|
1116 } else { |
|
1117 uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir)); |
|
1118 |
|
1119 if (f != 0) { |
|
1120 if (f < 15) return z + TILE_HEIGHT; |
|
1121 tileh = _inclined_tileh[f - 15]; |
|
1122 } |
|
1123 } |
979 } else { |
1124 } else { |
980 uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir)); |
1125 // HACK on the bridge? |
981 |
1126 if (_get_z_hint >= z + TILE_HEIGHT + (tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT)) return _get_z_hint; |
982 if (f != 0) { |
1127 |
983 if (f < 15) return z + TILE_HEIGHT; |
1128 if (IsTransportUnderBridge(tile)) { |
984 tileh = _inclined_tileh[f - 15]; |
1129 uint f = _bridge_foundations[GetBridgeAxis(tile)][tileh]; |
|
1130 |
|
1131 if (f != 0) { |
|
1132 if (f < 15) return z + TILE_HEIGHT; |
|
1133 tileh = _inclined_tileh[f - 15]; |
|
1134 } |
985 } |
1135 } |
986 } |
1136 } |
987 } |
1137 } |
988 |
1138 |
989 return z + GetPartialZ(x, y, tileh); |
1139 return z + GetPartialZ(x, y, tileh); |
1191 v->vehstatus &= ~VS_HIDDEN; |
1380 v->vehstatus &= ~VS_HIDDEN; |
1192 return 4; |
1381 return 4; |
1193 } |
1382 } |
1194 } |
1383 } |
1195 } else if (IsBridge(tile)) { // XXX is this necessary? |
1384 } else if (IsBridge(tile)) { // XXX is this necessary? |
1196 DiagDirection dir; |
|
1197 |
|
1198 if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) { |
1385 if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) { |
1199 /* modify speed of vehicle */ |
1386 if (IsBridgeRamp(tile) || v->z_pos > GetTileMaxZ(tile)) { |
1200 uint16 spd = _bridge[GetBridgeType(tile)].speed; |
1387 /* modify speed of vehicle */ |
1201 |
1388 uint16 spd = _bridge[GetBridgeType(tile)].speed; |
1202 if (v->type == VEH_Road) spd *= 2; |
1389 if (v->type == VEH_Road) spd *= 2; |
1203 if (v->cur_speed > spd) v->cur_speed = spd; |
1390 if (v->cur_speed > spd) v->cur_speed = spd; |
1204 } |
1391 } |
1205 |
|
1206 dir = GetBridgeRampDirection(tile); |
|
1207 if (DirToDiagDir(v->direction) == dir) { |
|
1208 switch (dir) { |
|
1209 default: |
|
1210 case DIAGDIR_NE: if ((x & 0xF) != 0) return 0; break; |
|
1211 case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break; |
|
1212 case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break; |
|
1213 case DIAGDIR_NW: if ((y & 0xF) != 0) return 0; break; |
|
1214 } |
|
1215 if (v->type == VEH_Train) { |
|
1216 v->u.rail.track = 0x40; |
|
1217 CLRBIT(v->u.rail.flags, VRF_GOINGUP); |
|
1218 CLRBIT(v->u.rail.flags, VRF_GOINGDOWN); |
|
1219 } else { |
|
1220 v->u.road.state = 0xFF; |
|
1221 } |
|
1222 return 4; |
|
1223 } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { |
|
1224 v->tile = tile; |
|
1225 if (v->type == VEH_Train) { |
|
1226 if (v->u.rail.track == 0x40) { |
|
1227 v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2); |
|
1228 return 4; |
|
1229 } |
|
1230 } else { |
|
1231 if (v->u.road.state == 0xFF) { |
|
1232 v->u.road.state = _road_exit_tunnel_state[dir]; |
|
1233 v->u.road.frame = 0; |
|
1234 return 4; |
|
1235 } |
|
1236 } |
|
1237 return 0; |
|
1238 } |
1392 } |
1239 } |
1393 } |
1240 return 0; |
1394 return 0; |
|
1395 } |
|
1396 |
|
1397 TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v) |
|
1398 { |
|
1399 TileIndex tile; |
|
1400 TileIndexDiff delta = (v->direction & 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0); |
|
1401 byte z = v->z_pos; |
|
1402 |
|
1403 for (tile = v->tile;; tile += delta) { |
|
1404 if (IsTunnelTile(tile) && GetTileZ(tile) == z) break; |
|
1405 } |
|
1406 return tile; |
1241 } |
1407 } |
1242 |
1408 |
1243 const TileTypeProcs _tile_type_tunnelbridge_procs = { |
1409 const TileTypeProcs _tile_type_tunnelbridge_procs = { |
1244 DrawTile_TunnelBridge, /* draw_tile_proc */ |
1410 DrawTile_TunnelBridge, /* draw_tile_proc */ |
1245 GetSlopeZ_TunnelBridge, /* get_slope_z_proc */ |
1411 GetSlopeZ_TunnelBridge, /* get_slope_z_proc */ |