112 DrawSprite(6 + _roadveh_images[spritenum], pal, x, y); |
115 DrawSprite(6 + _roadveh_images[spritenum], pal, x, y); |
113 } |
116 } |
114 |
117 |
115 static int32 EstimateRoadVehCost(EngineID engine_type) |
118 static int32 EstimateRoadVehCost(EngineID engine_type) |
116 { |
119 { |
117 return ((_price.roadveh_base >> 3) * RoadVehInfo(engine_type)->base_cost) >> 5; |
120 return ((_price.roadveh_base >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5; |
118 } |
121 } |
119 |
122 |
120 /** Build a road vehicle. |
123 /** Build a road vehicle. |
121 * @param tile tile of depot where road vehicle is built |
124 * @param tile tile of depot where road vehicle is built |
|
125 * @param flags operation to perform |
122 * @param p1 bus/truck type being built (engine) |
126 * @param p1 bus/truck type being built (engine) |
123 * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number |
127 * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number |
124 */ |
128 */ |
125 int32 CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
129 int32 CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
126 { |
130 { |
127 int32 cost; |
131 int32 cost; |
128 Vehicle *v; |
132 Vehicle *v; |
129 UnitID unit_num; |
133 UnitID unit_num; |
130 Engine *e; |
134 Engine *e; |
131 |
135 |
132 if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE); |
136 if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE); |
133 |
137 |
134 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
138 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
135 |
139 |
136 cost = EstimateRoadVehCost(p1); |
140 cost = EstimateRoadVehCost(p1); |
137 if (flags & DC_QUERY_COST) return cost; |
141 if (flags & DC_QUERY_COST) return cost; |
138 |
142 |
139 /* The ai_new queries the vehicle cost before building the route, |
143 /* The ai_new queries the vehicle cost before building the route, |
140 * so we must check against cheaters no sooner than now. --pasky */ |
144 * so we must check against cheaters no sooner than now. --pasky */ |
141 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
145 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
142 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
146 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
|
147 |
|
148 if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE); |
143 |
149 |
144 v = AllocateVehicle(); |
150 v = AllocateVehicle(); |
145 if (v == NULL) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
151 if (v == NULL) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
146 |
152 |
147 /* find the first free roadveh id */ |
153 /* find the first free roadveh id */ |
162 v->tile = tile; |
168 v->tile = tile; |
163 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2; |
169 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2; |
164 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2; |
170 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2; |
165 v->x_pos = x; |
171 v->x_pos = x; |
166 v->y_pos = y; |
172 v->y_pos = y; |
167 v->z_pos = GetSlopeZ(x,y); |
173 v->z_pos = GetSlopeZ(x, y); |
168 v->z_height = 6; |
|
169 |
174 |
170 v->u.road.state = RVSB_IN_DEPOT; |
175 v->u.road.state = RVSB_IN_DEPOT; |
171 v->vehstatus = VS_HIDDEN|VS_STOPPED|VS_DEFPAL; |
176 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
172 |
177 |
173 v->spritenum = rvi->image_index; |
178 v->spritenum = rvi->image_index; |
174 v->cargo_type = rvi->cargo_type; |
179 v->cargo_type = rvi->cargo_type; |
175 v->cargo_subtype = 0; |
180 v->cargo_subtype = 0; |
176 v->cargo_cap = rvi->capacity; |
181 v->cargo_cap = rvi->capacity; |
186 |
191 |
187 v->last_station_visited = INVALID_STATION; |
192 v->last_station_visited = INVALID_STATION; |
188 v->max_speed = rvi->max_speed; |
193 v->max_speed = rvi->max_speed; |
189 v->engine_type = (byte)p1; |
194 v->engine_type = (byte)p1; |
190 |
195 |
|
196 v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; |
|
197 v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype); |
|
198 |
191 e = GetEngine(p1); |
199 e = GetEngine(p1); |
192 v->reliability = e->reliability; |
200 v->reliability = e->reliability; |
193 v->reliability_spd_dec = e->reliability_spd_dec; |
201 v->reliability_spd_dec = e->reliability_spd_dec; |
194 v->max_age = e->lifelength * 366; |
202 v->max_age = e->lifelength * 366; |
195 _new_vehicle_id = v->index; |
203 _new_vehicle_id = v->index; |
199 v->service_interval = _patches.servint_roadveh; |
207 v->service_interval = _patches.servint_roadveh; |
200 |
208 |
201 v->date_of_last_service = _date; |
209 v->date_of_last_service = _date; |
202 v->build_year = _cur_year; |
210 v->build_year = _cur_year; |
203 |
211 |
204 v->type = VEH_ROAD; |
212 v = new (v) RoadVehicle(); |
205 v->cur_image = 0xC15; |
213 v->cur_image = 0xC15; |
206 v->random_bits = VehicleRandomBits(); |
214 v->random_bits = VehicleRandomBits(); |
207 |
215 |
208 v->vehicle_flags = 0; |
216 v->vehicle_flags = 0; |
209 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
217 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
|
218 |
|
219 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
210 |
220 |
211 VehiclePositionChanged(v); |
221 VehiclePositionChanged(v); |
212 |
222 |
213 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
223 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
214 RebuildVehicleLists(); |
224 RebuildVehicleLists(); |
344 } else if (_patches.new_pathfinding_all) { |
357 } else if (_patches.new_pathfinding_all) { |
345 NPFFoundTargetData ftd; |
358 NPFFoundTargetData ftd; |
346 /* See where we are now */ |
359 /* See where we are now */ |
347 Trackdir trackdir = GetVehicleTrackdir(v); |
360 Trackdir trackdir = GetVehicleTrackdir(v); |
348 |
361 |
349 ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE); |
362 ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE); |
350 if (ftd.best_bird_dist == 0) { |
363 if (ftd.best_bird_dist == 0) { |
351 return GetDepotByTile(ftd.node.tile); /* Target found */ |
364 return GetDepotByTile(ftd.node.tile); /* Target found */ |
352 } else { |
365 } else { |
353 return NULL; /* Target not found */ |
366 return NULL; /* Target not found */ |
354 } |
367 } |
359 rfdd.owner = v->owner; |
372 rfdd.owner = v->owner; |
360 rfdd.best_length = (uint)-1; |
373 rfdd.best_length = (uint)-1; |
361 |
374 |
362 /* search in all directions */ |
375 /* search in all directions */ |
363 for (DiagDirection i = DIAGDIR_BEGIN; i != DIAGDIR_END; i++) { |
376 for (DiagDirection i = DIAGDIR_BEGIN; i != DIAGDIR_END; i++) { |
364 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, i, EnumRoadSignalFindDepot, NULL, &rfdd); |
377 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, i, EnumRoadSignalFindDepot, NULL, &rfdd); |
365 } |
378 } |
366 |
379 |
367 if (rfdd.best_length == (uint)-1) return NULL; |
380 if (rfdd.best_length == (uint)-1) return NULL; |
368 |
381 |
369 return GetDepotByTile(rfdd.tile); |
382 return GetDepotByTile(rfdd.tile); |
370 } |
383 } |
371 } |
384 } |
372 |
385 |
373 /** Send a road vehicle to the depot. |
386 /** Send a road vehicle to the depot. |
374 * @param tile unused |
387 * @param tile unused |
|
388 * @param flags operation to perform |
375 * @param p1 vehicle ID to send to the depot |
389 * @param p1 vehicle ID to send to the depot |
376 * @param p2 various bitmasked elements |
390 * @param p2 various bitmasked elements |
377 * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h) |
391 * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h) |
378 * - p2 bit 8-10 - VLW flag (for mass goto depot) |
392 * - p2 bit 8-10 - VLW flag (for mass goto depot) |
379 */ |
393 */ |
427 |
441 |
428 dep = FindClosestRoadDepot(v); |
442 dep = FindClosestRoadDepot(v); |
429 if (dep == NULL) return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); |
443 if (dep == NULL) return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); |
430 |
444 |
431 if (flags & DC_EXEC) { |
445 if (flags & DC_EXEC) { |
|
446 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
|
447 |
432 ClearSlot(v); |
448 ClearSlot(v); |
433 v->current_order.type = OT_GOTO_DEPOT; |
449 v->current_order.type = OT_GOTO_DEPOT; |
434 v->current_order.flags = OF_NON_STOP; |
450 v->current_order.flags = OF_NON_STOP; |
435 if (!(p2 & DEPOT_SERVICE)) SETBIT(v->current_order.flags, OFB_HALT_IN_DEPOT); |
451 if (!(p2 & DEPOT_SERVICE)) SETBIT(v->current_order.flags, OFB_HALT_IN_DEPOT); |
436 v->current_order.refit_cargo = CT_INVALID; |
452 v->current_order.refit_cargo = CT_INVALID; |
456 v = GetVehicle(p1); |
473 v = GetVehicle(p1); |
457 |
474 |
458 if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR; |
475 if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR; |
459 |
476 |
460 if (v->vehstatus & VS_STOPPED || |
477 if (v->vehstatus & VS_STOPPED || |
|
478 v->u.road.roadtype == ROADTYPE_TRAM || |
461 v->u.road.crashed_ctr != 0 || |
479 v->u.road.crashed_ctr != 0 || |
462 v->breakdown_ctr != 0 || |
480 v->breakdown_ctr != 0 || |
463 v->u.road.overtaking != 0 || |
481 v->u.road.overtaking != 0 || |
464 v->u.road.state == RVSB_WORMHOLE || |
482 v->u.road.state == RVSB_WORMHOLE || |
465 IsRoadVehInDepot(v) || |
483 IsRoadVehInDepot(v) || |
466 v->cur_speed < 5) { |
484 v->cur_speed < 5) { |
467 return CMD_ERROR; |
485 return CMD_ERROR; |
468 } |
486 } |
469 |
487 |
|
488 if (IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) return CMD_ERROR; |
|
489 |
470 if (IsTunnelTile(v->tile) && DirToDiagDir(v->direction) == GetTunnelDirection(v->tile)) return CMD_ERROR; |
490 if (IsTunnelTile(v->tile) && DirToDiagDir(v->direction) == GetTunnelDirection(v->tile)) return CMD_ERROR; |
471 if (IsBridgeTile(v->tile) && DirToDiagDir(v->direction) == GetBridgeRampDirection(v->tile)) return CMD_ERROR; |
491 if (IsBridgeTile(v->tile) && DirToDiagDir(v->direction) == GetBridgeRampDirection(v->tile)) return CMD_ERROR; |
472 |
492 |
473 if (flags & DC_EXEC) v->u.road.reverse_ctr = 180; |
493 if (flags & DC_EXEC) v->u.road.reverse_ctr = 180; |
474 |
494 |
475 return 0; |
495 return 0; |
476 } |
496 } |
477 |
497 |
478 |
498 |
479 static void MarkRoadVehDirty(Vehicle *v) |
499 void RoadVehicle::MarkDirty() |
480 { |
500 { |
481 v->cur_image = GetRoadVehImage(v, v->direction); |
501 this->cur_image = GetRoadVehImage(this, this->direction); |
482 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
502 MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1); |
483 } |
503 } |
484 |
504 |
485 static void UpdateRoadVehDeltaXY(Vehicle *v) |
505 void RoadVehicle::UpdateDeltaXY(Direction direction) |
486 { |
506 { |
487 #define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) |
507 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
488 static const uint32 _delta_xy_table[8] = { |
508 static const uint32 _delta_xy_table[8] = { |
489 MKIT(3, 3, -1, -1), |
509 MKIT(3, 3, -1, -1), |
490 MKIT(3, 7, -1, -3), |
510 MKIT(3, 7, -1, -3), |
491 MKIT(3, 3, -1, -1), |
511 MKIT(3, 3, -1, -1), |
492 MKIT(7, 3, -3, -1), |
512 MKIT(7, 3, -3, -1), |
494 MKIT(3, 7, -1, -3), |
514 MKIT(3, 7, -1, -3), |
495 MKIT(3, 3, -1, -1), |
515 MKIT(3, 3, -1, -1), |
496 MKIT(7, 3, -3, -1), |
516 MKIT(7, 3, -3, -1), |
497 }; |
517 }; |
498 #undef MKIT |
518 #undef MKIT |
499 uint32 x = _delta_xy_table[v->direction]; |
519 |
500 v->x_offs = GB(x, 0, 8); |
520 uint32 x = _delta_xy_table[direction]; |
501 v->y_offs = GB(x, 8, 8); |
521 this->x_offs = GB(x, 0, 8); |
502 v->sprite_width = GB(x, 16, 8); |
522 this->y_offs = GB(x, 8, 8); |
503 v->sprite_height = GB(x, 24, 8); |
523 this->sprite_width = GB(x, 16, 8); |
|
524 this->sprite_height = GB(x, 24, 8); |
|
525 this->z_height = 6; |
504 } |
526 } |
505 |
527 |
506 static void ClearCrashedStation(Vehicle *v) |
528 static void ClearCrashedStation(Vehicle *v) |
507 { |
529 { |
508 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
530 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
707 |
729 |
708 rs = GetStation(order->dest)->GetPrimaryRoadStop( |
730 rs = GetStation(order->dest)->GetPrimaryRoadStop( |
709 IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK |
731 IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK |
710 ); |
732 ); |
711 |
733 |
|
734 TileIndex dest = INVALID_TILE; |
712 if (rs != NULL) { |
735 if (rs != NULL) { |
713 TileIndex dest = rs->xy; |
736 uint mindist = MAX_UVALUE(uint); |
714 uint mindist = DistanceManhattan(v->tile, rs->xy); |
737 |
715 |
738 for (; rs != NULL; rs = rs->next) { |
716 for (rs = rs->next; rs != NULL; rs = rs->next) { |
739 /* The vehicle cannot go to this roadstop */ |
|
740 if ((GetRoadTypes(rs->xy) & v->u.road.compatible_roadtypes) == ROADTYPES_NONE) continue; |
|
741 |
717 uint dist = DistanceManhattan(v->tile, rs->xy); |
742 uint dist = DistanceManhattan(v->tile, rs->xy); |
718 |
743 |
719 if (dist < mindist) { |
744 if (dist < mindist) { |
720 mindist = dist; |
745 mindist = dist; |
721 dest = rs->xy; |
746 dest = rs->xy; |
722 } |
747 } |
723 } |
748 } |
724 v->dest_tile = dest; |
749 } |
|
750 |
|
751 if (dest != INVALID_TILE) { |
|
752 v->dest_tile = dest; |
725 } else { |
753 } else { |
726 // There is no stop left at the station, so don't even TRY to go there |
754 /* There is no stop left at the station, so don't even TRY to go there */ |
727 v->cur_order_index++; |
755 v->cur_order_index++; |
728 v->dest_tile = 0; |
756 v->dest_tile = 0; |
729 } |
757 } |
730 break; |
758 break; |
731 } |
759 } |
737 default: |
765 default: |
738 v->dest_tile = 0; |
766 v->dest_tile = 0; |
739 break; |
767 break; |
740 } |
768 } |
741 |
769 |
742 InvalidateVehicleOrder(v); |
|
743 } |
|
744 |
|
745 static void HandleRoadVehLoading(Vehicle *v) |
|
746 { |
|
747 switch (v->current_order.type) { |
|
748 case OT_LOADING: { |
|
749 Order b; |
|
750 |
|
751 if (--v->load_unload_time_rem != 0) return; |
|
752 |
|
753 if (CanFillVehicle(v) && (v->current_order.flags & OF_FULL_LOAD || |
|
754 (_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)))) { |
|
755 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); |
|
756 if (LoadUnloadVehicle(v, false)) { |
|
757 InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
758 MarkRoadVehDirty(v); |
|
759 } |
|
760 return; |
|
761 } |
|
762 |
|
763 b = v->current_order; |
|
764 v->LeaveStation(); |
|
765 if (!(b.flags & OF_NON_STOP)) return; |
|
766 break; |
|
767 } |
|
768 |
|
769 case OT_DUMMY: break; |
|
770 |
|
771 default: return; |
|
772 } |
|
773 |
|
774 v->cur_order_index++; |
|
775 InvalidateVehicleOrder(v); |
770 InvalidateVehicleOrder(v); |
776 } |
771 } |
777 |
772 |
778 static void StartRoadVehSound(const Vehicle* v) |
773 static void StartRoadVehSound(const Vehicle* v) |
779 { |
774 { |
826 rvf.y = y; |
821 rvf.y = y; |
827 rvf.dir = dir; |
822 rvf.dir = dir; |
828 rvf.veh = v; |
823 rvf.veh = v; |
829 u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose); |
824 u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose); |
830 |
825 |
831 // This code protects a roadvehicle from being blocked for ever |
826 /* This code protects a roadvehicle from being blocked for ever |
832 // If more than 1480 / 74 days a road vehicle is blocked, it will |
827 * If more than 1480 / 74 days a road vehicle is blocked, it will |
833 // drive just through it. The ultimate backup-code of TTD. |
828 * drive just through it. The ultimate backup-code of TTD. |
834 // It can be disabled. |
829 * It can be disabled. */ |
835 if (u == NULL) { |
830 if (u == NULL) { |
836 v->u.road.blocked_ctr = 0; |
831 v->u.road.blocked_ctr = 0; |
837 return NULL; |
832 return NULL; |
838 } |
833 } |
839 |
834 |
851 |
846 |
852 st->had_vehicle_of_type |= HVOT_BUS; |
847 st->had_vehicle_of_type |= HVOT_BUS; |
853 SetDParam(0, st->index); |
848 SetDParam(0, st->index); |
854 flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); |
849 flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); |
855 AddNewsItem( |
850 AddNewsItem( |
856 STR_902F_CITIZENS_CELEBRATE_FIRST, |
851 v->u.road.roadtype == ROADTYPE_ROAD ? STR_902F_CITIZENS_CELEBRATE_FIRST : STR_902F_CITIZENS_CELEBRATE_FIRST_TRAM, |
857 flags, |
852 flags, |
858 v->index, |
853 v->index, |
859 0); |
854 0); |
860 } |
855 } |
861 } else { |
856 } else { |
865 |
860 |
866 st->had_vehicle_of_type |= HVOT_TRUCK; |
861 st->had_vehicle_of_type |= HVOT_TRUCK; |
867 SetDParam(0, st->index); |
862 SetDParam(0, st->index); |
868 flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); |
863 flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); |
869 AddNewsItem( |
864 AddNewsItem( |
870 STR_9030_CITIZENS_CELEBRATE_FIRST, |
865 v->u.road.roadtype == ROADTYPE_ROAD ? STR_9030_CITIZENS_CELEBRATE_FIRST : STR_9030_CITIZENS_CELEBRATE_FIRST_TRAM, |
871 flags, |
866 flags, |
872 v->index, |
867 v->index, |
873 0 |
868 0 |
874 ); |
869 ); |
875 } |
870 } |
879 static bool RoadVehAccelerate(Vehicle *v) |
874 static bool RoadVehAccelerate(Vehicle *v) |
880 { |
875 { |
881 uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0); |
876 uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0); |
882 byte t; |
877 byte t; |
883 |
878 |
884 // Clamp |
879 /* Clamp */ |
885 spd = min(spd, v->max_speed); |
880 spd = min(spd, v->max_speed); |
886 if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) { |
881 if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) { |
887 spd = min(spd, GetBridge(GetBridgeType(v->tile))->speed * 2); |
882 spd = min(spd, GetBridge(GetBridgeType(v->tile))->speed * 2); |
888 } |
883 } |
889 |
884 |
890 //updates statusbar only if speed have changed to save CPU time |
885 /* updates statusbar only if speed have changed to save CPU time */ |
891 if (spd != v->cur_speed) { |
886 if (spd != v->cur_speed) { |
892 v->cur_speed = spd; |
887 v->cur_speed = spd; |
893 if (_patches.vehicle_speed) { |
888 if (_patches.vehicle_speed) { |
894 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
889 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
895 } |
890 } |
896 } |
891 } |
897 |
892 |
898 // Decrease somewhat when turning |
893 /* Decrease somewhat when turning */ |
899 if (!(v->direction & 1)) spd = spd * 3 >> 2; |
894 if (!(v->direction & 1)) spd = spd * 3 >> 2; |
900 |
895 |
901 if (spd == 0) return false; |
896 if (spd == 0) return false; |
902 |
897 |
903 if ((byte)++spd == 0) return true; |
898 if ((byte)++spd == 0) return true; |
972 !(u->vehstatus & VS_STOPPED) && |
967 !(u->vehstatus & VS_STOPPED) && |
973 u->cur_speed != 0) { |
968 u->cur_speed != 0) { |
974 return; |
969 return; |
975 } |
970 } |
976 |
971 |
|
972 /* Trams can't overtake other trams */ |
|
973 if (v->u.road.roadtype == ROADTYPE_TRAM) return; |
|
974 |
977 if (v->direction != u->direction || !(v->direction & 1)) return; |
975 if (v->direction != u->direction || !(v->direction & 1)) return; |
978 |
976 |
979 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
977 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
980 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
978 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
981 |
979 |
982 tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F; |
980 tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes) & 0x3F; |
983 if ((tt & 3) == 0) return; |
981 if ((tt & 3) == 0) return; |
984 if ((tt & 0x3C) != 0) return; |
982 if ((tt & 0x3C) != 0) return; |
985 |
983 |
986 if (tt == 3) tt = (v->direction & 2) ? 2 : 1; |
984 if (tt == 3) tt = (v->direction & 2) ? 2 : 1; |
987 od.tilebits = tt; |
985 od.tilebits = tt; |
1048 frd->mindist = dist; |
1046 frd->mindist = dist; |
1049 } |
1047 } |
1050 return false; |
1048 return false; |
1051 } |
1049 } |
1052 |
1050 |
1053 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes) |
1051 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes) |
1054 { |
1052 { |
1055 |
1053 |
1056 void* perf = NpfBeginInterval(); |
1054 void* perf = NpfBeginInterval(); |
1057 NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, owner, railtypes); |
1055 NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, sub_type, owner, railtypes); |
1058 int t = NpfEndInterval(perf); |
1056 int t = NpfEndInterval(perf); |
1059 DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size); |
1057 DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size); |
1060 return ret; |
1058 return ret; |
1061 } |
1059 } |
1062 |
1060 |
1063 /** |
1061 /** |
1064 * Returns direction to for a road vehicle to take or |
1062 * Returns direction to for a road vehicle to take or |
1065 * INVALID_TRACKDIR if the direction is currently blocked |
1063 * INVALID_TRACKDIR if the direction is currently blocked |
1066 * @param v the vehicle to do the pathfinding for |
1064 * @param v the Vehicle to do the pathfinding for |
1067 * @param tile the where to start the pathfinding |
1065 * @param tile the where to start the pathfinding |
1068 * @param enterdir the direction the vehicle enters the tile from |
1066 * @param enterdir the direction the vehicle enters the tile from |
1069 * @return the trackdir to take |
1067 * @return the Trackdir to take |
1070 */ |
1068 */ |
1071 static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection enterdir) |
1069 static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection enterdir) |
1072 { |
1070 { |
1073 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; } |
1071 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; } |
1074 |
1072 |
1075 TileIndex desttile; |
1073 TileIndex desttile; |
1076 FindRoadToChooseData frd; |
1074 FindRoadToChooseData frd; |
1077 Trackdir best_track; |
1075 Trackdir best_track; |
1078 |
1076 |
1079 uint32 r = GetTileTrackStatus(tile, TRANSPORT_ROAD); |
1077 uint32 r = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes); |
1080 TrackdirBits signal = (TrackdirBits)GB(r, 16, 16); |
1078 TrackdirBits signal = (TrackdirBits)GB(r, 16, 16); |
1081 TrackdirBits trackdirs = (TrackdirBits)GB(r, 0, 16); |
1079 TrackdirBits trackdirs = (TrackdirBits)GB(r, 0, 16); |
1082 |
1080 |
1083 if (IsTileType(tile, MP_STREET)) { |
1081 if (IsTileType(tile, MP_STREET)) { |
1084 if (GetRoadTileType(tile) == ROAD_TILE_DEPOT && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) { |
1082 if (GetRoadTileType(tile) == ROAD_TILE_DEPOT && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.compatible_roadtypes) == 0)) { |
1085 /* Road depot owned by another player or with the wrong orientation */ |
1083 /* Road depot owned by another player or with the wrong orientation */ |
1086 trackdirs = TRACKDIR_BIT_NONE; |
1084 trackdirs = TRACKDIR_BIT_NONE; |
1087 } |
1085 } |
1088 } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) { |
1086 } else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) { |
1089 /* Standard road stop (drive-through stops are treated as normal road) */ |
1087 /* Standard road stop (drive-through stops are treated as normal road) */ |
1149 |
1147 |
1150 NPFFillWithOrderData(&fstd, v); |
1148 NPFFillWithOrderData(&fstd, v); |
1151 trackdir = DiagdirToDiagTrackdir(enterdir); |
1149 trackdir = DiagdirToDiagTrackdir(enterdir); |
1152 //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); |
1150 //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); |
1153 |
1151 |
1154 ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE); |
1152 ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE); |
1155 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
1153 if (ftd.best_trackdir == INVALID_TRACKDIR) { |
1156 /* We are already at our target. Just do something */ |
1154 /* We are already at our target. Just do something |
1157 //TODO: maybe display error? |
1155 * @todo: maybe display error? |
1158 //TODO: go straight ahead if possible? |
1156 * @todo: go straight ahead if possible? */ |
1159 return_track(FindFirstBit2x64(trackdirs)); |
1157 return_track(FindFirstBit2x64(trackdirs)); |
1160 } else { |
1158 } else { |
1161 /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains |
1159 /* 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, |
1160 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 |
1161 we did not find our target, but ftd.best_trackdir contains the direction leading |
1199 for (int i = 0; bitmask != 0; bitmask >>= 1, i++) { |
1197 for (int i = 0; bitmask != 0; bitmask >>= 1, i++) { |
1200 if (HASBIT(bitmask, 0)) { |
1198 if (HASBIT(bitmask, 0)) { |
1201 if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track |
1199 if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track |
1202 frd.maxtracklen = (uint)-1; |
1200 frd.maxtracklen = (uint)-1; |
1203 frd.mindist = (uint)-1; |
1201 frd.mindist = (uint)-1; |
1204 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); |
1202 FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd); |
1205 |
1203 |
1206 if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) { |
1204 if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) { |
1207 best_dist = frd.mindist; |
1205 best_dist = frd.mindist; |
1208 best_maxlen = frd.maxtracklen; |
1206 best_maxlen = frd.maxtracklen; |
1209 best_track = (Trackdir)i; |
1207 best_track = (Trackdir)i; |
1221 |
1219 |
1222 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile) |
1220 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile) |
1223 { |
1221 { |
1224 uint dist; |
1222 uint dist; |
1225 if (_patches.yapf.road_use_yapf) { |
1223 if (_patches.yapf.road_use_yapf) { |
1226 // use YAPF |
1224 /* use YAPF */ |
1227 dist = YapfRoadVehDistanceToTile(v, tile); |
1225 dist = YapfRoadVehDistanceToTile(v, tile); |
1228 } else { |
1226 } else { |
1229 // use NPF |
1227 /* use NPF */ |
1230 NPFFindStationOrTileData fstd; |
1228 NPFFindStationOrTileData fstd; |
1231 Trackdir trackdir = GetVehicleTrackdir(v); |
1229 Trackdir trackdir = GetVehicleTrackdir(v); |
1232 assert(trackdir != INVALID_TRACKDIR); |
1230 assert(trackdir != INVALID_TRACKDIR); |
1233 |
1231 |
1234 fstd.dest_coords = tile; |
1232 fstd.dest_coords = tile; |
1235 fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station |
1233 fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station |
1236 |
1234 |
1237 dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist; |
1235 dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE).best_path_dist; |
1238 // change units from NPF_TILE_LENGTH to # of tiles |
1236 /* change units from NPF_TILE_LENGTH to # of tiles */ |
1239 if (dist != UINT_MAX) |
1237 if (dist != UINT_MAX) |
1240 dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH; |
1238 dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH; |
1241 } |
1239 } |
1242 return dist; |
1240 return dist; |
1243 } |
1241 } |
1275 Direction old_dir; |
1273 Direction old_dir; |
1276 RoadDriveEntry rd; |
1274 RoadDriveEntry rd; |
1277 int x,y; |
1275 int x,y; |
1278 uint32 r; |
1276 uint32 r; |
1279 |
1277 |
1280 // decrease counters |
1278 /* decrease counters */ |
1281 v->tick_counter++; |
1279 v->tick_counter++; |
1282 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
1280 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
1283 |
1281 |
1284 // handle crashed |
1282 /* handle crashed */ |
1285 if (v->u.road.crashed_ctr != 0) { |
1283 if (v->u.road.crashed_ctr != 0) { |
1286 RoadVehIsCrashed(v); |
1284 RoadVehIsCrashed(v); |
1287 return; |
1285 return; |
1288 } |
1286 } |
1289 |
1287 |
1290 RoadVehCheckTrainCrash(v); |
1288 RoadVehCheckTrainCrash(v); |
1291 |
1289 |
1292 // road vehicle has broken down? |
1290 /* road vehicle has broken down? */ |
1293 if (v->breakdown_ctr != 0) { |
1291 if (v->breakdown_ctr != 0) { |
1294 if (v->breakdown_ctr <= 2) { |
1292 if (v->breakdown_ctr <= 2) { |
1295 HandleBrokenRoadVeh(v); |
1293 HandleBrokenRoadVeh(v); |
1296 return; |
1294 return; |
1297 } |
1295 } |
1315 |
1313 |
1316 dir = GetRoadDepotDirection(v->tile); |
1314 dir = GetRoadDepotDirection(v->tile); |
1317 v->direction = DiagDirToDir(dir); |
1315 v->direction = DiagDirToDir(dir); |
1318 |
1316 |
1319 tdir = _roadveh_depot_exit_trackdir[dir]; |
1317 tdir = _roadveh_depot_exit_trackdir[dir]; |
1320 rdp = _road_drive_data[(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; |
1318 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; |
1321 |
1319 |
1322 x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); |
1320 x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); |
1323 y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); |
1321 y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); |
1324 |
1322 |
1325 if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return; |
1323 if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return; |
1333 v->vehstatus &= ~VS_HIDDEN; |
1331 v->vehstatus &= ~VS_HIDDEN; |
1334 v->u.road.state = tdir; |
1332 v->u.road.state = tdir; |
1335 v->u.road.frame = RVC_DEPOT_START_FRAME; |
1333 v->u.road.frame = RVC_DEPOT_START_FRAME; |
1336 |
1334 |
1337 v->cur_image = GetRoadVehImage(v, v->direction); |
1335 v->cur_image = GetRoadVehImage(v, v->direction); |
1338 UpdateRoadVehDeltaXY(v); |
1336 v->UpdateDeltaXY(v->direction); |
1339 SetRoadVehPosition(v,x,y); |
1337 SetRoadVehPosition(v,x,y); |
1340 |
1338 |
1341 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1339 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1342 return; |
1340 return; |
1343 } |
1341 } |
1369 } |
1367 } |
1370 |
1368 |
1371 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1369 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1372 /* Vehicle has just entered a bridge or tunnel */ |
1370 /* Vehicle has just entered a bridge or tunnel */ |
1373 v->cur_image = GetRoadVehImage(v, v->direction); |
1371 v->cur_image = GetRoadVehImage(v, v->direction); |
1374 UpdateRoadVehDeltaXY(v); |
1372 v->UpdateDeltaXY(v->direction); |
1375 SetRoadVehPosition(v,gp.x,gp.y); |
1373 SetRoadVehPosition(v,gp.x,gp.y); |
1376 return; |
1374 return; |
1377 } |
1375 } |
1378 |
1376 |
1379 v->x_pos = gp.x; |
1377 v->x_pos = gp.x; |
1384 } |
1382 } |
1385 |
1383 |
1386 /* Get move position data for next frame. |
1384 /* Get move position data for next frame. |
1387 * For a drive-through road stop use 'straight road' move data. |
1385 * For a drive-through road stop use 'straight road' move data. |
1388 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1386 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1389 rd = _road_drive_data[( |
1387 rd = _road_drive_data[v->u.road.roadtype][( |
1390 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1388 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1391 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1389 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1392 |
1390 |
1393 if (rd.x & RDE_NEXT_TILE) { |
1391 if (rd.x & RDE_NEXT_TILE) { |
1394 TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3); |
1392 TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3); |
1403 } |
1401 } |
1404 |
1402 |
1405 again: |
1403 again: |
1406 if (IsReversingRoadTrackdir(dir)) { |
1404 if (IsReversingRoadTrackdir(dir)) { |
1407 /* Turning around */ |
1405 /* Turning around */ |
1408 tile = v->tile; |
1406 if (v->u.road.roadtype == ROADTYPE_TRAM) { |
|
1407 RoadBits needed; // The road bits the tram needs to be able to turn around |
|
1408 switch (dir) { |
|
1409 default: NOT_REACHED(); |
|
1410 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; |
|
1411 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; |
|
1412 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; |
|
1413 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; |
|
1414 } |
|
1415 if (!IsTileType(tile, MP_STREET) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) { |
|
1416 /* The tram cannot turn here */ |
|
1417 v->cur_speed = 0; |
|
1418 return; |
|
1419 } |
|
1420 } else if (IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) { |
|
1421 v->cur_speed = 0; |
|
1422 return; |
|
1423 } else { |
|
1424 tile = v->tile; |
|
1425 } |
1409 } |
1426 } |
1410 |
1427 |
1411 /* Get position data for first frame on the new tile */ |
1428 /* Get position data for first frame on the new tile */ |
1412 rdp = _road_drive_data[(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; |
1429 rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; |
1413 |
1430 |
1414 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1431 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1415 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1432 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1416 |
1433 |
1417 newdir = RoadVehGetSlidingDirection(v, x, y); |
1434 newdir = RoadVehGetSlidingDirection(v, x, y); |
1527 v->direction = new_dir; |
1545 v->direction = new_dir; |
1528 v->cur_speed -= (v->cur_speed >> 2); |
1546 v->cur_speed -= (v->cur_speed >> 2); |
1529 if (old_dir != v->u.road.state) { |
1547 if (old_dir != v->u.road.state) { |
1530 /* The vehicle is in a road stop */ |
1548 /* The vehicle is in a road stop */ |
1531 v->cur_image = GetRoadVehImage(v, new_dir); |
1549 v->cur_image = GetRoadVehImage(v, new_dir); |
1532 UpdateRoadVehDeltaXY(v); |
1550 v->UpdateDeltaXY(v->direction); |
1533 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1551 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1534 /* Note, return here means that the frame counter is not incremented |
1552 /* Note, return here means that the frame counter is not incremented |
1535 * for vehicles changing direction in a road stop. This causes frames to |
1553 * for vehicles changing direction in a road stop. This causes frames to |
1536 * be repeated. (XXX) Is this intended? */ |
1554 * be repeated. (XXX) Is this intended? */ |
1537 return; |
1555 return; |
1557 * Note, if vehicle is loading/unloading it has already been handled, |
1575 * Note, if vehicle is loading/unloading it has already been handled, |
1558 * so if we get here the vehicle has just arrived or is just ready to leave. */ |
1576 * so if we get here the vehicle has just arrived or is just ready to leave. */ |
1559 if (v->current_order.type != OT_LEAVESTATION && |
1577 if (v->current_order.type != OT_LEAVESTATION && |
1560 v->current_order.type != OT_GOTO_DEPOT) { |
1578 v->current_order.type != OT_GOTO_DEPOT) { |
1561 /* Vehicle has arrived at a bay in a road stop */ |
1579 /* Vehicle has arrived at a bay in a road stop */ |
1562 Order old_order; |
|
1563 |
1580 |
1564 if (IsDriveThroughStopTile(v->tile)) { |
1581 if (IsDriveThroughStopTile(v->tile)) { |
1565 TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction)); |
1582 TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction)); |
1566 RoadStop::Type type = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK; |
1583 RoadStop::Type type = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK; |
1567 |
|
1568 assert(HASBIT(v->u.road.state, RVS_IS_STOPPING)); |
|
1569 |
1584 |
1570 /* Check if next inline bay is free */ |
1585 /* Check if next inline bay is free */ |
1571 if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) { |
1586 if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) { |
1572 RoadStop *rs_n = GetRoadStopByTile(next_tile, type); |
1587 RoadStop *rs_n = GetRoadStopByTile(next_tile, type); |
1573 |
1588 |
1589 rs->SetEntranceBusy(false); |
1604 rs->SetEntranceBusy(false); |
1590 |
1605 |
1591 v->last_station_visited = GetStationIndex(v->tile); |
1606 v->last_station_visited = GetStationIndex(v->tile); |
1592 |
1607 |
1593 RoadVehArrivesAt(v, st); |
1608 RoadVehArrivesAt(v, st); |
1594 |
|
1595 old_order = v->current_order; |
|
1596 v->BeginLoading(); |
1609 v->BeginLoading(); |
1597 v->current_order.flags = 0; |
1610 |
1598 |
|
1599 if (old_order.type == OT_GOTO_STATION && |
|
1600 v->current_order.dest == v->last_station_visited) { |
|
1601 v->current_order.flags = |
|
1602 (old_order.flags & (OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER)) | OF_NON_STOP; |
|
1603 } |
|
1604 |
|
1605 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); |
|
1606 if (LoadUnloadVehicle(v, true)) { |
|
1607 InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
1608 MarkRoadVehDirty(v); |
|
1609 } |
|
1610 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
|
1611 return; |
1611 return; |
1612 } |
1612 } |
1613 |
1613 |
1614 /* Vehicle is ready to leave a bay in a road stop */ |
1614 /* Vehicle is ready to leave a bay in a road stop */ |
1615 if (v->current_order.type != OT_GOTO_DEPOT) { |
1615 if (v->current_order.type != OT_GOTO_DEPOT) { |
1626 |
1626 |
1627 if (rs == v->u.road.slot) { |
1627 if (rs == v->u.road.slot) { |
1628 /* We are leaving the correct station */ |
1628 /* We are leaving the correct station */ |
1629 ClearSlot(v); |
1629 ClearSlot(v); |
1630 } else if (v->u.road.slot != NULL) { |
1630 } else if (v->u.road.slot != NULL) { |
1631 /* We are leaving the wrong station */ |
1631 /* We are leaving the wrong station |
1632 //XXX The question is .. what to do? Actually we shouldn't be here |
1632 * XXX The question is .. what to do? Actually we shouldn't be here |
1633 //but I guess we need to clear the slot |
1633 * 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); |
1634 DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index); |
1635 if (v->tile != v->dest_tile) { |
1635 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); |
1636 DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile); |
1637 } |
1637 } |
1638 if (v->dest_tile != v->u.road.slot->xy) { |
1638 if (v->dest_tile != v->u.road.slot->xy) { |
1665 /* Move to next frame unless vehicle arrived at a stop position |
1665 /* Move to next frame unless vehicle arrived at a stop position |
1666 * in a depot or entered a tunnel/bridge */ |
1666 * in a depot or entered a tunnel/bridge */ |
1667 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1667 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1668 |
1668 |
1669 v->cur_image = GetRoadVehImage(v, v->direction); |
1669 v->cur_image = GetRoadVehImage(v, v->direction); |
1670 UpdateRoadVehDeltaXY(v); |
1670 v->UpdateDeltaXY(v->direction); |
1671 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1671 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1672 } |
1672 } |
1673 |
1673 |
1674 static void AgeRoadVehCargo(Vehicle *v) |
1674 static void AgeRoadVehCargo(Vehicle *v) |
1675 { |
1675 { |
1690 if (_patches.servint_roadveh == 0) return; |
1690 if (_patches.servint_roadveh == 0) return; |
1691 if (!VehicleNeedsService(v)) return; |
1691 if (!VehicleNeedsService(v)) return; |
1692 if (v->vehstatus & VS_STOPPED) return; |
1692 if (v->vehstatus & VS_STOPPED) return; |
1693 if (_patches.gotodepot && VehicleHasDepotOrders(v)) return; |
1693 if (_patches.gotodepot && VehicleHasDepotOrders(v)) return; |
1694 |
1694 |
1695 // Don't interfere with a depot visit scheduled by the user, or a |
1695 /* Don't interfere with a depot visit scheduled by the user, or a |
1696 // depot visit by the order list. |
1696 * depot visit by the order list. */ |
1697 if (v->current_order.type == OT_GOTO_DEPOT && |
1697 if (v->current_order.type == OT_GOTO_DEPOT && |
1698 (v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0) |
1698 (v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0) |
1699 return; |
1699 return; |
1700 |
1700 |
1701 // If we already got a slot at a stop, use that FIRST, and go to a depot later |
1701 /* 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; |
1702 if (v->u.road.slot != NULL) return; |
1703 |
1703 |
1704 if (IsRoadVehInDepot(v)) { |
1704 if (IsRoadVehInDepot(v)) { |
1705 VehicleServiceInDepot(v); |
1705 VehicleServiceInDepot(v); |
1706 return; |
1706 return; |
1707 } |
1707 } |
1708 |
1708 |
1709 // XXX If we already have a depot order, WHY do we search over and over? |
1709 /* XXX If we already have a depot order, WHY do we search over and over? */ |
1710 depot = FindClosestRoadDepot(v); |
1710 depot = FindClosestRoadDepot(v); |
1711 |
1711 |
1712 if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) { |
1712 if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) { |
1713 if (v->current_order.type == OT_GOTO_DEPOT) { |
1713 if (v->current_order.type == OT_GOTO_DEPOT) { |
1714 v->current_order.type = OT_DUMMY; |
1714 v->current_order.type = OT_DUMMY; |
1836 } |
1839 } |
1837 } |
1840 } |
1838 |
1841 |
1839 /** Refit a road vehicle to the specified cargo type |
1842 /** Refit a road vehicle to the specified cargo type |
1840 * @param tile unused |
1843 * @param tile unused |
|
1844 * @param flags operation to perform |
1841 * @param p1 Vehicle ID of the vehicle to refit |
1845 * @param p1 Vehicle ID of the vehicle to refit |
1842 * @param p2 Bitstuffed elements |
1846 * @param p2 Bitstuffed elements |
1843 * - p2 = (bit 0-7) - the new cargo type to refit to |
1847 * - p2 = (bit 0-7) - the new cargo type to refit to |
1844 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
1848 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
|
1849 * - p2 = (bit 16) - refit only this vehicle (ignored) |
|
1850 * @return cost of refit or error |
1845 */ |
1851 */ |
1846 int32 CmdRefitRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1852 int32 CmdRefitRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1847 { |
1853 { |
1848 Vehicle *v; |
1854 Vehicle *v; |
1849 int32 cost; |
1855 int32 cost; |
1884 CargoID old_cid = rvi->cargo_type; |
1890 CargoID old_cid = rvi->cargo_type; |
1885 /* normally, the capacity depends on the cargo type, a vehicle can |
1891 /* normally, the capacity depends on the cargo type, a vehicle can |
1886 * carry twice as much mail/goods as normal cargo, and four times as |
1892 * carry twice as much mail/goods as normal cargo, and four times as |
1887 * many passengers |
1893 * many passengers |
1888 */ |
1894 */ |
1889 capacity = rvi->capacity; |
1895 capacity = GetVehicleProperty(v, 0x0F, rvi->capacity); |
1890 switch (old_cid) { |
1896 switch (old_cid) { |
1891 case CT_PASSENGERS: break; |
1897 case CT_PASSENGERS: break; |
1892 case CT_MAIL: |
1898 case CT_MAIL: |
1893 case CT_GOODS: capacity *= 2; break; |
1899 case CT_GOODS: capacity *= 2; break; |
1894 default: capacity *= 4; break; |
1900 default: capacity *= 4; break; |