src/roadveh_cmd.cpp
changeset 9105 ecc85c6d9176
parent 9059 04edde3eb0c6
child 9107 3e57b96e98f2
equal deleted inserted replaced
9104:928a6de16975 9105:ecc85c6d9176
  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