116 } |
117 } |
117 |
118 |
118 static int32 EstimateRoadVehCost(EngineID engine_type) |
119 static int32 EstimateRoadVehCost(EngineID engine_type) |
119 { |
120 { |
120 return ((_eco->GetPrice(CEconomy::ROADVEH_BASE) >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5; |
121 return ((_eco->GetPrice(CEconomy::ROADVEH_BASE) >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5; |
|
122 } |
|
123 |
|
124 byte GetRoadVehLength(const Vehicle *v) |
|
125 { |
|
126 byte length = 8; |
|
127 |
|
128 uint16 veh_len = GetVehicleCallback(CBID_TRAIN_VEHICLE_LENGTH, 0, 0, v->engine_type, v); |
|
129 if (veh_len != CALLBACK_FAILED) { |
|
130 length -= clamp(veh_len, 0, 7); |
|
131 } |
|
132 |
|
133 return length; |
|
134 } |
|
135 |
|
136 void RoadVehUpdateCache(Vehicle *v) |
|
137 { |
|
138 assert(v->type == VEH_ROAD); |
|
139 assert(IsRoadVehFront(v)); |
|
140 |
|
141 for (Vehicle *u = v; u != NULL; u = u->next) { |
|
142 /* Update the v->first cache. */ |
|
143 if (u->first == NULL) u->first = v; |
|
144 |
|
145 /* Update the 'first engine' */ |
|
146 u->u.road.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type; |
|
147 |
|
148 /* Update the length of the vehicle. */ |
|
149 u->u.road.cached_veh_length = GetRoadVehLength(u); |
|
150 } |
121 } |
151 } |
122 |
152 |
123 /** Build a road vehicle. |
153 /** Build a road vehicle. |
124 * @param tile tile of depot where road vehicle is built |
154 * @param tile tile of depot where road vehicle is built |
125 * @param flags operation to perform |
155 * @param flags operation to perform |
143 /* The ai_new queries the vehicle cost before building the route, |
173 /* The ai_new queries the vehicle cost before building the route, |
144 * so we must check against cheaters no sooner than now. --pasky */ |
174 * so we must check against cheaters no sooner than now. --pasky */ |
145 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
175 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
146 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
176 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
147 |
177 |
148 v = AllocateVehicle(); |
178 if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE); |
149 if (v == NULL) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
179 |
|
180 uint num_vehicles = 1 + CountArticulatedParts(p1); |
|
181 |
|
182 /* Allow for the front and up to 10 articulated parts. */ |
|
183 Vehicle *vl[11]; |
|
184 memset(&vl, 0, sizeof(vl)); |
|
185 |
|
186 if (!AllocateVehicles(vl, num_vehicles)) { |
|
187 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
188 } |
|
189 |
|
190 v = vl[0]; |
150 |
191 |
151 /* find the first free roadveh id */ |
192 /* find the first free roadveh id */ |
152 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); |
193 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); |
153 if (unit_num > _patches.max_roadveh) |
194 if (unit_num > _patches.max_roadveh) |
154 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
195 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
205 v->build_year = _cur_year; |
246 v->build_year = _cur_year; |
206 |
247 |
207 v = new (v) RoadVehicle(); |
248 v = new (v) RoadVehicle(); |
208 v->cur_image = 0xC15; |
249 v->cur_image = 0xC15; |
209 v->random_bits = VehicleRandomBits(); |
250 v->random_bits = VehicleRandomBits(); |
|
251 SetRoadVehFront(v); |
|
252 |
|
253 v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; |
|
254 v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype); |
|
255 v->u.road.cached_veh_length = GetRoadVehLength(v); |
210 |
256 |
211 v->vehicle_flags = 0; |
257 v->vehicle_flags = 0; |
212 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
258 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
213 |
259 |
|
260 v->first = NULL; |
214 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
261 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
|
262 |
|
263 AddArticulatedParts(vl, VEH_ROAD); |
215 |
264 |
216 VehiclePositionChanged(v); |
265 VehiclePositionChanged(v); |
217 |
266 |
218 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
267 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
219 RebuildVehicleLists(); |
268 RebuildVehicleLists(); |
563 { |
632 { |
564 static const DirDiff delta[] = { |
633 static const DirDiff delta[] = { |
565 DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT |
634 DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT |
566 }; |
635 }; |
567 |
636 |
568 uint32 r = Random(); |
637 do { |
569 |
638 uint32 r = Random(); |
570 v->direction = ChangeDir(v->direction, delta[r & 3]); |
639 |
571 BeginVehicleMove(v); |
640 v->direction = ChangeDir(v->direction, delta[r & 3]); |
572 v->UpdateDeltaXY(v->direction); |
641 BeginVehicleMove(v); |
573 v->cur_image = GetRoadVehImage(v, v->direction); |
642 v->UpdateDeltaXY(v->direction); |
574 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
643 v->cur_image = GetRoadVehImage(v, v->direction); |
|
644 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
|
645 } while ((v = v->next) != NULL); |
575 } |
646 } |
576 |
647 |
577 static void RoadVehIsCrashed(Vehicle *v) |
648 static void RoadVehIsCrashed(Vehicle *v) |
578 { |
649 { |
579 v->u.road.crashed_ctr++; |
650 v->u.road.crashed_ctr++; |
580 if (v->u.road.crashed_ctr == 2) { |
651 if (v->u.road.crashed_ctr == 2) { |
581 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); |
652 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); |
582 } else if (v->u.road.crashed_ctr <= 45) { |
653 } else if (v->u.road.crashed_ctr <= 45) { |
583 if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v); |
654 if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v); |
584 } else if (v->u.road.crashed_ctr >= 2220) { |
655 } else if (v->u.road.crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) { |
585 RoadVehDelete(v); |
656 DeleteLastRoadVeh(v); |
586 } |
657 } |
587 } |
658 } |
588 |
659 |
589 static void* EnumCheckRoadVehCrashTrain(Vehicle* v, void* data) |
660 static void* EnumCheckRoadVehCrashTrain(Vehicle* v, void* data) |
590 { |
661 { |
952 !(u->vehstatus & VS_STOPPED) && |
1035 !(u->vehstatus & VS_STOPPED) && |
953 u->cur_speed != 0) { |
1036 u->cur_speed != 0) { |
954 return; |
1037 return; |
955 } |
1038 } |
956 |
1039 |
|
1040 /* Trams can't overtake other trams */ |
|
1041 if (v->u.road.roadtype == ROADTYPE_TRAM) return; |
|
1042 |
|
1043 /* For now, articulated road vehicles can't overtake anything. */ |
|
1044 if (RoadVehHasArticPart(v)) return; |
|
1045 |
957 if (v->direction != u->direction || !(v->direction & 1)) return; |
1046 if (v->direction != u->direction || !(v->direction & 1)) return; |
958 |
1047 |
959 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
1048 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
960 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
1049 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
961 |
1050 |
962 tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F; |
1051 tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes) & 0x3F; |
963 if ((tt & 3) == 0) return; |
1052 if ((tt & 3) == 0) return; |
964 if ((tt & 0x3C) != 0) return; |
1053 if ((tt & 0x3C) != 0) return; |
965 |
1054 |
966 if (tt == 3) tt = (v->direction & 2) ? 2 : 1; |
1055 if (tt == 3) tt = (v->direction & 2) ? 2 : 1; |
967 od.tilebits = tt; |
1056 od.tilebits = tt; |
1028 frd->mindist = dist; |
1117 frd->mindist = dist; |
1029 } |
1118 } |
1030 return false; |
1119 return false; |
1031 } |
1120 } |
1032 |
1121 |
1033 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes) |
1122 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes) |
1034 { |
1123 { |
1035 |
1124 |
1036 void* perf = NpfBeginInterval(); |
1125 void* perf = NpfBeginInterval(); |
1037 NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, owner, railtypes); |
1126 NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, sub_type, owner, railtypes); |
1038 int t = NpfEndInterval(perf); |
1127 int t = NpfEndInterval(perf); |
1039 DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size); |
1128 DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size); |
1040 return ret; |
1129 return ret; |
1041 } |
1130 } |
1042 |
1131 |
1054 |
1143 |
1055 TileIndex desttile; |
1144 TileIndex desttile; |
1056 FindRoadToChooseData frd; |
1145 FindRoadToChooseData frd; |
1057 Trackdir best_track; |
1146 Trackdir best_track; |
1058 |
1147 |
1059 uint32 r = GetTileTrackStatus(tile, TRANSPORT_ROAD); |
1148 uint32 r = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes); |
1060 TrackdirBits signal = (TrackdirBits)GB(r, 16, 16); |
1149 TrackdirBits signal = (TrackdirBits)GB(r, 16, 16); |
1061 TrackdirBits trackdirs = (TrackdirBits)GB(r, 0, 16); |
1150 TrackdirBits trackdirs = (TrackdirBits)GB(r, 0, 16); |
1062 |
1151 |
1063 if (IsTileType(tile, MP_STREET)) { |
1152 if (IsTileType(tile, MP_STREET)) { |
1064 if (GetRoadTileType(tile) == ROAD_TILE_DEPOT && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) { |
1153 if (GetRoadTileType(tile) == ROAD_TILE_DEPOT && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.compatible_roadtypes) == 0)) { |
1065 /* Road depot owned by another player or with the wrong orientation */ |
1154 /* Road depot owned by another player or with the wrong orientation */ |
1066 trackdirs = TRACKDIR_BIT_NONE; |
1155 trackdirs = TRACKDIR_BIT_NONE; |
1067 } |
1156 } |
1068 } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) { |
1157 } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) { |
1069 /* Standard road stop (drive-through stops are treated as normal road) */ |
1158 /* Standard road stop (drive-through stops are treated as normal road) */ |
1129 |
1218 |
1130 NPFFillWithOrderData(&fstd, v); |
1219 NPFFillWithOrderData(&fstd, v); |
1131 trackdir = DiagdirToDiagTrackdir(enterdir); |
1220 trackdir = DiagdirToDiagTrackdir(enterdir); |
1132 //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); |
1221 //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); |
1133 |
1222 |
1134 ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE); |
1223 ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE); |
1135 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
1224 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
1136 /* We are already at our target. Just do something |
1225 /* We are already at our target. Just do something |
1137 * @todo: maybe display error? |
1226 * @todo: maybe display error? |
1138 * @todo: go straight ahead if possible? */ |
1227 * @todo: go straight ahead if possible? */ |
1139 return_track(FindFirstBit2x64(trackdirs)); |
1228 return_track(FindFirstBit2x64(trackdirs)); |
1179 for (int i = 0; bitmask != 0; bitmask >>= 1, i++) { |
1268 for (int i = 0; bitmask != 0; bitmask >>= 1, i++) { |
1180 if (HASBIT(bitmask, 0)) { |
1269 if (HASBIT(bitmask, 0)) { |
1181 if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track |
1270 if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track |
1182 frd.maxtracklen = (uint)-1; |
1271 frd.maxtracklen = (uint)-1; |
1183 frd.mindist = (uint)-1; |
1272 frd.mindist = (uint)-1; |
1184 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); |
1273 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); |
1185 |
1274 |
1186 if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) { |
1275 if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) { |
1187 best_dist = frd.mindist; |
1276 best_dist = frd.mindist; |
1188 best_maxlen = frd.maxtracklen; |
1277 best_maxlen = frd.maxtracklen; |
1189 best_track = (Trackdir)i; |
1278 best_track = (Trackdir)i; |
1247 19, 19, 15, 15, 0, 0, 0, 0, |
1336 19, 19, 15, 15, 0, 0, 0, 0, |
1248 16, 16, 12, 12, 0, 0, 0, 0, |
1337 16, 16, 12, 12, 0, 0, 0, 0, |
1249 15, 15, 11, 11 |
1338 15, 15, 11, 11 |
1250 }; |
1339 }; |
1251 |
1340 |
1252 static void RoadVehController(Vehicle *v) |
1341 static bool RoadVehLeaveDepot(Vehicle *v, bool first) |
|
1342 { |
|
1343 /* Don't leave if not all the wagons are in the depot. */ |
|
1344 for (const Vehicle *u = v; u != NULL; u = u->next) { |
|
1345 if (u->u.road.state != RVSB_IN_DEPOT || u->tile != v->tile) return false; |
|
1346 } |
|
1347 |
|
1348 DiagDirection dir = GetRoadDepotDirection(v->tile); |
|
1349 v->direction = DiagDirToDir(dir); |
|
1350 |
|
1351 Trackdir tdir = _roadveh_depot_exit_trackdir[dir]; |
|
1352 const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; |
|
1353 |
|
1354 int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); |
|
1355 int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); |
|
1356 |
|
1357 if (first) { |
|
1358 if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return true; |
|
1359 |
|
1360 VehicleServiceInDepot(v); |
|
1361 |
|
1362 StartRoadVehSound(v); |
|
1363 |
|
1364 /* Vehicle is about to leave a depot */ |
|
1365 v->cur_speed = 0; |
|
1366 } |
|
1367 |
|
1368 BeginVehicleMove(v); |
|
1369 |
|
1370 v->vehstatus &= ~VS_HIDDEN; |
|
1371 v->u.road.state = tdir; |
|
1372 v->u.road.frame = RVC_DEPOT_START_FRAME; |
|
1373 |
|
1374 v->cur_image = GetRoadVehImage(v, v->direction); |
|
1375 v->UpdateDeltaXY(v->direction); |
|
1376 SetRoadVehPosition(v,x,y); |
|
1377 |
|
1378 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
|
1379 |
|
1380 return true; |
|
1381 } |
|
1382 |
|
1383 static Trackdir FollowPreviousRoadVehicle(const Vehicle *v, const Vehicle *prev, TileIndex tile, DiagDirection entry_dir) |
|
1384 { |
|
1385 if (prev->tile == v->tile) { |
|
1386 /* If the previous vehicle is on the same tile as this vehicle is |
|
1387 * then it must have reversed. */ |
|
1388 return _road_reverse_table[entry_dir]; |
|
1389 } |
|
1390 |
|
1391 byte prev_state = prev->u.road.state; |
|
1392 Trackdir dir; |
|
1393 |
|
1394 if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) { |
|
1395 DiagDirection diag_dir = INVALID_DIAGDIR; |
|
1396 |
|
1397 if (IsTunnelTile(tile)) { |
|
1398 diag_dir = GetTunnelDirection(tile); |
|
1399 } else if (IsBridgeTile(tile)) { |
|
1400 diag_dir = GetBridgeRampDirection(tile); |
|
1401 } else if (IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_DEPOT) { |
|
1402 diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile)); |
|
1403 } |
|
1404 |
|
1405 if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR; |
|
1406 dir = DiagdirToDiagTrackdir(diag_dir); |
|
1407 } else if (HASBIT(prev_state, RVS_IN_DT_ROAD_STOP)) { |
|
1408 dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK); |
|
1409 } else if (prev_state < TRACKDIR_END) { |
|
1410 dir = (Trackdir)prev_state; |
|
1411 } else { |
|
1412 return INVALID_TRACKDIR; |
|
1413 } |
|
1414 |
|
1415 /* Do some sanity checking. */ |
|
1416 static const RoadBits required_roadbits[] = { |
|
1417 ROAD_X, ROAD_Y, ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE, |
|
1418 ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X, ROAD_Y |
|
1419 }; |
|
1420 RoadBits required = required_roadbits[dir & 0x07]; |
|
1421 |
|
1422 if ((required & GetAnyRoadBits(tile, v->u.road.roadtype)) == ROAD_NONE) { |
|
1423 dir = INVALID_TRACKDIR; |
|
1424 } |
|
1425 |
|
1426 return dir; |
|
1427 } |
|
1428 |
|
1429 static bool IndividualRoadVehicleController(Vehicle *v, const Vehicle *prev) |
1253 { |
1430 { |
1254 Direction new_dir; |
1431 Direction new_dir; |
1255 Direction old_dir; |
1432 Direction old_dir; |
1256 RoadDriveEntry rd; |
1433 RoadDriveEntry rd; |
1257 int x,y; |
1434 int x,y; |
1258 uint32 r; |
1435 uint32 r; |
1259 |
|
1260 /* decrease counters */ |
|
1261 v->tick_counter++; |
|
1262 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
|
1263 |
|
1264 /* handle crashed */ |
|
1265 if (v->u.road.crashed_ctr != 0) { |
|
1266 RoadVehIsCrashed(v); |
|
1267 return; |
|
1268 } |
|
1269 |
|
1270 RoadVehCheckTrainCrash(v); |
|
1271 |
|
1272 /* road vehicle has broken down? */ |
|
1273 if (v->breakdown_ctr != 0) { |
|
1274 if (v->breakdown_ctr <= 2) { |
|
1275 HandleBrokenRoadVeh(v); |
|
1276 return; |
|
1277 } |
|
1278 v->breakdown_ctr--; |
|
1279 } |
|
1280 |
|
1281 if (v->vehstatus & VS_STOPPED) return; |
|
1282 |
|
1283 ProcessRoadVehOrder(v); |
|
1284 v->HandleLoading(); |
|
1285 |
|
1286 if (v->current_order.type == OT_LOADING) return; |
|
1287 |
|
1288 if (IsRoadVehInDepot(v)) { |
|
1289 /* Vehicle is about to leave a depot */ |
|
1290 DiagDirection dir; |
|
1291 const RoadDriveEntry* rdp; |
|
1292 Trackdir tdir; |
|
1293 |
|
1294 v->cur_speed = 0; |
|
1295 |
|
1296 dir = GetRoadDepotDirection(v->tile); |
|
1297 v->direction = DiagDirToDir(dir); |
|
1298 |
|
1299 tdir = _roadveh_depot_exit_trackdir[dir]; |
|
1300 rdp = _road_drive_data[(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; |
|
1301 |
|
1302 x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); |
|
1303 y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); |
|
1304 |
|
1305 if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return; |
|
1306 |
|
1307 VehicleServiceInDepot(v); |
|
1308 |
|
1309 StartRoadVehSound(v); |
|
1310 |
|
1311 BeginVehicleMove(v); |
|
1312 |
|
1313 v->vehstatus &= ~VS_HIDDEN; |
|
1314 v->u.road.state = tdir; |
|
1315 v->u.road.frame = RVC_DEPOT_START_FRAME; |
|
1316 |
|
1317 v->cur_image = GetRoadVehImage(v, v->direction); |
|
1318 v->UpdateDeltaXY(v->direction); |
|
1319 SetRoadVehPosition(v,x,y); |
|
1320 |
|
1321 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
|
1322 return; |
|
1323 } |
|
1324 |
|
1325 /* Check if vehicle needs to proceed, return if it doesn't */ |
|
1326 if (!RoadVehAccelerate(v)) return; |
|
1327 |
1436 |
1328 if (v->u.road.overtaking != 0) { |
1437 if (v->u.road.overtaking != 0) { |
1329 if (++v->u.road.overtaking_ctr >= 35) |
1438 if (++v->u.road.overtaking_ctr >= 35) |
1330 /* If overtaking just aborts at a random moment, we can have a out-of-bound problem, |
1439 /* If overtaking just aborts at a random moment, we can have a out-of-bound problem, |
1331 * if the vehicle started a corner. To protect that, only allow an abort of |
1440 * if the vehicle started a corner. To protect that, only allow an abort of |
1333 if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) { |
1442 if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) { |
1334 v->u.road.overtaking = 0; |
1443 v->u.road.overtaking = 0; |
1335 } |
1444 } |
1336 } |
1445 } |
1337 |
1446 |
|
1447 /* If this vehicle is in a depot and we've reached this point it must be |
|
1448 * one of the articulated parts. It will stay in the depot until activated |
|
1449 * by the previous vehicle in the chain when it gets to the right place. */ |
|
1450 if (IsRoadVehInDepot(v)) return true; |
|
1451 |
1338 /* Save old vehicle position to use at end of move to set viewport area dirty */ |
1452 /* Save old vehicle position to use at end of move to set viewport area dirty */ |
1339 BeginVehicleMove(v); |
1453 BeginVehicleMove(v); |
1340 |
1454 |
1341 if (v->u.road.state == RVSB_WORMHOLE) { |
1455 if (v->u.road.state == RVSB_WORMHOLE) { |
1342 /* Vehicle is entering a depot or is on a bridge or in a tunnel */ |
1456 /* Vehicle is entering a depot or is on a bridge or in a tunnel */ |
1343 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
1457 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
1344 |
1458 |
1345 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction); |
1459 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction); |
1346 if (u != NULL && u->cur_speed < v->cur_speed) { |
1460 if (u != NULL && u->cur_speed < v->cur_speed) { |
1347 v->cur_speed = u->cur_speed; |
1461 v->cur_speed = u->cur_speed; |
1348 return; |
1462 return false; |
1349 } |
1463 } |
1350 |
1464 |
1351 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1465 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1352 /* Vehicle has just entered a bridge or tunnel */ |
1466 /* Vehicle has just entered a bridge or tunnel */ |
1353 v->cur_image = GetRoadVehImage(v, v->direction); |
1467 v->cur_image = GetRoadVehImage(v, v->direction); |
1354 v->UpdateDeltaXY(v->direction); |
1468 v->UpdateDeltaXY(v->direction); |
1355 SetRoadVehPosition(v,gp.x,gp.y); |
1469 SetRoadVehPosition(v,gp.x,gp.y); |
1356 return; |
1470 return true; |
1357 } |
1471 } |
1358 |
1472 |
1359 v->x_pos = gp.x; |
1473 v->x_pos = gp.x; |
1360 v->y_pos = gp.y; |
1474 v->y_pos = gp.y; |
1361 VehiclePositionChanged(v); |
1475 VehiclePositionChanged(v); |
1362 if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v); |
1476 if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v); |
1363 return; |
1477 return true; |
1364 } |
1478 } |
1365 |
1479 |
1366 /* Get move position data for next frame. |
1480 /* Get move position data for next frame. |
1367 * For a drive-through road stop use 'straight road' move data. |
1481 * For a drive-through road stop use 'straight road' move data. |
1368 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1482 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1369 rd = _road_drive_data[( |
1483 rd = _road_drive_data[v->u.road.roadtype][( |
1370 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1484 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1371 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1485 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1372 |
1486 |
1373 if (rd.x & RDE_NEXT_TILE) { |
1487 if (rd.x & RDE_NEXT_TILE) { |
1374 TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3); |
1488 TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3); |
1375 Trackdir dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3)); |
1489 Trackdir dir; |
1376 uint32 r; |
1490 uint32 r; |
1377 Direction newdir; |
1491 Direction newdir; |
1378 const RoadDriveEntry *rdp; |
1492 const RoadDriveEntry *rdp; |
1379 |
1493 |
|
1494 if (IsRoadVehFront(v)) { |
|
1495 /* If this is the front engine, look for the right path. */ |
|
1496 dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3)); |
|
1497 } else { |
|
1498 dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3)); |
|
1499 } |
|
1500 |
1380 if (dir == INVALID_TRACKDIR) { |
1501 if (dir == INVALID_TRACKDIR) { |
|
1502 if (!IsRoadVehFront(v)) error("!Disconnecting road vehicle."); |
1381 v->cur_speed = 0; |
1503 v->cur_speed = 0; |
1382 return; |
1504 return false; |
1383 } |
1505 } |
1384 |
1506 |
1385 again: |
1507 again: |
1386 if (IsReversingRoadTrackdir(dir)) { |
1508 if (IsReversingRoadTrackdir(dir)) { |
1387 /* Turning around */ |
1509 /* Turning around */ |
1388 tile = v->tile; |
1510 if (v->u.road.roadtype == ROADTYPE_TRAM) { |
|
1511 RoadBits needed; // The road bits the tram needs to be able to turn around |
|
1512 switch (dir) { |
|
1513 default: NOT_REACHED(); |
|
1514 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; |
|
1515 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; |
|
1516 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; |
|
1517 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; |
|
1518 } |
|
1519 if (!IsTileType(tile, MP_STREET) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || HasRoadWorks(tile) || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) { |
|
1520 /* The tram cannot turn here */ |
|
1521 v->cur_speed = 0; |
|
1522 return false; |
|
1523 } |
|
1524 } else if (IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) { |
|
1525 v->cur_speed = 0; |
|
1526 return false; |
|
1527 } else { |
|
1528 tile = v->tile; |
|
1529 } |
1389 } |
1530 } |
1390 |
1531 |
1391 /* Get position data for first frame on the new tile */ |
1532 /* Get position data for first frame on the new tile */ |
1392 rdp = _road_drive_data[(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; |
1533 rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; |
1393 |
1534 |
1394 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1535 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1395 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1536 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1396 |
1537 |
1397 newdir = RoadVehGetSlidingDirection(v, x, y); |
1538 newdir = RoadVehGetSlidingDirection(v, x, y); |
1398 if (RoadVehFindCloseTo(v, x, y, newdir) != NULL) return; |
1539 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1399 |
1540 |
1400 r = VehicleEnterTile(v, tile, x, y); |
1541 r = VehicleEnterTile(v, tile, x, y); |
1401 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1542 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1402 if (!IsTileType(tile, MP_TUNNELBRIDGE)) { |
1543 if (!IsTileType(tile, MP_TUNNELBRIDGE)) { |
1403 v->cur_speed = 0; |
1544 v->cur_speed = 0; |
1404 return; |
1545 return false; |
1405 } |
1546 } |
1406 /* Try an about turn to re-enter the previous tile */ |
1547 /* Try an about turn to re-enter the previous tile */ |
1407 dir = _road_reverse_table[rd.x & 3]; |
1548 dir = _road_reverse_table[rd.x & 3]; |
1408 goto again; |
1549 goto again; |
1409 } |
1550 } |
1451 Direction newdir; |
1592 Direction newdir; |
1452 const RoadDriveEntry *rdp; |
1593 const RoadDriveEntry *rdp; |
1453 |
1594 |
1454 if (dir == INVALID_TRACKDIR) { |
1595 if (dir == INVALID_TRACKDIR) { |
1455 v->cur_speed = 0; |
1596 v->cur_speed = 0; |
1456 return; |
1597 return false; |
1457 } |
1598 } |
1458 |
1599 |
1459 rdp = _road_drive_data[(_opt.road_side << RVS_DRIVE_SIDE) + dir]; |
1600 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir]; |
1460 |
1601 |
1461 x = TileX(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].x; |
1602 x = TileX(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].x; |
1462 y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y; |
1603 y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y; |
1463 |
1604 |
1464 newdir = RoadVehGetSlidingDirection(v, x, y); |
1605 newdir = RoadVehGetSlidingDirection(v, x, y); |
1465 if (RoadVehFindCloseTo(v, x, y, newdir) != NULL) return; |
1606 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1466 |
1607 |
1467 r = VehicleEnterTile(v, v->tile, x, y); |
1608 r = VehicleEnterTile(v, v->tile, x, y); |
1468 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1609 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1469 v->cur_speed = 0; |
1610 v->cur_speed = 0; |
1470 return; |
1611 return false; |
1471 } |
1612 } |
1472 |
1613 |
1473 v->u.road.state = dir; |
1614 v->u.road.state = dir; |
1474 v->u.road.frame = RVC_TURN_AROUND_START_FRAME; |
1615 v->u.road.frame = RVC_TURN_AROUND_START_FRAME; |
1475 |
1616 |
1479 } |
1620 } |
1480 |
1621 |
1481 v->cur_image = GetRoadVehImage(v, newdir); |
1622 v->cur_image = GetRoadVehImage(v, newdir); |
1482 v->UpdateDeltaXY(v->direction); |
1623 v->UpdateDeltaXY(v->direction); |
1483 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1624 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1484 return; |
1625 return true; |
|
1626 } |
|
1627 |
|
1628 /* This vehicle is not in a wormhole and it hasn't entered a new tile. If |
|
1629 * it's on a depot tile, check if it's time to activate the next vehicle in |
|
1630 * the chain yet. */ |
|
1631 if (v->next != NULL && |
|
1632 IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_DEPOT) { |
|
1633 |
|
1634 if (v->u.road.frame == v->u.road.cached_veh_length + RVC_DEPOT_START_FRAME) { |
|
1635 RoadVehLeaveDepot(v->next, false); |
|
1636 } |
1485 } |
1637 } |
1486 |
1638 |
1487 /* Calculate new position for the vehicle */ |
1639 /* Calculate new position for the vehicle */ |
1488 x = (v->x_pos & ~15) + (rd.x & 15); |
1640 x = (v->x_pos & ~15) + (rd.x & 15); |
1489 y = (v->y_pos & ~15) + (rd.y & 15); |
1641 y = (v->y_pos & ~15) + (rd.y & 15); |
1490 |
1642 |
1491 new_dir = RoadVehGetSlidingDirection(v, x, y); |
1643 new_dir = RoadVehGetSlidingDirection(v, x, y); |
1492 |
1644 |
1493 if (!IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { |
1645 if (IsRoadVehFront(v) && !IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { |
1494 /* Vehicle is not in a road stop. |
1646 /* Vehicle is not in a road stop. |
1495 * Check for another vehicle to overtake */ |
1647 * Check for another vehicle to overtake */ |
1496 Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); |
1648 Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); |
1497 |
1649 |
1498 if (u != NULL) { |
1650 if (u != NULL) { |
|
1651 v->cur_speed = u->cur_speed; |
1499 /* There is a vehicle in front overtake it if possible */ |
1652 /* There is a vehicle in front overtake it if possible */ |
1500 if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); |
1653 if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); |
1501 return; |
1654 return false; |
1502 } |
1655 } |
1503 } |
1656 } |
1504 |
1657 |
1505 old_dir = v->direction; |
1658 old_dir = v->direction; |
1506 if (new_dir != old_dir) { |
1659 if (new_dir != old_dir) { |
1512 v->UpdateDeltaXY(v->direction); |
1665 v->UpdateDeltaXY(v->direction); |
1513 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1666 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1514 /* Note, return here means that the frame counter is not incremented |
1667 /* Note, return here means that the frame counter is not incremented |
1515 * for vehicles changing direction in a road stop. This causes frames to |
1668 * for vehicles changing direction in a road stop. This causes frames to |
1516 * be repeated. (XXX) Is this intended? */ |
1669 * be repeated. (XXX) Is this intended? */ |
1517 return; |
1670 return true; |
1518 } |
1671 } |
1519 } |
1672 } |
1520 |
1673 |
1521 /* If the vehicle is in a normal road stop and the frame equals the stop frame OR |
1674 /* If the vehicle is in a normal road stop and the frame equals the stop frame OR |
1522 * if the vehicle is in a drive-through road stop and this is the destination station |
1675 * if the vehicle is in a drive-through road stop and this is the destination station |
1523 * and it's the correct type of stop (bus or truck) and the frame equals the stop frame... |
1676 * and it's the correct type of stop (bus or truck) and the frame equals the stop frame... |
1524 * (the station test and stop type test ensure that other vehicles, using the road stop as |
1677 * (the station test and stop type test ensure that other vehicles, using the road stop as |
1525 * a through route, do not stop) */ |
1678 * a through route, do not stop) */ |
1526 if ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && |
1679 if (IsRoadVehFront(v) && ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && |
1527 _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) || |
1680 _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) || |
1528 (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && |
1681 (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && |
1529 v->current_order.dest == GetStationIndex(v->tile) && |
1682 v->current_order.dest == GetStationIndex(v->tile) && |
1530 GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) && |
1683 GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) && |
1531 v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME)) { |
1684 v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) { |
1532 |
1685 |
1533 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1686 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1534 Station* st = GetStationByTile(v->tile); |
1687 Station* st = GetStationByTile(v->tile); |
1535 |
1688 |
1536 /* Vehicle is at the stop position (at a bay) in a road stop. |
1689 /* Vehicle is at the stop position (at a bay) in a road stop. |
1619 /* Check tile position conditions - i.e. stop position in depot, |
1772 /* Check tile position conditions - i.e. stop position in depot, |
1620 * entry onto bridge or into tunnel */ |
1773 * entry onto bridge or into tunnel */ |
1621 r = VehicleEnterTile(v, v->tile, x, y); |
1774 r = VehicleEnterTile(v, v->tile, x, y); |
1622 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1775 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1623 v->cur_speed = 0; |
1776 v->cur_speed = 0; |
1624 return; |
1777 return false; |
1625 } |
1778 } |
1626 |
1779 |
1627 /* Move to next frame unless vehicle arrived at a stop position |
1780 /* Move to next frame unless vehicle arrived at a stop position |
1628 * in a depot or entered a tunnel/bridge */ |
1781 * in a depot or entered a tunnel/bridge */ |
1629 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1782 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1630 |
1783 |
1631 v->cur_image = GetRoadVehImage(v, v->direction); |
1784 v->cur_image = GetRoadVehImage(v, v->direction); |
1632 v->UpdateDeltaXY(v->direction); |
1785 v->UpdateDeltaXY(v->direction); |
1633 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1786 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
|
1787 return true; |
|
1788 } |
|
1789 |
|
1790 static void RoadVehController(Vehicle *v) |
|
1791 { |
|
1792 /* decrease counters */ |
|
1793 v->tick_counter++; |
|
1794 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
|
1795 |
|
1796 /* handle crashed */ |
|
1797 if (v->u.road.crashed_ctr != 0) { |
|
1798 RoadVehIsCrashed(v); |
|
1799 return; |
|
1800 } |
|
1801 |
|
1802 RoadVehCheckTrainCrash(v); |
|
1803 |
|
1804 /* road vehicle has broken down? */ |
|
1805 if (v->breakdown_ctr != 0) { |
|
1806 if (v->breakdown_ctr <= 2) { |
|
1807 HandleBrokenRoadVeh(v); |
|
1808 return; |
|
1809 } |
|
1810 v->breakdown_ctr--; |
|
1811 } |
|
1812 |
|
1813 if (v->vehstatus & VS_STOPPED) return; |
|
1814 |
|
1815 ProcessRoadVehOrder(v); |
|
1816 v->HandleLoading(); |
|
1817 |
|
1818 if (v->current_order.type == OT_LOADING) return; |
|
1819 |
|
1820 if (IsRoadVehInDepot(v) && RoadVehLeaveDepot(v, true)) return; |
|
1821 |
|
1822 /* Check if vehicle needs to proceed, return if it doesn't */ |
|
1823 if (!RoadVehAccelerate(v)) return; |
|
1824 |
|
1825 for (Vehicle *prev = NULL; v != NULL; prev = v, v = v->next) { |
|
1826 if (!IndividualRoadVehicleController(v, prev)) break; |
|
1827 } |
1634 } |
1828 } |
1635 |
1829 |
1636 static void AgeRoadVehCargo(Vehicle *v) |
1830 static void AgeRoadVehCargo(Vehicle *v) |
1637 { |
1831 { |
1638 if (_age_cargo_skip_counter != 0) return; |
1832 if (_age_cargo_skip_counter != 0) return; |