1006 |
1006 |
1007 struct OvertakeData { |
1007 struct OvertakeData { |
1008 const Vehicle* u; |
1008 const Vehicle* u; |
1009 const Vehicle* v; |
1009 const Vehicle* v; |
1010 TileIndex tile; |
1010 TileIndex tile; |
1011 uint16 tilebits; |
1011 Trackdir trackdir; |
1012 }; |
1012 }; |
1013 |
1013 |
1014 static void* EnumFindVehToOvertake(Vehicle* v, void* data) |
1014 static void* EnumFindVehBlockingOvertake(Vehicle* v, void* data) |
1015 { |
1015 { |
1016 const OvertakeData* od = (OvertakeData*)data; |
1016 const OvertakeData* od = (OvertakeData*)data; |
1017 |
1017 |
1018 return |
1018 return |
1019 v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v ? |
1019 v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v ? |
1020 v : NULL; |
1020 v : NULL; |
1021 } |
1021 } |
1022 |
1022 |
1023 static bool FindRoadVehToOvertake(OvertakeData *od) |
1023 /** |
1024 { |
1024 * Check if overtaking is possible on a piece of track |
1025 uint32 bits; |
1025 * |
1026 |
1026 * @param od Information about the tile and the involved vehicles |
1027 bits = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes); |
1027 * @return true if we have to abort overtaking |
1028 bits |= bits >> 8; |
1028 */ |
1029 |
1029 static bool CheckRoadBlockedForOvertaking(OvertakeData *od) |
1030 if (!(od->tilebits & bits) || (bits & 0x3C3C) || (bits & 0x3F3F0000)) |
1030 { |
1031 return true; |
1031 uint32 ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes); |
1032 return VehicleFromPos(od->tile, od, EnumFindVehToOvertake) != NULL; |
1032 TrackdirBits trackdirbits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK); |
|
1033 TrackdirBits red_signals = (TrackdirBits)((ts >> 16) & TRACKDIR_BIT_MASK); // barred level crossing |
|
1034 TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits); |
|
1035 |
|
1036 /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */ |
|
1037 if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true; |
|
1038 |
|
1039 /* Are there more vehicles on the tile except the two vehicles involved in overtaking */ |
|
1040 return VehicleFromPos(od->tile, od, EnumFindVehBlockingOvertake) != NULL; |
1033 } |
1041 } |
1034 |
1042 |
1035 static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u) |
1043 static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u) |
1036 { |
1044 { |
1037 OvertakeData od; |
1045 OvertakeData od; |
1038 uint16 tt; |
|
1039 |
1046 |
1040 od.v = v; |
1047 od.v = v; |
1041 od.u = u; |
1048 od.u = u; |
1042 |
1049 |
1043 if (u->max_speed >= v->max_speed && |
1050 if (u->max_speed >= v->max_speed && |
1053 if (IsTileType(v->tile, MP_STATION)) return; |
1060 if (IsTileType(v->tile, MP_STATION)) return; |
1054 |
1061 |
1055 /* For now, articulated road vehicles can't overtake anything. */ |
1062 /* For now, articulated road vehicles can't overtake anything. */ |
1056 if (RoadVehHasArticPart(v)) return; |
1063 if (RoadVehHasArticPart(v)) return; |
1057 |
1064 |
|
1065 /* Vehicles are not driving in same direction || direction is not a diagonal direction */ |
1058 if (v->direction != u->direction || !(v->direction & 1)) return; |
1066 if (v->direction != u->direction || !(v->direction & 1)) return; |
1059 |
1067 |
1060 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
1068 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
1061 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
1069 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
1062 |
1070 |
1063 tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes); |
1071 od.trackdir = DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
1064 tt |= tt >> 8; |
1072 |
1065 tt &= 0x3F; |
1073 /* Are the current and the next tile suitable for overtaking? |
1066 |
1074 * - Does the track continue along od.trackdir |
1067 if ((tt & 3) == 0) return; |
1075 * - No junctions |
1068 if ((tt & 0x3C) != 0) return; |
1076 * - No barred levelcrossing |
1069 |
1077 * - No other vehicles in the way |
1070 if (tt == 3) tt = (v->direction & 2) ? 2 : 1; |
1078 */ |
1071 od.tilebits = tt; |
|
1072 |
|
1073 od.tile = v->tile; |
1079 od.tile = v->tile; |
1074 if (FindRoadVehToOvertake(&od)) return; |
1080 if (CheckRoadBlockedForOvertaking(&od)) return; |
1075 |
1081 |
1076 od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction)); |
1082 od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction)); |
1077 if (FindRoadVehToOvertake(&od)) return; |
1083 if (CheckRoadBlockedForOvertaking(&od)) return; |
1078 |
1084 |
1079 if (od.u->cur_speed == 0 || od.u->vehstatus& VS_STOPPED) { |
1085 if (od.u->cur_speed == 0 || od.u->vehstatus& VS_STOPPED) { |
1080 v->u.road.overtaking_ctr = 0x11; |
1086 v->u.road.overtaking_ctr = 0x11; |
1081 v->u.road.overtaking = 0x10; |
1087 v->u.road.overtaking = 0x10; |
1082 } else { |
1088 } else { |
1083 // if (FindRoadVehToOvertake(&od)) return; |
1089 // if (CheckRoadBlockedForOvertaking(&od)) return; |
1084 v->u.road.overtaking_ctr = 0; |
1090 v->u.road.overtaking_ctr = 0; |
1085 v->u.road.overtaking = 0x10; |
1091 v->u.road.overtaking = 0x10; |
1086 } |
1092 } |
1087 } |
1093 } |
1088 |
1094 |