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); |
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)); |
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, |