OpenTTD Source  20241124-master-g9399a92a4f
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.back().tile == 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.back().tile != tile) {
970  /* Vehicle didn't expect a choice here, invalidate its path. */
971  v->path.clear();
972  } else {
973  Trackdir trackdir = v->path.back().trackdir;
974 
975  if (HasBit(trackdirs, trackdir)) {
976  v->path.pop_back();
977  return_track(trackdir);
978  }
979 
980  /* Vehicle expected a choice which is no longer available. */
981  v->path.clear();
982  }
983  }
984 
985  best_track = YapfRoadVehicleChooseTrack(v, tile, enterdir, trackdirs, path_found, v->path);
986 
987  v->HandlePathfindingResult(path_found);
988 
989 found_best_track:;
990 
991  if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
992 
993  return best_track;
994 }
995 
997  uint8_t x, y;
998 };
999 
1000 #include "table/roadveh_movement.h"
1001 
1002 bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
1003 {
1004  /* Don't leave unless v and following wagons are in the depot. */
1005  for (const RoadVehicle *u = v; u != nullptr; u = u->Next()) {
1006  if (u->state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
1007  }
1008 
1010  v->direction = DiagDirToDir(dir);
1011 
1012  Trackdir tdir = DiagDirToDiagTrackdir(dir);
1013  const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
1014 
1015  int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
1016  int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
1017 
1018  if (first) {
1019  /* We are leaving a depot, but have to go to the exact same one; re-enter */
1020  if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
1021  VehicleEnterDepot(v);
1022  return true;
1023  }
1024 
1025  if (RoadVehFindCloseTo(v, x, y, v->direction, false) != nullptr) return true;
1026 
1028  v->LeaveUnbunchingDepot();
1029 
1030  StartRoadVehSound(v);
1031 
1032  /* Vehicle is about to leave a depot */
1033  v->cur_speed = 0;
1034  }
1035 
1036  v->vehstatus &= ~VS_HIDDEN;
1037  v->state = tdir;
1038  v->frame = RVC_DEPOT_START_FRAME;
1039 
1040  v->x_pos = x;
1041  v->y_pos = y;
1042  v->UpdatePosition();
1043  v->UpdateInclination(true, true);
1044 
1046 
1047  return true;
1048 }
1049 
1050 static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
1051 {
1052  if (prev->tile == v->tile && !already_reversed) {
1053  /* If the previous vehicle is on the same tile as this vehicle is
1054  * then it must have reversed. */
1055  return _road_reverse_table[entry_dir];
1056  }
1057 
1058  uint8_t prev_state = prev->state;
1059  Trackdir dir;
1060 
1061  if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
1062  DiagDirection diag_dir = INVALID_DIAGDIR;
1063 
1064  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1065  diag_dir = GetTunnelBridgeDirection(tile);
1066  } else if (IsRoadDepotTile(tile)) {
1067  diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
1068  }
1069 
1070  if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
1071  dir = DiagDirToDiagTrackdir(diag_dir);
1072  } else {
1073  if (already_reversed && prev->tile != tile) {
1074  /*
1075  * The vehicle has reversed, but did not go straight back.
1076  * It immediately turn onto another tile. This means that
1077  * the roadstate of the previous vehicle cannot be used
1078  * as the direction we have to go with this vehicle.
1079  *
1080  * Next table is build in the following way:
1081  * - first row for when the vehicle in front went to the northern or
1082  * western tile, second for southern and eastern.
1083  * - columns represent the entry direction.
1084  * - cell values are determined by the Trackdir one has to take from
1085  * the entry dir (column) to the tile in north or south by only
1086  * going over the trackdirs used for turning 90 degrees, i.e.
1087  * TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
1088  */
1089  static const Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
1092  dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
1093  } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
1094  dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
1095  } else if (prev_state < TRACKDIR_END) {
1096  dir = (Trackdir)prev_state;
1097  } else {
1098  return INVALID_TRACKDIR;
1099  }
1100  }
1101 
1102  /* Do some sanity checking. */
1103  static const RoadBits required_roadbits[] = {
1106  };
1107  RoadBits required = required_roadbits[dir & 0x07];
1108 
1109  if ((required & GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true)) == ROAD_NONE) {
1110  dir = INVALID_TRACKDIR;
1111  }
1112 
1113  return dir;
1114 }
1115 
1125 {
1126  /* The 'current' company is not necessarily the owner of the vehicle. */
1127  Backup<CompanyID> cur_company(_current_company, c);
1128 
1130 
1131  cur_company.Restore();
1132  return ret.Succeeded();
1133 }
1134 
1135 bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
1136 {
1137  if (v->overtaking != 0) {
1138  if (IsTileType(v->tile, MP_STATION)) {
1139  /* Force us to be not overtaking! */
1140  v->overtaking = 0;
1141  } else if (++v->overtaking_ctr >= RV_OVERTAKE_TIMEOUT) {
1142  /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
1143  * if the vehicle started a corner. To protect that, only allow an abort of
1144  * overtake if we are on straight roads */
1146  v->overtaking = 0;
1147  }
1148  }
1149  }
1150 
1151  /* If this vehicle is in a depot and we've reached this point it must be
1152  * one of the articulated parts. It will stay in the depot until activated
1153  * by the previous vehicle in the chain when it gets to the right place. */
1154  if (v->IsInDepot()) return true;
1155 
1156  if (v->state == RVSB_WORMHOLE) {
1157  /* Vehicle is entering a depot or is on a bridge or in a tunnel */
1159 
1160  if (v->IsFrontEngine()) {
1161  const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
1162  if (u != nullptr) {
1163  v->cur_speed = u->First()->cur_speed;
1164  return false;
1165  }
1166  }
1167 
1169  /* Vehicle has just entered a bridge or tunnel */
1170  v->x_pos = gp.x;
1171  v->y_pos = gp.y;
1172  v->UpdatePosition();
1173  v->UpdateInclination(true, true);
1174  return true;
1175  }
1176 
1177  v->x_pos = gp.x;
1178  v->y_pos = gp.y;
1179  v->UpdatePosition();
1180  if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
1181  return true;
1182  }
1183 
1184  /* Get move position data for next frame.
1185  * For a drive-through road stop use 'straight road' move data.
1186  * In this case v->state is masked to give the road stop entry direction. */
1187  RoadDriveEntry rd = _road_drive_data[GetRoadTramType(v->roadtype)][(
1189  (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
1190 
1191  if (rd.x & RDE_NEXT_TILE) {
1192  TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
1193  Trackdir dir;
1194 
1195  if (v->IsFrontEngine()) {
1196  /* If this is the front engine, look for the right path. */
1197  if (HasTileAnyRoadType(tile, v->compatible_roadtypes)) {
1198  dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
1199  } else {
1200  dir = _road_reverse_table[(DiagDirection)(rd.x & 3)];
1201  }
1202  } else {
1203  dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
1204  }
1205 
1206  if (dir == INVALID_TRACKDIR) {
1207  if (!v->IsFrontEngine()) FatalError("Disconnecting road vehicle.");
1208  v->cur_speed = 0;
1209  return false;
1210  }
1211 
1212 again:
1213  uint start_frame = RVC_DEFAULT_START_FRAME;
1214  if (IsReversingRoadTrackdir(dir)) {
1215  /* When turning around we can't be overtaking. */
1216  v->overtaking = 0;
1217 
1218  /* Turning around */
1219  if (RoadTypeIsTram(v->roadtype)) {
1220  /* Determine the road bits the tram needs to be able to turn around
1221  * using the 'big' corner loop. */
1222  RoadBits needed;
1223  switch (dir) {
1224  default: NOT_REACHED();
1225  case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
1226  case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
1227  case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
1228  case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
1229  }
1230  if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
1231  (v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
1233  (needed & GetRoadBits(tile, RTT_TRAM)) != ROAD_NONE)) {
1234  /*
1235  * Taking the 'big' corner for trams only happens when:
1236  * - The previous vehicle in this (articulated) tram chain is
1237  * already on the 'next' tile, we just follow them regardless of
1238  * anything. When it is NOT on the 'next' tile, the tram started
1239  * doing a reversing turn when the piece of tram track on the next
1240  * tile did not exist yet. Do not use the big tram loop as that is
1241  * going to cause the tram to split up.
1242  * - Or the front of the tram can drive over the next tile.
1243  */
1244  } else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RTT_TRAM, false)) == ROAD_NONE)) {
1245  /*
1246  * Taking the 'small' corner for trams only happens when:
1247  * - We are not the from vehicle of an articulated tram.
1248  * - Or when the company cannot build on the next tile.
1249  *
1250  * The 'small' corner means that the vehicle is on the end of a
1251  * tram track and needs to start turning there. To do this properly
1252  * the tram needs to start at an offset in the tram turning 'code'
1253  * for 'big' corners. It furthermore does not go to the next tile,
1254  * so that needs to be fixed too.
1255  */
1256  tile = v->tile;
1257  start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
1258  } else {
1259  /* The company can build on the next tile, so wait till they do. */
1260  v->cur_speed = 0;
1261  return false;
1262  }
1263  } else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
1264  v->cur_speed = 0;
1265  return false;
1266  } else {
1267  tile = v->tile;
1268  }
1269  }
1270 
1271  /* Get position data for first frame on the new tile */
1272  const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
1273 
1274  int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
1275  int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
1276 
1277  Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1278  if (v->IsFrontEngine()) {
1279  const Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1280  if (u != nullptr) {
1281  v->cur_speed = u->First()->cur_speed;
1282  /* We might be blocked, prevent pathfinding rerun as we already know where we are heading to. */
1283  v->path.emplace_back(dir, tile);
1284  return false;
1285  }
1286  }
1287 
1288  uint32_t r = VehicleEnterTile(v, tile, x, y);
1289  if (HasBit(r, VETS_CANNOT_ENTER)) {
1290  if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
1291  v->cur_speed = 0;
1292  return false;
1293  }
1294  /* Try an about turn to re-enter the previous tile */
1295  dir = _road_reverse_table[rd.x & 3];
1296  goto again;
1297  }
1298 
1299  if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
1300  if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
1301  /* New direction is trying to turn vehicle around.
1302  * We can't turn at the exit of a road stop so wait.*/
1303  v->cur_speed = 0;
1304  return false;
1305  }
1306 
1307  /* If we are a drive through road stop and the next tile is of
1308  * the same road stop and the next tile isn't this one (i.e. we
1309  * are not reversing), then keep the reservation and state.
1310  * This way we will not be shortly unregister from the road
1311  * stop. It also makes it possible to load when on the edge of
1312  * two road stops; otherwise you could get vehicles that should
1313  * be loading but are not actually loading. */
1314  if (IsDriveThroughStopTile(v->tile) &&
1316  v->tile != tile) {
1317  /* So, keep 'our' state */
1318  dir = (Trackdir)v->state;
1319  } else if (IsStationRoadStop(v->tile)) {
1320  /* We're not continuing our drive through road stop, so leave. */
1322  }
1323  }
1324 
1325  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
1326  TileIndex old_tile = v->tile;
1327 
1328  v->tile = tile;
1329  v->state = (uint8_t)dir;
1330  v->frame = start_frame;
1331  RoadTramType rtt = GetRoadTramType(v->roadtype);
1332  if (GetRoadType(old_tile, rtt) != GetRoadType(tile, rtt)) {
1333  if (v->IsFrontEngine()) {
1334  RoadVehUpdateCache(v);
1335  }
1336  v->First()->CargoChanged();
1337  }
1338  }
1339  if (new_dir != v->direction) {
1340  v->direction = new_dir;
1341  if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1342  }
1343  v->x_pos = x;
1344  v->y_pos = y;
1345  v->UpdatePosition();
1346  RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
1347  return true;
1348  }
1349 
1350  if (rd.x & RDE_TURNED) {
1351  /* Vehicle has finished turning around, it will now head back onto the same tile */
1352  Trackdir dir;
1353  uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
1354 
1355  if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RTT_TRAM, true))) {
1356  /*
1357  * The tram is turning around with one tram 'roadbit'. This means that
1358  * it is using the 'big' corner 'drive data'. However, to support the
1359  * trams to take a small corner, there is a 'turned' marker in the middle
1360  * of the turning 'drive data'. When the tram took the long corner, we
1361  * will still use the 'big' corner drive data, but we advance it one
1362  * frame. We furthermore set the driving direction so the turning is
1363  * going to be properly shown.
1364  */
1365  turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
1366  switch (rd.x & 0x3) {
1367  default: NOT_REACHED();
1368  case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
1369  case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
1370  case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
1371  case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
1372  }
1373  } else {
1374  if (v->IsFrontEngine()) {
1375  /* If this is the front engine, look for the right path. */
1376  dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
1377  } else {
1378  dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
1379  }
1380  }
1381 
1382  if (dir == INVALID_TRACKDIR) {
1383  v->cur_speed = 0;
1384  return false;
1385  }
1386 
1387  const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
1388 
1389  int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
1390  int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
1391 
1392  Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1393  if (v->IsFrontEngine()) {
1394  const Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1395  if (u != nullptr) {
1396  v->cur_speed = u->First()->cur_speed;
1397  /* We might be blocked, prevent pathfinding rerun as we already know where we are heading to. */
1398  v->path.emplace_back(dir, v->tile);
1399  return false;
1400  }
1401  }
1402 
1403  uint32_t r = VehicleEnterTile(v, v->tile, x, y);
1404  if (HasBit(r, VETS_CANNOT_ENTER)) {
1405  v->cur_speed = 0;
1406  return false;
1407  }
1408 
1409  v->state = dir;
1410  v->frame = turn_around_start_frame;
1411 
1412  if (new_dir != v->direction) {
1413  v->direction = new_dir;
1414  if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1415  }
1416 
1417  v->x_pos = x;
1418  v->y_pos = y;
1419  v->UpdatePosition();
1420  RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
1421  return true;
1422  }
1423 
1424  /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
1425  * it's on a depot tile, check if it's time to activate the next vehicle in
1426  * the chain yet. */
1427  if (v->Next() != nullptr && IsRoadDepotTile(v->tile)) {
1428  if (v->frame == v->gcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
1429  RoadVehLeaveDepot(v->Next(), false);
1430  }
1431  }
1432 
1433  /* Calculate new position for the vehicle */
1434  int x = (v->x_pos & ~15) + (rd.x & 15);
1435  int y = (v->y_pos & ~15) + (rd.y & 15);
1436 
1437  Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1438 
1439  if (v->IsFrontEngine() && !IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
1440  /* Vehicle is not in a road stop.
1441  * Check for another vehicle to overtake */
1442  RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1443 
1444  if (u != nullptr) {
1445  u = u->First();
1446  /* There is a vehicle in front overtake it if possible */
1447  if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
1448  if (v->overtaking == 0) v->cur_speed = u->cur_speed;
1449 
1450  /* In case an RV is stopped in a road stop, why not try to load? */
1451  if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
1453  v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
1455  Station *st = Station::GetByTile(v->tile);
1456  v->last_station_visited = st->index;
1457  RoadVehArrivesAt(v, st);
1458  v->BeginLoading();
1459  }
1460  return false;
1461  }
1462  }
1463 
1464  Direction old_dir = v->direction;
1465  if (new_dir != old_dir) {
1466  v->direction = new_dir;
1467  if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1468 
1469  /* Delay the vehicle in curves by making it require one additional frame per turning direction (two in total).
1470  * A vehicle has to spend at least 9 frames on a tile, so the following articulated part can follow.
1471  * (The following part may only be one tile behind, and the front part is moved before the following ones.)
1472  * The short (inner) curve has 8 frames, this elongates it to 10. */
1473  v->UpdateViewport(true, true);
1474  return true;
1475  }
1476 
1477  /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
1478  * if the vehicle is in a drive-through road stop and this is the destination station
1479  * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
1480  * (the station test and stop type test ensure that other vehicles, using the road stop as
1481  * a through route, do not stop) */
1482  if (v->IsFrontEngine() && ((IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
1484  (IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
1486  v->owner == GetTileOwner(v->tile) &&
1488  v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
1489 
1491  Station *st = Station::GetByTile(v->tile);
1492 
1493  /* Vehicle is at the stop position (at a bay) in a road stop.
1494  * Note, if vehicle is loading/unloading it has already been handled,
1495  * so if we get here the vehicle has just arrived or is just ready to leave. */
1496  if (!HasBit(v->state, RVS_ENTERED_STOP)) {
1497  /* Vehicle has arrived at a bay in a road stop */
1498 
1499  if (IsDriveThroughStopTile(v->tile)) {
1500  TileIndex next_tile = TileAddByDir(v->tile, v->direction);
1501 
1502  /* Check if next inline bay is free and has compatible road. */
1504  v->frame++;
1505  v->x_pos = x;
1506  v->y_pos = y;
1507  v->UpdatePosition();
1508  RoadZPosAffectSpeed(v, v->UpdateInclination(true, false));
1509  return true;
1510  }
1511  }
1512 
1513  rs->SetEntranceBusy(false);
1515 
1516  v->last_station_visited = st->index;
1517 
1518  if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
1519  RoadVehArrivesAt(v, st);
1520  v->BeginLoading();
1521  return false;
1522  }
1523  } else {
1524  /* Vehicle is ready to leave a bay in a road stop */
1525  if (rs->IsEntranceBusy()) {
1526  /* Road stop entrance is busy, so wait as there is nowhere else to go */
1527  v->cur_speed = 0;
1528  return false;
1529  }
1530  if (v->current_order.IsType(OT_LEAVESTATION)) v->current_order.Free();
1531  }
1532 
1533  if (IsBayRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
1534 
1535  StartRoadVehSound(v);
1537  }
1538 
1539  /* Check tile position conditions - i.e. stop position in depot,
1540  * entry onto bridge or into tunnel */
1541  uint32_t r = VehicleEnterTile(v, v->tile, x, y);
1542  if (HasBit(r, VETS_CANNOT_ENTER)) {
1543  v->cur_speed = 0;
1544  return false;
1545  }
1546 
1547  if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
1548  v->current_order.Free();
1549  }
1550 
1551  /* Move to next frame unless vehicle arrived at a stop position
1552  * in a depot or entered a tunnel/bridge */
1553  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
1554  v->x_pos = x;
1555  v->y_pos = y;
1556  v->UpdatePosition();
1557  RoadZPosAffectSpeed(v, v->UpdateInclination(false, true));
1558  return true;
1559 }
1560 
1561 static bool RoadVehController(RoadVehicle *v)
1562 {
1563  /* decrease counters */
1564  v->current_order_time++;
1565  if (v->reverse_ctr != 0) v->reverse_ctr--;
1566 
1567  /* handle crashed */
1568  if (v->vehstatus & VS_CRASHED || RoadVehCheckTrainCrash(v)) {
1569  return RoadVehIsCrashed(v);
1570  }
1571 
1572  /* road vehicle has broken down? */
1573  if (v->HandleBreakdown()) return true;
1574  if (v->vehstatus & VS_STOPPED) {
1575  v->SetLastSpeed();
1576  return true;
1577  }
1578 
1579  ProcessOrders(v);
1580  v->HandleLoading();
1581 
1582  if (v->current_order.IsType(OT_LOADING)) return true;
1583 
1584  if (v->IsInDepot()) {
1585  /* Check if we should wait here for unbunching. */
1586  if (v->IsWaitingForUnbunching()) return true;
1587  if (RoadVehLeaveDepot(v, true)) return true;
1588  }
1589 
1590  v->ShowVisualEffect();
1591 
1592  /* Check how far the vehicle needs to proceed */
1593  int j = v->UpdateSpeed();
1594 
1595  int adv_spd = v->GetAdvanceDistance();
1596  bool blocked = false;
1597  while (j >= adv_spd) {
1598  j -= adv_spd;
1599 
1600  RoadVehicle *u = v;
1601  for (RoadVehicle *prev = nullptr; u != nullptr; prev = u, u = u->Next()) {
1602  if (!IndividualRoadVehicleController(u, prev)) {
1603  blocked = true;
1604  break;
1605  }
1606  }
1607  if (blocked) break;
1608 
1609  /* Determine distance to next map position */
1610  adv_spd = v->GetAdvanceDistance();
1611 
1612  /* Test for a collision, but only if another movement will occur. */
1613  if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
1614  }
1615 
1616  v->SetLastSpeed();
1617 
1618  for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
1619  if ((u->vehstatus & VS_HIDDEN) != 0) continue;
1620 
1621  u->UpdateViewport(false, false);
1622  }
1623 
1624  /* If movement is blocked, set 'progress' to its maximum, so the roadvehicle does
1625  * not accelerate again before it can actually move. I.e. make sure it tries to advance again
1626  * on next tick to discover whether it is still blocked. */
1627  if (v->progress == 0) v->progress = blocked ? adv_spd - 1 : j;
1628 
1629  return true;
1630 }
1631 
1633 {
1634  const Engine *e = this->GetEngine();
1635  if (e->u.road.running_cost_class == INVALID_PRICE) return 0;
1636 
1637  uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->u.road.running_cost);
1638  if (cost_factor == 0) return 0;
1639 
1640  return GetPrice(e->u.road.running_cost_class, cost_factor, e->GetGRF());
1641 }
1642 
1644 {
1646 
1647  this->tick_counter++;
1648 
1649  if (this->IsFrontEngine()) {
1650  if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
1651  return RoadVehController(this);
1652  }
1653 
1654  return true;
1655 }
1656 
1657 void RoadVehicle::SetDestTile(TileIndex tile)
1658 {
1659  if (tile == this->dest_tile) return;
1660  this->path.clear();
1661  this->dest_tile = tile;
1662 }
1663 
1664 static void CheckIfRoadVehNeedsService(RoadVehicle *v)
1665 {
1666  /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
1667  if (Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
1668  if (v->IsChainInDepot()) {
1670  return;
1671  }
1672 
1674 
1675  FindDepotData rfdd = FindClosestRoadDepot(v, max_penalty);
1676  /* Only go to the depot if it is not too far out of our way. */
1677  if (rfdd.best_length == UINT_MAX || rfdd.best_length > max_penalty) {
1678  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1679  /* If we were already heading for a depot but it has
1680  * suddenly moved farther away, we continue our normal
1681  * schedule? */
1682  v->current_order.MakeDummy();
1684  }
1685  return;
1686  }
1687 
1688  DepotID depot = GetDepotIndex(rfdd.tile);
1689 
1690  if (v->current_order.IsType(OT_GOTO_DEPOT) &&
1692  !Chance16(1, 20)) {
1693  return;
1694  }
1695 
1698  v->SetDestTile(rfdd.tile);
1700 }
1701 
1704 {
1705  if (!this->IsFrontEngine()) return;
1706  AgeVehicle(this);
1707 }
1708 
1711 {
1712  if (!this->IsFrontEngine()) return;
1713  EconomyAgeVehicle(this);
1714 
1715  if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
1716  if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
1717 
1718  CheckIfRoadVehNeedsService(this);
1719 
1720  CheckOrders(this);
1721 
1722  if (this->running_ticks == 0) return;
1723 
1725 
1726  this->profit_this_year -= cost.GetCost();
1727  this->running_ticks = 0;
1728 
1729  SubtractMoneyFromCompanyFract(this->owner, cost);
1730 
1733 }
1734 
1736 {
1737  if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
1738 
1739  if (this->IsInDepot()) {
1740  /* We'll assume the road vehicle is facing outwards */
1741  return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
1742  }
1743 
1744  if (IsBayRoadStopTile(this->tile)) {
1745  /* We'll assume the road vehicle is facing outwards */
1746  return DiagDirToDiagTrackdir(GetBayRoadStopDir(this->tile)); // Road vehicle in a station
1747  }
1748 
1749  /* Drive through road stops / wormholes (tunnels) */
1750  if (this->state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
1751 
1752  /* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
1753  * otherwise transform it into a valid track direction */
1754  return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
1755 }
1756 
1758 {
1759  uint16_t weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnits(this->GetEngine()->DetermineCapacity(this));
1760 
1761  /* Vehicle weight is not added for articulated parts. */
1762  if (!this->IsArticulatedPart()) {
1763  /* Road vehicle weight is in units of 1/4 t. */
1764  weight += GetVehicleProperty(this, PROP_ROADVEH_WEIGHT, RoadVehInfo(this->engine_type)->weight) / 4;
1765  }
1766 
1767  return weight;
1768 }
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:210
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:188
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:164
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:100
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:48
uint8_t original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition: engine_base.h:59
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:171
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:47
uint8_t flags
Flags of the engine.
Definition: engine_base.h:55
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:98
uint Crash(bool flooded=false) override
Crash the (whole) vehicle chain.
void OnNewEconomyDay() override
Economy day handler.
uint8_t state
Definition: roadveh.h:100
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:122
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:110
AccelStatus GetAccelerationStatus() const
Checks the current acceleration status of this vehicle.
Definition: roadveh.h:223
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:105
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:104
void OnNewCalendarDay() override
Calandar day handler.
bool IsInDepot() const override
Check whether the vehicle is in the depot.
Definition: roadveh.h:128
RoadVehPathCache path
Cached path.
Definition: roadveh.h:99
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:108
uint8_t overtaking
Set to RVSB_DRIVE_SIDE when overtaking, otherwise 0.
Definition: roadveh.h:103
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:529
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:538
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