176 /* The ai_new queries the vehicle cost before building the route, |
176 /* The ai_new queries the vehicle cost before building the route, |
177 * so we must check against cheaters no sooner than now. --pasky */ |
177 * so we must check against cheaters no sooner than now. --pasky */ |
178 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
178 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
179 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
179 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
180 |
180 |
181 if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE); |
181 if (HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) != HasBit(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE); |
182 |
182 |
183 uint num_vehicles = 1 + CountArticulatedParts(p1, false); |
183 uint num_vehicles = 1 + CountArticulatedParts(p1, false); |
184 |
184 |
185 /* Allow for the front and the articulated parts, plus one to "terminate" the list. */ |
185 /* Allow for the front and the articulated parts, plus one to "terminate" the list. */ |
186 Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1)); |
186 Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1)); |
191 } |
191 } |
192 |
192 |
193 v = vl[0]; |
193 v = vl[0]; |
194 |
194 |
195 /* find the first free roadveh id */ |
195 /* find the first free roadveh id */ |
196 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); |
196 unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); |
197 if (unit_num > _patches.max_roadveh) |
197 if (unit_num > _patches.max_roadveh) |
198 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
198 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
199 |
199 |
200 if (flags & DC_EXEC) { |
200 if (flags & DC_EXEC) { |
201 int x; |
201 int x; |
202 int y; |
202 int y; |
203 |
203 |
204 const RoadVehicleInfo *rvi = RoadVehInfo(p1); |
204 const RoadVehicleInfo *rvi = RoadVehInfo(p1); |
205 |
205 |
|
206 v = new (v) RoadVehicle(); |
206 v->unitnumber = unit_num; |
207 v->unitnumber = unit_num; |
207 v->direction = DiagDirToDir(GetRoadDepotDirection(tile)); |
208 v->direction = DiagDirToDir(GetRoadDepotDirection(tile)); |
208 v->owner = _current_player; |
209 v->owner = _current_player; |
209 |
210 |
210 v->tile = tile; |
211 v->tile = tile; |
246 v->service_interval = _patches.servint_roadveh; |
247 v->service_interval = _patches.servint_roadveh; |
247 |
248 |
248 v->date_of_last_service = _date; |
249 v->date_of_last_service = _date; |
249 v->build_year = _cur_year; |
250 v->build_year = _cur_year; |
250 |
251 |
251 v = new (v) RoadVehicle(); |
|
252 v->cur_image = 0xC15; |
252 v->cur_image = 0xC15; |
253 v->random_bits = VehicleRandomBits(); |
253 v->random_bits = VehicleRandomBits(); |
254 SetRoadVehFront(v); |
254 SetRoadVehFront(v); |
255 |
255 |
256 v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; |
256 v->u.road.roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; |
257 v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype); |
257 v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype); |
258 v->u.road.cached_veh_length = GetRoadVehLength(v); |
258 v->u.road.cached_veh_length = GetRoadVehLength(v); |
259 |
259 |
260 v->vehicle_flags = 0; |
260 v->vehicle_flags = 0; |
261 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
261 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
262 |
262 |
263 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
263 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
264 |
264 |
265 AddArticulatedParts(vl, VEH_ROAD); |
265 AddArticulatedParts(vl, VEH_ROAD); |
266 |
266 |
473 |
475 |
474 if (v->IsInDepot()) return CMD_ERROR; |
476 if (v->IsInDepot()) return CMD_ERROR; |
475 |
477 |
476 /* If the current orders are already goto-depot */ |
478 /* If the current orders are already goto-depot */ |
477 if (v->current_order.type == OT_GOTO_DEPOT) { |
479 if (v->current_order.type == OT_GOTO_DEPOT) { |
478 if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) { |
480 if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OFB_HALT_IN_DEPOT)) { |
479 /* We called with a different DEPOT_SERVICE setting. |
481 /* We called with a different DEPOT_SERVICE setting. |
480 * Now we change the setting to apply the new one and let the vehicle head for the same depot. |
482 * Now we change the setting to apply the new one and let the vehicle head for the same depot. |
481 * Note: the if is (true for requesting service == true for ordered to stop in depot) */ |
483 * Note: the if is (true for requesting service == true for ordered to stop in depot) */ |
482 if (flags & DC_EXEC) { |
484 if (flags & DC_EXEC) { |
483 CLRBIT(v->current_order.flags, OFB_PART_OF_ORDERS); |
485 ClrBit(v->current_order.flags, OFB_PART_OF_ORDERS); |
484 TOGGLEBIT(v->current_order.flags, OFB_HALT_IN_DEPOT); |
486 ToggleBit(v->current_order.flags, OFB_HALT_IN_DEPOT); |
485 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
487 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
486 } |
488 } |
487 return CommandCost(); |
489 return CommandCost(); |
488 } |
490 } |
489 |
491 |
490 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
492 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
491 if (flags & DC_EXEC) { |
493 if (flags & DC_EXEC) { |
492 /* If the orders to 'goto depot' are in the orders list (forced servicing), |
494 /* If the orders to 'goto depot' are in the orders list (forced servicing), |
493 * then skip to the next order; effectively cancelling this forced service */ |
495 * then skip to the next order; effectively cancelling this forced service */ |
494 if (HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) |
496 if (HasBit(v->current_order.flags, OFB_PART_OF_ORDERS)) |
495 v->cur_order_index++; |
497 v->cur_order_index++; |
496 |
498 |
497 v->current_order.type = OT_DUMMY; |
499 v->current_order.type = OT_DUMMY; |
498 v->current_order.flags = 0; |
500 v->current_order.flags = 0; |
499 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
501 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
508 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
510 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
509 |
511 |
510 ClearSlot(v); |
512 ClearSlot(v); |
511 v->current_order.type = OT_GOTO_DEPOT; |
513 v->current_order.type = OT_GOTO_DEPOT; |
512 v->current_order.flags = OF_NON_STOP; |
514 v->current_order.flags = OF_NON_STOP; |
513 if (!(p2 & DEPOT_SERVICE)) SETBIT(v->current_order.flags, OFB_HALT_IN_DEPOT); |
515 if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OFB_HALT_IN_DEPOT); |
514 v->current_order.refit_cargo = CT_INVALID; |
516 v->current_order.refit_cargo = CT_INVALID; |
515 v->current_order.dest = dep->index; |
517 v->current_order.dest = dep->index; |
516 v->dest_tile = dep->xy; |
518 v->dest_tile = dep->xy; |
517 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
519 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
518 } |
520 } |
869 short y_diff = v->y_pos - rvf->y; |
871 short y_diff = v->y_pos - rvf->y; |
870 |
872 |
871 return |
873 return |
872 v->type == VEH_ROAD && |
874 v->type == VEH_ROAD && |
873 !v->IsInDepot() && |
875 !v->IsInDepot() && |
874 myabs(v->z_pos - rvf->veh->z_pos) < 6 && |
876 abs(v->z_pos - rvf->veh->z_pos) < 6 && |
875 v->direction == rvf->dir && |
877 v->direction == rvf->dir && |
876 rvf->veh->First() != v->First() && |
878 rvf->veh->First() != v->First() && |
877 (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) && |
879 (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) && |
878 (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) && |
880 (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) && |
879 (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) && |
881 (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) && |
883 |
885 |
884 static Vehicle* RoadVehFindCloseTo(Vehicle* v, int x, int y, Direction dir) |
886 static Vehicle* RoadVehFindCloseTo(Vehicle* v, int x, int y, Direction dir) |
885 { |
887 { |
886 RoadVehFindData rvf; |
888 RoadVehFindData rvf; |
887 Vehicle *u; |
889 Vehicle *u; |
888 |
890 Vehicle *front = v->First(); |
889 if (v->u.road.reverse_ctr != 0) return NULL; |
891 |
|
892 if (front->u.road.reverse_ctr != 0) return NULL; |
890 |
893 |
891 rvf.x = x; |
894 rvf.x = x; |
892 rvf.y = y; |
895 rvf.y = y; |
893 rvf.dir = dir; |
896 rvf.dir = dir; |
894 rvf.veh = v; |
897 rvf.veh = v; |
895 u = (Vehicle*)VehicleFromPosXY(x, y, &rvf, EnumCheckRoadVehClose); |
898 if (front->u.road.state == RVSB_WORMHOLE) { |
|
899 u = (Vehicle*)VehicleFromPos(v->tile, &rvf, EnumCheckRoadVehClose); |
|
900 } else { |
|
901 u = (Vehicle*)VehicleFromPosXY(x, y, &rvf, EnumCheckRoadVehClose); |
|
902 } |
896 |
903 |
897 /* This code protects a roadvehicle from being blocked for ever |
904 /* This code protects a roadvehicle from being blocked for ever |
898 * If more than 1480 / 74 days a road vehicle is blocked, it will |
905 * If more than 1480 / 74 days a road vehicle is blocked, it will |
899 * drive just through it. The ultimate backup-code of TTD. |
906 * drive just through it. The ultimate backup-code of TTD. |
900 * It can be disabled. */ |
907 * It can be disabled. */ |
901 if (u == NULL) { |
908 if (u == NULL) { |
902 v->u.road.blocked_ctr = 0; |
909 front->u.road.blocked_ctr = 0; |
903 return NULL; |
910 return NULL; |
904 } |
911 } |
905 |
912 |
906 if (++v->u.road.blocked_ctr > 1480) return NULL; |
913 if (++front->u.road.blocked_ctr > 1480) return NULL; |
907 |
914 |
908 return u; |
915 return u; |
909 } |
916 } |
910 |
917 |
911 static void RoadVehArrivesAt(const Vehicle* v, Station* st) |
918 static void RoadVehArrivesAt(const Vehicle* v, Station* st) |
1205 /* We've got no destination, pick a random track */ |
1212 /* We've got no destination, pick a random track */ |
1206 return_track(PickRandomBit(trackdirs)); |
1213 return_track(PickRandomBit(trackdirs)); |
1207 } |
1214 } |
1208 |
1215 |
1209 /* Only one track to choose between? */ |
1216 /* Only one track to choose between? */ |
1210 if (!(KillFirstBit2x64(trackdirs))) { |
1217 if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) { |
1211 return_track(FindFirstBit2x64(trackdirs)); |
1218 return_track(FindFirstBit2x64(trackdirs)); |
1212 } |
1219 } |
1213 |
1220 |
1214 if (_patches.yapf.road_use_yapf) { |
1221 if (_patches.yapf.road_use_yapf) { |
1215 Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir); |
1222 Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir); |
1268 best_track = INVALID_TRACKDIR; |
1275 best_track = INVALID_TRACKDIR; |
1269 uint best_dist = (uint)-1; |
1276 uint best_dist = (uint)-1; |
1270 uint best_maxlen = (uint)-1; |
1277 uint best_maxlen = (uint)-1; |
1271 uint bitmask = (uint)trackdirs; |
1278 uint bitmask = (uint)trackdirs; |
1272 for (int i = 0; bitmask != 0; bitmask >>= 1, i++) { |
1279 for (int i = 0; bitmask != 0; bitmask >>= 1, i++) { |
1273 if (HASBIT(bitmask, 0)) { |
1280 if (HasBit(bitmask, 0)) { |
1274 if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track |
1281 if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track |
1275 frd.maxtracklen = (uint)-1; |
1282 frd.maxtracklen = (uint)-1; |
1276 frd.mindist = (uint)-1; |
1283 frd.mindist = (uint)-1; |
1277 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); |
1284 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); |
1278 |
1285 |
1319 RDE_NEXT_TILE = 0x80, |
1326 RDE_NEXT_TILE = 0x80, |
1320 RDE_TURNED = 0x40, |
1327 RDE_TURNED = 0x40, |
1321 |
1328 |
1322 /* Start frames for when a vehicle enters a tile/changes its state. |
1329 /* Start frames for when a vehicle enters a tile/changes its state. |
1323 * The start frame is different for vehicles that turned around or |
1330 * The start frame is different for vehicles that turned around or |
1324 * are leaving the depot as the do not start at the edge of the tile */ |
1331 * are leaving the depot as the do not start at the edge of the tile. |
1325 RVC_DEFAULT_START_FRAME = 0, |
1332 * For trams there are a few different start frames as there are two |
1326 RVC_TURN_AROUND_START_FRAME = 1, |
1333 * places where trams can turn. */ |
1327 RVC_DEPOT_START_FRAME = 6, |
1334 RVC_DEFAULT_START_FRAME = 0, |
|
1335 RVC_TURN_AROUND_START_FRAME = 1, |
|
1336 RVC_DEPOT_START_FRAME = 6, |
|
1337 RVC_START_FRAME_AFTER_LONG_TRAM = 22, |
|
1338 RVC_TURN_AROUND_START_FRAME_SHORT_TRAM = 16, |
1328 /* Stop frame for a vehicle in a drive-through stop */ |
1339 /* Stop frame for a vehicle in a drive-through stop */ |
1329 RVC_DRIVE_THROUGH_STOP_FRAME = 7 |
1340 RVC_DRIVE_THROUGH_STOP_FRAME = 7 |
1330 }; |
1341 }; |
1331 |
1342 |
1332 struct RoadDriveEntry { |
1343 struct RoadDriveEntry { |
1333 byte x, y; |
1344 byte x, y; |
1334 }; |
1345 }; |
1406 diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile)); |
1417 diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile)); |
1407 } |
1418 } |
1408 |
1419 |
1409 if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR; |
1420 if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR; |
1410 dir = DiagdirToDiagTrackdir(diag_dir); |
1421 dir = DiagdirToDiagTrackdir(diag_dir); |
1411 } else if (HASBIT(prev_state, RVS_IN_DT_ROAD_STOP)) { |
1422 } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) { |
1412 dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK); |
1423 dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK); |
1413 } else if (prev_state < TRACKDIR_END) { |
1424 } else if (prev_state < TRACKDIR_END) { |
1414 dir = (Trackdir)prev_state; |
1425 if (already_reversed && prev->tile != tile) { |
|
1426 /* |
|
1427 * The vehicle has reversed, but did not go straight back. |
|
1428 * It immediatelly turn onto another tile. This means that |
|
1429 * the roadstate of the previous vehicle cannot be used |
|
1430 * as the direction we have to go with this vehicle. |
|
1431 * |
|
1432 * Next table is build in the following way: |
|
1433 * - first row for when the vehicle in front went to the northern or |
|
1434 * western tile, second for southern and eastern. |
|
1435 * - columns represent the entry direction. |
|
1436 * - cell values are determined by the Trackdir one has to take from |
|
1437 * the entry dir (column) to the tile in north or south by only |
|
1438 * going over the trackdirs used for turning 90 degrees, i.e. |
|
1439 * TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}. |
|
1440 */ |
|
1441 Trackdir reversed_turn_lookup[2][DIAGDIR_END] = { |
|
1442 { TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N, TRACKDIR_UPPER_E }, |
|
1443 { TRACKDIR_RIGHT_S, TRACKDIR_LOWER_W, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S }}; |
|
1444 dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)]; |
|
1445 } else { |
|
1446 dir = (Trackdir)prev_state; |
|
1447 } |
1415 } else { |
1448 } else { |
1416 return INVALID_TRACKDIR; |
1449 return INVALID_TRACKDIR; |
1417 } |
1450 } |
1418 |
1451 |
1419 /* Do some sanity checking. */ |
1452 /* Do some sanity checking. */ |
1459 if (v->u.road.state == RVSB_WORMHOLE) { |
1515 if (v->u.road.state == RVSB_WORMHOLE) { |
1460 /* Vehicle is entering a depot or is on a bridge or in a tunnel */ |
1516 /* Vehicle is entering a depot or is on a bridge or in a tunnel */ |
1461 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
1517 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
1462 |
1518 |
1463 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction); |
1519 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction); |
1464 if (u != NULL && u->cur_speed < v->cur_speed) { |
1520 if (u != NULL && u->First()->cur_speed < v->cur_speed) { |
1465 v->cur_speed = u->cur_speed; |
1521 v->cur_speed = u->First()->cur_speed; |
1466 return false; |
1522 return false; |
1467 } |
1523 } |
1468 |
1524 |
1469 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1525 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1470 /* Vehicle has just entered a bridge or tunnel */ |
1526 /* Vehicle has just entered a bridge or tunnel */ |
1471 v->cur_image = v->GetImage(v->direction); |
1527 v->cur_image = v->GetImage(v->direction); |
1472 v->UpdateDeltaXY(v->direction); |
1528 v->UpdateDeltaXY(v->direction); |
1473 SetRoadVehPosition(v,gp.x,gp.y); |
1529 SetRoadVehPosition(v,gp.x,gp.y); |
1474 return true; |
1530 return true; |
1483 |
1539 |
1484 /* Get move position data for next frame. |
1540 /* Get move position data for next frame. |
1485 * For a drive-through road stop use 'straight road' move data. |
1541 * For a drive-through road stop use 'straight road' move data. |
1486 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1542 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1487 rd = _road_drive_data[v->u.road.roadtype][( |
1543 rd = _road_drive_data[v->u.road.roadtype][( |
1488 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1544 (HasBit(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1489 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1545 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1490 |
1546 |
1491 if (rd.x & RDE_NEXT_TILE) { |
1547 if (rd.x & RDE_NEXT_TILE) { |
1492 TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3)); |
1548 TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3)); |
1493 Trackdir dir; |
1549 Trackdir dir; |
1507 v->cur_speed = 0; |
1563 v->cur_speed = 0; |
1508 return false; |
1564 return false; |
1509 } |
1565 } |
1510 |
1566 |
1511 again: |
1567 again: |
|
1568 uint start_frame = RVC_DEFAULT_START_FRAME; |
1512 if (IsReversingRoadTrackdir(dir)) { |
1569 if (IsReversingRoadTrackdir(dir)) { |
1513 /* Turning around */ |
1570 /* Turning around */ |
1514 if (v->u.road.roadtype == ROADTYPE_TRAM) { |
1571 if (v->u.road.roadtype == ROADTYPE_TRAM) { |
1515 RoadBits needed; // The road bits the tram needs to be able to turn around |
1572 /* Determine the road bits the tram needs to be able to turn around |
|
1573 * using the 'big' corner loop. */ |
|
1574 RoadBits needed; |
1516 switch (dir) { |
1575 switch (dir) { |
1517 default: NOT_REACHED(); |
1576 default: NOT_REACHED(); |
1518 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; |
1577 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; |
1519 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; |
1578 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; |
1520 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; |
1579 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; |
1521 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; |
1580 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; |
1522 } |
1581 } |
1523 if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || HasRoadWorks(tile) || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) { |
1582 if ((v->Previous() != NULL && v->Previous()->tile == tile) || |
1524 /* The tram cannot turn here */ |
1583 (IsRoadVehFront(v) && IsTileType(tile, MP_ROAD) && |
|
1584 GetRoadTileType(tile) == ROAD_TILE_NORMAL && !HasRoadWorks(tile) && |
|
1585 (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) { |
|
1586 /* |
|
1587 * Taking the 'big' corner for trams only happens when: |
|
1588 * - The previous vehicle in this (articulated) tram chain is |
|
1589 * already on the 'next' tile, we just follow them regardless of |
|
1590 * anything. When it is NOT on the 'next' tile, the tram started |
|
1591 * doing a reversing turn when the piece of tram track on the next |
|
1592 * tile did not exist yet. Do not use the big tram loop as that is |
|
1593 * going to cause the tram to split up. |
|
1594 * - Or the front of the tram can drive over the next tile. |
|
1595 */ |
|
1596 } else if (!IsRoadVehFront(v) || !CanBuildTramTrackOnTile(tile)) { |
|
1597 /* |
|
1598 * Taking the 'small' corner for trams only happens when: |
|
1599 * - We are not the from vehicle of an articulated tram. |
|
1600 * - Or when the player cannot build on the next tile. |
|
1601 * |
|
1602 * The 'small' corner means that the vehicle is on the end of a |
|
1603 * tram track and needs to start turning there. To do this properly |
|
1604 * the tram needs to start at an offset in the tram turning 'code' |
|
1605 * for 'big' corners. It furthermore does not go to the next tile, |
|
1606 * so that needs to be fixed too. |
|
1607 */ |
|
1608 tile = v->tile; |
|
1609 start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM; |
|
1610 } else { |
|
1611 /* The player can build on the next tile, so wait till (s)he does. */ |
1525 v->cur_speed = 0; |
1612 v->cur_speed = 0; |
1526 return false; |
1613 return false; |
1527 } |
1614 } |
1528 } else if (IsTileType(v->tile, MP_ROAD) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) { |
1615 } else if (IsTileType(v->tile, MP_ROAD) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) { |
1529 v->cur_speed = 0; |
1616 v->cur_speed = 0; |
1534 } |
1621 } |
1535 |
1622 |
1536 /* Get position data for first frame on the new tile */ |
1623 /* Get position data for first frame on the new tile */ |
1537 rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; |
1624 rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; |
1538 |
1625 |
1539 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1626 x = TileX(tile) * TILE_SIZE + rdp[start_frame].x; |
1540 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1627 y = TileY(tile) * TILE_SIZE + rdp[start_frame].y; |
1541 |
1628 |
1542 newdir = RoadVehGetSlidingDirection(v, x, y); |
1629 newdir = RoadVehGetSlidingDirection(v, x, y); |
1543 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1630 if (IsRoadVehFront(v)) { |
|
1631 Vehicle *u = RoadVehFindCloseTo(v, x, y, newdir); |
|
1632 if (u != NULL) { |
|
1633 v->cur_speed = u->First()->cur_speed; |
|
1634 return false; |
|
1635 } |
|
1636 } |
1544 |
1637 |
1545 r = VehicleEnterTile(v, tile, x, y); |
1638 r = VehicleEnterTile(v, tile, x, y); |
1546 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1639 if (HasBit(r, VETS_CANNOT_ENTER)) { |
1547 if (!IsTileType(tile, MP_TUNNELBRIDGE)) { |
1640 if (!IsTileType(tile, MP_TUNNELBRIDGE)) { |
1548 v->cur_speed = 0; |
1641 v->cur_speed = 0; |
1549 return false; |
1642 return false; |
1550 } |
1643 } |
1551 /* Try an about turn to re-enter the previous tile */ |
1644 /* Try an about turn to re-enter the previous tile */ |
1563 if (IsRoadStop(v->tile)) { |
1656 if (IsRoadStop(v->tile)) { |
1564 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1657 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1565 |
1658 |
1566 /* Vehicle is leaving a road stop tile, mark bay as free |
1659 /* Vehicle is leaving a road stop tile, mark bay as free |
1567 * For drive-through stops, only do it if the vehicle stopped here */ |
1660 * For drive-through stops, only do it if the vehicle stopped here */ |
1568 if (IsStandardRoadStopTile(v->tile) || HASBIT(v->u.road.state, RVS_IS_STOPPING)) { |
1661 if (IsStandardRoadStopTile(v->tile) || HasBit(v->u.road.state, RVS_IS_STOPPING)) { |
1569 rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY)); |
1662 rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY)); |
1570 CLRBIT(v->u.road.state, RVS_IS_STOPPING); |
1663 ClrBit(v->u.road.state, RVS_IS_STOPPING); |
1571 } |
1664 } |
1572 if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false); |
1665 if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false); |
1573 } |
1666 } |
1574 } |
1667 } |
1575 |
1668 |
1576 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) { |
1669 if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { |
1577 v->tile = tile; |
1670 v->tile = tile; |
1578 v->u.road.state = (byte)dir; |
1671 v->u.road.state = (byte)dir; |
1579 v->u.road.frame = RVC_DEFAULT_START_FRAME; |
1672 v->u.road.frame = start_frame; |
1580 } |
1673 } |
1581 if (newdir != v->direction) { |
1674 if (newdir != v->direction) { |
1582 v->direction = newdir; |
1675 v->direction = newdir; |
1583 v->cur_speed -= v->cur_speed >> 2; |
1676 v->cur_speed -= v->cur_speed >> 2; |
1584 } |
1677 } |
1594 Trackdir dir; |
1687 Trackdir dir; |
1595 uint32 r; |
1688 uint32 r; |
1596 Direction newdir; |
1689 Direction newdir; |
1597 const RoadDriveEntry *rdp; |
1690 const RoadDriveEntry *rdp; |
1598 |
1691 |
1599 if (IsRoadVehFront(v)) { |
1692 uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME; |
1600 /* If this is the front engine, look for the right path. */ |
1693 |
1601 dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3)); |
1694 RoadBits tram; |
|
1695 if (v->u.road.roadtype == ROADTYPE_TRAM && CountBits(tram = GetRoadBits(v->tile, ROADTYPE_TRAM)) == 1) { |
|
1696 /* |
|
1697 * The tram is turning around with one tram 'roadbit'. This means that |
|
1698 * it is using the 'big' corner 'drive data'. However, to support the |
|
1699 * trams to take a small corner, there is a 'turned' marker in the middle |
|
1700 * of the turning 'drive data'. When the tram took the long corner, we |
|
1701 * will still use the 'big' corner drive data, but we advance it one |
|
1702 * frame. We furthermore set the driving direction so the turning is |
|
1703 * going to be properly shown. |
|
1704 */ |
|
1705 turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM; |
|
1706 switch (tram) { |
|
1707 default: NOT_REACHED(); |
|
1708 case ROAD_SW: dir = TRACKDIR_RVREV_NE; break; |
|
1709 case ROAD_NW: dir = TRACKDIR_RVREV_SE; break; |
|
1710 case ROAD_NE: dir = TRACKDIR_RVREV_SW; break; |
|
1711 case ROAD_SE: dir = TRACKDIR_RVREV_NW; break; |
|
1712 } |
1602 } else { |
1713 } else { |
1603 dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true); |
1714 if (IsRoadVehFront(v)) { |
|
1715 /* If this is the front engine, look for the right path. */ |
|
1716 dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3)); |
|
1717 } else { |
|
1718 dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true); |
|
1719 } |
1604 } |
1720 } |
1605 |
1721 |
1606 if (dir == INVALID_TRACKDIR) { |
1722 if (dir == INVALID_TRACKDIR) { |
1607 v->cur_speed = 0; |
1723 v->cur_speed = 0; |
1608 return false; |
1724 return false; |
1609 } |
1725 } |
1610 |
1726 |
1611 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir]; |
1727 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir]; |
1612 |
1728 |
1613 x = TileX(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].x; |
1729 x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x; |
1614 y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y; |
1730 y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y; |
1615 |
1731 |
1616 newdir = RoadVehGetSlidingDirection(v, x, y); |
1732 newdir = RoadVehGetSlidingDirection(v, x, y); |
1617 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1733 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1618 |
1734 |
1619 r = VehicleEnterTile(v, v->tile, x, y); |
1735 r = VehicleEnterTile(v, v->tile, x, y); |
1620 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1736 if (HasBit(r, VETS_CANNOT_ENTER)) { |
1621 v->cur_speed = 0; |
1737 v->cur_speed = 0; |
1622 return false; |
1738 return false; |
1623 } |
1739 } |
1624 |
1740 |
1625 v->u.road.state = dir; |
1741 v->u.road.state = dir; |
1626 v->u.road.frame = RVC_TURN_AROUND_START_FRAME; |
1742 v->u.road.frame = turn_around_start_frame; |
1627 |
1743 |
1628 if (newdir != v->direction) { |
1744 if (newdir != v->direction) { |
1629 v->direction = newdir; |
1745 v->direction = newdir; |
1630 v->cur_speed -= v->cur_speed >> 2; |
1746 v->cur_speed -= v->cur_speed >> 2; |
1631 } |
1747 } |
1657 /* Vehicle is not in a road stop. |
1773 /* Vehicle is not in a road stop. |
1658 * Check for another vehicle to overtake */ |
1774 * Check for another vehicle to overtake */ |
1659 Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); |
1775 Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); |
1660 |
1776 |
1661 if (u != NULL) { |
1777 if (u != NULL) { |
|
1778 u = u->First(); |
1662 /* There is a vehicle in front overtake it if possible */ |
1779 /* There is a vehicle in front overtake it if possible */ |
1663 if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); |
1780 if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); |
1664 if (v->u.road.overtaking == 0) v->cur_speed = u->cur_speed; |
1781 if (v->u.road.overtaking == 0) v->cur_speed = u->cur_speed; |
1665 return false; |
1782 return false; |
1666 } |
1783 } |
1710 |
1827 |
1711 /* Check if next inline bay is free */ |
1828 /* Check if next inline bay is free */ |
1712 if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) { |
1829 if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) { |
1713 RoadStop *rs_n = GetRoadStopByTile(next_tile, type); |
1830 RoadStop *rs_n = GetRoadStopByTile(next_tile, type); |
1714 |
1831 |
1715 if (rs_n->IsFreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY))) { |
1832 if (rs_n->IsFreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY))) { |
1716 /* Bay in next stop along is free - use it */ |
1833 /* Bay in next stop along is free - use it */ |
1717 ClearSlot(v); |
1834 ClearSlot(v); |
1718 rs_n->num_vehicles++; |
1835 rs_n->num_vehicles++; |
1719 v->u.road.slot = rs_n; |
1836 v->u.road.slot = rs_n; |
1720 v->dest_tile = rs_n->xy; |
1837 v->dest_tile = rs_n->xy; |
1781 } |
1898 } |
1782 |
1899 |
1783 /* Check tile position conditions - i.e. stop position in depot, |
1900 /* Check tile position conditions - i.e. stop position in depot, |
1784 * entry onto bridge or into tunnel */ |
1901 * entry onto bridge or into tunnel */ |
1785 r = VehicleEnterTile(v, v->tile, x, y); |
1902 r = VehicleEnterTile(v, v->tile, x, y); |
1786 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1903 if (HasBit(r, VETS_CANNOT_ENTER)) { |
1787 v->cur_speed = 0; |
1904 v->cur_speed = 0; |
1788 return false; |
1905 return false; |
1789 } |
1906 } |
1790 |
1907 |
1791 /* Move to next frame unless vehicle arrived at a stop position |
1908 /* Move to next frame unless vehicle arrived at a stop position |
1792 * in a depot or entered a tunnel/bridge */ |
1909 * in a depot or entered a tunnel/bridge */ |
1793 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1910 if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1794 |
1911 |
1795 v->cur_image = v->GetImage(v->direction); |
1912 v->cur_image = v->GetImage(v->direction); |
1796 v->UpdateDeltaXY(v->direction); |
1913 v->UpdateDeltaXY(v->direction); |
1797 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1914 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1798 return true; |
1915 return true; |
2010 { |
2127 { |
2011 Vehicle *v; |
2128 Vehicle *v; |
2012 CommandCost cost; |
2129 CommandCost cost; |
2013 CargoID new_cid = GB(p2, 0, 8); |
2130 CargoID new_cid = GB(p2, 0, 8); |
2014 byte new_subtype = GB(p2, 8, 8); |
2131 byte new_subtype = GB(p2, 8, 8); |
2015 bool only_this = HASBIT(p2, 16); |
2132 bool only_this = HasBit(p2, 16); |
2016 uint16 capacity = CALLBACK_FAILED; |
2133 uint16 capacity = CALLBACK_FAILED; |
2017 uint total_capacity = 0; |
2134 uint total_capacity = 0; |
2018 |
2135 |
2019 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
2136 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
2020 |
2137 |
2033 * [Refit] button near each wagon. */ |
2150 * [Refit] button near each wagon. */ |
2034 if (!CanRefitTo(v->engine_type, new_cid)) continue; |
2151 if (!CanRefitTo(v->engine_type, new_cid)) continue; |
2035 |
2152 |
2036 if (v->cargo_cap == 0) continue; |
2153 if (v->cargo_cap == 0) continue; |
2037 |
2154 |
2038 if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { |
2155 if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { |
2039 /* Back up the cargo type */ |
2156 /* Back up the cargo type */ |
2040 CargoID temp_cid = v->cargo_type; |
2157 CargoID temp_cid = v->cargo_type; |
2041 byte temp_subtype = v->cargo_subtype; |
2158 byte temp_subtype = v->cargo_subtype; |
2042 v->cargo_type = new_cid; |
2159 v->cargo_type = new_cid; |
2043 v->cargo_subtype = new_subtype; |
2160 v->cargo_subtype = new_subtype; |