127 int32 cost; |
129 int32 cost; |
128 Vehicle *v; |
130 Vehicle *v; |
129 UnitID unit_num; |
131 UnitID unit_num; |
130 Engine *e; |
132 Engine *e; |
131 |
133 |
132 if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE); |
134 if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE); |
133 |
135 |
134 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
136 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
135 |
137 |
136 cost = EstimateRoadVehCost(p1); |
138 cost = EstimateRoadVehCost(p1); |
137 if (flags & DC_QUERY_COST) return cost; |
139 if (flags & DC_QUERY_COST) return cost; |
661 { |
663 { |
662 const Order *order; |
664 const Order *order; |
663 |
665 |
664 switch (v->current_order.type) { |
666 switch (v->current_order.type) { |
665 case OT_GOTO_DEPOT: |
667 case OT_GOTO_DEPOT: |
666 // Let a depot order in the orderlist interrupt. |
668 /* Let a depot order in the orderlist interrupt. */ |
667 if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return; |
669 if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return; |
668 if (v->current_order.flags & OF_SERVICE_IF_NEEDED && |
670 if (v->current_order.flags & OF_SERVICE_IF_NEEDED && |
669 !VehicleNeedsService(v)) { |
671 !VehicleNeedsService(v)) { |
670 v->cur_order_index++; |
672 v->cur_order_index++; |
671 } |
673 } |
826 rvf.y = y; |
828 rvf.y = y; |
827 rvf.dir = dir; |
829 rvf.dir = dir; |
828 rvf.veh = v; |
830 rvf.veh = v; |
829 u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose); |
831 u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose); |
830 |
832 |
831 // This code protects a roadvehicle from being blocked for ever |
833 /* This code protects a roadvehicle from being blocked for ever |
832 // If more than 1480 / 74 days a road vehicle is blocked, it will |
834 * If more than 1480 / 74 days a road vehicle is blocked, it will |
833 // drive just through it. The ultimate backup-code of TTD. |
835 * drive just through it. The ultimate backup-code of TTD. |
834 // It can be disabled. |
836 * It can be disabled. */ |
835 if (u == NULL) { |
837 if (u == NULL) { |
836 v->u.road.blocked_ctr = 0; |
838 v->u.road.blocked_ctr = 0; |
837 return NULL; |
839 return NULL; |
838 } |
840 } |
839 |
841 |
879 static bool RoadVehAccelerate(Vehicle *v) |
881 static bool RoadVehAccelerate(Vehicle *v) |
880 { |
882 { |
881 uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0); |
883 uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0); |
882 byte t; |
884 byte t; |
883 |
885 |
884 // Clamp |
886 /* Clamp */ |
885 spd = min(spd, v->max_speed); |
887 spd = min(spd, v->max_speed); |
886 if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) { |
888 if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) { |
887 spd = min(spd, GetBridge(GetBridgeType(v->tile))->speed * 2); |
889 spd = min(spd, GetBridge(GetBridgeType(v->tile))->speed * 2); |
888 } |
890 } |
889 |
891 |
890 //updates statusbar only if speed have changed to save CPU time |
892 /* updates statusbar only if speed have changed to save CPU time */ |
891 if (spd != v->cur_speed) { |
893 if (spd != v->cur_speed) { |
892 v->cur_speed = spd; |
894 v->cur_speed = spd; |
893 if (_patches.vehicle_speed) { |
895 if (_patches.vehicle_speed) { |
894 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
896 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
895 } |
897 } |
896 } |
898 } |
897 |
899 |
898 // Decrease somewhat when turning |
900 /* Decrease somewhat when turning */ |
899 if (!(v->direction & 1)) spd = spd * 3 >> 2; |
901 if (!(v->direction & 1)) spd = spd * 3 >> 2; |
900 |
902 |
901 if (spd == 0) return false; |
903 if (spd == 0) return false; |
902 |
904 |
903 if ((byte)++spd == 0) return true; |
905 if ((byte)++spd == 0) return true; |
1151 trackdir = DiagdirToDiagTrackdir(enterdir); |
1153 trackdir = DiagdirToDiagTrackdir(enterdir); |
1152 //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); |
1154 //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); |
1153 |
1155 |
1154 ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE); |
1156 ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE); |
1155 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
1157 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
1156 /* We are already at our target. Just do something */ |
1158 /* We are already at our target. Just do something |
1157 //TODO: maybe display error? |
1159 * @todo: maybe display error? |
1158 //TODO: go straight ahead if possible? |
1160 * @todo: go straight ahead if possible? */ |
1159 return_track(FindFirstBit2x64(trackdirs)); |
1161 return_track(FindFirstBit2x64(trackdirs)); |
1160 } else { |
1162 } else { |
1161 /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains |
1163 /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains |
1162 the direction we need to take to get there, if ftd.best_bird_dist is not 0, |
1164 the direction we need to take to get there, if ftd.best_bird_dist is not 0, |
1163 we did not find our target, but ftd.best_trackdir contains the direction leading |
1165 we did not find our target, but ftd.best_trackdir contains the direction leading |
1221 |
1223 |
1222 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile) |
1224 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile) |
1223 { |
1225 { |
1224 uint dist; |
1226 uint dist; |
1225 if (_patches.yapf.road_use_yapf) { |
1227 if (_patches.yapf.road_use_yapf) { |
1226 // use YAPF |
1228 /* use YAPF */ |
1227 dist = YapfRoadVehDistanceToTile(v, tile); |
1229 dist = YapfRoadVehDistanceToTile(v, tile); |
1228 } else { |
1230 } else { |
1229 // use NPF |
1231 /* use NPF */ |
1230 NPFFindStationOrTileData fstd; |
1232 NPFFindStationOrTileData fstd; |
1231 Trackdir trackdir = GetVehicleTrackdir(v); |
1233 Trackdir trackdir = GetVehicleTrackdir(v); |
1232 assert(trackdir != INVALID_TRACKDIR); |
1234 assert(trackdir != INVALID_TRACKDIR); |
1233 |
1235 |
1234 fstd.dest_coords = tile; |
1236 fstd.dest_coords = tile; |
1235 fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station |
1237 fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station |
1236 |
1238 |
1237 dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist; |
1239 dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist; |
1238 // change units from NPF_TILE_LENGTH to # of tiles |
1240 /* change units from NPF_TILE_LENGTH to # of tiles */ |
1239 if (dist != UINT_MAX) |
1241 if (dist != UINT_MAX) |
1240 dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH; |
1242 dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH; |
1241 } |
1243 } |
1242 return dist; |
1244 return dist; |
1243 } |
1245 } |
1275 Direction old_dir; |
1277 Direction old_dir; |
1276 RoadDriveEntry rd; |
1278 RoadDriveEntry rd; |
1277 int x,y; |
1279 int x,y; |
1278 uint32 r; |
1280 uint32 r; |
1279 |
1281 |
1280 // decrease counters |
1282 /* decrease counters */ |
1281 v->tick_counter++; |
1283 v->tick_counter++; |
1282 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
1284 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
1283 |
1285 |
1284 // handle crashed |
1286 /* handle crashed */ |
1285 if (v->u.road.crashed_ctr != 0) { |
1287 if (v->u.road.crashed_ctr != 0) { |
1286 RoadVehIsCrashed(v); |
1288 RoadVehIsCrashed(v); |
1287 return; |
1289 return; |
1288 } |
1290 } |
1289 |
1291 |
1290 RoadVehCheckTrainCrash(v); |
1292 RoadVehCheckTrainCrash(v); |
1291 |
1293 |
1292 // road vehicle has broken down? |
1294 /* road vehicle has broken down? */ |
1293 if (v->breakdown_ctr != 0) { |
1295 if (v->breakdown_ctr != 0) { |
1294 if (v->breakdown_ctr <= 2) { |
1296 if (v->breakdown_ctr <= 2) { |
1295 HandleBrokenRoadVeh(v); |
1297 HandleBrokenRoadVeh(v); |
1296 return; |
1298 return; |
1297 } |
1299 } |
1626 |
1628 |
1627 if (rs == v->u.road.slot) { |
1629 if (rs == v->u.road.slot) { |
1628 /* We are leaving the correct station */ |
1630 /* We are leaving the correct station */ |
1629 ClearSlot(v); |
1631 ClearSlot(v); |
1630 } else if (v->u.road.slot != NULL) { |
1632 } else if (v->u.road.slot != NULL) { |
1631 /* We are leaving the wrong station */ |
1633 /* We are leaving the wrong station |
1632 //XXX The question is .. what to do? Actually we shouldn't be here |
1634 * XXX The question is .. what to do? Actually we shouldn't be here |
1633 //but I guess we need to clear the slot |
1635 * but I guess we need to clear the slot */ |
1634 DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index); |
1636 DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index); |
1635 if (v->tile != v->dest_tile) { |
1637 if (v->tile != v->dest_tile) { |
1636 DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile); |
1638 DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile); |
1637 } |
1639 } |
1638 if (v->dest_tile != v->u.road.slot->xy) { |
1640 if (v->dest_tile != v->u.road.slot->xy) { |
1690 if (_patches.servint_roadveh == 0) return; |
1692 if (_patches.servint_roadveh == 0) return; |
1691 if (!VehicleNeedsService(v)) return; |
1693 if (!VehicleNeedsService(v)) return; |
1692 if (v->vehstatus & VS_STOPPED) return; |
1694 if (v->vehstatus & VS_STOPPED) return; |
1693 if (_patches.gotodepot && VehicleHasDepotOrders(v)) return; |
1695 if (_patches.gotodepot && VehicleHasDepotOrders(v)) return; |
1694 |
1696 |
1695 // Don't interfere with a depot visit scheduled by the user, or a |
1697 /* Don't interfere with a depot visit scheduled by the user, or a |
1696 // depot visit by the order list. |
1698 * depot visit by the order list. */ |
1697 if (v->current_order.type == OT_GOTO_DEPOT && |
1699 if (v->current_order.type == OT_GOTO_DEPOT && |
1698 (v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0) |
1700 (v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0) |
1699 return; |
1701 return; |
1700 |
1702 |
1701 // If we already got a slot at a stop, use that FIRST, and go to a depot later |
1703 /* If we already got a slot at a stop, use that FIRST, and go to a depot later */ |
1702 if (v->u.road.slot != NULL) return; |
1704 if (v->u.road.slot != NULL) return; |
1703 |
1705 |
1704 if (IsRoadVehInDepot(v)) { |
1706 if (IsRoadVehInDepot(v)) { |
1705 VehicleServiceInDepot(v); |
1707 VehicleServiceInDepot(v); |
1706 return; |
1708 return; |
1707 } |
1709 } |
1708 |
1710 |
1709 // XXX If we already have a depot order, WHY do we search over and over? |
1711 /* XXX If we already have a depot order, WHY do we search over and over? */ |
1710 depot = FindClosestRoadDepot(v); |
1712 depot = FindClosestRoadDepot(v); |
1711 |
1713 |
1712 if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) { |
1714 if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) { |
1713 if (v->current_order.type == OT_GOTO_DEPOT) { |
1715 if (v->current_order.type == OT_GOTO_DEPOT) { |
1714 v->current_order.type = OT_DUMMY; |
1716 v->current_order.type = OT_DUMMY; |
1741 AgeVehicle(v); |
1743 AgeVehicle(v); |
1742 CheckIfRoadVehNeedsService(v); |
1744 CheckIfRoadVehNeedsService(v); |
1743 |
1745 |
1744 CheckOrders(v); |
1746 CheckOrders(v); |
1745 |
1747 |
1746 //Current slot has expired |
1748 /* Current slot has expired */ |
1747 if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot != NULL && v->u.road.slot_age-- == 0) { |
1749 if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot != NULL && v->u.road.slot_age-- == 0) { |
1748 DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X", |
1750 DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X", |
1749 v->unitnumber, v->index, v->u.road.slot->xy); |
1751 v->unitnumber, v->index, v->u.road.slot->xy); |
1750 ClearSlot(v); |
1752 ClearSlot(v); |
1751 } |
1753 } |