src/roadveh_cmd.cpp
changeset 6326 c904c7ea1c8d
parent 6325 f03f94f4d8fc
child 6328 806e938b9566
equal deleted inserted replaced
6325:f03f94f4d8fc 6326:c904c7ea1c8d
    72 	TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_Y_NW,
    72 	TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_Y_NW,
    73 	TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_X_NE,
    73 	TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_X_NE,
    74 	TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_Y_SE
    74 	TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_Y_SE
    75 };
    75 };
    76 
    76 
       
    77 /** Converts the exit direction of a depot to trackdir the vehicle is going to drive to */
       
    78 static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = {
       
    79 	TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW
       
    80 };
       
    81 
       
    82 /** Checks whether the trackdir means that we are reversing */
       
    83 static bool IsReversingRoadTrackdir(Trackdir dir)
       
    84 {
       
    85 	return (dir & 0x07) >= 6;
       
    86 }
       
    87 
       
    88 /** Checks whether the given trackdir is a straight road */
       
    89 static bool IsStraightRoadTrackdir(Trackdir dir)
       
    90 {
       
    91 	return (dir & 0x06) == 0;
       
    92 }
       
    93 
    77 int GetRoadVehImage(const Vehicle* v, Direction direction)
    94 int GetRoadVehImage(const Vehicle* v, Direction direction)
    78 {
    95 {
    79 	int img = v->spritenum;
    96 	int img = v->spritenum;
    80 	int image;
    97 	int image;
    81 
    98 
   159 		v->x_pos = x;
   176 		v->x_pos = x;
   160 		v->y_pos = y;
   177 		v->y_pos = y;
   161 		v->z_pos = GetSlopeZ(x,y);
   178 		v->z_pos = GetSlopeZ(x,y);
   162 		v->z_height = 6;
   179 		v->z_height = 6;
   163 
   180 
   164 		v->u.road.state = 254;
   181 		v->u.road.state = RVSB_IN_DEPOT;
   165 		v->vehstatus = VS_HIDDEN|VS_STOPPED|VS_DEFPAL;
   182 		v->vehstatus = VS_HIDDEN|VS_STOPPED|VS_DEFPAL;
   166 
   183 
   167 		v->spritenum = rvi->image_index;
   184 		v->spritenum = rvi->image_index;
   168 		v->cargo_type = rvi->cargo_type;
   185 		v->cargo_type = rvi->cargo_type;
   169 		v->cargo_subtype = 0;
   186 		v->cargo_subtype = 0;
   450 
   467 
   451 	if (v->vehstatus & VS_STOPPED ||
   468 	if (v->vehstatus & VS_STOPPED ||
   452 			v->u.road.crashed_ctr != 0 ||
   469 			v->u.road.crashed_ctr != 0 ||
   453 			v->breakdown_ctr != 0 ||
   470 			v->breakdown_ctr != 0 ||
   454 			v->u.road.overtaking != 0 ||
   471 			v->u.road.overtaking != 0 ||
   455 			v->u.road.state == 255 ||
   472 			v->u.road.state == RVSB_WORMHOLE ||
   456 			IsRoadVehInDepot(v) ||
   473 			IsRoadVehInDepot(v) ||
   457 			v->cur_speed < 5) {
   474 			v->cur_speed < 5) {
   458 		return CMD_ERROR;
   475 		return CMD_ERROR;
   459 	}
   476 	}
   460 
   477 
   500 
   517 
   501 	/* Mark the station entrance as not busy */
   518 	/* Mark the station entrance as not busy */
   502 	rs->SetEntranceBusy(false);
   519 	rs->SetEntranceBusy(false);
   503 
   520 
   504 	/* Free the parking bay */
   521 	/* Free the parking bay */
   505 	rs->FreeBay(HASBIT(v->u.road.state, 1) ? 1 : 0);
   522 	rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY) ? 1 : 0);
   506 }
   523 }
   507 
   524 
   508 static void RoadVehDelete(Vehicle *v)
   525 static void RoadVehDelete(Vehicle *v)
   509 {
   526 {
   510 	DeleteWindowById(WC_VEHICLE_VIEW, v->index);
   527 	DeleteWindowById(WC_VEHICLE_VIEW, v->index);
   605 
   622 
   606 static void RoadVehCheckTrainCrash(Vehicle *v)
   623 static void RoadVehCheckTrainCrash(Vehicle *v)
   607 {
   624 {
   608 	TileIndex tile;
   625 	TileIndex tile;
   609 
   626 
   610 	if (v->u.road.state == 255) return;
   627 	if (v->u.road.state == RVSB_WORMHOLE) return;
   611 
   628 
   612 	tile = v->tile;
   629 	tile = v->tile;
   613 
   630 
   614 	if (!IsLevelCrossingTile(tile)) return;
   631 	if (!IsLevelCrossingTile(tile)) return;
   615 
   632 
   873 	uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0);
   890 	uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0);
   874 	byte t;
   891 	byte t;
   875 
   892 
   876 	// Clamp
   893 	// Clamp
   877 	spd = min(spd, v->max_speed);
   894 	spd = min(spd, v->max_speed);
   878 	if (v->u.road.state == 255) spd = min(spd, SetSpeedLimitOnBridge(v));
   895 	if (v->u.road.state == RVSB_WORMHOLE) spd = min(spd, SetSpeedLimitOnBridge(v));
   879 
   896 
   880 	//updates statusbar only if speed have changed to save CPU time
   897 	//updates statusbar only if speed have changed to save CPU time
   881 	if (spd != v->cur_speed) {
   898 	if (spd != v->cur_speed) {
   882 		v->cur_speed = spd;
   899 		v->cur_speed = spd;
   883 		if (_patches.vehicle_speed) {
   900 		if (_patches.vehicle_speed) {
   964 		return;
   981 		return;
   965 	}
   982 	}
   966 
   983 
   967 	if (v->direction != u->direction || !(v->direction & 1)) return;
   984 	if (v->direction != u->direction || !(v->direction & 1)) return;
   968 
   985 
   969 	if (v->u.road.state >= 32 || (v->u.road.state & 7) > 1) return;
   986 	/* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
       
   987 	if (v->u.road.state >= RVS_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return;
   970 
   988 
   971 	tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F;
   989 	tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F;
   972 	if ((tt & 3) == 0) return;
   990 	if ((tt & 3) == 0) return;
   973 	if ((tt & 0x3C) != 0) return;
   991 	if ((tt & 0x3C) != 0) return;
   974 
   992 
  1240 	19, 19, 15, 15, 0, 0, 0, 0,
  1258 	19, 19, 15, 15, 0, 0, 0, 0,
  1241 	16, 16, 12, 12, 0, 0, 0, 0,
  1259 	16, 16, 12, 12, 0, 0, 0, 0,
  1242 	15, 15, 11, 11
  1260 	15, 15, 11, 11
  1243 };
  1261 };
  1244 
  1262 
  1245 /** Converts the exit direction of a depot to trackdir the vehicle is going to drive to */
       
  1246 static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = {
       
  1247 	TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW
       
  1248 };
       
  1249 
       
  1250 static void RoadVehController(Vehicle *v)
  1263 static void RoadVehController(Vehicle *v)
  1251 {
  1264 {
  1252 	Direction new_dir;
  1265 	Direction new_dir;
  1253 	Direction old_dir;
  1266 	Direction old_dir;
  1254 	RoadDriveEntry rd;
  1267 	RoadDriveEntry rd;
  1325 
  1338 
  1326 	if (v->u.road.overtaking != 0)  {
  1339 	if (v->u.road.overtaking != 0)  {
  1327 		if (++v->u.road.overtaking_ctr >= 35)
  1340 		if (++v->u.road.overtaking_ctr >= 35)
  1328 			/* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
  1341 			/* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
  1329 			 *  if the vehicle started a corner. To protect that, only allow an abort of
  1342 			 *  if the vehicle started a corner. To protect that, only allow an abort of
  1330 			 *  overtake if we are on straight road, which are the 8 states below */
  1343 			 *  overtake if we are on straight roads */
  1331 			if (v->u.road.state == 0  || v->u.road.state == 1  ||
  1344 			if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) {
  1332 					v->u.road.state == 8  || v->u.road.state == 9  ||
       
  1333 					v->u.road.state == 16 || v->u.road.state == 17 ||
       
  1334 					v->u.road.state == 24 || v->u.road.state == 25) {
       
  1335 				v->u.road.overtaking = 0;
  1345 				v->u.road.overtaking = 0;
  1336 			}
  1346 			}
  1337 	}
  1347 	}
  1338 
  1348 
  1339 	/* Save old vehicle position to use at end of move to set viewport area dirty */
  1349 	/* Save old vehicle position to use at end of move to set viewport area dirty */
  1340 	BeginVehicleMove(v);
  1350 	BeginVehicleMove(v);
  1341 
  1351 
  1342 	if (v->u.road.state == 255) {
  1352 	if (v->u.road.state == RVSB_WORMHOLE) {
  1343 		/* Vehicle is on a bridge or in a tunnel */
  1353 		/* Vehicle is on a bridge or in a tunnel */
  1344 		GetNewVehiclePosResult gp;
  1354 		GetNewVehiclePosResult gp;
  1345 
  1355 
  1346 		GetNewVehiclePos(v, &gp);
  1356 		GetNewVehiclePos(v, &gp);
  1347 
  1357 
  1365 		if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
  1375 		if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
  1366 		return;
  1376 		return;
  1367 	}
  1377 	}
  1368 
  1378 
  1369 	/* Get move position data for next frame */
  1379 	/* Get move position data for next frame */
  1370 	rd = _road_drive_data[(v->u.road.state + (_opt.road_side << 4)) ^ v->u.road.overtaking][v->u.road.frame + 1];
  1380 	rd = _road_drive_data[(v->u.road.state + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
  1371 
  1381 
  1372 	if (rd.x & 0x80) {
  1382 	if (rd.x & 0x80) {
  1373 		/* Vehicle is moving to the next tile */
  1383 		/* Vehicle is moving to the next tile */
  1374 		TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3);
  1384 		TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3);
  1375 		Trackdir dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
  1385 		Trackdir dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
  1382 			v->cur_speed = 0;
  1392 			v->cur_speed = 0;
  1383 			return;
  1393 			return;
  1384 		}
  1394 		}
  1385 
  1395 
  1386 again:
  1396 again:
  1387 		if ((dir & 7) >= 6) {
  1397 		if (IsReversingRoadTrackdir(dir)) {
  1388 			/* Turning around */
  1398 			/* Turning around */
  1389 			tile = v->tile;
  1399 			tile = v->tile;
  1390 		}
  1400 		}
  1391 
  1401 
  1392 		/* Get position data for first frame on the new tile */
  1402 		/* Get position data for first frame on the new tile */
  1404 			if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
  1414 			if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
  1405 				v->cur_speed = 0;
  1415 				v->cur_speed = 0;
  1406 				return;
  1416 				return;
  1407 			}
  1417 			}
  1408 			/* Try an about turn to re-enter the previous tile */
  1418 			/* Try an about turn to re-enter the previous tile */
  1409 			dir = _road_reverse_table[rd.x&3];
  1419 			dir = _road_reverse_table[rd.x & 3];
  1410 			goto again;
  1420 			goto again;
  1411 		}
  1421 		}
  1412 
  1422 
  1413 		if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IsTileType(v->tile, MP_STATION)) {
  1423 		if (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
  1414 			if ((dir & 7) >= 6) {
  1424 			if (IsReversingRoadTrackdir(dir)) {
  1415 				/* New direction is trying to turn vehicle around.
  1425 				/* New direction is trying to turn vehicle around.
  1416 				 * We can't turn at the exit of a road stop so wait.*/
  1426 				 * We can't turn at the exit of a road stop so wait.*/
  1417 				v->cur_speed = 0;
  1427 				v->cur_speed = 0;
  1418 				return;
  1428 				return;
  1419 			}
  1429 			}
  1420 			if (IsRoadStop(v->tile)) {
  1430 			if (IsRoadStop(v->tile)) {
  1421 				/* The tile that the vehicle is leaving is a road stop */
  1431 				/* The tile that the vehicle is leaving is a road stop */
  1422 				RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
  1432 				RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
  1423 
  1433 
  1424 				/* Vehicle is leaving a road stop tile, mark bay as free and clear the usage bit */
  1434 				/* Vehicle is leaving a road stop tile, mark bay as free and clear the usage bit */
  1425 				rs->FreeBay(HASBIT(v->u.road.state, 1) ? 1 : 0);
  1435 				rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY) ? 1 : 0);
  1426 				rs->SetEntranceBusy(false);
  1436 				rs->SetEntranceBusy(false);
  1427 			}
  1437 			}
  1428 		}
  1438 		}
  1429 
  1439 
  1430 		if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) {
  1440 		if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) {
  1473 			v->cur_speed = 0;
  1483 			v->cur_speed = 0;
  1474 			return;
  1484 			return;
  1475 		}
  1485 		}
  1476 
  1486 
  1477 		/* Set vehicle to second frame on the tile */
  1487 		/* Set vehicle to second frame on the tile */
  1478 		v->u.road.state = tmp & ~16;
  1488 		CLRBIT(v->u.road.state, RVS_DRIVE_SIDE);
  1479 		v->u.road.frame = 1;
  1489 		v->u.road.frame = 1;
  1480 
  1490 
  1481 		if (newdir != v->direction) {
  1491 		if (newdir != v->direction) {
  1482 			v->direction = newdir;
  1492 			v->direction = newdir;
  1483 			v->cur_speed -= v->cur_speed >> 2;
  1493 			v->cur_speed -= v->cur_speed >> 2;
  1493 	x = (v->x_pos & ~15) + (rd.x & 15);
  1503 	x = (v->x_pos & ~15) + (rd.x & 15);
  1494 	y = (v->y_pos & ~15) + (rd.y & 15);
  1504 	y = (v->y_pos & ~15) + (rd.y & 15);
  1495 
  1505 
  1496 	new_dir = RoadVehGetSlidingDirection(v, x, y);
  1506 	new_dir = RoadVehGetSlidingDirection(v, x, y);
  1497 
  1507 
  1498 	if (!IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30)) {
  1508 	if (!IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
  1499 		/* Vehicle is not in a road stop.
  1509 		/* Vehicle is not in a road stop.
  1500 		 * Check for another vehicle to overtake */
  1510 		 * Check for another vehicle to overtake */
  1501 		Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir);
  1511 		Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir);
  1502 
  1512 
  1503 		if (u != NULL) {
  1513 		if (u != NULL) {
  1522 			 * be repeated. Is this intended? */
  1532 			 * be repeated. Is this intended? */
  1523 			return;
  1533 			return;
  1524 		}
  1534 		}
  1525 	}
  1535 	}
  1526 
  1536 
  1527 	if (v->u.road.state >= 0x20 &&
  1537 	if (v->u.road.state >= RVSB_IN_ROAD_STOP &&
  1528 			_road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) {
  1538 			_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) {
  1529 		RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
  1539 		RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
  1530 		Station* st = GetStationByTile(v->tile);
  1540 		Station* st = GetStationByTile(v->tile);
  1531 
  1541 
  1532 		/* Vehicle is at the stop position (at a bay) in a road stop.
  1542 		/* Vehicle is at the stop position (at a bay) in a road stop.
  1533 		 * Note, if vehicle is loading/unloading it has already been handled,
  1543 		 * Note, if vehicle is loading/unloading it has already been handled,