branch | NewGRF_ports |
changeset 6719 | 4cc327ad39d5 |
parent 6694 | a10a42eefd52 |
child 6720 | 35756db7e577 |
6718:5a8b295aa345 | 6719:4cc327ad39d5 |
---|---|
59 }; |
59 }; |
60 |
60 |
61 Bridge _bridge[MAX_BRIDGES]; |
61 Bridge _bridge[MAX_BRIDGES]; |
62 |
62 |
63 |
63 |
64 // calculate the price factor for building a long bridge. |
64 /** calculate the price factor for building a long bridge. |
65 // basically the cost delta is 1,1, 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5, 6,6,6,6,6,6, 7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8, |
65 * basically the cost delta is 1,1, 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5, 6,6,6,6,6,6, 7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8, |
66 */ |
|
66 int CalcBridgeLenCostFactor(int x) |
67 int CalcBridgeLenCostFactor(int x) |
67 { |
68 { |
68 int n; |
69 int n; |
69 int r; |
70 int r; |
70 |
71 |
77 } |
78 } |
78 } |
79 } |
79 |
80 |
80 #define M(x) (1 << (x)) |
81 #define M(x) (1 << (x)) |
81 enum BridgeFoundation { |
82 enum BridgeFoundation { |
82 // foundation, whole tile is leveled up --> 3 corners raised |
83 /* foundation, whole tile is leveled up --> 3 corners raised */ |
83 BRIDGE_FULL_LEVELED_FOUNDATION = M(SLOPE_WSE) | M(SLOPE_NWS) | M(SLOPE_ENW) | M(SLOPE_SEN), |
84 BRIDGE_FULL_LEVELED_FOUNDATION = M(SLOPE_WSE) | M(SLOPE_NWS) | M(SLOPE_ENW) | M(SLOPE_SEN), |
84 // foundation, tile is partly leveled up --> 1 corner raised |
85 /* foundation, tile is partly leveled up --> 1 corner raised */ |
85 BRIDGE_PARTLY_LEVELED_FOUNDATION = M(SLOPE_W) | M(SLOPE_S) | M(SLOPE_E) | M(SLOPE_N), |
86 BRIDGE_PARTLY_LEVELED_FOUNDATION = M(SLOPE_W) | M(SLOPE_S) | M(SLOPE_E) | M(SLOPE_N), |
86 // no foundations (X,Y direction) |
87 /* no foundations (X,Y direction) */ |
87 BRIDGE_NO_FOUNDATION = M(SLOPE_FLAT) | M(SLOPE_SW) | M(SLOPE_SE) | M(SLOPE_NW) | M(SLOPE_NE), |
88 BRIDGE_NO_FOUNDATION = M(SLOPE_FLAT) | M(SLOPE_SW) | M(SLOPE_SE) | M(SLOPE_NW) | M(SLOPE_NE), |
88 BRIDGE_HORZ_RAMP = (BRIDGE_PARTLY_LEVELED_FOUNDATION | BRIDGE_NO_FOUNDATION) & ~M(SLOPE_FLAT) |
89 BRIDGE_HORZ_RAMP = (BRIDGE_PARTLY_LEVELED_FOUNDATION | BRIDGE_NO_FOUNDATION) & ~M(SLOPE_FLAT) |
89 }; |
90 }; |
90 #undef M |
91 #undef M |
91 |
92 |
165 return b->min_length <= bridge_len && bridge_len <= max; |
166 return b->min_length <= bridge_len && bridge_len <= max; |
166 } |
167 } |
167 |
168 |
168 /** Build a Bridge |
169 /** Build a Bridge |
169 * @param end_tile end tile |
170 * @param end_tile end tile |
171 * @param flags type of operation |
|
170 * @param p1 packed start tile coords (~ dx) |
172 * @param p1 packed start tile coords (~ dx) |
171 * @param p2 various bitstuffed elements |
173 * @param p2 various bitstuffed elements |
172 * - p2 = (bit 0- 7) - bridge type (hi bh) |
174 * - p2 = (bit 0- 7) - bridge type (hi bh) |
173 * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge. |
175 * - p2 = (bit 8-..) - rail type or road types. |
176 * - p2 = (bit 15 ) - set means road bridge. |
|
174 */ |
177 */ |
175 int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
178 int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
176 { |
179 { |
177 uint bridge_type; |
180 uint bridge_type; |
178 RailType railtype; |
181 RailType railtype; |
182 RoadTypes roadtypes; |
|
179 uint x; |
183 uint x; |
180 uint y; |
184 uint y; |
181 uint sx; |
185 uint sx; |
182 uint sy; |
186 uint sy; |
183 TileIndex tile_start; |
187 TileIndex tile_start; |
200 /* unpack parameters */ |
204 /* unpack parameters */ |
201 bridge_type = GB(p2, 0, 8); |
205 bridge_type = GB(p2, 0, 8); |
202 |
206 |
203 if (p1 >= MapSize()) return CMD_ERROR; |
207 if (p1 >= MapSize()) return CMD_ERROR; |
204 |
208 |
205 // type of bridge |
209 /* type of bridge */ |
206 if (HASBIT(p2, 15)) { |
210 if (HASBIT(p2, 15)) { |
207 railtype = INVALID_RAILTYPE; // road bridge |
211 railtype = INVALID_RAILTYPE; // road bridge |
212 roadtypes = (RoadTypes)GB(p2, 8, 3); |
|
213 if (!AreValidRoadTypes(roadtypes)) return CMD_ERROR; |
|
208 } else { |
214 } else { |
209 if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR; |
215 if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR; |
210 railtype = (RailType)GB(p2, 8, 8); |
216 railtype = (RailType)GB(p2, 8, 8); |
217 roadtypes = ROADTYPES_NONE; |
|
211 } |
218 } |
212 |
219 |
213 x = TileX(end_tile); |
220 x = TileX(end_tile); |
214 y = TileY(end_tile); |
221 y = TileY(end_tile); |
215 sx = TileX(p1); |
222 sx = TileX(p1); |
253 tileh_end = SLOPE_FLAT; |
260 tileh_end = SLOPE_FLAT; |
254 } |
261 } |
255 |
262 |
256 if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
263 if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
257 |
264 |
258 // Towns are not allowed to use bridges on slopes. |
265 /* Towns are not allowed to use bridges on slopes. */ |
259 allow_on_slopes = (!_is_old_ai_player |
266 allow_on_slopes = (!_is_old_ai_player |
260 && _current_player != OWNER_TOWN && _patches.build_on_slopes); |
267 && _current_player != OWNER_TOWN && _patches.build_on_slopes); |
261 |
268 |
262 TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL; |
269 TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL; |
263 |
270 |
295 } |
302 } |
296 |
303 |
297 cost = (bridge_len + 1) * _price.clear_bridge; // The cost of clearing the current bridge. |
304 cost = (bridge_len + 1) * _price.clear_bridge; // The cost of clearing the current bridge. |
298 replace_bridge = true; |
305 replace_bridge = true; |
299 replaced_bridge_type = GetBridgeType(tile_start); |
306 replaced_bridge_type = GetBridgeType(tile_start); |
307 |
|
308 /* Do not remove road types when upgrading a bridge */ |
|
309 roadtypes |= GetRoadTypes(tile_start); |
|
300 } else { |
310 } else { |
301 /* Build a new bridge. */ |
311 /* Build a new bridge. */ |
302 |
312 |
303 /* Try and clear the start landscape */ |
313 /* Try and clear the start landscape */ |
304 ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
314 ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
313 /* Try and clear the end landscape */ |
323 /* Try and clear the end landscape */ |
314 ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
324 ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
315 if (CmdFailed(ret)) return ret; |
325 if (CmdFailed(ret)) return ret; |
316 cost += ret; |
326 cost += ret; |
317 |
327 |
318 // false - end tile slope check |
328 /* false - end tile slope check */ |
319 terraformcost = CheckBridgeSlopeSouth(direction, tileh_end); |
329 terraformcost = CheckBridgeSlopeSouth(direction, tileh_end); |
320 if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes)) |
330 if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes)) |
321 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
331 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
322 cost += terraformcost; |
332 cost += terraformcost; |
323 } |
333 } |
348 |
358 |
349 if (railtype != INVALID_RAILTYPE) { |
359 if (railtype != INVALID_RAILTYPE) { |
350 MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype); |
360 MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype); |
351 MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype); |
361 MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype); |
352 } else { |
362 } else { |
353 MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir); |
363 MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes); |
354 MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir)); |
364 MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), roadtypes); |
355 } |
365 } |
356 MarkTileDirtyByTile(tile_start); |
366 MarkTileDirtyByTile(tile_start); |
357 MarkTileDirtyByTile(tile_end); |
367 MarkTileDirtyByTile(tile_end); |
358 } |
368 } |
359 |
369 |
436 return cost; |
446 return cost; |
437 } |
447 } |
438 |
448 |
439 |
449 |
440 /** Build Tunnel. |
450 /** Build Tunnel. |
441 * @param tile start tile of tunnel |
451 * @param start_tile start tile of tunnel |
442 * @param p1 railtype, 0x200 for road tunnel |
452 * @param flags type of operation |
453 * @param p1 railtype or roadtypes. bit 9 set means road tunnel |
|
443 * @param p2 unused |
454 * @param p2 unused |
444 */ |
455 */ |
445 int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) |
456 int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) |
446 { |
457 { |
447 TileIndexDiff delta; |
458 TileIndexDiff delta; |
453 uint end_z; |
464 uint end_z; |
454 int32 cost; |
465 int32 cost; |
455 int32 ret; |
466 int32 ret; |
456 |
467 |
457 _build_tunnel_endtile = 0; |
468 _build_tunnel_endtile = 0; |
458 |
469 if (!HASBIT(p1, 9)) { |
459 if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR; |
470 if (!ValParamRailtype(p1)) return CMD_ERROR; |
471 } else if (!AreValidRoadTypes((RoadTypes)GB(p1, 0, 3))) { |
|
472 return CMD_ERROR; |
|
473 } |
|
460 |
474 |
461 start_tileh = GetTileSlope(start_tile, &start_z); |
475 start_tileh = GetTileSlope(start_tile, &start_z); |
462 |
476 |
463 switch (start_tileh) { |
477 switch (start_tileh) { |
464 case SLOPE_SW: direction = DIAGDIR_SW; break; |
478 case SLOPE_SW: direction = DIAGDIR_SW; break; |
494 } |
508 } |
495 |
509 |
496 /* Add the cost of the entrance */ |
510 /* Add the cost of the entrance */ |
497 cost += _price.build_tunnel + ret; |
511 cost += _price.build_tunnel + ret; |
498 |
512 |
499 // if the command fails from here on we want the end tile to be highlighted |
513 /* if the command fails from here on we want the end tile to be highlighted */ |
500 _build_tunnel_endtile = end_tile; |
514 _build_tunnel_endtile = end_tile; |
501 |
515 |
502 // slope of end tile must be complementary to the slope of the start tile |
516 /* slope of end tile must be complementary to the slope of the start tile */ |
503 if (end_tileh != ComplementSlope(start_tileh)) { |
517 if (end_tileh != ComplementSlope(start_tileh)) { |
504 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); |
518 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); |
505 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); |
519 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); |
506 } else { |
520 } else { |
507 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
521 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
514 MakeRailTunnel(start_tile, _current_player, direction, (RailType)GB(p1, 0, 4)); |
528 MakeRailTunnel(start_tile, _current_player, direction, (RailType)GB(p1, 0, 4)); |
515 MakeRailTunnel(end_tile, _current_player, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4)); |
529 MakeRailTunnel(end_tile, _current_player, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4)); |
516 UpdateSignalsOnSegment(start_tile, direction); |
530 UpdateSignalsOnSegment(start_tile, direction); |
517 YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction))); |
531 YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction))); |
518 } else { |
532 } else { |
519 MakeRoadTunnel(start_tile, _current_player, direction); |
533 MakeRoadTunnel(start_tile, _current_player, direction, (RoadTypes)GB(p1, 0, 3)); |
520 MakeRoadTunnel(end_tile, _current_player, ReverseDiagDir(direction)); |
534 MakeRoadTunnel(end_tile, _current_player, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3)); |
521 } |
535 } |
522 } |
536 } |
523 |
537 |
524 return cost; |
538 return cost; |
525 } |
539 } |
589 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
603 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
590 } |
604 } |
591 } |
605 } |
592 |
606 |
593 if (flags & DC_EXEC) { |
607 if (flags & DC_EXEC) { |
594 // We first need to request the direction before calling DoClearSquare |
608 /* We first need to request the direction before calling DoClearSquare |
595 // else the direction is always 0.. dah!! ;) |
609 * else the direction is always 0.. dah!! ;) */ |
596 DiagDirection dir = GetTunnelDirection(tile); |
610 DiagDirection dir = GetTunnelDirection(tile); |
597 Track track; |
611 Track track; |
598 |
612 |
599 // Adjust the town's player rating. Do this before removing the tile owner info. |
613 /* Adjust the town's player rating. Do this before removing the tile owner info. */ |
600 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
614 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
601 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
615 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
602 |
616 |
603 DoClearSquare(tile); |
617 DoClearSquare(tile); |
604 DoClearSquare(endtile); |
618 DoClearSquare(endtile); |
634 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
648 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
635 |
649 |
636 if (!CheckAllowRemoveTunnelBridge(tile)) return CMD_ERROR; |
650 if (!CheckAllowRemoveTunnelBridge(tile)) return CMD_ERROR; |
637 |
651 |
638 endtile = GetOtherBridgeEnd(tile); |
652 endtile = GetOtherBridgeEnd(tile); |
639 |
653 byte bridge_height = GetBridgeHeight(tile); |
640 if (!EnsureNoVehicle(tile) || |
654 |
641 !EnsureNoVehicle(endtile) || |
655 if (FindVehicleOnTileZ(tile, bridge_height) != NULL || |
642 IsVehicleOnBridge(tile, endtile, GetBridgeHeight(tile))) { |
656 FindVehicleOnTileZ(endtile, bridge_height) != NULL || |
657 IsVehicleOnBridge(tile, endtile, bridge_height)) { |
|
643 return CMD_ERROR; |
658 return CMD_ERROR; |
644 } |
659 } |
645 |
660 |
646 direction = GetBridgeRampDirection(tile); |
661 direction = GetBridgeRampDirection(tile); |
647 delta = TileOffsByDiagDir(direction); |
662 delta = TileOffsByDiagDir(direction); |
659 |
674 |
660 if (flags & DC_EXEC) { |
675 if (flags & DC_EXEC) { |
661 TileIndex c; |
676 TileIndex c; |
662 Track track; |
677 Track track; |
663 |
678 |
664 //checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until |
679 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until |
665 // you have a "Poor" (0) town rating |
680 * you have a "Poor" (0) town rating */ |
666 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
681 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
667 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
682 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
668 |
683 |
669 DoClearSquare(tile); |
684 DoClearSquare(tile); |
670 DoClearSquare(endtile); |
685 DoClearSquare(endtile); |
715 |
730 |
716 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
731 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
717 |
732 |
718 if (GetRailType(tile) == totype) return CMD_ERROR; |
733 if (GetRailType(tile) == totype) return CMD_ERROR; |
719 |
734 |
720 // 'hidden' elrails can't be downgraded to normal rail when elrails are disabled |
735 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
721 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
736 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
722 |
737 |
723 endtile = CheckTunnelBusy(tile, &length); |
738 endtile = CheckTunnelBusy(tile, &length); |
724 if (endtile == INVALID_TILE) return CMD_ERROR; |
739 if (endtile == INVALID_TILE) return CMD_ERROR; |
725 |
740 |
738 } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) { |
753 } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) { |
739 |
754 |
740 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
755 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
741 |
756 |
742 endtile = GetOtherBridgeEnd(tile); |
757 endtile = GetOtherBridgeEnd(tile); |
743 |
758 byte bridge_height = GetBridgeHeight(tile); |
744 if (!EnsureNoVehicle(tile) || |
759 |
745 !EnsureNoVehicle(endtile) || |
760 if (FindVehicleOnTileZ(tile, bridge_height) != NULL || |
746 IsVehicleOnBridge(tile, endtile, GetBridgeHeight(tile))) { |
761 FindVehicleOnTileZ(endtile, bridge_height) != NULL || |
762 IsVehicleOnBridge(tile, endtile, bridge_height)) { |
|
747 return CMD_ERROR; |
763 return CMD_ERROR; |
748 } |
764 } |
749 |
765 |
750 if (GetRailType(tile) == totype) return CMD_ERROR; |
766 if (GetRailType(tile) == totype) return CMD_ERROR; |
751 |
767 |
790 { 1, 8, 4, 2, 2, 16, 9, 0 }, |
806 { 1, 8, 4, 2, 2, 16, 9, 0 }, |
791 { 4, 8, 1, 2, 16, 2, 0, 9 }, |
807 { 4, 8, 1, 2, 16, 2, 0, 9 }, |
792 { 2, 4, 8, 1, 2, 16, 9, 0 } |
808 { 2, 4, 8, 1, 2, 16, 9, 0 } |
793 }; |
809 }; |
794 |
810 |
795 if (_display_opt & DO_TRANS_BUILDINGS) { |
811 if (HASBIT(_transparent_opt, TO_BRIDGES)) { |
796 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
812 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
797 pal = PALETTE_TO_TRANSPARENT; |
813 pal = PALETTE_TO_TRANSPARENT; |
798 } else { |
814 } else { |
799 pal = psid->pal; |
815 pal = psid->pal; |
800 } |
816 } |
827 { |
843 { |
828 uint i; |
844 uint i; |
829 |
845 |
830 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) return tileh; |
846 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) return tileh; |
831 |
847 |
832 // inclined sloped building |
848 /* inclined sloped building */ |
833 switch (tileh) { |
849 switch (tileh) { |
834 case SLOPE_W: |
850 case SLOPE_W: |
835 case SLOPE_STEEP_W: i = 0; break; |
851 case SLOPE_STEEP_W: i = 0; break; |
836 case SLOPE_S: |
852 case SLOPE_S: |
837 case SLOPE_STEEP_S: i = 2; break; |
853 case SLOPE_STEEP_S: i = 2; break; |
844 if (axis != AXIS_X) ++i; |
860 if (axis != AXIS_X) ++i; |
845 return i + 15; |
861 return i + 15; |
846 } |
862 } |
847 |
863 |
848 /** |
864 /** |
865 * Draws the trambits over an already drawn (lower end) of a bridge. |
|
866 * @param x the x of the bridge |
|
867 * @param y the y of the bridge |
|
868 * @param z the z of the bridge |
|
869 * @param offset number representing whether to level or sloped and the direction |
|
870 * @param overlay do we want to still see the road? |
|
871 */ |
|
872 static void DrawBridgeTramBits(int x, int y, byte z, int offset, bool overlay) |
|
873 { |
|
874 static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } }; |
|
875 static const SpriteID back_offsets[6] = { 95, 95, 99, 102, 100, 101 }; |
|
876 static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 }; |
|
877 |
|
878 static const uint size_x[6] = { 11, 16, 16, 16, 16, 16 }; |
|
879 static const uint size_y[6] = { 16, 11, 16, 16, 16, 16 }; |
|
880 |
|
881 AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE, x, y, size_x[offset], size_y[offset], offset >= 2 ? 1 : 0, z); |
|
882 |
|
883 SpriteID front = SPR_TRAMWAY_BASE + front_offsets[offset]; |
|
884 SpriteID back = SPR_TRAMWAY_BASE + back_offsets[offset]; |
|
885 SpriteID pal = PAL_NONE; |
|
886 if (HASBIT(_transparent_opt, TO_BUILDINGS)) { |
|
887 SETBIT(front, PALETTE_MODIFIER_TRANSPARENT); |
|
888 SETBIT(back, PALETTE_MODIFIER_TRANSPARENT); |
|
889 pal = PALETTE_TO_TRANSPARENT; |
|
890 } |
|
891 |
|
892 AddSortableSpriteToDraw(back, pal, x, y, size_x[offset], size_y[offset], 0, z); |
|
893 /* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */ |
|
894 AddSortableSpriteToDraw(front, pal, x, y, size_x[offset], size_y[offset], offset >= 2 ? 0x30 : 0x10, z); |
|
895 } |
|
896 |
|
897 /** |
|
849 * Draws a tunnel of bridge tile. |
898 * Draws a tunnel of bridge tile. |
850 * For tunnels, this is rather simple, as you only needa draw the entrance. |
899 * For tunnels, this is rather simple, as you only needa draw the entrance. |
851 * Bridges are a bit more complex. base_offset is where the sprite selection comes into play |
900 * Bridges are a bit more complex. base_offset is where the sprite selection comes into play |
852 * and it works a bit like a bitmask.<p> For bridge heads: |
901 * and it works a bit like a bitmask.<p> For bridge heads: |
902 * @param ti TileInfo of the structure to draw |
|
853 * <ul><li>Bit 0: direction</li> |
903 * <ul><li>Bit 0: direction</li> |
854 * <li>Bit 1: northern or southern heads</li> |
904 * <li>Bit 1: northern or southern heads</li> |
855 * <li>Bit 2: Set if the bridge head is sloped</li> |
905 * <li>Bit 2: Set if the bridge head is sloped</li> |
856 * <li>Bit 3 and more: Railtype Specific subset</li> |
906 * <li>Bit 3 and more: Railtype Specific subset</li> |
857 * </ul> |
907 * </ul> |
871 |
921 |
872 if (HasTunnelSnowOrDesert(ti->tile)) image += 32; |
922 if (HasTunnelSnowOrDesert(ti->tile)) image += 32; |
873 |
923 |
874 image += GetTunnelDirection(ti->tile) * 2; |
924 image += GetTunnelDirection(ti->tile) * 2; |
875 DrawGroundSprite(image, PAL_NONE); |
925 DrawGroundSprite(image, PAL_NONE); |
876 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
926 if (GetTunnelTransportType(ti->tile) == TRANSPORT_ROAD) { |
877 |
927 DiagDirection dir = GetTunnelDirection(ti->tile); |
878 AddSortableSpriteToDraw(image+1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z); |
928 RoadTypes rts = GetRoadTypes(ti->tile); |
929 |
|
930 if (HASBIT(rts, ROADTYPE_TRAM)) { |
|
931 static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } }; |
|
932 |
|
933 DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][dir], PAL_NONE); |
|
934 AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + dir, PAL_NONE, ti->x, ti->y, 16, 16, 16, (byte)ti->z); |
|
935 } |
|
936 } else if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) { |
|
937 DrawCatenary(ti); |
|
938 } |
|
939 |
|
940 AddSortableSpriteToDraw(image + 1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z); |
|
879 DrawBridgeMiddle(ti); |
941 DrawBridgeMiddle(ti); |
880 } else if (IsBridge(ti->tile)) { // XXX is this necessary? |
942 } else if (IsBridge(ti->tile)) { // XXX is this necessary? |
881 const PalSpriteID *psid; |
943 const PalSpriteID *psid; |
882 int base_offset; |
944 int base_offset; |
883 bool ice = HasBridgeSnowOrDesert(ti->tile); |
945 bool ice = HasBridgeSnowOrDesert(ti->tile); |
884 |
946 |
885 if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) { |
947 if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) { |
886 base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset; |
948 base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset; |
887 assert(base_offset != 8); /* This one is used for roads */ |
949 assert(base_offset != 8); // This one is used for roads |
888 } else { |
950 } else { |
889 base_offset = 8; |
951 base_offset = 8; |
890 } |
952 } |
891 |
953 |
892 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
954 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
895 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
957 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
896 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
958 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
897 if (f != 0) DrawFoundation(ti, f); |
959 if (f != 0) DrawFoundation(ti, f); |
898 } |
960 } |
899 |
961 |
900 // HACK Wizardry to convert the bridge ramp direction into a sprite offset |
962 /* HACK Wizardry to convert the bridge ramp direction into a sprite offset */ |
901 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
963 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
902 |
964 |
903 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
965 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
904 |
966 |
905 /* Table number 6 always refers to the bridge heads for any bridge type */ |
967 /* Table number 6 always refers to the bridge heads for any bridge type */ |
909 DrawClearLandTile(ti, 3); |
971 DrawClearLandTile(ti, 3); |
910 } else { |
972 } else { |
911 DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh], PAL_NONE); |
973 DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh], PAL_NONE); |
912 } |
974 } |
913 |
975 |
914 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
|
915 |
|
916 image = psid->sprite; |
976 image = psid->sprite; |
917 |
977 |
918 // draw ramp |
978 /* draw ramp */ |
919 if (_display_opt & DO_TRANS_BUILDINGS) { |
979 if (HASBIT(_transparent_opt, TO_BRIDGES)) { |
920 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
980 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
921 pal = PALETTE_TO_TRANSPARENT; |
981 pal = PALETTE_TO_TRANSPARENT; |
922 } else { |
982 } else { |
923 pal = psid->pal; |
983 pal = psid->pal; |
924 } |
984 } |
925 |
985 |
926 /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on |
986 /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on |
927 * it doesn't disappear behind it |
987 * it doesn't disappear behind it |
928 */ |
988 */ |
929 AddSortableSpriteToDraw( |
989 AddSortableSpriteToDraw( |
930 image, pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z |
990 image, pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z |
931 ); |
991 ); |
992 |
|
993 if (GetBridgeTransportType(ti->tile) == TRANSPORT_ROAD) { |
|
994 RoadTypes rts = GetRoadTypes(ti->tile); |
|
995 |
|
996 if (HASBIT(rts, ROADTYPE_TRAM)) { |
|
997 uint offset = GetBridgeRampDirection(ti->tile); |
|
998 uint z = ti->z; |
|
999 if (ti->tileh != SLOPE_FLAT) { |
|
1000 offset = (offset + 1) & 1; |
|
1001 z += TILE_HEIGHT; |
|
1002 } else { |
|
1003 offset += 2; |
|
1004 } |
|
1005 DrawBridgeTramBits(ti->x, ti->y, z, offset, HASBIT(rts, ROADTYPE_ROAD)); |
|
1006 } |
|
1007 } else if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) { |
|
1008 DrawCatenary(ti); |
|
1009 } |
|
932 |
1010 |
933 DrawBridgeMiddle(ti); |
1011 DrawBridgeMiddle(ti); |
934 } |
1012 } |
935 } |
1013 } |
936 |
1014 |
1003 psid = base_offset + GetBridgeSpriteTable(type, piece); |
1081 psid = base_offset + GetBridgeSpriteTable(type, piece); |
1004 if (axis != AXIS_X) psid += 4; |
1082 if (axis != AXIS_X) psid += 4; |
1005 |
1083 |
1006 x = ti->x; |
1084 x = ti->x; |
1007 y = ti->y; |
1085 y = ti->y; |
1008 z = GetBridgeHeight(rampsouth) - 3; |
1086 uint bridge_z = GetBridgeHeight(rampsouth); |
1087 z = bridge_z - 3; |
|
1009 |
1088 |
1010 image = psid->sprite; |
1089 image = psid->sprite; |
1011 if (_display_opt & DO_TRANS_BUILDINGS) { |
1090 if (HASBIT(_transparent_opt, TO_BRIDGES)) { |
1012 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1091 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1013 pal = PALETTE_TO_TRANSPARENT; |
1092 pal = PALETTE_TO_TRANSPARENT; |
1014 } else { |
1093 } else { |
1015 pal = psid->pal; |
1094 pal = psid->pal; |
1016 } |
1095 } |
1021 AddSortableSpriteToDraw(image, pal, x, y, 11, 16, 1, z); |
1100 AddSortableSpriteToDraw(image, pal, x, y, 11, 16, 1, z); |
1022 } |
1101 } |
1023 |
1102 |
1024 psid++; |
1103 psid++; |
1025 image = psid->sprite; |
1104 image = psid->sprite; |
1026 if (_display_opt & DO_TRANS_BUILDINGS) { |
1105 if (HASBIT(_transparent_opt, TO_BRIDGES)) { |
1027 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1106 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1028 pal = PALETTE_TO_TRANSPARENT; |
1107 pal = PALETTE_TO_TRANSPARENT; |
1029 } else { |
1108 } else { |
1030 pal = psid->pal; |
1109 pal = psid->pal; |
1031 } |
1110 } |
1032 |
1111 |
1033 // draw roof, the component of the bridge which is logically between the vehicle and the camera |
1112 if (GetBridgeTransportType(rampsouth) == TRANSPORT_ROAD) { |
1113 RoadTypes rts = GetRoadTypes(rampsouth); |
|
1114 |
|
1115 if (HASBIT(rts, ROADTYPE_TRAM)) { |
|
1116 DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HASBIT(rts, ROADTYPE_ROAD)); |
|
1117 } |
|
1118 } else if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) { |
|
1119 DrawCatenary(ti); |
|
1120 } |
|
1121 |
|
1122 /* draw roof, the component of the bridge which is logically between the vehicle and the camera */ |
|
1034 if (axis == AXIS_X) { |
1123 if (axis == AXIS_X) { |
1035 y += 12; |
1124 y += 12; |
1036 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, pal, x, y, 16, 1, 0x28, z); |
1125 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, pal, x, y, 16, 1, 0x28, z); |
1037 } else { |
1126 } else { |
1038 x += 12; |
1127 x += 12; |
1039 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, pal, x, y, 1, 16, 0x28, z); |
1128 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, pal, x, y, 1, 16, 0x28, z); |
1040 } |
1129 } |
1041 |
1130 |
1042 if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
|
1043 |
|
1044 psid++; |
1131 psid++; |
1045 if (ti->z + 5 == z) { |
1132 if (ti->z + 5 == z) { |
1046 // draw poles below for small bridges |
1133 /* draw poles below for small bridges */ |
1047 if (psid->sprite != 0) { |
1134 if (psid->sprite != 0) { |
1048 image = psid->sprite; |
1135 image = psid->sprite; |
1049 if (_display_opt & DO_TRANS_BUILDINGS) { |
1136 if (HASBIT(_transparent_opt, TO_BRIDGES)) { |
1050 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1137 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1051 pal = PALETTE_TO_TRANSPARENT; |
1138 pal = PALETTE_TO_TRANSPARENT; |
1052 } else { |
1139 } else { |
1053 pal = psid->pal; |
1140 pal = psid->pal; |
1054 } |
1141 } |
1055 |
1142 |
1056 DrawGroundSpriteAt(image, pal, x, y, z); |
1143 DrawGroundSpriteAt(image, pal, x, y, z); |
1057 } |
1144 } |
1058 } else if (_patches.bridge_pillars) { |
1145 } else if (_patches.bridge_pillars) { |
1059 // draw pillars below for high bridges |
1146 /* draw pillars below for high bridges */ |
1060 DrawBridgePillars(psid, ti, axis, type, x, y, z); |
1147 DrawBridgePillars(psid, ti, axis, type, x, y, z); |
1061 } |
1148 } |
1062 } |
1149 } |
1063 |
1150 |
1064 |
1151 |
1071 y &= 0xF; |
1158 y &= 0xF; |
1072 |
1159 |
1073 if (IsTunnel(tile)) { |
1160 if (IsTunnel(tile)) { |
1074 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1161 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1075 |
1162 |
1076 // In the tunnel entrance? |
1163 /* In the tunnel entrance? */ |
1077 if (5 <= pos && pos <= 10) return z; |
1164 if (5 <= pos && pos <= 10) return z; |
1078 } else { |
1165 } else { |
1079 DiagDirection dir = GetBridgeRampDirection(tile); |
1166 DiagDirection dir = GetBridgeRampDirection(tile); |
1080 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x); |
1167 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x); |
1081 |
1168 |
1082 // On the bridge ramp? |
1169 /* On the bridge ramp? */ |
1083 if (5 <= pos && pos <= 10) { |
1170 if (5 <= pos && pos <= 10) { |
1084 uint delta; |
1171 uint delta; |
1085 |
1172 |
1086 if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2; |
1173 if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2; |
1087 if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT; |
1174 if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT; |
1216 { |
1303 { |
1217 /* not used */ |
1304 /* not used */ |
1218 } |
1305 } |
1219 |
1306 |
1220 |
1307 |
1221 static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode) |
1308 static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode) |
1222 { |
1309 { |
1223 if (IsTunnel(tile)) { |
1310 if (IsTunnel(tile)) { |
1224 if (GetTunnelTransportType(tile) != mode) return 0; |
1311 if (GetTunnelTransportType(tile) != mode) return 0; |
1312 if (GetTunnelTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0; |
|
1225 return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101; |
1313 return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101; |
1226 } else { |
1314 } else { |
1227 if (GetBridgeTransportType(tile) != mode) return 0; |
1315 if (GetBridgeTransportType(tile) != mode) return 0; |
1316 if (GetBridgeTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0; |
|
1228 return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101; |
1317 return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101; |
1229 } |
1318 } |
1230 } |
1319 } |
1231 |
1320 |
1232 static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player) |
1321 static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player) |
1234 if (!IsTileOwner(tile, old_player)) return; |
1323 if (!IsTileOwner(tile, old_player)) return; |
1235 |
1324 |
1236 if (new_player != PLAYER_SPECTATOR) { |
1325 if (new_player != PLAYER_SPECTATOR) { |
1237 SetTileOwner(tile, new_player); |
1326 SetTileOwner(tile, new_player); |
1238 } else { |
1327 } else { |
1239 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
1328 if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) { |
1329 /* When clearing the bridge/tunnel failed there are still vehicles on/in |
|
1330 * the bridge/tunnel. As all *our* vehicles are already removed, they |
|
1331 * must be of another owner. Therefor this must be a road bridge/tunnel. |
|
1332 * In that case we can safely reassign the ownership to OWNER_NONE. */ |
|
1333 assert((IsTunnel(tile) ? GetTunnelTransportType(tile) : GetBridgeTransportType(tile)) == TRANSPORT_ROAD); |
|
1334 SetTileOwner(tile, OWNER_NONE); |
|
1335 } |
|
1240 } |
1336 } |
1241 } |
1337 } |
1242 |
1338 |
1243 |
1339 |
1244 static const byte _tunnel_fractcoord_1[4] = {0x8E, 0x18, 0x81, 0xE8}; |
1340 static const byte _tunnel_fractcoord_1[4] = {0x8E, 0x18, 0x81, 0xE8}; |
1300 } else if (v->type == VEH_ROAD) { |
1396 } else if (v->type == VEH_ROAD) { |
1301 fc = (x & 0xF) + (y << 4); |
1397 fc = (x & 0xF) + (y << 4); |
1302 dir = GetTunnelDirection(tile); |
1398 dir = GetTunnelDirection(tile); |
1303 vdir = DirToDiagDir(v->direction); |
1399 vdir = DirToDiagDir(v->direction); |
1304 |
1400 |
1305 // Enter tunnel? |
1401 /* Enter tunnel? */ |
1306 if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) { |
1402 if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) { |
1307 if (fc == _tunnel_fractcoord_4[dir] || |
1403 if (fc == _tunnel_fractcoord_4[dir] || |
1308 fc == _tunnel_fractcoord_5[dir]) { |
1404 fc == _tunnel_fractcoord_5[dir]) { |
1309 v->tile = tile; |
1405 v->tile = tile; |
1310 v->u.road.state = RVSB_WORMHOLE; |
1406 v->u.road.state = RVSB_WORMHOLE; |