OpenTTD Source  20241108-master-g80f628063a
roadveh_cmd.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "roadveh.h"
12 #include "command_func.h"
13 #include "error_func.h"
14 #include "news_func.h"
15 #include "station_base.h"
16 #include "company_func.h"
17 #include "articulated_vehicles.h"
18 #include "newgrf_sound.h"
19 #include "pathfinder/yapf/yapf.h"
20 #include "strings_func.h"
21 #include "tunnelbridge_map.h"
24 #include "vehicle_func.h"
25 #include "sound_func.h"
26 #include "ai/ai.hpp"
27 #include "game/game.hpp"
28 #include "depot_map.h"
29 #include "effectvehicle_func.h"
30 #include "roadstop_base.h"
31 #include "spritecache.h"
32 #include "core/random_func.hpp"
33 #include "company_base.h"
34 #include "core/backup_type.hpp"
35 #include "newgrf.h"
36 #include "zoom_func.h"
37 #include "framerate_type.h"
38 #include "roadveh_cmd.h"
39 #include "road_cmd.h"
40 
41 #include "table/strings.h"
42 
43 #include "safeguards.h"
44 
45 static const uint16_t _roadveh_images[] = {
46  0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14,
47  0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74,
48  0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C,
49  0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC,
50  0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC,
51  0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4,
52  0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C,
53  0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4
54 };
55 
56 static const uint16_t _roadveh_full_adder[] = {
57  0, 88, 0, 0, 0, 0, 48, 48,
58  48, 48, 0, 0, 64, 64, 0, 16,
59  16, 0, 88, 0, 0, 0, 0, 48,
60  48, 48, 48, 0, 0, 64, 64, 0,
61  16, 16, 0, 88, 0, 0, 0, 0,
62  48, 48, 48, 48, 0, 0, 64, 64,
63  0, 16, 16, 0, 8, 8, 8, 8,
64  0, 0, 0, 8, 8, 8, 8
65 };
66 static_assert(lengthof(_roadveh_images) == lengthof(_roadveh_full_adder));
67 
68 template <>
69 bool IsValidImageIndex<VEH_ROAD>(uint8_t image_index)
70 {
71  return image_index < lengthof(_roadveh_images);
72 }
73 
74 static const Trackdir _road_reverse_table[DIAGDIR_END] = {
76 };
77 
82 bool RoadVehicle::IsBus() const
83 {
84  assert(this->IsFrontEngine());
86 }
87 
94 {
95  int reference_width = ROADVEHINFO_DEFAULT_VEHICLE_WIDTH;
96 
97  if (offset != nullptr) {
98  offset->x = ScaleSpriteTrad(reference_width) / 2;
99  offset->y = 0;
100  }
101  return ScaleSpriteTrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
102 }
103 
104 static void GetRoadVehIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
105 {
106  const Engine *e = Engine::Get(engine);
107  uint8_t spritenum = e->u.road.image_index;
108 
109  if (is_custom_sprite(spritenum)) {
110  GetCustomVehicleIcon(engine, DIR_W, image_type, result);
111  if (result->IsValid()) return;
112 
113  spritenum = e->original_image_index;
114  }
115 
116  assert(IsValidImageIndex<VEH_ROAD>(spritenum));
117  result->Set(DIR_W + _roadveh_images[spritenum]);
118 }
119 
120 void RoadVehicle::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
121 {
122  uint8_t spritenum = this->spritenum;
123 
124  if (is_custom_sprite(spritenum)) {
125  GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
126  if (result->IsValid()) return;
127 
129  }
130 
131  assert(IsValidImageIndex<VEH_ROAD>(spritenum));
132  SpriteID sprite = direction + _roadveh_images[spritenum];
133 
134  if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
135 
136  result->Set(sprite);
137 }
138 
148 void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
149 {
150  VehicleSpriteSeq seq;
151  GetRoadVehIcon(engine, image_type, &seq);
152 
153  Rect rect;
154  seq.GetBounds(&rect);
155  preferred_x = Clamp(preferred_x,
156  left - UnScaleGUI(rect.left),
157  right - UnScaleGUI(rect.right));
158 
159  seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
160 }
161 
171 void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
172 {
173  VehicleSpriteSeq seq;
174  GetRoadVehIcon(engine, image_type, &seq);
175 
176  Rect rect;
177  seq.GetBounds(&rect);
178 
179  width = UnScaleGUI(rect.Width());
180  height = UnScaleGUI(rect.Height());
181  xoffs = UnScaleGUI(rect.left);
182  yoffs = UnScaleGUI(rect.top);
183 }
184 
190 static uint GetRoadVehLength(const RoadVehicle *v)
191 {
192  const Engine *e = v->GetEngine();
193  uint length = VEHICLE_LENGTH;
194 
195  uint16_t veh_len = CALLBACK_FAILED;
196  if (e->GetGRF() != nullptr && e->GetGRF()->grf_version >= 8) {
197  /* Use callback 36 */
198  veh_len = GetVehicleProperty(v, PROP_ROADVEH_SHORTEN_FACTOR, CALLBACK_FAILED);
199  if (veh_len != CALLBACK_FAILED && veh_len >= VEHICLE_LENGTH) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_LENGTH, veh_len);
200  } else {
201  /* Use callback 11 */
202  veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
203  }
204  if (veh_len == CALLBACK_FAILED) veh_len = e->u.road.shorten_factor;
205  if (veh_len != 0) {
206  length -= Clamp(veh_len, 0, VEHICLE_LENGTH - 1);
207  }
208 
209  return length;
210 }
211 
218 void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
219 {
220  assert(v->type == VEH_ROAD);
221  assert(v->IsFrontEngine());
222 
224 
226 
227  for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
228  /* Check the v->first cache. */
229  assert(u->First() == v);
230 
231  /* Update the 'first engine' */
232  u->gcache.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
233 
234  /* Update the length of the vehicle. */
235  uint veh_len = GetRoadVehLength(u);
236  /* Verify length hasn't changed. */
237  if (same_length && veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
238 
239  u->gcache.cached_veh_length = veh_len;
240  v->gcache.cached_total_length += u->gcache.cached_veh_length;
241 
242  /* Update visual effect */
243  u->UpdateVisualEffect();
244 
245  /* Update cargo aging period. */
246  u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_ROADVEH_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
247  }
248 
249  uint max_speed = GetVehicleProperty(v, PROP_ROADVEH_SPEED, 0);
250  v->vcache.cached_max_speed = (max_speed != 0) ? max_speed * 4 : RoadVehInfo(v->engine_type)->max_speed;
251 }
252 
262 {
263  /* Check that the vehicle can drive on the road in question */
264  RoadType rt = e->u.road.roadtype;
265  const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
266  if (!HasTileAnyRoadType(tile, rti->powered_roadtypes)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
267 
268  if (flags & DC_EXEC) {
269  const RoadVehicleInfo *rvi = &e->u.road;
270 
271  RoadVehicle *v = new RoadVehicle();
272  *ret = v;
274  v->owner = _current_company;
275 
276  v->tile = tile;
277  int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
278  int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
279  v->x_pos = x;
280  v->y_pos = y;
281  v->z_pos = GetSlopePixelZ(x, y, true);
282 
283  v->state = RVSB_IN_DEPOT;
285 
286  v->spritenum = rvi->image_index;
288  assert(IsValidCargoID(v->cargo_type));
289  v->cargo_cap = rvi->capacity;
290  v->refit_cap = 0;
291 
292  v->last_station_visited = INVALID_STATION;
293  v->last_loading_station = INVALID_STATION;
294  v->engine_type = e->index;
295  v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
296 
297  v->reliability = e->reliability;
299  v->max_age = e->GetLifeLengthInDays();
300 
301  v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh);
302 
306 
307  v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
308  v->random_bits = Random();
309  v->SetFrontEngine();
310 
311  v->roadtype = rt;
314 
316  v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
317 
320 
321  /* Call various callbacks after the whole consist has been constructed */
322  for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
323  u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
324  u->refit_cap = 0;
326  u->InvalidateNewGRFCache();
327  }
329  /* Initialize cached values for realistic acceleration. */
331 
332  v->UpdatePosition();
333 
335  }
336 
337  return CommandCost();
338 }
339 
340 static FindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance)
341 {
342  if (IsRoadDepotTile(v->tile)) return FindDepotData(v->tile, 0);
343 
344  return YapfRoadVehicleFindNearestDepot(v, max_distance);
345 }
346 
348 {
349  FindDepotData rfdd = FindClosestRoadDepot(this, 0);
350  if (rfdd.best_length == UINT_MAX) return ClosestDepot();
351 
352  return ClosestDepot(rfdd.tile, GetDepotIndex(rfdd.tile));
353 }
354 
362 {
364  if (v == nullptr) return CMD_ERROR;
365 
366  if (!v->IsPrimaryVehicle()) return CMD_ERROR;
367 
368  CommandCost ret = CheckOwnership(v->owner);
369  if (ret.Failed()) return ret;
370 
371  if ((v->vehstatus & VS_STOPPED) ||
372  (v->vehstatus & VS_CRASHED) ||
373  v->breakdown_ctr != 0 ||
374  v->overtaking != 0 ||
375  v->state == RVSB_WORMHOLE ||
376  v->IsInDepot() ||
377  v->current_order.IsType(OT_LOADING)) {
378  return CMD_ERROR;
379  }
380 
382 
384 
385  if (flags & DC_EXEC) {
386  v->reverse_ctr = 180;
387 
388  /* Unbunching data is no longer valid. */
390  }
391 
392  return CommandCost();
393 }
394 
395 
397 {
398  for (RoadVehicle *v = this; v != nullptr; v = v->Next()) {
399  v->colourmap = PAL_NONE;
400  v->UpdateViewport(true, false);
401  }
402  this->CargoChanged();
403 }
404 
406 {
407  static const int8_t _delta_xy_table[8][10] = {
408  /* y_extent, x_extent, y_offs, x_offs, y_bb_offs, x_bb_offs, y_extent_shorten, x_extent_shorten, y_bb_offs_shorten, x_bb_offs_shorten */
409  {3, 3, -1, -1, 0, 0, -1, -1, -1, -1}, // N
410  {3, 7, -1, -3, 0, -1, 0, -1, 0, 0}, // NE
411  {3, 3, -1, -1, 0, 0, 1, -1, 1, -1}, // E
412  {7, 3, -3, -1, -1, 0, 0, 0, 1, 0}, // SE
413  {3, 3, -1, -1, 0, 0, 1, 1, 1, 1}, // S
414  {3, 7, -1, -3, 0, -1, 0, 0, 0, 1}, // SW
415  {3, 3, -1, -1, 0, 0, -1, 1, -1, 1}, // W
416  {7, 3, -3, -1, -1, 0, -1, 0, 0, 0}, // NW
417  };
418 
419  int shorten = VEHICLE_LENGTH - this->gcache.cached_veh_length;
420  if (!IsDiagonalDirection(this->direction)) shorten >>= 1;
421 
422  const int8_t *bb = _delta_xy_table[this->direction];
423  this->x_bb_offs = bb[5] + bb[9] * shorten;
424  this->y_bb_offs = bb[4] + bb[8] * shorten;;
425  this->x_offs = bb[3];
426  this->y_offs = bb[2];
427  this->x_extent = bb[1] + bb[7] * shorten;
428  this->y_extent = bb[0] + bb[6] * shorten;
429  this->z_extent = 6;
430 }
431 
437 {
438  int max_speed = this->gcache.cached_max_track_speed;
439 
440  /* Limit speed to 50% while reversing, 75% in curves. */
441  for (const RoadVehicle *u = this; u != nullptr; u = u->Next()) {
442  if (_settings_game.vehicle.roadveh_acceleration_model == AM_REALISTIC) {
444  max_speed = this->gcache.cached_max_track_speed / 2;
445  break;
446  } else if ((u->direction & 1) == 0) {
447  max_speed = this->gcache.cached_max_track_speed * 3 / 4;
448  }
449  }
450 
451  /* Vehicle is on the middle part of a bridge. */
452  if (u->state == RVSB_WORMHOLE && !(u->vehstatus & VS_HIDDEN)) {
453  max_speed = std::min(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed * 2);
454  }
455  }
456 
457  return std::min(max_speed, this->current_order.GetMaxSpeed() * 2);
458 }
459 
465 {
466  RoadVehicle *first = v->First();
467  Vehicle *u = v;
468  for (; v->Next() != nullptr; v = v->Next()) u = v;
469  u->SetNext(nullptr);
470  v->last_station_visited = first->last_station_visited; // for PreDestructor
471 
472  /* Only leave the road stop when we're really gone. */
473  if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
474 
475  delete v;
476 }
477 
478 static void RoadVehSetRandomDirection(RoadVehicle *v)
479 {
480  static const DirDiff delta[] = {
482  };
483 
484  do {
485  uint32_t r = Random();
486 
487  v->direction = ChangeDir(v->direction, delta[r & 3]);
488  v->UpdateViewport(true, true);
489  } while ((v = v->Next()) != nullptr);
490 }
491 
498 {
499  v->crashed_ctr++;
500  if (v->crashed_ctr == 2) {
502  } else if (v->crashed_ctr <= 45) {
503  if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
504  } else if (v->crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
505  bool ret = v->Next() != nullptr;
507  return ret;
508  }
509 
510  return true;
511 }
512 
520 {
521  const Vehicle *u = (Vehicle*)data;
522 
523  return (v->type == VEH_TRAIN &&
524  abs(v->z_pos - u->z_pos) <= 6 &&
525  abs(v->x_pos - u->x_pos) <= 4 &&
526  abs(v->y_pos - u->y_pos) <= 4) ? v : nullptr;
527 }
528 
529 uint RoadVehicle::Crash(bool flooded)
530 {
531  uint victims = this->GroundVehicleBase::Crash(flooded);
532  if (this->IsFrontEngine()) {
533  victims += 1; // driver
534 
535  /* If we're in a drive through road stop we ought to leave it */
536  if (IsInsideMM(this->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
537  RoadStop::GetByTile(this->tile, GetRoadStopType(this->tile))->Leave(this);
538  }
539  }
540  this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
541  return victims;
542 }
543 
544 static void RoadVehCrash(RoadVehicle *v)
545 {
546  uint victims = v->Crash();
547 
548  AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
549  Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
550 
551  SetDParam(0, victims);
552  StringID newsitem = (victims == 1) ? STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH;
553  NewsType newstype = NT_ACCIDENT;
554 
555  if (v->owner != _local_company) {
556  newstype = NT_ACCIDENT_OTHER;
557  }
558 
559  AddTileNewsItem(newsitem, newstype, v->tile);
560 
561  ModifyStationRatingAround(v->tile, v->owner, -160, 22);
562  if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
563 }
564 
565 static bool RoadVehCheckTrainCrash(RoadVehicle *v)
566 {
567  for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
568  if (u->state == RVSB_WORMHOLE) continue;
569 
570  TileIndex tile = u->tile;
571 
572  if (!IsLevelCrossingTile(tile)) continue;
573 
575  RoadVehCrash(v);
576  return true;
577  }
578  }
579 
580  return false;
581 }
582 
583 TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
584 {
585  if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
586 
587  const Station *st = Station::Get(station);
588  if (!CanVehicleUseStation(this, st)) {
589  /* There is no stop left at the station, so don't even TRY to go there */
590  this->IncrementRealOrderIndex();
591  return 0;
592  }
593 
594  return st->xy;
595 }
596 
597 static void StartRoadVehSound(const RoadVehicle *v)
598 {
599  if (!PlayVehicleSound(v, VSE_START)) {
600  SoundID s = RoadVehInfo(v->engine_type)->sfx;
601  if (s == SND_19_DEPARTURE_OLD_RV_1 && (v->tick_counter & 3) == 0) {
603  }
604  SndPlayVehicleFx(s, v);
605  }
606 }
607 
609  int x;
610  int y;
611  const Vehicle *veh;
612  Vehicle *best;
613  uint best_diff;
614  Direction dir;
615 };
616 
617 static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
618 {
619  static const int8_t dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
620  static const int8_t dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
621 
622  RoadVehFindData *rvf = (RoadVehFindData*)data;
623 
624  short x_diff = v->x_pos - rvf->x;
625  short y_diff = v->y_pos - rvf->y;
626 
627  if (v->type == VEH_ROAD &&
628  !v->IsInDepot() &&
629  abs(v->z_pos - rvf->veh->z_pos) < 6 &&
630  v->direction == rvf->dir &&
631  rvf->veh->First() != v->First() &&
632  (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
633  (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
634  (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
635  (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0))) {
636  uint diff = abs(x_diff) + abs(y_diff);
637 
638  if (diff < rvf->best_diff || (diff == rvf->best_diff && v->index < rvf->best->index)) {
639  rvf->best = v;
640  rvf->best_diff = diff;
641  }
642  }
643 
644  return nullptr;
645 }
646 
647 static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction dir, bool update_blocked_ctr = true)
648 {
649  RoadVehFindData rvf;
650  RoadVehicle *front = v->First();
651 
652  if (front->reverse_ctr != 0) return nullptr;
653 
654  rvf.x = x;
655  rvf.y = y;
656  rvf.dir = dir;
657  rvf.veh = v;
658  rvf.best_diff = UINT_MAX;
659 
660  if (front->state == RVSB_WORMHOLE) {
661  FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
662  FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
663  } else {
664  FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
665  }
666 
667  /* This code protects a roadvehicle from being blocked for ever
668  * If more than 1480 / 74 days a road vehicle is blocked, it will
669  * drive just through it. The ultimate backup-code of TTD.
670  * It can be disabled. */
671  if (rvf.best_diff == UINT_MAX) {
672  front->blocked_ctr = 0;
673  return nullptr;
674  }
675 
676  if (update_blocked_ctr && ++front->blocked_ctr > 1480) return nullptr;
677 
678  return RoadVehicle::From(rvf.best);
679 }
680 
686 static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
687 {
688  if (v->IsBus()) {
689  /* Check if station was ever visited before */
690  if (!(st->had_vehicle_of_type & HVOT_BUS)) {
691  st->had_vehicle_of_type |= HVOT_BUS;
692  SetDParam(0, st->index);
694  RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
696  v->index,
697  st->index
698  );
699  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
700  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
701  }
702  } else {
703  /* Check if station was ever visited before */
704  if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
705  st->had_vehicle_of_type |= HVOT_TRUCK;
706  SetDParam(0, st->index);
708  RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
710  v->index,
711  st->index
712  );
713  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
714  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
715  }
716  }
717 }
718 
727 {
729  default: NOT_REACHED();
730  case AM_ORIGINAL:
731  return this->DoUpdateSpeed(this->overtaking != 0 ? 512 : 256, 0, this->GetCurrentMaxSpeed());
732 
733  case AM_REALISTIC:
734  return this->DoUpdateSpeed(this->GetAcceleration() + (this->overtaking != 0 ? 256 : 0), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 4, this->GetCurrentMaxSpeed());
735  }
736 }
737 
738 static Direction RoadVehGetNewDirection(const RoadVehicle *v, int x, int y)
739 {
740  static const Direction _roadveh_new_dir[] = {
743  DIR_E , DIR_SE, DIR_S
744  };
745 
746  x = x - v->x_pos + 1;
747  y = y - v->y_pos + 1;
748 
749  if ((uint)x > 2 || (uint)y > 2) return v->direction;
750  return _roadveh_new_dir[y * 4 + x];
751 }
752 
753 static Direction RoadVehGetSlidingDirection(const RoadVehicle *v, int x, int y)
754 {
755  Direction new_dir = RoadVehGetNewDirection(v, x, y);
756  Direction old_dir = v->direction;
757  DirDiff delta;
758 
759  if (new_dir == old_dir) return old_dir;
760  delta = (DirDifference(new_dir, old_dir) > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
761  return ChangeDir(old_dir, delta);
762 }
763 
764 struct OvertakeData {
765  const RoadVehicle *u;
766  const RoadVehicle *v;
767  TileIndex tile;
768  Trackdir trackdir;
769 };
770 
771 static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
772 {
773  const OvertakeData *od = (OvertakeData*)data;
774 
775  return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : nullptr;
776 }
777 
785 {
786  if (!HasTileAnyRoadType(od->tile, od->v->compatible_roadtypes)) return true;
787  TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, GetRoadTramType(od->v->roadtype));
788  TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
789  TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
790  TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
791 
792  /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
793  if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
794 
795  /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
796  return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
797 }
798 
799 static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
800 {
801  OvertakeData od;
802 
803  od.v = v;
804  od.u = u;
805 
806  /* Trams can't overtake other trams */
807  if (RoadTypeIsTram(v->roadtype)) return;
808 
809  /* Don't overtake in stations */
810  if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
811 
812  /* For now, articulated road vehicles can't overtake anything. */
813  if (v->HasArticulatedPart()) return;
814 
815  /* Vehicles are not driving in same direction || direction is not a diagonal direction */
816  if (v->direction != u->direction || !(v->direction & 1)) return;
817 
818  /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
820 
821  /* Can't overtake a vehicle that is moving faster than us. If the vehicle in front is
822  * accelerating, take the maximum speed for the comparison, else the current speed.
823  * Original acceleration always accelerates, so always use the maximum speed. */
824  int u_speed = (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL || u->GetAcceleration() > 0) ? u->GetCurrentMaxSpeed() : u->cur_speed;
825  if (u_speed >= v->GetCurrentMaxSpeed() &&
826  !(u->vehstatus & VS_STOPPED) &&
827  u->cur_speed != 0) {
828  return;
829  }
830 
831  od.trackdir = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
832 
833  /* Are the current and the next tile suitable for overtaking?
834  * - Does the track continue along od.trackdir
835  * - No junctions
836  * - No barred levelcrossing
837  * - No other vehicles in the way
838  */
839  od.tile = v->tile;
840  if (CheckRoadBlockedForOvertaking(&od)) return;
841 
842  od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
843  if (CheckRoadBlockedForOvertaking(&od)) return;
844 
845  /* When the vehicle in front of us is stopped we may only take
846  * half the time to pass it than when the vehicle is moving. */
847  v->overtaking_ctr = (od.u->cur_speed == 0 || (od.u->vehstatus & VS_STOPPED)) ? RV_OVERTAKE_TIMEOUT / 2 : 0;
849 }
850 
851 static void RoadZPosAffectSpeed(RoadVehicle *v, int old_z)
852 {
853  if (old_z == v->z_pos || _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) return;
854 
855  if (old_z < v->z_pos) {
856  v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
857  } else {
858  uint16_t spd = v->cur_speed + 2;
859  if (spd <= v->gcache.cached_max_track_speed) v->cur_speed = spd;
860  }
861 }
862 
863 static int PickRandomBit(uint bits)
864 {
865  uint i;
866  uint num = RandomRange(CountBits(bits));
867 
868  for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
869  return i;
870 }
871 
881 {
882 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
883 
884  TileIndex desttile;
885  Trackdir best_track;
886  bool path_found = true;
887 
888  TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype));
889  TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
890  TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
891 
892  if (IsTileType(tile, MP_ROAD)) {
893  if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) {
894  /* Road depot owned by another company or with the wrong orientation */
895  trackdirs = TRACKDIR_BIT_NONE;
896  }
897  } else if (IsTileType(tile, MP_STATION) && IsBayRoadStopTile(tile)) {
898  /* Standard road stop (drive-through stops are treated as normal road) */
899 
900  if (!IsTileOwner(tile, v->owner) || GetBayRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
901  /* different station owner or wrong orientation or the vehicle has articulated parts */
902  trackdirs = TRACKDIR_BIT_NONE;
903  } else {
904  /* Our station */
905  RoadStopType rstype = v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK;
906 
907  if (GetRoadStopType(tile) != rstype) {
908  /* Wrong station type */
909  trackdirs = TRACKDIR_BIT_NONE;
910  } else {
911  /* Proper station type, check if there is free loading bay */
913  !RoadStop::GetByTile(tile, rstype)->HasFreeBay()) {
914  /* Station is full and RV queuing is off */
915  trackdirs = TRACKDIR_BIT_NONE;
916  }
917  }
918  }
919  }
920  /* The above lookups should be moved to GetTileTrackStatus in the
921  * future, but that requires more changes to the pathfinder and other
922  * stuff, probably even more arguments to GTTS.
923  */
924 
925  /* Remove tracks unreachable from the enter dir */
926  trackdirs &= DiagdirReachesTrackdirs(enterdir);
927  if (trackdirs == TRACKDIR_BIT_NONE) {
928  /* If vehicle expected a path, it no longer exists, so invalidate it. */
929  if (!v->path.empty()) v->path.clear();
930  /* No reachable tracks, so we'll reverse */
931  return_track(_road_reverse_table[enterdir]);
932  }
933 
934  if (v->reverse_ctr != 0) {
935  bool reverse = true;
936  if (RoadTypeIsTram(v->roadtype)) {
937  /* Trams may only reverse on a tile if it contains at least the straight
938  * trackbits or when it is a valid turning tile (i.e. one roadbit) */
939  RoadBits rb = GetAnyRoadBits(tile, RTT_TRAM);
940  RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
941  reverse = ((rb & straight) == straight) ||
942  (rb == DiagDirToRoadBits(enterdir));
943  }
944  if (reverse) {
945  v->reverse_ctr = 0;
946  if (v->tile != tile) {
947  return_track(_road_reverse_table[enterdir]);
948  }
949  }
950  }
951 
952  desttile = v->dest_tile;
953  if (desttile == 0) {
954  /* We've got no destination, pick a random track */
955  return_track(PickRandomBit(trackdirs));
956  }
957 
958  /* Only one track to choose between? */
959  if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) {
960  if (!v->path.empty() && v->path.tile.front() == tile) {
961  /* Vehicle expected a choice here, invalidate its path. */
962  v->path.clear();
963  }
964  return_track(FindFirstBit(trackdirs));
965  }
966 
967  /* Attempt to follow cached path. */
968  if (!v->path.empty()) {
969  if (v->path.tile.front() != tile) {
970  /* Vehicle didn't expect a choice here, invalidate its path. */
971  v->path.clear();
972  } else {
973  Trackdir trackdir = v->path.td.front();
974 
975  if (HasBit(trackdirs, trackdir)) {
976  v->path.td.pop_front();
977  v->path.tile.pop_front();
978  return_track(trackdir);
979  }
980 
981  /* Vehicle expected a choice which is no longer available. */
982  v->path.clear();
983  }
984  }
985 
986  best_track = YapfRoadVehicleChooseTrack(v, tile, enterdir, trackdirs, path_found, v->path);
987 
988  v->HandlePathfindingResult(path_found);
989 
990 found_best_track:;
991 
992  if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
993 
994  return best_track;
995 }
996 
998  uint8_t x, y;
999 };
1000 
1001 #include "table/roadveh_movement.h"
1002 
1003 bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
1004 {
1005  /* Don't leave unless v and following wagons are in the depot. */
1006  for (const RoadVehicle *u = v; u != nullptr; u = u->Next()) {
1007  if (u->state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
1008  }
1009 
1011  v->direction = DiagDirToDir(dir);
1012 
1013  Trackdir tdir = DiagDirToDiagTrackdir(dir);
1014  const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
1015 
1016  int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
1017  int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
1018 
1019  if (first) {
1020  /* We are leaving a depot, but have to go to the exact same one; re-enter */
1021  if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
1022  VehicleEnterDepot(v);
1023  return true;
1024  }
1025 
1026  if (RoadVehFindCloseTo(v, x, y, v->direction, false) != nullptr) return true;
1027 
1029  v->LeaveUnbunchingDepot();
1030 
1031  StartRoadVehSound(v);
1032 
1033  /* Vehicle is about to leave a depot */
1034  v->cur_speed = 0;
1035  }
1036 
1037  v->vehstatus &= ~VS_HIDDEN;
1038  v->state = tdir;
1039  v->frame = RVC_DEPOT_START_FRAME;
1040 
1041  v->x_pos = x;
1042  v->y_pos = y;
1043  v->UpdatePosition();
1044  v->UpdateInclination(true, true);
1045 
1047 
1048  return true;
1049 }
1050 
1051 static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
1052 {
1053  if (prev->tile == v->tile && !already_reversed) {
1054  /* If the previous vehicle is on the same tile as this vehicle is
1055  * then it must have reversed. */
1056  return _road_reverse_table[entry_dir];
1057  }
1058 
1059  uint8_t prev_state = prev->state;
1060  Trackdir dir;
1061 
1062  if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
1063  DiagDirection diag_dir = INVALID_DIAGDIR;
1064 
1065  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1066  diag_dir = GetTunnelBridgeDirection(tile);
1067  } else if (IsRoadDepotTile(tile)) {
1068  diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
1069  }
1070 
1071  if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
1072  dir = DiagDirToDiagTrackdir(diag_dir);
1073  } else {
1074  if (already_reversed && prev->tile != tile) {
1075  /*
1076  * The vehicle has reversed, but did not go straight back.
1077  * It immediately turn onto another tile. This means that
1078  * the roadstate of the previous vehicle cannot be used
1079  * as the direction we have to go with this vehicle.
1080  *
1081  * Next table is build in the following way:
1082  * - first row for when the vehicle in front went to the northern or
1083  * western tile, second for southern and eastern.
1084  * - columns represent the entry direction.
1085  * - cell values are determined by the Trackdir one has to take from
1086  * the entry dir (column) to the tile in north or south by only
1087  * going over the trackdirs used for turning 90 degrees, i.e.
1088  * TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
1089  */
1090  static const Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
1093  dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
1094  } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
1095  dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
1096  } else if (prev_state < TRACKDIR_END) {
1097  dir = (Trackdir)prev_state;
1098  } else {
1099  return INVALID_TRACKDIR;
1100  }
1101  }
1102 
1103  /* Do some sanity checking. */
1104  static const RoadBits required_roadbits[] = {
1107  };
1108  RoadBits required = required_roadbits[dir & 0x07];
1109 
1110  if ((required & GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true)) == ROAD_NONE) {
1111  dir = INVALID_TRACKDIR;
1112  }
1113 
1114  return dir;
1115 }
1116 
1126 {
1127  /* The 'current' company is not necessarily the owner of the vehicle. */
1128  Backup<CompanyID> cur_company(_current_company, c);
1129 
1131 
1132  cur_company.Restore();
1133  return ret.Succeeded();
1134 }
1135 
1136 bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
1137 {
1138  if (v->overtaking != 0) {
1139  if (IsTileType(v->tile, MP_STATION)) {
1140  /* Force us to be not overtaking! */
1141  v->overtaking = 0;
1142  } else if (++v->overtaking_ctr >= RV_OVERTAKE_TIMEOUT) {
1143  /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
1144  * if the vehicle started a corner. To protect that, only allow an abort of
1145  * overtake if we are on straight roads */
1147  v->overtaking = 0;
1148  }
1149  }
1150  }
1151 
1152  /* If this vehicle is in a depot and we've reached this point it must be
1153  * one of the articulated parts. It will stay in the depot until activated
1154  * by the previous vehicle in the chain when it gets to the right place. */
1155  if (v->IsInDepot()) return true;
1156 
1157  if (v->state == RVSB_WORMHOLE) {
1158  /* Vehicle is entering a depot or is on a bridge or in a tunnel */
1160 
1161  if (v->IsFrontEngine()) {
1162  const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
1163  if (u != nullptr) {
1164  v->cur_speed = u->First()->cur_speed;
1165  return false;
1166  }
1167  }
1168 
1170  /* Vehicle has just entered a bridge or tunnel */
1171  v->x_pos = gp.x;
1172  v->y_pos = gp.y;
1173  v->UpdatePosition();
1174  v->UpdateInclination(true, true);
1175  return true;
1176  }
1177 
1178  v->x_pos = gp.x;
1179  v->y_pos = gp.y;
1180  v->UpdatePosition();
1181  if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
1182  return true;
1183  }
1184 
1185  /* Get move position data for next frame.
1186  * For a drive-through road stop use 'straight road' move data.
1187  * In this case v->state is masked to give the road stop entry direction. */
1188  RoadDriveEntry rd = _road_drive_data[GetRoadTramType(v->roadtype)][(
1190  (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
1191 
1192  if (rd.x & RDE_NEXT_TILE) {
1193  TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
1194  Trackdir dir;
1195 
1196  if (v->IsFrontEngine()) {
1197  /* If this is the front engine, look for the right path. */
1198  if (HasTileAnyRoadType(tile, v->compatible_roadtypes)) {
1199  dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
1200  } else {
1201  dir = _road_reverse_table[(DiagDirection)(rd.x & 3)];
1202  }
1203  } else {
1204  dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
1205  }
1206 
1207  if (dir == INVALID_TRACKDIR) {
1208  if (!v->IsFrontEngine()) FatalError("Disconnecting road vehicle.");
1209  v->cur_speed = 0;
1210  return false;
1211  }
1212 
1213 again:
1214  uint start_frame = RVC_DEFAULT_START_FRAME;
1215  if (IsReversingRoadTrackdir(dir)) {
1216  /* When turning around we can't be overtaking. */
1217  v->overtaking = 0;
1218 
1219  /* Turning around */
1220  if (RoadTypeIsTram(v->roadtype)) {
1221  /* Determine the road bits the tram needs to be able to turn around
1222  * using the 'big' corner loop. */
1223  RoadBits needed;
1224  switch (dir) {
1225  default: NOT_REACHED();
1226  case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
1227  case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
1228  case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
1229  case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
1230  }
1231  if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
1232  (v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
1234  (needed & GetRoadBits(tile, RTT_TRAM)) != ROAD_NONE)) {
1235  /*
1236  * Taking the 'big' corner for trams only happens when:
1237  * - The previous vehicle in this (articulated) tram chain is
1238  * already on the 'next' tile, we just follow them regardless of
1239  * anything. When it is NOT on the 'next' tile, the tram started
1240  * doing a reversing turn when the piece of tram track on the next
1241  * tile did not exist yet. Do not use the big tram loop as that is
1242  * going to cause the tram to split up.
1243  * - Or the front of the tram can drive over the next tile.
1244  */
1245  } else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RTT_TRAM, false)) == ROAD_NONE)) {
1246  /*
1247  * Taking the 'small' corner for trams only happens when:
1248  * - We are not the from vehicle of an articulated tram.
1249  * - Or when the company cannot build on the next tile.
1250  *
1251  * The 'small' corner means that the vehicle is on the end of a
1252  * tram track and needs to start turning there. To do this properly
1253  * the tram needs to start at an offset in the tram turning 'code'
1254  * for 'big' corners. It furthermore does not go to the next tile,
1255  * so that needs to be fixed too.
1256  */
1257  tile = v->tile;
1258  start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
1259  } else {
1260  /* The company can build on the next tile, so wait till they do. */
1261  v->cur_speed = 0;
1262  return false;
1263  }
1264  } else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
1265  v->cur_speed = 0;
1266  return false;
1267  } else {
1268  tile = v->tile;
1269  }
1270  }
1271 
1272  /* Get position data for first frame on the new tile */
1273  const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
1274 
1275  int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
1276  int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
1277 
1278  Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1279  if (v->IsFrontEngine()) {
1280  const Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1281  if (u != nullptr) {
1282  v->cur_speed = u->First()->cur_speed;
1283  /* We might be blocked, prevent pathfinding rerun as we already know where we are heading to. */
1284  v->path.tile.push_front(tile);
1285  v->path.td.push_front(dir);
1286  return false;
1287  }
1288  }
1289 
1290  uint32_t r = VehicleEnterTile(v, tile, x, y);
1291  if (HasBit(r, VETS_CANNOT_ENTER)) {
1292  if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
1293  v->cur_speed = 0;
1294  return false;
1295  }
1296  /* Try an about turn to re-enter the previous tile */
1297  dir = _road_reverse_table[rd.x & 3];
1298  goto again;
1299  }
1300 
1301  if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
1302  if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
1303  /* New direction is trying to turn vehicle around.
1304  * We can't turn at the exit of a road stop so wait.*/
1305  v->cur_speed = 0;
1306  return false;
1307  }
1308 
1309  /* If we are a drive through road stop and the next tile is of
1310  * the same road stop and the next tile isn't this one (i.e. we
1311  * are not reversing), then keep the reservation and state.
1312  * This way we will not be shortly unregister from the road
1313  * stop. It also makes it possible to load when on the edge of
1314  * two road stops; otherwise you could get vehicles that should
1315  * be loading but are not actually loading. */
1316  if (IsDriveThroughStopTile(v->tile) &&
1318  v->tile != tile) {
1319  /* So, keep 'our' state */
1320  dir = (Trackdir)v->state;
1321  } else if (IsStationRoadStop(v->tile)) {
1322  /* We're not continuing our drive through road stop, so leave. */
1324  }
1325  }
1326 
1327  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
1328  TileIndex old_tile = v->tile;
1329 
1330  v->tile = tile;
1331  v->state = (uint8_t)dir;
1332  v->frame = start_frame;
1333  RoadTramType rtt = GetRoadTramType(v->roadtype);
1334  if (GetRoadType(old_tile, rtt) != GetRoadType(tile, rtt)) {
1335  if (v->IsFrontEngine()) {
1336  RoadVehUpdateCache(v);
1337  }
1338  v->First()->CargoChanged();
1339  }
1340  }
1341  if (new_dir != v->direction) {
1342  v->direction = new_dir;
1343  if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1344  }
1345  v->x_pos = x;
1346  v->y_pos = y;
1347  v->UpdatePosition();
1348  RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
1349  return true;
1350  }
1351 
1352  if (rd.x & RDE_TURNED) {
1353  /* Vehicle has finished turning around, it will now head back onto the same tile */
1354  Trackdir dir;
1355  uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
1356 
1357  if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RTT_TRAM, true))) {
1358  /*
1359  * The tram is turning around with one tram 'roadbit'. This means that
1360  * it is using the 'big' corner 'drive data'. However, to support the
1361  * trams to take a small corner, there is a 'turned' marker in the middle
1362  * of the turning 'drive data'. When the tram took the long corner, we
1363  * will still use the 'big' corner drive data, but we advance it one
1364  * frame. We furthermore set the driving direction so the turning is
1365  * going to be properly shown.
1366  */
1367  turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
1368  switch (rd.x & 0x3) {
1369  default: NOT_REACHED();
1370  case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
1371  case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
1372  case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
1373  case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
1374  }
1375  } else {
1376  if (v->IsFrontEngine()) {
1377  /* If this is the front engine, look for the right path. */
1378  dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
1379  } else {
1380  dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
1381  }
1382  }
1383 
1384  if (dir == INVALID_TRACKDIR) {
1385  v->cur_speed = 0;
1386  return false;
1387  }
1388 
1389  const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
1390 
1391  int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
1392  int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
1393 
1394  Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1395  if (v->IsFrontEngine()) {
1396  const Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1397  if (u != nullptr) {
1398  v->cur_speed = u->First()->cur_speed;
1399  /* We might be blocked, prevent pathfinding rerun as we already know where we are heading to. */
1400  v->path.tile.push_front(v->tile);
1401  v->path.td.push_front(dir);
1402  return false;
1403  }
1404  }
1405 
1406  uint32_t r = VehicleEnterTile(v, v->tile, x, y);
1407  if (HasBit(r, VETS_CANNOT_ENTER)) {
1408  v->cur_speed = 0;
1409  return false;
1410  }
1411 
1412  v->state = dir;
1413  v->frame = turn_around_start_frame;
1414 
1415  if (new_dir != v->direction) {
1416  v->direction = new_dir;
1417  if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1418  }
1419 
1420  v->x_pos = x;
1421  v->y_pos = y;
1422  v->UpdatePosition();
1423  RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
1424  return true;
1425  }
1426 
1427  /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
1428  * it's on a depot tile, check if it's time to activate the next vehicle in
1429  * the chain yet. */
1430  if (v->Next() != nullptr && IsRoadDepotTile(v->tile)) {
1431  if (v->frame == v->gcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
1432  RoadVehLeaveDepot(v->Next(), false);
1433  }
1434  }
1435 
1436  /* Calculate new position for the vehicle */
1437  int x = (v->x_pos & ~15) + (rd.x & 15);
1438  int y = (v->y_pos & ~15) + (rd.y & 15);
1439 
1440  Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1441 
1442  if (v->IsFrontEngine() && !IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
1443  /* Vehicle is not in a road stop.
1444  * Check for another vehicle to overtake */
1445  RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1446 
1447  if (u != nullptr) {
1448  u = u->First();
1449  /* There is a vehicle in front overtake it if possible */
1450  if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
1451  if (v->overtaking == 0) v->cur_speed = u->cur_speed;
1452 
1453  /* In case an RV is stopped in a road stop, why not try to load? */
1454  if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
1456  v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
1458  Station *st = Station::GetByTile(v->tile);
1459  v->last_station_visited = st->index;
1460  RoadVehArrivesAt(v, st);
1461  v->BeginLoading();
1462  }
1463  return false;
1464  }
1465  }
1466 
1467  Direction old_dir = v->direction;
1468  if (new_dir != old_dir) {
1469  v->direction = new_dir;
1470  if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1471 
1472  /* Delay the vehicle in curves by making it require one additional frame per turning direction (two in total).
1473  * A vehicle has to spend at least 9 frames on a tile, so the following articulated part can follow.
1474  * (The following part may only be one tile behind, and the front part is moved before the following ones.)
1475  * The short (inner) curve has 8 frames, this elongates it to 10. */
1476  v->UpdateViewport(true, true);
1477  return true;
1478  }
1479 
1480  /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
1481  * if the vehicle is in a drive-through road stop and this is the destination station
1482  * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
1483  * (the station test and stop type test ensure that other vehicles, using the road stop as
1484  * a through route, do not stop) */
1485  if (v->IsFrontEngine() && ((IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
1487  (IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
1489  v->owner == GetTileOwner(v->tile) &&
1491  v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
1492 
1494  Station *st = Station::GetByTile(v->tile);
1495 
1496  /* Vehicle is at the stop position (at a bay) in a road stop.
1497  * Note, if vehicle is loading/unloading it has already been handled,
1498  * so if we get here the vehicle has just arrived or is just ready to leave. */
1499  if (!HasBit(v->state, RVS_ENTERED_STOP)) {
1500  /* Vehicle has arrived at a bay in a road stop */
1501 
1502  if (IsDriveThroughStopTile(v->tile)) {
1503  TileIndex next_tile = TileAddByDir(v->tile, v->direction);
1504 
1505  /* Check if next inline bay is free and has compatible road. */
1507  v->frame++;
1508  v->x_pos = x;
1509  v->y_pos = y;
1510  v->UpdatePosition();
1511  RoadZPosAffectSpeed(v, v->UpdateInclination(true, false));
1512  return true;
1513  }
1514  }
1515 
1516  rs->SetEntranceBusy(false);
1518 
1519  v->last_station_visited = st->index;
1520 
1521  if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
1522  RoadVehArrivesAt(v, st);
1523  v->BeginLoading();
1524  return false;
1525  }
1526  } else {
1527  /* Vehicle is ready to leave a bay in a road stop */
1528  if (rs->IsEntranceBusy()) {
1529  /* Road stop entrance is busy, so wait as there is nowhere else to go */
1530  v->cur_speed = 0;
1531  return false;
1532  }
1533  if (v->current_order.IsType(OT_LEAVESTATION)) v->current_order.Free();
1534  }
1535 
1536  if (IsBayRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
1537 
1538  StartRoadVehSound(v);
1540  }
1541 
1542  /* Check tile position conditions - i.e. stop position in depot,
1543  * entry onto bridge or into tunnel */
1544  uint32_t r = VehicleEnterTile(v, v->tile, x, y);
1545  if (HasBit(r, VETS_CANNOT_ENTER)) {
1546  v->cur_speed = 0;
1547  return false;
1548  }
1549 
1550  if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
1551  v->current_order.Free();
1552  }
1553 
1554  /* Move to next frame unless vehicle arrived at a stop position
1555  * in a depot or entered a tunnel/bridge */
1556  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
1557  v->x_pos = x;
1558  v->y_pos = y;
1559  v->UpdatePosition();
1560  RoadZPosAffectSpeed(v, v->UpdateInclination(false, true));
1561  return true;
1562 }
1563 
1564 static bool RoadVehController(RoadVehicle *v)
1565 {
1566  /* decrease counters */
1567  v->current_order_time++;
1568  if (v->reverse_ctr != 0) v->reverse_ctr--;
1569 
1570  /* handle crashed */
1571  if (v->vehstatus & VS_CRASHED || RoadVehCheckTrainCrash(v)) {
1572  return RoadVehIsCrashed(v);
1573  }
1574 
1575  /* road vehicle has broken down? */
1576  if (v->HandleBreakdown()) return true;
1577  if (v->vehstatus & VS_STOPPED) {
1578  v->SetLastSpeed();
1579  return true;
1580  }
1581 
1582  ProcessOrders(v);
1583  v->HandleLoading();
1584 
1585  if (v->current_order.IsType(OT_LOADING)) return true;
1586 
1587  if (v->IsInDepot()) {
1588  /* Check if we should wait here for unbunching. */
1589  if (v->IsWaitingForUnbunching()) return true;
1590  if (RoadVehLeaveDepot(v, true)) return true;
1591  }
1592 
1593  v->ShowVisualEffect();
1594 
1595  /* Check how far the vehicle needs to proceed */
1596  int j = v->UpdateSpeed();
1597 
1598  int adv_spd = v->GetAdvanceDistance();
1599  bool blocked = false;
1600  while (j >= adv_spd) {
1601  j -= adv_spd;
1602 
1603  RoadVehicle *u = v;
1604  for (RoadVehicle *prev = nullptr; u != nullptr; prev = u, u = u->Next()) {
1605  if (!IndividualRoadVehicleController(u, prev)) {
1606  blocked = true;
1607  break;
1608  }
1609  }
1610  if (blocked) break;
1611 
1612  /* Determine distance to next map position */
1613  adv_spd = v->GetAdvanceDistance();
1614 
1615  /* Test for a collision, but only if another movement will occur. */
1616  if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
1617  }
1618 
1619  v->SetLastSpeed();
1620 
1621  for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
1622  if ((u->vehstatus & VS_HIDDEN) != 0) continue;
1623 
1624  u->UpdateViewport(false, false);
1625  }
1626 
1627  /* If movement is blocked, set 'progress' to its maximum, so the roadvehicle does
1628  * not accelerate again before it can actually move. I.e. make sure it tries to advance again
1629  * on next tick to discover whether it is still blocked. */
1630  if (v->progress == 0) v->progress = blocked ? adv_spd - 1 : j;
1631 
1632  return true;
1633 }
1634 
1636 {
1637  const Engine *e = this->GetEngine();
1638  if (e->u.road.running_cost_class == INVALID_PRICE) return 0;
1639 
1640  uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->u.road.running_cost);
1641  if (cost_factor == 0) return 0;
1642 
1643  return GetPrice(e->u.road.running_cost_class, cost_factor, e->GetGRF());
1644 }
1645 
1647 {
1649 
1650  this->tick_counter++;
1651 
1652  if (this->IsFrontEngine()) {
1653  if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
1654  return RoadVehController(this);
1655  }
1656 
1657  return true;
1658 }
1659 
1660 void RoadVehicle::SetDestTile(TileIndex tile)
1661 {
1662  if (tile == this->dest_tile) return;
1663  this->path.clear();
1664  this->dest_tile = tile;
1665 }
1666 
1667 static void CheckIfRoadVehNeedsService(RoadVehicle *v)
1668 {
1669  /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
1670  if (Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
1671  if (v->IsChainInDepot()) {
1673  return;
1674  }
1675 
1677 
1678  FindDepotData rfdd = FindClosestRoadDepot(v, max_penalty);
1679  /* Only go to the depot if it is not too far out of our way. */
1680  if (rfdd.best_length == UINT_MAX || rfdd.best_length > max_penalty) {
1681  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1682  /* If we were already heading for a depot but it has
1683  * suddenly moved farther away, we continue our normal
1684  * schedule? */
1685  v->current_order.MakeDummy();
1687  }
1688  return;
1689  }
1690 
1691  DepotID depot = GetDepotIndex(rfdd.tile);
1692 
1693  if (v->current_order.IsType(OT_GOTO_DEPOT) &&
1695  !Chance16(1, 20)) {
1696  return;
1697  }
1698 
1701  v->SetDestTile(rfdd.tile);
1703 }
1704 
1707 {
1708  if (!this->IsFrontEngine()) return;
1709  AgeVehicle(this);
1710 }
1711 
1714 {
1715  if (!this->IsFrontEngine()) return;
1716  EconomyAgeVehicle(this);
1717 
1718  if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
1719  if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
1720 
1721  CheckIfRoadVehNeedsService(this);
1722 
1723  CheckOrders(this);
1724 
1725  if (this->running_ticks == 0) return;
1726 
1728 
1729  this->profit_this_year -= cost.GetCost();
1730  this->running_ticks = 0;
1731 
1732  SubtractMoneyFromCompanyFract(this->owner, cost);
1733 
1736 }
1737 
1739 {
1740  if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
1741 
1742  if (this->IsInDepot()) {
1743  /* We'll assume the road vehicle is facing outwards */
1744  return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
1745  }
1746 
1747  if (IsBayRoadStopTile(this->tile)) {
1748  /* We'll assume the road vehicle is facing outwards */
1749  return DiagDirToDiagTrackdir(GetBayRoadStopDir(this->tile)); // Road vehicle in a station
1750  }
1751 
1752  /* Drive through road stops / wormholes (tunnels) */
1753  if (this->state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
1754 
1755  /* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
1756  * otherwise transform it into a valid track direction */
1757  return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
1758 }
1759 
1761 {
1762  uint16_t weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnits(this->GetEngine()->DetermineCapacity(this));
1763 
1764  /* Vehicle weight is not added for articulated parts. */
1765  if (!this->IsArticulatedPart()) {
1766  /* Road vehicle weight is in units of 1/4 t. */
1767  weight += GetVehicleProperty(this, PROP_ROADVEH_WEIGHT, RoadVehInfo(this->engine_type)->weight) / 4;
1768  }
1769 
1770  return weight;
1771 }
Base functions for all AIs.
void AddArticulatedParts(Vehicle *first)
Add the remaining articulated parts to the given vehicle.
void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
Checks whether the specs of freshly build articulated vehicles are consistent with the information sp...
Functions related to articulated vehicles.
Class for backupping variables and making sure they are restored later.
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
constexpr T KillFirstBit(T value)
Clear the first bit in an integer.
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition: bridge.h:66
BridgeType GetBridgeType(Tile t)
Determines the type of bridge on a tile.
Definition: bridge_map.h:56
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
bool IsCargoInClass(CargoID c, CargoClass cc)
Does cargo c have cargo class cc?
Definition: cargotype.h:232
@ CC_PASSENGERS
Passengers.
Definition: cargotype.h:50
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:243
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
bool Failed() const
Did this command fail?
Definition: command_type.h:171
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:146
RAII class for measuring multi-step elements of performance.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition: road.h:122
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static constexpr int DAYS_IN_YEAR
days per year
static Date date
Current date in days (day counter).
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition: cargopacket.h:434
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_NO_WATER
don't allow building on water
Definition: command_type.h:379
@ DC_EXEC
execute the given command
Definition: command_type.h:376
Definition of stuff that is very close to a company, like the company struct itself.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
Subtract money from a company, including the money fraction.
Functions related to companies.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Map related accessors for depots.
DepotID GetDepotIndex(Tile t)
Get the index of which depot is attached to the tile.
Definition: depot_map.h:52
uint16_t DepotID
Type for the unique identifier of depots.
Definition: depot_type.h:13
DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Direction DiagDirToDir(DiagDirection dir)
Convert a DiagDirection to a Direction.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
bool IsDiagonalDirection(Direction dir)
Checks if a given Direction is diagonal.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
Direction
Defines the 8 directions on the map.
@ DIR_SW
Southwest.
@ DIR_NW
Northwest.
@ INVALID_DIR
Flag for an invalid direction.
@ DIR_N
North.
@ DIR_SE
Southeast.
@ DIR_S
South.
@ DIR_NE
Northeast.
@ DIR_W
West.
@ DIR_E
East.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
DirDiff
Allow incrementing of Direction variables.
@ DIRDIFF_45LEFT
Angle of 45 degrees left.
@ DIRDIFF_REVERSE
One direction is the opposite of the other one.
@ DIRDIFF_45RIGHT
Angle of 45 degrees right.
@ DIRDIFF_SAME
Both directions faces to the same direction.
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition: economy.cpp:969
@ EXPENSES_ROADVEH_RUN
Running costs road vehicles.
Definition: economy_type.h:176
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
Functions related to effect vehicles.
@ EV_EXPLOSION_LARGE
Various explosions.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:206
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
@ ENGINE_EXCLUSIVE_PREVIEW
This vehicle is in the exclusive preview stage, either being used or being offered to a company.
Definition: engine_type.h:184
Error reporting related functions.
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
Types for recording game performance data.
@ PFE_GL_ROADVEHS
Time spend processing road vehicles.
Base functions for all Games.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:19
@ AS_BRAKE
We want to stop.
@ GVF_SUPPRESS_IMPLICIT_ORDERS
Disable insertion and removal of automatic orders until the vehicle completes the real order.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition: landscape.cpp:303
TileIndex TileAddByDir(TileIndex tile, Direction dir)
Adds a Direction to a tile.
Definition: map_func.h:596
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition: math_func.hpp:268
Base for the NewGRF implementation.
@ CBID_VEHICLE_LENGTH
Vehicle length, returns the amount of 1/8's the vehicle is shorter for trains and RVs.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
@ PROP_ROADVEH_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_ROADVEH_WEIGHT
Weight in 1/4 t.
@ PROP_ROADVEH_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_ROADVEH_SHORTEN_FACTOR
Shorter vehicles.
@ PROP_ROADVEH_SPEED
Max. speed: 1 unit = 1/0.8 mph = 2 km-ish/h.
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event, bool force)
Checks whether a NewGRF wants to play a different vehicle sound effect.
Functions related to NewGRF provided sounds.
@ VSE_START
Vehicle starting, i.e. leaving, the station.
Definition: newgrf_sound.h:19
Functions related to news.
void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station=INVALID_STATION)
Adds a newsitem referencing a vehicle.
Definition: news_func.h:30
NewsType
Type of news.
Definition: news_type.h:23
@ NT_ACCIDENT_OTHER
An accident or disaster has occurred.
Definition: news_type.h:27
@ NT_ARRIVAL_COMPANY
First vehicle arrived for company.
Definition: news_type.h:24
@ NT_ARRIVAL_OTHER
First vehicle arrived for competitor.
Definition: news_type.h:25
@ NT_ACCIDENT
An accident or disaster has occurred.
Definition: news_type.h:26
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2127
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition: order_cmd.cpp:1711
@ ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS
The vehicle will not stop at any stations it passes except the destination.
Definition: order_type.h:74
@ ODTFB_SERVICE
This depot order is because of the servicing limit.
Definition: order_type.h:95
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
Definition: random_func.hpp:88
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition: road.h:227
Road related functions.
RoadBits AxisToRoadBits(Axis a)
Create the road-part which belongs to the given Axis.
Definition: road_func.h:111
RoadBits DiagDirToRoadBits(DiagDirection d)
Create the road-part which belongs to the given DiagDirection.
Definition: road_func.h:96
RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance)
Returns the RoadBits on an arbitrary tile Special behaviour:
Definition: road_map.cpp:33
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition: road_map.h:74
static debug_inline bool IsRoadDepot(Tile t)
Return whether a tile is a road depot.
Definition: road_map.h:106
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition: road_map.h:95
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition: road_map.h:128
bool HasTileAnyRoadType(Tile t, RoadTypes rts)
Check if a tile has one of the specified road types.
Definition: road_map.h:222
DisallowedRoadDirections GetDisallowedRoadDirections(Tile t)
Gets the disallowed directions.
Definition: road_map.h:301
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition: road_map.h:565
static debug_inline bool IsRoadDepotTile(Tile t)
Return whether a tile is a road depot tile.
Definition: road_map.h:116
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition: road_map.h:513
RoadBits
Enumeration for the road parts on a tile.
Definition: road_type.h:52
@ ROAD_SW
South-west part.
Definition: road_type.h:55
@ ROAD_NONE
No road-part is build.
Definition: road_type.h:53
@ ROAD_NE
North-east part.
Definition: road_type.h:57
@ ROAD_SE
South-east part.
Definition: road_type.h:56
@ ROAD_Y
Full road along the y-axis (north-west + south-east)
Definition: road_type.h:59
@ ROAD_NW
North-west part.
Definition: road_type.h:54
@ ROAD_X
Full road along the x-axis (south-west + north-east)
Definition: road_type.h:58
RoadType
The different roadtypes we support.
Definition: road_type.h:25
@ DRD_NONE
None of the directions are disallowed.
Definition: road_type.h:74
Base class for roadstops.
Road vehicle states.
static const uint RDE_TURNED
We just finished turning.
Definition: roadveh.h:62
static const uint8_t RV_OVERTAKE_TIMEOUT
The number of ticks a vehicle has for overtaking.
Definition: roadveh.h:79
@ RVSB_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition: roadveh.h:51
@ RVS_ENTERED_STOP
Only set when a vehicle has entered the stop.
Definition: roadveh.h:43
@ RVSB_IN_ROAD_STOP
The vehicle is in a road stop.
Definition: roadveh.h:49
@ RVSB_ROAD_STOP_TRACKDIR_MASK
Only bits 0 and 3 are used to encode the trackdir for road stops.
Definition: roadveh.h:57
@ RVS_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition: roadveh.h:46
@ RVSB_TRACKDIR_MASK
The mask used to extract track dirs.
Definition: roadveh.h:56
@ RVSB_DRIVE_SIDE
The vehicle is at the opposite side of the road.
Definition: roadveh.h:54
@ RVSB_IN_DEPOT
The vehicle is in a depot.
Definition: roadveh.h:38
@ RVSB_WORMHOLE
The vehicle is in a tunnel and/or bridge.
Definition: roadveh.h:39
@ RVS_DRIVE_SIDE
Only used when retrieving move data.
Definition: roadveh.h:44
static const uint RDE_NEXT_TILE
State information about the Road Vehicle controller.
Definition: roadveh.h:61
static Vehicle * EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
Check routine whether a road and a train vehicle have collided.
static bool RoadVehIsCrashed(RoadVehicle *v)
Road vehicle chain has crashed.
static uint GetRoadVehLength(const RoadVehicle *v)
Get length of a road vehicle.
static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
A road vehicle arrives at a station.
static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
Check if overtaking is possible on a piece of track.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
Update the cache of a road vehicle.
static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadType rt, RoadBits r)
Can a tram track build without destruction on the given tile?
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a road vehicle sprite heading west (used for lists).
void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
Draw a road vehicle engine.
static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection enterdir)
Returns direction to for a road vehicle to take or INVALID_TRACKDIR if the direction is currently blo...
static void DeleteLastRoadVeh(RoadVehicle *v)
Delete last vehicle of a chain road vehicles.
CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a road vehicle.
CommandCost CmdTurnRoadVeh(DoCommandFlag flags, VehicleID veh_id)
Turn a roadvehicle around.
Command definitions related to road vehicles.
Data about how a road vehicle must drive on a tile.
const uint8_t _road_stop_stop_frame[]
Table of road stop stop frames, when to stop at a road stop.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
Functions related to sound.
@ SND_19_DEPARTURE_OLD_RV_1
23 == 0x17 Station departure: truck and old bus (1) (non-toyland)
Definition: sound_type.h:62
@ SND_12_EXPLOSION
16 == 0x10 Destruction, crashes, disasters, ...
Definition: sound_type.h:55
@ SND_1A_DEPARTURE_OLD_RV_2
24 == 0x18 Station departure: truck and old bus (2) (random variation of SND_19_DEPARTURE_OLD_RV_1) (...
Definition: sound_type.h:63
Functions to cache sprites in memory.
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1605
Base classes/functions for stations.
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition: station_map.h:266
bool IsDriveThroughStopTile(Tile t)
Is tile t a drive through road stop station or waypoint?
Definition: station_map.h:276
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
bool IsStationRoadStop(Tile t)
Is the station at t a road station?
Definition: station_map.h:223
DiagDirection GetBayRoadStopDir(Tile t)
Gets the direction the bay road stop entrance points towards.
Definition: station_map.h:344
RoadStopType GetRoadStopType(Tile t)
Get the road stop type of this tile.
Definition: station_map.h:56
RoadStopType
Types of RoadStops.
Definition: station_type.h:45
@ ROADSTOP_BUS
A standard stop for buses.
Definition: station_type.h:46
@ ROADSTOP_TRUCK
A standard stop for trucks.
Definition: station_type.h:47
@ HVOT_TRUCK
Station has seen a truck.
Definition: station_type.h:68
@ HVOT_BUS
Station has seen a bus.
Definition: station_type.h:67
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
void Restore()
Restore the variable.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:21
uint16_t vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:34
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
TileIndex xy
Base tile of the station.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: bridge.h:47
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:134
SoundSettings sound
sound effect settings
Structure to return information about the closest depot location, and whether it could be found.
Definition: vehicle_base.h:230
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
Definition: engine_type.h:159
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:96
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the engine is tied to.
Definition: engine.cpp:157
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition: engine_base.h:42
uint8_t original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition: engine_base.h:55
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:167
TimerGameCalendar::Date GetLifeLengthInDays() const
Returns the vehicle's (not model's!) life length in days.
Definition: engine.cpp:443
uint16_t reliability
Current reliability of the engine.
Definition: engine_base.h:41
uint8_t flags
Flags of the engine.
Definition: engine_base.h:49
Helper container to find a depot.
uint best_length
The distance towards the depot in penalty, or UINT_MAX if not found.
TileIndex tile
The tile of the depot.
PathfinderSettings pf
settings for all pathfinders
VehicleSettings vehicle
options for vehicles
Position information of a vehicle after it moved.
Definition: vehicle_func.h:77
TileIndex new_tile
Tile of the vehicle after moving.
Definition: vehicle_func.h:80
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:78
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
uint16_t cached_total_length
Length of the whole vehicle (valid only for the first engine).
uint8_t cached_veh_length
Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can b...
uint16_t cached_max_track_speed
Maximum consist speed (in internal units) limited by track type (valid only for the first engine).
bool IsChainInDepot() const override
Check whether the whole vehicle chain is in the depot.
int UpdateInclination(bool new_tile, bool update_delta)
Checks if the vehicle is in a slope and sets the required flags in that case.
GroundVehicleCache gcache
Cache of often calculated values.
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
void SetFrontEngine()
Set front engine state.
uint Crash(bool flooded) override
Common code executed for crashed ground vehicles.
uint DoUpdateSpeed(uint accel, int min_speed, int max_speed)
Update the speed of the vehicle.
int GetAcceleration() const
Calculates the acceleration of the vehicle under its current conditions.
void SetLastSpeed()
Update the GUI variant of the current speed of the vehicle.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:200
uint16_t GetMaxSpeed() const
Get the maxmimum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition: order_base.h:201
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:103
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:70
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:133
void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoID cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition: order_cmd.cpp:90
void Free()
'Free' the order
Definition: order_cmd.cpp:63
bool ShouldStopAtStation(const Vehicle *v, StationID station) const
Check whether the given vehicle should stop at the given station based on this order and the non-stop...
Definition: order_cmd.cpp:2225
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition: order_base.h:140
YAPFSettings yapf
pathfinder settings for the yet another pathfinder
bool roadveh_queue
buggy road vehicle queueing
Coordinates of a point in 2D.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
int Height() const
Get height of Rect.
A Stop for a Road Vehicle.
Definition: roadstop_base.h:22
void SetEntranceBusy(bool busy)
Makes an entrance occupied or free.
void Leave(RoadVehicle *rv)
Leave the road stop.
Definition: roadstop.cpp:214
bool IsEntranceBusy() const
Checks whether the entrance of the road stop is occupied by a vehicle.
static bool IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next)
Checks whether the 'next' tile is still part of the road same drive through stop 'rs' in the same dir...
Definition: roadstop.cpp:303
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition: roadstop.cpp:264
Information about a road vehicle.
Definition: engine_type.h:114
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
Definition: engine_type.h:120
RoadType roadtype
Road type.
Definition: engine_type.h:128
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
Definition: engine_type.h:127
Buses, trucks and trams belong to this class.
Definition: roadveh.h:106
uint Crash(bool flooded=false) override
Crash the (whole) vehicle chain.
void OnNewEconomyDay() override
Economy day handler.
uint8_t state
Definition: roadveh.h:108
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a road vehicle image in the GUI.
Definition: roadveh_cmd.cpp:93
Money GetRunningCost() const override
Gets the running cost of a vehicle.
bool IsPrimaryVehicle() const override
Whether this is the primary vehicle in the chain.
Definition: roadveh.h:130
uint16_t GetMaxWeight() const override
Calculates the weight value that this vehicle will have when fully loaded with its current cargo.
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition: roadveh.h:118
AccelStatus GetAccelerationStatus() const
Checks the current acceleration status of this vehicle.
Definition: roadveh.h:231
void UpdateDeltaXY() override
Updates the x and y offsets and the size of the sprite used for this vehicle.
uint16_t crashed_ctr
Animation counter when the vehicle has crashed.
Definition: roadveh.h:113
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition: roadveh_cmd.cpp:82
uint8_t overtaking_ctr
The length of the current overtake attempt.
Definition: roadveh.h:112
void OnNewCalendarDay() override
Calandar day handler.
bool IsInDepot() const override
Check whether the vehicle is in the depot.
Definition: roadveh.h:136
RoadVehPathCache path
Cached path.
Definition: roadveh.h:107
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
int GetCurrentMaxSpeed() const override
Calculates the maximum speed of the vehicle under its current conditions.
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition: roadveh.h:116
uint8_t overtaking
Set to RVSB_DRIVE_SIDE when overtaking, otherwise 0.
Definition: roadveh.h:111
int UpdateSpeed()
This function looks at the vehicle and updates its speed (cur_speed and subspeed) variables.
bool Tick() override
Calls the tick handler of the vehicle.
ClosestDepot FindClosestDepot() override
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
void MarkDirty() override
Marks the vehicles to be redrawn and updates cached variables.
bool disaster
Play disaster and accident sounds.
static Station * Get(size_t index)
Gets station with given index.
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
T * Previous() const
Get previous vehicle in the chain.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * Next() const
Get next vehicle in the chain.
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
T * First() const
Get the first vehicle in the chain.
static T * GetIfValid(size_t index)
Returns vehicle if the index is a valid index for this vehicle type.
Station data structure.
Definition: station_base.h:439
uint16_t cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition: vehicle_base.h:126
uint8_t roadveh_acceleration_model
realistic acceleration for road vehicles
uint8_t road_side
the side of the road vehicles drive on
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:135
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:103
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Definition: vehicle_base.h:168
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:131
Vehicle data structure.
Definition: vehicle_base.h:244
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
int32_t z_pos
z coordinate.
Definition: vehicle_base.h:306
Direction direction
facing
Definition: vehicle_base.h:307
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:747
void IncrementRealOrderIndex()
Advanced cur_real_order_index to the next real order, keeps care of the wrap-around and invalidates t...
Definition: vehicle_base.h:886
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:341
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:645
uint8_t x_extent
x-extent of vehicle bounding box
Definition: vehicle_base.h:316
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
Definition: vehicle_base.h:295
uint16_t cargo_cap
total capacity
Definition: vehicle_base.h:344
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
Definition: vehicle_base.h:338
uint16_t random_bits
Bits used for randomized variational spritegroups.
Definition: vehicle_base.h:335
uint8_t day_counter
Increased by one for each day.
Definition: vehicle_base.h:349
void HandleLoading(bool mode=false)
Handle the loading of the vehicle; when not it skips through dummy orders and does nothing in all oth...
Definition: vehicle.cpp:2430
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition: vehicle_base.h:273
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:963
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition: vehicle_base.h:288
uint8_t breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:299
uint GetAdvanceDistance()
Determines the vehicle "progress" needed for moving a step.
Definition: vehicle_base.h:457
uint8_t z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:318
TimerGameCalendar::Date date_of_last_service_newgrf
Last calendar date the vehicle had a service at a depot, unchanged by the date cheat to protect again...
Definition: vehicle_base.h:296
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:954
void LeaveUnbunchingDepot()
Leave an unbunching depot and calculate the next departure time for shared order vehicles.
Definition: vehicle.cpp:2514
int8_t y_offs
y offset for vehicle sprite
Definition: vehicle_base.h:322
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:945
int8_t x_bb_offs
x offset of vehicle bounding box
Definition: vehicle_base.h:319
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:356
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:342
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition: vehicle.cpp:791
int8_t x_offs
x offset for vehicle sprite
Definition: vehicle_base.h:321
int32_t y_pos
y coordinate.
Definition: vehicle_base.h:305
int32_t x_pos
x coordinate.
Definition: vehicle_base.h:304
uint8_t y_extent
y-extent of vehicle bounding box
Definition: vehicle_base.h:317
uint16_t refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:345
void InvalidateNewGRFCache()
Invalidates cached NewGRF variables.
Definition: vehicle_base.h:495
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:364
int8_t y_bb_offs
y offset of vehicle bounding box
Definition: vehicle_base.h:320
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2203
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Definition: vehicle_base.h:315
uint16_t cur_speed
current speed
Definition: vehicle_base.h:328
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition: vehicle.cpp:2561
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition: vehicle.cpp:2937
TimerGameCalendar::Date max_age
Maximum age.
Definition: vehicle_base.h:294
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
Definition: vehicle_base.h:368
uint16_t reliability
Reliability.
Definition: vehicle_base.h:297
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds,...
Definition: vehicle.cpp:1363
uint8_t progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition: vehicle_base.h:332
uint16_t reliability_spd_dec
Reliability decrease speed.
Definition: vehicle_base.h:298
uint8_t tick_counter
Increased by one for each tick.
Definition: vehicle_base.h:350
virtual bool IsInDepot() const
Check whether the vehicle is in the depot.
Definition: vehicle_base.h:548
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:271
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1693
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:337
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle)
Definition: vehicle_base.h:504
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition: vehicle.cpp:2787
TimerGameCalendar::Year build_year
Year the vehicle has been built.
Definition: vehicle_base.h:291
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:309
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:272
uint8_t running_ticks
Number of ticks this vehicle was not stopped this day.
Definition: vehicle_base.h:351
uint32_t maximum_go_to_depot_penalty
What is the maximum penalty that may be endured for going to a depot.
@ VETS_CANNOT_ENTER
The vehicle cannot enter the tile.
Definition: tile_cmd.h:24
@ VETS_ENTERED_WORMHOLE
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition: tile_cmd.h:23
VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition: vehicle.cpp:1838
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:214
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition: tile_map.h:178
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
@ MP_ROAD
A tile with road (or tram tracks)
Definition: tile_type.h:50
@ MP_STATION
A tile of a station.
Definition: tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:57
Definition of the game-calendar-timer.
Definition of the game-economy-timer.
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition: track_func.h:352
bool IsReversingRoadTrackdir(Trackdir dir)
Checks whether the trackdir means that we are reversing.
Definition: track_func.h:673
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition: track_func.h:555
bool IsStraightRoadTrackdir(Trackdir dir)
Checks whether the given trackdir is a straight road.
Definition: track_func.h:684
Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:537
TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
Returns the red-signal-information of a TrackStatus.
Definition: track_func.h:376
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition: track_func.h:308
TrackBits
Allow incrementing of Track variables.
Definition: track_type.h:35
@ TRACK_BIT_CROSS
X-Y-axis cross.
Definition: track_type.h:43
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:67
@ TRACKDIR_RVREV_NE
(Road vehicle) reverse direction north-east
Definition: track_type.h:75
@ TRACKDIR_LOWER_E
Lower track and direction to east.
Definition: track_type.h:72
@ TRACKDIR_RIGHT_N
Right track and direction to north.
Definition: track_type.h:82
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition: track_type.h:86
@ TRACKDIR_UPPER_E
Upper track and direction to east.
Definition: track_type.h:71
@ TRACKDIR_LEFT_S
Left track and direction to south.
Definition: track_type.h:73
@ TRACKDIR_UPPER_W
Upper track and direction to west.
Definition: track_type.h:79
@ TRACKDIR_RVREV_SE
(Road vehicle) reverse direction south-east
Definition: track_type.h:76
@ TRACKDIR_LOWER_W
Lower track and direction to west.
Definition: track_type.h:80
@ TRACKDIR_END
Used for iterations.
Definition: track_type.h:85
@ TRACKDIR_RIGHT_S
Right track and direction to south.
Definition: track_type.h:74
@ TRACKDIR_RVREV_NW
(Road vehicle) reverse direction north-west
Definition: track_type.h:84
@ TRACKDIR_RVREV_SW
(Road vehicle) reverse direction south-west
Definition: track_type.h:83
@ TRACKDIR_LEFT_N
Left track and direction to north.
Definition: track_type.h:81
TrackdirBits
Allow incrementing of Trackdir variables.
Definition: track_type.h:98
@ TRACKDIR_BIT_NONE
No track build.
Definition: track_type.h:99
@ TRANSPORT_ROAD
Transport by road vehicle.
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition: vehicle.cpp:1552
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle in on a specific location.
Definition: vehicle.cpp:461
void VehicleLengthChanged(const Vehicle *u)
Logs a bug in GRF and shows a warning message if this is for the first time this happened.
Definition: vehicle.cpp:346
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition: vehicle.cpp:167
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:445
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition: vehicle.cpp:1784
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:520
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:505
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1301
void EconomyAgeVehicle(Vehicle *v)
Update economy age of a vehicle.
Definition: vehicle.cpp:1429
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:3058
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1441
@ VF_BUILT_AS_PROTOTYPE
Vehicle is a prototype (accepted as exclusive preview).
Definition: vehicle_base.h:47
@ VS_STOPPED
Vehicle is stopped by the player.
Definition: vehicle_base.h:34
@ VS_HIDDEN
Vehicle is not visible.
Definition: vehicle_base.h:33
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
@ VS_DEFPAL
Use default vehicle palette.
Definition: vehicle_base.h:36
Functions related to vehicles.
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:78
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
uint32_t VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
Definition: vehicle_type.h:69
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3119
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3211
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3106
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3093
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
Definition: window_type.h:314
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition: window_type.h:351
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition: window_type.h:200
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition: window_type.h:339
Entry point for OpenTTD to YAPF.
Trackdir YapfRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirs, bool &path_found, RoadVehPathCache &path_cache)
Finds the best path for given road vehicle using YAPF.
Definition: yapf_road.cpp:534
FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_penalty)
Used when user sends road vehicle to the nearest depot or if road vehicle needs servicing using YAPF.
Definition: yapf_road.cpp:543
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition: zoom_func.h:107
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:77