OpenTTD
train_cmd.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "error.h"
14 #include "articulated_vehicles.h"
15 #include "command_func.h"
17 #include "pathfinder/yapf/yapf.hpp"
18 #include "news_func.h"
19 #include "company_func.h"
20 #include "newgrf_sound.h"
21 #include "newgrf_text.h"
22 #include "strings_func.h"
23 #include "viewport_func.h"
24 #include "vehicle_func.h"
25 #include "sound_func.h"
26 #include "ai/ai.hpp"
27 #include "game/game.hpp"
28 #include "newgrf_station.h"
29 #include "effectvehicle_func.h"
30 #include "network/network.h"
31 #include "spritecache.h"
32 #include "core/random_func.hpp"
33 #include "company_base.h"
34 #include "newgrf.h"
35 #include "order_backup.h"
36 #include "zoom_func.h"
37 #include "newgrf_debug.h"
38 #include "framerate_type.h"
39 
40 #include "table/strings.h"
41 #include "table/train_cmd.h"
42 
43 #include "safeguards.h"
44 
45 static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
46 static bool TrainCheckIfLineEnds(Train *v, bool reverse = true);
47 bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // Also used in vehicle_sl.cpp.
49 static void CheckIfTrainNeedsService(Train *v);
50 static void CheckNextTrainTile(Train *v);
51 
52 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8};
53 static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
54 
55 template <>
56 bool IsValidImageIndex<VEH_TRAIN>(uint8 image_index)
57 {
58  return image_index < lengthof(_engine_sprite_base);
59 }
60 
61 
68 {
69  if (!CargoSpec::Get(cargo)->is_freight) return 1;
71 }
72 
75 {
76  const Train *v;
77  bool first = true;
78 
79  FOR_ALL_TRAINS(v) {
80  if (v->First() == v && !(v->vehstatus & VS_CRASHED)) {
81  for (const Train *u = v, *w = v->Next(); w != nullptr; u = w, w = w->Next()) {
82  if (u->track != TRACK_BIT_DEPOT) {
83  if ((w->track != TRACK_BIT_DEPOT &&
84  max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->CalcNextVehicleOffset()) ||
85  (w->track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) {
86  SetDParam(0, v->index);
87  SetDParam(1, v->owner);
88  ShowErrorMessage(STR_BROKEN_VEHICLE_LENGTH, INVALID_STRING_ID, WL_CRITICAL);
89 
90  if (!_networking && first) {
91  first = false;
93  }
94  /* Break so we warn only once for each train. */
95  break;
96  }
97  }
98  }
99  }
100  }
101 }
102 
110 {
111  uint16 max_speed = UINT16_MAX;
112 
113  assert(this->IsFrontEngine() || this->IsFreeWagon());
114 
115  const RailVehicleInfo *rvi_v = RailVehInfo(this->engine_type);
116  EngineID first_engine = this->IsFrontEngine() ? this->engine_type : INVALID_ENGINE;
117  this->gcache.cached_total_length = 0;
118  this->compatible_railtypes = RAILTYPES_NONE;
119 
120  bool train_can_tilt = true;
121 
122  for (Train *u = this; u != nullptr; u = u->Next()) {
123  const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
124 
125  /* Check the this->first cache. */
126  assert(u->First() == this);
127 
128  /* update the 'first engine' */
129  u->gcache.first_engine = this == u ? INVALID_ENGINE : first_engine;
130  u->railtype = rvi_u->railtype;
131 
132  if (u->IsEngine()) first_engine = u->engine_type;
133 
134  /* Set user defined data to its default value */
135  u->tcache.user_def_data = rvi_u->user_def_data;
136  this->InvalidateNewGRFCache();
137  u->InvalidateNewGRFCache();
138  }
139 
140  for (Train *u = this; u != nullptr; u = u->Next()) {
141  /* Update user defined data (must be done before other properties) */
142  u->tcache.user_def_data = GetVehicleProperty(u, PROP_TRAIN_USER_DATA, u->tcache.user_def_data);
143  this->InvalidateNewGRFCache();
144  u->InvalidateNewGRFCache();
145  }
146 
147  for (Train *u = this; u != nullptr; u = u->Next()) {
148  const Engine *e_u = u->GetEngine();
149  const RailVehicleInfo *rvi_u = &e_u->u.rail;
150 
151  if (!HasBit(e_u->info.misc_flags, EF_RAIL_TILTS)) train_can_tilt = false;
152 
153  /* Cache wagon override sprite group. nullptr is returned if there is none */
154  u->tcache.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->gcache.first_engine);
155 
156  /* Reset colour map */
157  u->colourmap = PAL_NONE;
158 
159  /* Update powered-wagon-status and visual effect */
160  u->UpdateVisualEffect(true);
161 
162  if (rvi_v->pow_wag_power != 0 && rvi_u->railveh_type == RAILVEH_WAGON &&
163  UsesWagonOverride(u) && !HasBit(u->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
164  /* wagon is powered */
165  SetBit(u->flags, VRF_POWEREDWAGON); // cache 'powered' status
166  } else {
167  ClrBit(u->flags, VRF_POWEREDWAGON);
168  }
169 
170  if (!u->IsArticulatedPart()) {
171  /* Do not count powered wagons for the compatible railtypes, as wagons always
172  have railtype normal */
173  if (rvi_u->power > 0) {
174  this->compatible_railtypes |= GetRailTypeInfo(u->railtype)->powered_railtypes;
175  }
176 
177  /* Some electric engines can be allowed to run on normal rail. It happens to all
178  * existing electric engines when elrails are disabled and then re-enabled */
179  if (HasBit(u->flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
180  u->railtype = RAILTYPE_RAIL;
181  u->compatible_railtypes |= RAILTYPES_RAIL;
182  }
183 
184  /* max speed is the minimum of the speed limits of all vehicles in the consist */
185  if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings_game.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) {
186  uint16 speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed);
187  if (speed != 0) max_speed = min(speed, max_speed);
188  }
189  }
190 
191  uint16 new_cap = e_u->DetermineCapacity(u);
192  if (allowed_changes & CCF_CAPACITY) {
193  /* Update vehicle capacity. */
194  if (u->cargo_cap > new_cap) u->cargo.Truncate(new_cap);
195  u->refit_cap = min(new_cap, u->refit_cap);
196  u->cargo_cap = new_cap;
197  } else {
198  /* Verify capacity hasn't changed. */
199  if (new_cap != u->cargo_cap) ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_CAPACITY, GBUG_VEH_CAPACITY, true);
200  }
201  u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_TRAIN_CARGO_AGE_PERIOD, e_u->info.cargo_age_period);
202 
203  /* check the vehicle length (callback) */
204  uint16 veh_len = CALLBACK_FAILED;
205  if (e_u->GetGRF() != nullptr && e_u->GetGRF()->grf_version >= 8) {
206  /* Use callback 36 */
207  veh_len = GetVehicleProperty(u, PROP_TRAIN_SHORTEN_FACTOR, CALLBACK_FAILED);
208 
209  if (veh_len != CALLBACK_FAILED && veh_len >= VEHICLE_LENGTH) {
211  }
212  } else if (HasBit(e_u->info.callback_mask, CBM_VEHICLE_LENGTH)) {
213  /* Use callback 11 */
214  veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
215  }
216  if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
217  veh_len = VEHICLE_LENGTH - Clamp(veh_len, 0, VEHICLE_LENGTH - 1);
218 
219  if (allowed_changes & CCF_LENGTH) {
220  /* Update vehicle length. */
221  u->gcache.cached_veh_length = veh_len;
222  } else {
223  /* Verify length hasn't changed. */
224  if (veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
225  }
226 
227  this->gcache.cached_total_length += u->gcache.cached_veh_length;
228  this->InvalidateNewGRFCache();
229  u->InvalidateNewGRFCache();
230  }
231 
232  /* store consist weight/max speed in cache */
233  this->vcache.cached_max_speed = max_speed;
234  this->tcache.cached_tilt = train_can_tilt;
235  this->tcache.cached_max_curve_speed = this->GetCurveSpeedLimit();
236 
237  /* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
238  this->CargoChanged();
239 
240  if (this->IsFrontEngine()) {
241  this->UpdateAcceleration();
245  InvalidateNewGRFInspectWindow(GSF_TRAINS, this->index);
246  }
247 }
248 
259 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length)
260 {
261  const Station *st = Station::Get(station_id);
262  *station_ahead = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE;
263  *station_length = st->GetPlatformLength(tile) * TILE_SIZE;
264 
265  /* Default to the middle of the station for stations stops that are not in
266  * the order list like intermediate stations when non-stop is disabled */
268  if (v->gcache.cached_total_length >= *station_length) {
269  /* The train is longer than the station, make it stop at the far end of the platform */
270  osl = OSL_PLATFORM_FAR_END;
271  } else if (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == station_id) {
272  osl = v->current_order.GetStopLocation();
273  }
274 
275  /* The stop location of the FRONT! of the train */
276  int stop;
277  switch (osl) {
278  default: NOT_REACHED();
279 
281  stop = v->gcache.cached_total_length;
282  break;
283 
284  case OSL_PLATFORM_MIDDLE:
285  stop = *station_length - (*station_length - v->gcache.cached_total_length) / 2;
286  break;
287 
289  stop = *station_length;
290  break;
291  }
292 
293  /* Subtract half the front vehicle length of the train so we get the real
294  * stop location of the train. */
295  return stop - (v->gcache.cached_veh_length + 1) / 2;
296 }
297 
298 
304 {
305  assert(this->First() == this);
306 
307  static const int absolute_max_speed = UINT16_MAX;
308  int max_speed = absolute_max_speed;
309 
310  if (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) return max_speed;
311 
312  int curvecount[2] = {0, 0};
313 
314  /* first find the curve speed limit */
315  int numcurve = 0;
316  int sum = 0;
317  int pos = 0;
318  int lastpos = -1;
319  for (const Vehicle *u = this; u->Next() != nullptr; u = u->Next(), pos++) {
320  Direction this_dir = u->direction;
321  Direction next_dir = u->Next()->direction;
322 
323  DirDiff dirdiff = DirDifference(this_dir, next_dir);
324  if (dirdiff == DIRDIFF_SAME) continue;
325 
326  if (dirdiff == DIRDIFF_45LEFT) curvecount[0]++;
327  if (dirdiff == DIRDIFF_45RIGHT) curvecount[1]++;
328  if (dirdiff == DIRDIFF_45LEFT || dirdiff == DIRDIFF_45RIGHT) {
329  if (lastpos != -1) {
330  numcurve++;
331  sum += pos - lastpos;
332  if (pos - lastpos == 1 && max_speed > 88) {
333  max_speed = 88;
334  }
335  }
336  lastpos = pos;
337  }
338 
339  /* if we have a 90 degree turn, fix the speed limit to 60 */
340  if (dirdiff == DIRDIFF_90LEFT || dirdiff == DIRDIFF_90RIGHT) {
341  max_speed = 61;
342  }
343  }
344 
345  if (numcurve > 0 && max_speed > 88) {
346  if (curvecount[0] == 1 && curvecount[1] == 1) {
347  max_speed = absolute_max_speed;
348  } else {
349  sum /= numcurve;
350  max_speed = 232 - (13 - Clamp(sum, 1, 12)) * (13 - Clamp(sum, 1, 12));
351  }
352  }
353 
354  if (max_speed != absolute_max_speed) {
355  /* Apply the engine's rail type curve speed advantage, if it slowed by curves */
356  const RailtypeInfo *rti = GetRailTypeInfo(this->railtype);
357  max_speed += (max_speed / 2) * rti->curve_speed;
358 
359  if (this->tcache.cached_tilt) {
360  /* Apply max_speed bonus of 20% for a tilting train */
361  max_speed += max_speed / 5;
362  }
363  }
364 
365  return max_speed;
366 }
367 
373 {
374  int max_speed = _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ?
376  this->tcache.cached_max_curve_speed;
377 
378  if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && IsRailStationTile(this->tile)) {
379  StationID sid = GetStationIndex(this->tile);
380  if (this->current_order.ShouldStopAtStation(this, sid)) {
381  int station_ahead;
382  int station_length;
383  int stop_at = GetTrainStopLocation(sid, this->tile, this, &station_ahead, &station_length);
384 
385  /* The distance to go is whatever is still ahead of the train minus the
386  * distance from the train's stop location to the end of the platform */
387  int distance_to_go = station_ahead / TILE_SIZE - (station_length - stop_at) / TILE_SIZE;
388 
389  if (distance_to_go > 0) {
390  int st_max_speed = 120;
391 
392  int delta_v = this->cur_speed / (distance_to_go + 1);
393  if (max_speed > (this->cur_speed - delta_v)) {
394  st_max_speed = this->cur_speed - (delta_v / 10);
395  }
396 
397  st_max_speed = max(st_max_speed, 25 * distance_to_go);
398  max_speed = min(max_speed, st_max_speed);
399  }
400  }
401  }
402 
403  for (const Train *u = this; u != nullptr; u = u->Next()) {
404  if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == TRACK_BIT_DEPOT) {
405  max_speed = min(max_speed, 61);
406  break;
407  }
408 
409  /* Vehicle is on the middle part of a bridge. */
410  if (u->track == TRACK_BIT_WORMHOLE && !(u->vehstatus & VS_HIDDEN)) {
411  max_speed = min(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed);
412  }
413  }
414 
415  max_speed = min(max_speed, this->current_order.GetMaxSpeed());
416  return min(max_speed, this->gcache.cached_max_track_speed);
417 }
418 
421 {
422  assert(this->IsFrontEngine() || this->IsFreeWagon());
423 
424  uint power = this->gcache.cached_power;
425  uint weight = this->gcache.cached_weight;
426  assert(weight != 0);
427  this->acceleration = Clamp(power / weight * 4, 1, 255);
428 }
429 
436 {
437  int reference_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
438  int vehicle_pitch = 0;
439 
440  const Engine *e = this->GetEngine();
441  if (e->GetGRF() != nullptr && is_custom_sprite(e->u.rail.image_index)) {
442  reference_width = e->GetGRF()->traininfo_vehicle_width;
443  vehicle_pitch = e->GetGRF()->traininfo_vehicle_pitch;
444  }
445 
446  if (offset != nullptr) {
447  offset->x = ScaleGUITrad(reference_width) / 2;
448  offset->y = ScaleGUITrad(vehicle_pitch);
449  }
450  return ScaleGUITrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
451 }
452 
453 static SpriteID GetDefaultTrainSprite(uint8 spritenum, Direction direction)
454 {
455  assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
456  return ((direction + _engine_sprite_add[spritenum]) & _engine_sprite_and[spritenum]) + _engine_sprite_base[spritenum];
457 }
458 
466 {
467  uint8 spritenum = this->spritenum;
468 
469  if (HasBit(this->flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
470 
471  if (is_custom_sprite(spritenum)) {
472  GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
473  if (result->IsValid()) return;
474 
475  spritenum = this->GetEngine()->original_image_index;
476  }
477 
478  assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
479  SpriteID sprite = GetDefaultTrainSprite(spritenum, direction);
480 
481  if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _wagon_full_adder[spritenum];
482 
483  result->Set(sprite);
484 }
485 
486 static void GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType image_type, VehicleSpriteSeq *result)
487 {
488  const Engine *e = Engine::Get(engine);
489  Direction dir = rear_head ? DIR_E : DIR_W;
490  uint8 spritenum = e->u.rail.image_index;
491 
492  if (is_custom_sprite(spritenum)) {
493  GetCustomVehicleIcon(engine, dir, image_type, result);
494  if (result->IsValid()) {
495  if (e->GetGRF() != nullptr) {
497  }
498  return;
499  }
500 
501  spritenum = Engine::Get(engine)->original_image_index;
502  }
503 
504  if (rear_head) spritenum++;
505 
506  result->Set(GetDefaultTrainSprite(spritenum, DIR_W));
507 }
508 
509 void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
510 {
511  if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
512  int yf = y;
513  int yr = y;
514 
515  VehicleSpriteSeq seqf, seqr;
516  GetRailIcon(engine, false, yf, image_type, &seqf);
517  GetRailIcon(engine, true, yr, image_type, &seqr);
518 
519  Rect rectf, rectr;
520  seqf.GetBounds(&rectf);
521  seqr.GetBounds(&rectr);
522 
523  preferred_x = Clamp(preferred_x,
524  left - UnScaleGUI(rectf.left) + ScaleGUITrad(14),
525  right - UnScaleGUI(rectr.right) - ScaleGUITrad(15));
526 
527  seqf.Draw(preferred_x - ScaleGUITrad(14), yf, pal, pal == PALETTE_CRASH);
528  seqr.Draw(preferred_x + ScaleGUITrad(15), yr, pal, pal == PALETTE_CRASH);
529  } else {
530  VehicleSpriteSeq seq;
531  GetRailIcon(engine, false, y, image_type, &seq);
532 
533  Rect rect;
534  seq.GetBounds(&rect);
535  preferred_x = Clamp(preferred_x,
536  left - UnScaleGUI(rect.left),
537  right - UnScaleGUI(rect.right));
538 
539  seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
540  }
541 }
542 
552 void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
553 {
554  int y = 0;
555 
556  VehicleSpriteSeq seq;
557  GetRailIcon(engine, false, y, image_type, &seq);
558 
559  Rect rect;
560  seq.GetBounds(&rect);
561 
562  width = UnScaleGUI(rect.right - rect.left + 1);
563  height = UnScaleGUI(rect.bottom - rect.top + 1);
564  xoffs = UnScaleGUI(rect.left);
565  yoffs = UnScaleGUI(rect.top);
566 
567  if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
568  GetRailIcon(engine, true, y, image_type, &seq);
569  seq.GetBounds(&rect);
570 
571  /* Calculate values relative to an imaginary center between the two sprites. */
572  width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(rect.right) - xoffs;
573  height = max<uint>(height, UnScaleGUI(rect.bottom - rect.top + 1));
574  xoffs = xoffs - ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
575  yoffs = min(yoffs, UnScaleGUI(rect.top));
576  }
577 }
578 
588 {
589  const RailVehicleInfo *rvi = &e->u.rail;
590 
591  /* Check that the wagon can drive on the track in question */
592  if (!IsCompatibleRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
593 
594  if (flags & DC_EXEC) {
595  Train *v = new Train();
596  *ret = v;
597  v->spritenum = rvi->image_index;
598 
599  v->engine_type = e->index;
600  v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
601 
603 
604  v->direction = DiagDirToDir(dir);
605  v->tile = tile;
606 
607  int x = TileX(tile) * TILE_SIZE | _vehicle_initial_x_fract[dir];
608  int y = TileY(tile) * TILE_SIZE | _vehicle_initial_y_fract[dir];
609 
610  v->x_pos = x;
611  v->y_pos = y;
612  v->z_pos = GetSlopePixelZ(x, y);
613  v->owner = _current_company;
614  v->track = TRACK_BIT_DEPOT;
616 
617  v->SetWagon();
618 
619  v->SetFreeWagon();
621 
623  v->cargo_cap = rvi->capacity;
624  v->refit_cap = 0;
625 
626  v->railtype = rvi->railtype;
627 
629  v->build_year = _cur_year;
630  v->sprite_seq.Set(SPR_IMG_QUERY);
632 
633  v->group_id = DEFAULT_GROUP;
634 
636 
637  _new_vehicle_id = v->index;
638 
639  v->UpdatePosition();
642 
644 
645  /* Try to connect the vehicle to one of free chains of wagons. */
646  Train *w;
647  FOR_ALL_TRAINS(w) {
648  if (w->tile == tile &&
649  w->IsFreeWagon() &&
650  w->engine_type == e->index &&
651  w->First() != v &&
652  !(w->vehstatus & VS_CRASHED)) {
653  DoCommand(0, v->index | 1 << 20, w->Last()->index, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
654  break;
655  }
656  }
657  }
658 
659  return CommandCost();
660 }
661 
663 static void NormalizeTrainVehInDepot(const Train *u)
664 {
665  const Train *v;
666  FOR_ALL_TRAINS(v) {
667  if (v->IsFreeWagon() && v->tile == u->tile &&
668  v->track == TRACK_BIT_DEPOT) {
669  if (DoCommand(0, v->index | 1 << 20, u->index, DC_EXEC,
671  break;
672  }
673  }
674 }
675 
676 static void AddRearEngineToMultiheadedTrain(Train *v)
677 {
678  Train *u = new Train();
679  v->value >>= 1;
680  u->value = v->value;
681  u->direction = v->direction;
682  u->owner = v->owner;
683  u->tile = v->tile;
684  u->x_pos = v->x_pos;
685  u->y_pos = v->y_pos;
686  u->z_pos = v->z_pos;
687  u->track = TRACK_BIT_DEPOT;
688  u->vehstatus = v->vehstatus & ~VS_STOPPED;
689  u->spritenum = v->spritenum + 1;
690  u->cargo_type = v->cargo_type;
692  u->cargo_cap = v->cargo_cap;
693  u->refit_cap = v->refit_cap;
694  u->railtype = v->railtype;
695  u->engine_type = v->engine_type;
697  u->build_year = v->build_year;
698  u->sprite_seq.Set(SPR_IMG_QUERY);
700  v->SetMultiheaded();
701  u->SetMultiheaded();
702  v->SetNext(u);
703  u->UpdatePosition();
704 
705  /* Now we need to link the front and rear engines together */
706  v->other_multiheaded_part = u;
707  u->other_multiheaded_part = v;
708 }
709 
720 {
721  const RailVehicleInfo *rvi = &e->u.rail;
722 
723  if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(tile, flags, e, ret);
724 
725  /* Check if depot and new engine uses the same kind of tracks *
726  * We need to see if the engine got power on the tile to avoid electric engines in non-electric depots */
727  if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
728 
729  if (flags & DC_EXEC) {
731  int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
732  int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
733 
734  Train *v = new Train();
735  *ret = v;
736  v->direction = DiagDirToDir(dir);
737  v->tile = tile;
738  v->owner = _current_company;
739  v->x_pos = x;
740  v->y_pos = y;
741  v->z_pos = GetSlopePixelZ(x, y);
742  v->track = TRACK_BIT_DEPOT;
744  v->spritenum = rvi->image_index;
746  v->cargo_cap = rvi->capacity;
747  v->refit_cap = 0;
748  v->last_station_visited = INVALID_STATION;
749  v->last_loading_station = INVALID_STATION;
750 
751  v->engine_type = e->index;
752  v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
753 
754  v->reliability = e->reliability;
756  v->max_age = e->GetLifeLengthInDays();
757 
758  v->railtype = rvi->railtype;
759  _new_vehicle_id = v->index;
760 
761  v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains);
763  v->build_year = _cur_year;
764  v->sprite_seq.Set(SPR_IMG_QUERY);
766 
768  v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
769 
770  v->group_id = DEFAULT_GROUP;
771 
772  v->SetFrontEngine();
773  v->SetEngine();
774 
775  v->UpdatePosition();
776 
777  if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
778  AddRearEngineToMultiheadedTrain(v);
779  } else {
781  }
782 
785 
786  if (!HasBit(data, 0) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
788  }
789 
791  }
792 
793  return CommandCost();
794 }
795 
796 static Train *FindGoodVehiclePos(const Train *src)
797 {
798  EngineID eng = src->engine_type;
799  TileIndex tile = src->tile;
800 
801  Train *dst;
802  FOR_ALL_TRAINS(dst) {
803  if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED)) {
804  /* check so all vehicles in the line have the same engine. */
805  Train *t = dst;
806  while (t->engine_type == eng) {
807  t = t->Next();
808  if (t == nullptr) return dst;
809  }
810  }
811  }
812 
813  return nullptr;
814 }
815 
817 typedef std::vector<Train *> TrainList;
818 
825 {
826  for (; t != nullptr; t = t->Next()) list.push_back(t);
827 }
828 
834 {
835  /* No train, nothing to do. */
836  if (list.size() == 0) return;
837 
838  Train *prev = nullptr;
839  /* Iterate over the list and rebuild it. */
840  for (Train *t : list) {
841  if (prev != nullptr) {
842  prev->SetNext(t);
843  } else if (t->Previous() != nullptr) {
844  /* Make sure the head of the train is always the first in the chain. */
845  t->Previous()->SetNext(nullptr);
846  }
847  prev = t;
848  }
849 }
850 
856 static void RemoveFromConsist(Train *part, bool chain = false)
857 {
858  Train *tail = chain ? part->Last() : part->GetLastEnginePart();
859 
860  /* Unlink at the front, but make it point to the next
861  * vehicle after the to be remove part. */
862  if (part->Previous() != nullptr) part->Previous()->SetNext(tail->Next());
863 
864  /* Unlink at the back */
865  tail->SetNext(nullptr);
866 }
867 
873 static void InsertInConsist(Train *dst, Train *chain)
874 {
875  /* We do not want to add something in the middle of an articulated part. */
876  assert(dst != nullptr && (dst->Next() == nullptr || !dst->Next()->IsArticulatedPart()));
877 
878  chain->Last()->SetNext(dst->Next());
879  dst->SetNext(chain);
880 }
881 
887 static void NormaliseDualHeads(Train *t)
888 {
889  for (; t != nullptr; t = t->GetNextVehicle()) {
890  if (!t->IsMultiheaded() || !t->IsEngine()) continue;
891 
892  /* Make sure that there are no free cars before next engine */
893  Train *u;
894  for (u = t; u->Next() != nullptr && !u->Next()->IsEngine(); u = u->Next()) {}
895 
896  if (u == t->other_multiheaded_part) continue;
897 
898  /* Remove the part from the 'wrong' train */
899  RemoveFromConsist(t->other_multiheaded_part);
900  /* And add it to the 'right' train */
901  InsertInConsist(u, t->other_multiheaded_part);
902  }
903 }
904 
909 static void NormaliseSubtypes(Train *chain)
910 {
911  /* Nothing to do */
912  if (chain == nullptr) return;
913 
914  /* We must be the first in the chain. */
915  assert(chain->Previous() == nullptr);
916 
917  /* Set the appropriate bits for the first in the chain. */
918  if (chain->IsWagon()) {
919  chain->SetFreeWagon();
920  } else {
921  assert(chain->IsEngine());
922  chain->SetFrontEngine();
923  }
924 
925  /* Now clear the bits for the rest of the chain */
926  for (Train *t = chain->Next(); t != nullptr; t = t->Next()) {
927  t->ClearFreeWagon();
928  t->ClearFrontEngine();
929  }
930 }
931 
941 static CommandCost CheckNewTrain(Train *original_dst, Train *dst, Train *original_src, Train *src)
942 {
943  /* Just add 'new' engines and subtract the original ones.
944  * If that's less than or equal to 0 we can be sure we did
945  * not add any engines (read: trains) along the way. */
946  if ((src != nullptr && src->IsEngine() ? 1 : 0) +
947  (dst != nullptr && dst->IsEngine() ? 1 : 0) -
948  (original_src != nullptr && original_src->IsEngine() ? 1 : 0) -
949  (original_dst != nullptr && original_dst->IsEngine() ? 1 : 0) <= 0) {
950  return CommandCost();
951  }
952 
953  /* Get a free unit number and check whether it's within the bounds.
954  * There will always be a maximum of one new train. */
956 
957  return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
958 }
959 
966 {
967  /* No multi-part train, no need to check. */
968  if (t == nullptr || t->Next() == nullptr || !t->IsEngine()) return CommandCost();
969 
970  /* The maximum length for a train. For each part we decrease this by one
971  * and if the result is negative the train is simply too long. */
973 
974  Train *head = t;
975  Train *prev = t;
976 
977  /* Break the prev -> t link so it always holds within the loop. */
978  t = t->Next();
979  prev->SetNext(nullptr);
980 
981  /* Make sure the cache is cleared. */
982  head->InvalidateNewGRFCache();
983 
984  while (t != nullptr) {
985  allowed_len -= t->gcache.cached_veh_length;
986 
987  Train *next = t->Next();
988 
989  /* Unlink the to-be-added piece; it is already unlinked from the previous
990  * part due to the fact that the prev -> t link is broken. */
991  t->SetNext(nullptr);
992 
993  /* Don't check callback for articulated or rear dual headed parts */
994  if (!t->IsArticulatedPart() && !t->IsRearDualheaded()) {
995  /* Back up and clear the first_engine data to avoid using wagon override group */
996  EngineID first_engine = t->gcache.first_engine;
998 
999  /* We don't want the cache to interfere. head's cache is cleared before
1000  * the loop and after each callback does not need to be cleared here. */
1001  t->InvalidateNewGRFCache();
1002 
1003  uint16 callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, head->engine_type, t, head);
1004 
1005  /* Restore original first_engine data */
1006  t->gcache.first_engine = first_engine;
1007 
1008  /* We do not want to remember any cached variables from the test run */
1009  t->InvalidateNewGRFCache();
1010  head->InvalidateNewGRFCache();
1011 
1012  if (callback != CALLBACK_FAILED) {
1013  /* A failing callback means everything is okay */
1014  StringID error = STR_NULL;
1015 
1016  if (head->GetGRF()->grf_version < 8) {
1017  if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1018  if (callback < 0xFD) error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback);
1019  if (callback >= 0x100) ErrorUnknownCallbackResult(head->GetGRFID(), CBID_TRAIN_ALLOW_WAGON_ATTACH, callback);
1020  } else {
1021  if (callback < 0x400) {
1022  error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback);
1023  } else {
1024  switch (callback) {
1025  case 0x400: // allow if railtypes match (always the case for OpenTTD)
1026  case 0x401: // allow
1027  break;
1028 
1029  default: // unknown reason -> disallow
1030  case 0x402: // disallow attaching
1031  error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1032  break;
1033  }
1034  }
1035  }
1036 
1037  if (error != STR_NULL) return_cmd_error(error);
1038  }
1039  }
1040 
1041  /* And link it to the new part. */
1042  prev->SetNext(t);
1043  prev = t;
1044  t = next;
1045  }
1046 
1047  if (allowed_len < 0) return_cmd_error(STR_ERROR_TRAIN_TOO_LONG);
1048  return CommandCost();
1049 }
1050 
1061 static CommandCost ValidateTrains(Train *original_dst, Train *dst, Train *original_src, Train *src, bool check_limit)
1062 {
1063  /* Check whether we may actually construct the trains. */
1064  CommandCost ret = CheckTrainAttachment(src);
1065  if (ret.Failed()) return ret;
1066  ret = CheckTrainAttachment(dst);
1067  if (ret.Failed()) return ret;
1068 
1069  /* Check whether we need to build a new train. */
1070  return check_limit ? CheckNewTrain(original_dst, dst, original_src, src) : CommandCost();
1071 }
1072 
1081 static void ArrangeTrains(Train **dst_head, Train *dst, Train **src_head, Train *src, bool move_chain)
1082 {
1083  /* First determine the front of the two resulting trains */
1084  if (*src_head == *dst_head) {
1085  /* If we aren't moving part(s) to a new train, we are just moving the
1086  * front back and there is not destination head. */
1087  *dst_head = nullptr;
1088  } else if (*dst_head == nullptr) {
1089  /* If we are moving to a new train the head of the move train would become
1090  * the head of the new vehicle. */
1091  *dst_head = src;
1092  }
1093 
1094  if (src == *src_head) {
1095  /* If we are moving the front of a train then we are, in effect, creating
1096  * a new head for the train. Point to that. Unless we are moving the whole
1097  * train in which case there is not 'source' train anymore.
1098  * In case we are a multiheaded part we want the complete thing to come
1099  * with us, so src->GetNextUnit(), however... when we are e.g. a wagon
1100  * that is followed by a rear multihead we do not want to include that. */
1101  *src_head = move_chain ? nullptr :
1102  (src->IsMultiheaded() ? src->GetNextUnit() : src->GetNextVehicle());
1103  }
1104 
1105  /* Now it's just simply removing the part that we are going to move from the
1106  * source train and *if* the destination is a not a new train add the chain
1107  * at the destination location. */
1108  RemoveFromConsist(src, move_chain);
1109  if (*dst_head != src) InsertInConsist(dst, src);
1110 
1111  /* Now normalise the dual heads, that is move the dual heads around in such
1112  * a way that the head and rear of a dual head are in the same train */
1113  NormaliseDualHeads(*src_head);
1114  NormaliseDualHeads(*dst_head);
1115 }
1116 
1122 static void NormaliseTrainHead(Train *head)
1123 {
1124  /* Not much to do! */
1125  if (head == nullptr) return;
1126 
1127  /* Tell the 'world' the train changed. */
1128  head->ConsistChanged(CCF_ARRANGE);
1129  UpdateTrainGroupID(head);
1130 
1131  /* Not a front engine, i.e. a free wagon chain. No need to do more. */
1132  if (!head->IsFrontEngine()) return;
1133 
1134  /* Update the refit button and window */
1137 
1138  /* If we don't have a unit number yet, set one. */
1139  if (head->unitnumber != 0) return;
1141 }
1142 
1155 CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1156 {
1157  VehicleID s = GB(p1, 0, 20);
1158  VehicleID d = GB(p2, 0, 20);
1159  bool move_chain = HasBit(p1, 20);
1160 
1161  Train *src = Train::GetIfValid(s);
1162  if (src == nullptr) return CMD_ERROR;
1163 
1164  CommandCost ret = CheckOwnership(src->owner);
1165  if (ret.Failed()) return ret;
1166 
1167  /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */
1168  if (src->vehstatus & VS_CRASHED) return CMD_ERROR;
1169 
1170  /* if nothing is selected as destination, try and find a matching vehicle to drag to. */
1171  Train *dst;
1172  if (d == INVALID_VEHICLE) {
1173  dst = src->IsEngine() ? nullptr : FindGoodVehiclePos(src);
1174  } else {
1175  dst = Train::GetIfValid(d);
1176  if (dst == nullptr) return CMD_ERROR;
1177 
1178  CommandCost ret = CheckOwnership(dst->owner);
1179  if (ret.Failed()) return ret;
1180 
1181  /* Do not allow appending to crashed vehicles, too */
1182  if (dst->vehstatus & VS_CRASHED) return CMD_ERROR;
1183  }
1184 
1185  /* if an articulated part is being handled, deal with its parent vehicle */
1186  src = src->GetFirstEnginePart();
1187  if (dst != nullptr) {
1188  dst = dst->GetFirstEnginePart();
1189  }
1190 
1191  /* don't move the same vehicle.. */
1192  if (src == dst) return CommandCost();
1193 
1194  /* locate the head of the two chains */
1195  Train *src_head = src->First();
1196  Train *dst_head;
1197  if (dst != nullptr) {
1198  dst_head = dst->First();
1199  if (dst_head->tile != src_head->tile) return CMD_ERROR;
1200  /* Now deal with articulated part of destination wagon */
1201  dst = dst->GetLastEnginePart();
1202  } else {
1203  dst_head = nullptr;
1204  }
1205 
1206  if (src->IsRearDualheaded()) return_cmd_error(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT);
1207 
1208  /* When moving all wagons, we can't have the same src_head and dst_head */
1209  if (move_chain && src_head == dst_head) return CommandCost();
1210 
1211  /* When moving a multiheaded part to be place after itself, bail out. */
1212  if (!move_chain && dst != nullptr && dst->IsRearDualheaded() && src == dst->other_multiheaded_part) return CommandCost();
1213 
1214  /* Check if all vehicles in the source train are stopped inside a depot. */
1215  if (!src_head->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1216 
1217  /* Check if all vehicles in the destination train are stopped inside a depot. */
1218  if (dst_head != nullptr && !dst_head->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1219 
1220  /* First make a backup of the order of the trains. That way we can do
1221  * whatever we want with the order and later on easily revert. */
1222  TrainList original_src;
1223  TrainList original_dst;
1224 
1225  MakeTrainBackup(original_src, src_head);
1226  MakeTrainBackup(original_dst, dst_head);
1227 
1228  /* Also make backup of the original heads as ArrangeTrains can change them.
1229  * For the destination head we do not care if it is the same as the source
1230  * head because in that case it's just a copy. */
1231  Train *original_src_head = src_head;
1232  Train *original_dst_head = (dst_head == src_head ? nullptr : dst_head);
1233 
1234  /* We want this information from before the rearrangement, but execute this after the validation.
1235  * original_src_head can't be nullptr; src is by definition != nullptr, so src_head can't be nullptr as
1236  * src->GetFirst() always yields non-nullptr, so eventually original_src_head != nullptr as well. */
1237  bool original_src_head_front_engine = original_src_head->IsFrontEngine();
1238  bool original_dst_head_front_engine = original_dst_head != nullptr && original_dst_head->IsFrontEngine();
1239 
1240  /* (Re)arrange the trains in the wanted arrangement. */
1241  ArrangeTrains(&dst_head, dst, &src_head, src, move_chain);
1242 
1243  if ((flags & DC_AUTOREPLACE) == 0) {
1244  /* If the autoreplace flag is set we do not need to test for the validity
1245  * because we are going to revert the train to its original state. As we
1246  * assume the original state was correct autoreplace can skip this. */
1247  CommandCost ret = ValidateTrains(original_dst_head, dst_head, original_src_head, src_head, true);
1248  if (ret.Failed()) {
1249  /* Restore the train we had. */
1250  RestoreTrainBackup(original_src);
1251  RestoreTrainBackup(original_dst);
1252  return ret;
1253  }
1254  }
1255 
1256  /* do it? */
1257  if (flags & DC_EXEC) {
1258  /* Remove old heads from the statistics */
1259  if (original_src_head_front_engine) GroupStatistics::CountVehicle(original_src_head, -1);
1260  if (original_dst_head_front_engine) GroupStatistics::CountVehicle(original_dst_head, -1);
1261 
1262  /* First normalise the sub types of the chains. */
1263  NormaliseSubtypes(src_head);
1264  NormaliseSubtypes(dst_head);
1265 
1266  /* There are 14 different cases:
1267  * 1) front engine gets moved to a new train, it stays a front engine.
1268  * a) the 'next' part is a wagon that becomes a free wagon chain.
1269  * b) the 'next' part is an engine that becomes a front engine.
1270  * c) there is no 'next' part, nothing else happens
1271  * 2) front engine gets moved to another train, it is not a front engine anymore
1272  * a) the 'next' part is a wagon that becomes a free wagon chain.
1273  * b) the 'next' part is an engine that becomes a front engine.
1274  * c) there is no 'next' part, nothing else happens
1275  * 3) front engine gets moved to later in the current train, it is not a front engine anymore.
1276  * a) the 'next' part is a wagon that becomes a free wagon chain.
1277  * b) the 'next' part is an engine that becomes a front engine.
1278  * 4) free wagon gets moved
1279  * a) the 'next' part is a wagon that becomes a free wagon chain.
1280  * b) the 'next' part is an engine that becomes a front engine.
1281  * c) there is no 'next' part, nothing else happens
1282  * 5) non front engine gets moved and becomes a new train, nothing else happens
1283  * 6) non front engine gets moved within a train / to another train, nothing happens
1284  * 7) wagon gets moved, nothing happens
1285  */
1286  if (src == original_src_head && src->IsEngine() && !src->IsFrontEngine()) {
1287  /* Cases #2 and #3: the front engine gets trashed. */
1293  DeleteNewGRFInspectWindow(GSF_TRAINS, src->index);
1295 
1296  /* Delete orders, group stuff and the unit number as we're not the
1297  * front of any vehicle anymore. */
1298  DeleteVehicleOrders(src);
1300  src->unitnumber = 0;
1301  }
1302 
1303  /* We weren't a front engine but are becoming one. So
1304  * we should be put in the default group. */
1305  if (original_src_head != src && dst_head == src) {
1308  }
1309 
1310  /* Add new heads to statistics */
1311  if (src_head != nullptr && src_head->IsFrontEngine()) GroupStatistics::CountVehicle(src_head, 1);
1312  if (dst_head != nullptr && dst_head->IsFrontEngine()) GroupStatistics::CountVehicle(dst_head, 1);
1313 
1314  /* Handle 'new engine' part of cases #1b, #2b, #3b, #4b and #5 in NormaliseTrainHead. */
1315  NormaliseTrainHead(src_head);
1316  NormaliseTrainHead(dst_head);
1317 
1318  if ((flags & DC_NO_CARGO_CAP_CHECK) == 0) {
1319  CheckCargoCapacity(src_head);
1320  CheckCargoCapacity(dst_head);
1321  }
1322 
1323  if (src_head != nullptr) src_head->First()->MarkDirty();
1324  if (dst_head != nullptr) dst_head->First()->MarkDirty();
1325 
1326  /* We are undoubtedly changing something in the depot and train list. */
1329  } else {
1330  /* We don't want to execute what we're just tried. */
1331  RestoreTrainBackup(original_src);
1332  RestoreTrainBackup(original_dst);
1333  }
1334 
1335  return CommandCost();
1336 }
1337 
1349 CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint32 user)
1350 {
1351  /* Sell a chain of vehicles or not? */
1352  bool sell_chain = HasBit(data, 0);
1353 
1355  Train *first = v->First();
1356 
1357  if (v->IsRearDualheaded()) return_cmd_error(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT);
1358 
1359  /* First make a backup of the order of the train. That way we can do
1360  * whatever we want with the order and later on easily revert. */
1361  TrainList original;
1362  MakeTrainBackup(original, first);
1363 
1364  /* We need to keep track of the new head and the head of what we're going to sell. */
1365  Train *new_head = first;
1366  Train *sell_head = nullptr;
1367 
1368  /* Split the train in the wanted way. */
1369  ArrangeTrains(&sell_head, nullptr, &new_head, v, sell_chain);
1370 
1371  /* We don't need to validate the second train; it's going to be sold. */
1372  CommandCost ret = ValidateTrains(nullptr, nullptr, first, new_head, (flags & DC_AUTOREPLACE) == 0);
1373  if (ret.Failed()) {
1374  /* Restore the train we had. */
1375  RestoreTrainBackup(original);
1376  return ret;
1377  }
1378 
1379  if (first->orders.list == nullptr && !OrderList::CanAllocateItem()) {
1380  /* Restore the train we had. */
1381  RestoreTrainBackup(original);
1382  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1383  }
1384 
1386  for (Train *t = sell_head; t != nullptr; t = t->Next()) cost.AddCost(-t->value);
1387 
1388  /* do it? */
1389  if (flags & DC_EXEC) {
1390  /* First normalise the sub types of the chain. */
1391  NormaliseSubtypes(new_head);
1392 
1393  if (v == first && v->IsEngine() && !sell_chain && new_head != nullptr && new_head->IsFrontEngine()) {
1394  /* We are selling the front engine. In this case we want to
1395  * 'give' the order, unit number and such to the new head. */
1396  new_head->orders.list = first->orders.list;
1397  new_head->AddToShared(first);
1398  DeleteVehicleOrders(first);
1399 
1400  /* Copy other important data from the front engine */
1401  new_head->CopyVehicleConfigAndStatistics(first);
1402  GroupStatistics::CountVehicle(new_head, 1); // after copying over the profit
1403  } else if (v->IsPrimaryVehicle() && data & (MAKE_ORDER_BACKUP_FLAG >> 20)) {
1404  OrderBackup::Backup(v, user);
1405  }
1406 
1407  /* We need to update the information about the train. */
1408  NormaliseTrainHead(new_head);
1409 
1410  /* We are undoubtedly changing something in the depot and train list. */
1413 
1414  /* Actually delete the sold 'goods' */
1415  delete sell_head;
1416  } else {
1417  /* We don't want to execute what we're just tried. */
1418  RestoreTrainBackup(original);
1419  }
1420 
1421  return cost;
1422 }
1423 
1425 {
1426  /* Set common defaults. */
1427  this->x_offs = -1;
1428  this->y_offs = -1;
1429  this->x_extent = 3;
1430  this->y_extent = 3;
1431  this->z_extent = 6;
1432  this->x_bb_offs = 0;
1433  this->y_bb_offs = 0;
1434 
1435  if (!IsDiagonalDirection(this->direction)) {
1436  static const int _sign_table[] =
1437  {
1438  /* x, y */
1439  -1, -1, // DIR_N
1440  -1, 1, // DIR_E
1441  1, 1, // DIR_S
1442  1, -1, // DIR_W
1443  };
1444 
1445  int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length) / 2;
1446 
1447  /* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
1448  this->x_offs -= half_shorten * _sign_table[this->direction];
1449  this->y_offs -= half_shorten * _sign_table[this->direction + 1];
1450  this->x_extent += this->x_bb_offs = half_shorten * _sign_table[direction];
1451  this->y_extent += this->y_bb_offs = half_shorten * _sign_table[direction + 1];
1452  } else {
1453  switch (this->direction) {
1454  /* Shorten southern corner of the bounding box according the vehicle length
1455  * and center the bounding box on the vehicle. */
1456  case DIR_NE:
1457  this->x_offs = 1 - (this->gcache.cached_veh_length + 1) / 2;
1458  this->x_extent = this->gcache.cached_veh_length - 1;
1459  this->x_bb_offs = -1;
1460  break;
1461 
1462  case DIR_NW:
1463  this->y_offs = 1 - (this->gcache.cached_veh_length + 1) / 2;
1464  this->y_extent = this->gcache.cached_veh_length - 1;
1465  this->y_bb_offs = -1;
1466  break;
1467 
1468  /* Move northern corner of the bounding box down according to vehicle length
1469  * and center the bounding box on the vehicle. */
1470  case DIR_SW:
1471  this->x_offs = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH;
1472  this->x_extent = VEHICLE_LENGTH - 1;
1473  this->x_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
1474  break;
1475 
1476  case DIR_SE:
1477  this->y_offs = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH;
1478  this->y_extent = VEHICLE_LENGTH - 1;
1479  this->y_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
1480  break;
1481 
1482  default:
1483  NOT_REACHED();
1484  }
1485  }
1486 }
1487 
1492 static void MarkTrainAsStuck(Train *v)
1493 {
1494  if (!HasBit(v->flags, VRF_TRAIN_STUCK)) {
1495  /* It is the first time the problem occurred, set the "train stuck" flag. */
1496  SetBit(v->flags, VRF_TRAIN_STUCK);
1497 
1498  v->wait_counter = 0;
1499 
1500  /* Stop train */
1501  v->cur_speed = 0;
1502  v->subspeed = 0;
1503  v->SetLastSpeed();
1504 
1506  }
1507 }
1508 
1516 static void SwapTrainFlags(uint16 *swap_flag1, uint16 *swap_flag2)
1517 {
1518  uint16 flag1 = *swap_flag1;
1519  uint16 flag2 = *swap_flag2;
1520 
1521  /* Clear the flags */
1522  ClrBit(*swap_flag1, GVF_GOINGUP_BIT);
1523  ClrBit(*swap_flag1, GVF_GOINGDOWN_BIT);
1524  ClrBit(*swap_flag2, GVF_GOINGUP_BIT);
1525  ClrBit(*swap_flag2, GVF_GOINGDOWN_BIT);
1526 
1527  /* Reverse the rail-flags (if needed) */
1528  if (HasBit(flag1, GVF_GOINGUP_BIT)) {
1529  SetBit(*swap_flag2, GVF_GOINGDOWN_BIT);
1530  } else if (HasBit(flag1, GVF_GOINGDOWN_BIT)) {
1531  SetBit(*swap_flag2, GVF_GOINGUP_BIT);
1532  }
1533  if (HasBit(flag2, GVF_GOINGUP_BIT)) {
1534  SetBit(*swap_flag1, GVF_GOINGDOWN_BIT);
1535  } else if (HasBit(flag2, GVF_GOINGDOWN_BIT)) {
1536  SetBit(*swap_flag1, GVF_GOINGUP_BIT);
1537  }
1538 }
1539 
1545 {
1546  /* Reverse the direction. */
1547  if (v->track != TRACK_BIT_DEPOT) v->direction = ReverseDir(v->direction);
1548 
1549  /* Call the proper EnterTile function unless we are in a wormhole. */
1550  if (v->track != TRACK_BIT_WORMHOLE) {
1551  VehicleEnterTile(v, v->tile, v->x_pos, v->y_pos);
1552  } else {
1553  /* VehicleEnter_TunnelBridge() sets TRACK_BIT_WORMHOLE when the vehicle
1554  * is on the last bit of the bridge head (frame == TILE_SIZE - 1).
1555  * If we were swapped with such a vehicle, we have set TRACK_BIT_WORMHOLE,
1556  * when we shouldn't have. Check if this is the case. */
1557  TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
1558  if (IsTileType(vt, MP_TUNNELBRIDGE)) {
1559  VehicleEnterTile(v, vt, v->x_pos, v->y_pos);
1560  if (v->track != TRACK_BIT_WORMHOLE && IsBridgeTile(v->tile)) {
1561  /* We have just left the wormhole, possibly set the
1562  * "goingdown" bit. UpdateInclination() can be used
1563  * because we are at the border of the tile. */
1564  v->UpdatePosition();
1565  v->UpdateInclination(true, true);
1566  return;
1567  }
1568  }
1569  }
1570 
1571  v->UpdatePosition();
1572  v->UpdateViewport(true, true);
1573 }
1574 
1581 void ReverseTrainSwapVeh(Train *v, int l, int r)
1582 {
1583  Train *a, *b;
1584 
1585  /* locate vehicles to swap */
1586  for (a = v; l != 0; l--) a = a->Next();
1587  for (b = v; r != 0; r--) b = b->Next();
1588 
1589  if (a != b) {
1590  /* swap the hidden bits */
1591  {
1592  uint16 tmp = (a->vehstatus & ~VS_HIDDEN) | (b->vehstatus & VS_HIDDEN);
1593  b->vehstatus = (b->vehstatus & ~VS_HIDDEN) | (a->vehstatus & VS_HIDDEN);
1594  a->vehstatus = tmp;
1595  }
1596 
1597  Swap(a->track, b->track);
1598  Swap(a->direction, b->direction);
1599  Swap(a->x_pos, b->x_pos);
1600  Swap(a->y_pos, b->y_pos);
1601  Swap(a->tile, b->tile);
1602  Swap(a->z_pos, b->z_pos);
1603 
1604  SwapTrainFlags(&a->gv_flags, &b->gv_flags);
1605 
1608  } else {
1609  /* Swap GVF_GOINGUP_BIT/GVF_GOINGDOWN_BIT.
1610  * This is a little bit redundant way, a->gv_flags will
1611  * be (re)set twice, but it reduces code duplication */
1612  SwapTrainFlags(&a->gv_flags, &a->gv_flags);
1614  }
1615 }
1616 
1617 
1623 static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
1624 {
1625  return (v->type == VEH_TRAIN) ? v : nullptr;
1626 }
1627 
1628 
1636 {
1637  if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return nullptr;
1638 
1639  Train *t = Train::From(v);
1640  if (!t->IsFrontEngine()) return nullptr;
1641 
1642  TileIndex tile = *(TileIndex *)data;
1643 
1644  if (TrainApproachingCrossingTile(t) != tile) return nullptr;
1645 
1646  return t;
1647 }
1648 
1649 
1657 {
1658  assert(IsLevelCrossingTile(tile));
1659 
1661  TileIndex tile_from = tile + TileOffsByDiagDir(dir);
1662 
1663  if (HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum)) return true;
1664 
1665  dir = ReverseDiagDir(dir);
1666  tile_from = tile + TileOffsByDiagDir(dir);
1667 
1668  return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum);
1669 }
1670 
1671 
1679 {
1680  assert(IsLevelCrossingTile(tile));
1681 
1682  /* reserved || train on crossing || train approaching crossing */
1683  bool new_state = HasCrossingReservation(tile) || HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
1684 
1685  if (new_state != IsCrossingBarred(tile)) {
1686  if (new_state && sound) {
1687  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
1688  }
1689  SetCrossingBarred(tile, new_state);
1690  MarkTileDirtyByTile(tile);
1691  }
1692 }
1693 
1694 
1701 {
1702  if (!IsCrossingBarred(tile)) {
1703  BarCrossing(tile);
1704  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
1705  MarkTileDirtyByTile(tile);
1706  }
1707 }
1708 
1709 
1716 {
1717  Train *base = v;
1718  Train *first = base; // first vehicle to move
1719  Train *last = v->Last(); // last vehicle to move
1720  uint length = CountVehiclesInChain(v);
1721 
1722  while (length > 2) {
1723  last = last->Previous();
1724  first = first->Next();
1725 
1726  int differential = base->CalcNextVehicleOffset() - last->CalcNextVehicleOffset();
1727 
1728  /* do not update images now
1729  * negative differential will be handled in AdvanceWagonsAfterSwap() */
1730  for (int i = 0; i < differential; i++) TrainController(first, last->Next());
1731 
1732  base = first; // == base->Next()
1733  length -= 2;
1734  }
1735 }
1736 
1737 
1744 {
1745  /* first of all, fix the situation when the train was entering a depot */
1746  Train *dep = v; // last vehicle in front of just left depot
1747  while (dep->Next() != nullptr && (dep->track == TRACK_BIT_DEPOT || dep->Next()->track != TRACK_BIT_DEPOT)) {
1748  dep = dep->Next(); // find first vehicle outside of a depot, with next vehicle inside a depot
1749  }
1750 
1751  Train *leave = dep->Next(); // first vehicle in a depot we are leaving now
1752 
1753  if (leave != nullptr) {
1754  /* 'pull' next wagon out of the depot, so we won't miss it (it could stay in depot forever) */
1755  int d = TicksToLeaveDepot(dep);
1756 
1757  if (d <= 0) {
1758  leave->vehstatus &= ~VS_HIDDEN; // move it out of the depot
1759  leave->track = TrackToTrackBits(GetRailDepotTrack(leave->tile));
1760  for (int i = 0; i >= d; i--) TrainController(leave, nullptr); // maybe move it, and maybe let another wagon leave
1761  }
1762  } else {
1763  dep = nullptr; // no vehicle in a depot, so no vehicle leaving a depot
1764  }
1765 
1766  Train *base = v;
1767  Train *first = base; // first vehicle to move
1768  Train *last = v->Last(); // last vehicle to move
1769  uint length = CountVehiclesInChain(v);
1770 
1771  /* We have to make sure all wagons that leave a depot because of train reversing are moved correctly
1772  * they have already correct spacing, so we have to make sure they are moved how they should */
1773  bool nomove = (dep == nullptr); // If there is no vehicle leaving a depot, limit the number of wagons moved immediately.
1774 
1775  while (length > 2) {
1776  /* we reached vehicle (originally) in front of a depot, stop now
1777  * (we would move wagons that are already moved with new wagon length). */
1778  if (base == dep) break;
1779 
1780  /* the last wagon was that one leaving a depot, so do not move it anymore */
1781  if (last == dep) nomove = true;
1782 
1783  last = last->Previous();
1784  first = first->Next();
1785 
1786  int differential = last->CalcNextVehicleOffset() - base->CalcNextVehicleOffset();
1787 
1788  /* do not update images now */
1789  for (int i = 0; i < differential; i++) TrainController(first, (nomove ? last->Next() : nullptr));
1790 
1791  base = first; // == base->Next()
1792  length -= 2;
1793  }
1794 }
1795 
1801 {
1802  if (IsRailDepotTile(v->tile)) {
1804  }
1805 
1806  /* Clear path reservation in front if train is not stuck. */
1807  if (!HasBit(v->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v);
1808 
1809  /* Check if we were approaching a rail/road-crossing */
1811 
1812  /* count number of vehicles */
1813  int r = CountVehiclesInChain(v) - 1; // number of vehicles - 1
1814 
1816 
1817  /* swap start<>end, start+1<>end-1, ... */
1818  int l = 0;
1819  do {
1820  ReverseTrainSwapVeh(v, l++, r--);
1821  } while (l <= r);
1822 
1824 
1825  if (IsRailDepotTile(v->tile)) {
1827  }
1828 
1829  ToggleBit(v->flags, VRF_TOGGLE_REVERSE);
1830 
1831  ClrBit(v->flags, VRF_REVERSING);
1832 
1833  /* recalculate cached data */
1835 
1836  /* update all images */
1837  for (Train *u = v; u != nullptr; u = u->Next()) u->UpdateViewport(false, false);
1838 
1839  /* update crossing we were approaching */
1840  if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
1841 
1842  /* maybe we are approaching crossing now, after reversal */
1843  crossing = TrainApproachingCrossingTile(v);
1844  if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing);
1845 
1846  /* If we are inside a depot after reversing, don't bother with path reserving. */
1847  if (v->track == TRACK_BIT_DEPOT) {
1848  /* Can't be stuck here as inside a depot is always a safe tile. */
1850  ClrBit(v->flags, VRF_TRAIN_STUCK);
1851  return;
1852  }
1853 
1854  /* VehicleExitDir does not always produce the desired dir for depots and
1855  * tunnels/bridges that is needed for UpdateSignalsOnSegment. */
1856  DiagDirection dir = VehicleExitDir(v->direction, v->track);
1858 
1860  /* If we are currently on a tile with conventional signals, we can't treat the
1861  * current tile as a safe tile or we would enter a PBS block without a reservation. */
1862  bool first_tile_okay = !(IsTileType(v->tile, MP_RAILWAY) &&
1864  !IsPbsSignal(GetSignalType(v->tile, FindFirstTrack(v->track))));
1865 
1866  /* If we are on a depot tile facing outwards, do not treat the current tile as safe. */
1867  if (IsRailDepotTile(v->tile) && TrackdirToExitdir(v->GetVehicleTrackdir()) == GetRailDepotDirection(v->tile)) first_tile_okay = false;
1868 
1870  if (TryPathReserve(v, false, first_tile_okay)) {
1871  /* Do a look-ahead now in case our current tile was already a safe tile. */
1872  CheckNextTrainTile(v);
1873  } else if (v->current_order.GetType() != OT_LOADING) {
1874  /* Do not wait for a way out when we're still loading */
1875  MarkTrainAsStuck(v);
1876  }
1877  } else if (HasBit(v->flags, VRF_TRAIN_STUCK)) {
1878  /* A train not inside a PBS block can't be stuck. */
1879  ClrBit(v->flags, VRF_TRAIN_STUCK);
1880  v->wait_counter = 0;
1881  }
1882 }
1883 
1893 CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1894 {
1895  Train *v = Train::GetIfValid(p1);
1896  if (v == nullptr) return CMD_ERROR;
1897 
1898  CommandCost ret = CheckOwnership(v->owner);
1899  if (ret.Failed()) return ret;
1900 
1901  if (p2 != 0) {
1902  /* turn a single unit around */
1903 
1904  if (v->IsMultiheaded() || HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) {
1905  return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
1906  }
1907  if (!HasBit(EngInfo(v->engine_type)->misc_flags, EF_RAIL_FLIPS)) return CMD_ERROR;
1908 
1909  Train *front = v->First();
1910  /* make sure the vehicle is stopped in the depot */
1911  if (!front->IsStoppedInDepot()) {
1912  return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1913  }
1914 
1915  if (flags & DC_EXEC) {
1916  ToggleBit(v->flags, VRF_REVERSE_DIRECTION);
1917 
1918  front->ConsistChanged(CCF_ARRANGE);
1923  }
1924  } else {
1925  /* turn the whole train around */
1926  if ((v->vehstatus & VS_CRASHED) || v->breakdown_ctr != 0) return CMD_ERROR;
1927 
1928  if (flags & DC_EXEC) {
1929  /* Properly leave the station if we are loading and won't be loading anymore */
1930  if (v->current_order.IsType(OT_LOADING)) {
1931  const Vehicle *last = v;
1932  while (last->Next() != nullptr) last = last->Next();
1933 
1934  /* not a station || different station --> leave the station */
1935  if (!IsTileType(last->tile, MP_STATION) || GetStationIndex(last->tile) != GetStationIndex(v->tile)) {
1936  v->LeaveStation();
1937  }
1938  }
1939 
1940  /* We cancel any 'skip signal at dangers' here */
1941  v->force_proceed = TFP_NONE;
1943 
1944  if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && v->cur_speed != 0) {
1945  ToggleBit(v->flags, VRF_REVERSING);
1946  } else {
1947  v->cur_speed = 0;
1948  v->SetLastSpeed();
1951  }
1952  }
1953  }
1954  return CommandCost();
1955 }
1956 
1966 CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1967 {
1968  Train *t = Train::GetIfValid(p1);
1969  if (t == nullptr) return CMD_ERROR;
1970 
1971  if (!t->IsPrimaryVehicle()) return CMD_ERROR;
1972 
1973  CommandCost ret = CheckOwnership(t->owner);
1974  if (ret.Failed()) return ret;
1975 
1976 
1977  if (flags & DC_EXEC) {
1978  /* If we are forced to proceed, cancel that order.
1979  * If we are marked stuck we would want to force the train
1980  * to proceed to the next signal. In the other cases we
1981  * would like to pass the signal at danger and run till the
1982  * next signal we encounter. */
1983  t->force_proceed = t->force_proceed == TFP_SIGNAL ? TFP_NONE : HasBit(t->flags, VRF_TRAIN_STUCK) || t->IsChainInDepot() ? TFP_STUCK : TFP_SIGNAL;
1985  }
1986 
1987  return CommandCost();
1988 }
1989 
1997 static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
1998 {
1999  assert(!(v->vehstatus & VS_CRASHED));
2000 
2001  if (IsRailDepotTile(v->tile)) return FindDepotData(v->tile, 0);
2002 
2003  PBSTileInfo origin = FollowTrainReservation(v);
2004  if (IsRailDepotTile(origin.tile)) return FindDepotData(origin.tile, 0);
2005 
2007  case VPF_NPF: return NPFTrainFindNearestDepot(v, max_distance);
2008  case VPF_YAPF: return YapfTrainFindNearestDepot(v, max_distance);
2009 
2010  default: NOT_REACHED();
2011  }
2012 }
2013 
2021 bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
2022 {
2023  FindDepotData tfdd = FindClosestTrainDepot(this, 0);
2024  if (tfdd.best_length == UINT_MAX) return false;
2025 
2026  if (location != nullptr) *location = tfdd.tile;
2027  if (destination != nullptr) *destination = GetDepotIndex(tfdd.tile);
2028  if (reverse != nullptr) *reverse = tfdd.reverse;
2029 
2030  return true;
2031 }
2032 
2035 {
2036  static const SoundFx sfx[] = {
2037  SND_04_TRAIN,
2038  SND_0A_TRAIN_HORN,
2039  SND_0A_TRAIN_HORN,
2040  SND_47_MAGLEV_2,
2041  SND_41_MAGLEV
2042  };
2043 
2044  if (PlayVehicleSound(this, VSE_START)) return;
2045 
2046  EngineID engtype = this->engine_type;
2047  SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
2048 }
2049 
2054 static void CheckNextTrainTile(Train *v)
2055 {
2056  /* Don't do any look-ahead if path_backoff_interval is 255. */
2057  if (_settings_game.pf.path_backoff_interval == 255) return;
2058 
2059  /* Exit if we are inside a depot. */
2060  if (v->track == TRACK_BIT_DEPOT) return;
2061 
2062  switch (v->current_order.GetType()) {
2063  /* Exit if we reached our destination depot. */
2064  case OT_GOTO_DEPOT:
2065  if (v->tile == v->dest_tile) return;
2066  break;
2067 
2068  case OT_GOTO_WAYPOINT:
2069  /* If we reached our waypoint, make sure we see that. */
2071  break;
2072 
2073  case OT_NOTHING:
2074  case OT_LEAVESTATION:
2075  case OT_LOADING:
2076  /* Exit if the current order doesn't have a destination, but the train has orders. */
2077  if (v->GetNumOrders() > 0) return;
2078  break;
2079 
2080  default:
2081  break;
2082  }
2083  /* Exit if we are on a station tile and are going to stop. */
2085 
2086  Trackdir td = v->GetVehicleTrackdir();
2087 
2088  /* On a tile with a red non-pbs signal, don't look ahead. */
2089  if (IsTileType(v->tile, MP_RAILWAY) && HasSignalOnTrackdir(v->tile, td) &&
2090  !IsPbsSignal(GetSignalType(v->tile, TrackdirToTrack(td))) &&
2091  GetSignalStateByTrackdir(v->tile, td) == SIGNAL_STATE_RED) return;
2092 
2093  CFollowTrackRail ft(v);
2094  if (!ft.Follow(v->tile, td)) return;
2095 
2097  /* Next tile is not reserved. */
2100  /* If the next tile is a PBS signal, try to make a reservation. */
2104  }
2105  ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, nullptr, false);
2106  }
2107  }
2108  }
2109 }
2110 
2117 {
2118  /* bail out if not all wagons are in the same depot or not in a depot at all */
2119  for (const Train *u = v; u != nullptr; u = u->Next()) {
2120  if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
2121  }
2122 
2123  /* if the train got no power, then keep it in the depot */
2124  if (v->gcache.cached_power == 0) {
2125  v->vehstatus |= VS_STOPPED;
2127  return true;
2128  }
2129 
2130  SigSegState seg_state;
2131 
2132  if (v->force_proceed == TFP_NONE) {
2133  /* force proceed was not pressed */
2134  if (++v->wait_counter < 37) {
2136  return true;
2137  }
2138 
2139  v->wait_counter = 0;
2140 
2142  if (seg_state == SIGSEG_FULL || HasDepotReservation(v->tile)) {
2143  /* Full and no PBS signal in block or depot reserved, can't exit. */
2145  return true;
2146  }
2147  } else {
2149  }
2150 
2151  /* We are leaving a depot, but have to go to the exact same one; re-enter. */
2152  if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
2153  /* Service when depot has no reservation. */
2155  return true;
2156  }
2157 
2158  /* Only leave when we can reserve a path to our destination. */
2159  if (seg_state == SIGSEG_PBS && !TryPathReserve(v) && v->force_proceed == TFP_NONE) {
2160  /* No path and no force proceed. */
2162  MarkTrainAsStuck(v);
2163  return true;
2164  }
2165 
2166  SetDepotReservation(v->tile, true);
2168 
2171  v->PlayLeaveStationSound();
2172 
2173  v->track = TRACK_BIT_X;
2174  if (v->direction & 2) v->track = TRACK_BIT_Y;
2175 
2176  v->vehstatus &= ~VS_HIDDEN;
2177  v->cur_speed = 0;
2178 
2179  v->UpdateViewport(true, true);
2180  v->UpdatePosition();
2182  v->UpdateAcceleration();
2184 
2185  return false;
2186 }
2187 
2194 static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir)
2195 {
2196  DiagDirection dir = TrackdirToExitdir(track_dir);
2197 
2198  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
2199  /* Are we just leaving a tunnel/bridge? */
2200  if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
2201  TileIndex end = GetOtherTunnelBridgeEnd(tile);
2202 
2203  if (TunnelBridgeIsFree(tile, end, v).Succeeded()) {
2204  /* Free the reservation only if no other train is on the tiles. */
2205  SetTunnelBridgeReservation(tile, false);
2206  SetTunnelBridgeReservation(end, false);
2207 
2209  if (IsBridge(tile)) {
2210  MarkBridgeDirty(tile);
2211  } else {
2212  MarkTileDirtyByTile(tile);
2213  MarkTileDirtyByTile(end);
2214  }
2215  }
2216  }
2217  }
2218  } else if (IsRailStationTile(tile)) {
2219  TileIndex new_tile = TileAddByDiagDir(tile, dir);
2220  /* If the new tile is not a further tile of the same station, we
2221  * clear the reservation for the whole platform. */
2222  if (!IsCompatibleTrainStationTile(new_tile, tile)) {
2224  }
2225  } else {
2226  /* Any other tile */
2227  UnreserveRailTrack(tile, TrackdirToTrack(track_dir));
2228  }
2229 }
2230 
2236 {
2237  assert(v->IsFrontEngine());
2238 
2239  TileIndex tile = v->tile;
2240  Trackdir td = v->GetVehicleTrackdir();
2241  bool free_tile = !(IsRailStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
2242  StationID station_id = IsRailStationTile(v->tile) ? GetStationIndex(v->tile) : INVALID_STATION;
2243 
2244  /* Can't be holding a reservation if we enter a depot. */
2245  if (IsRailDepotTile(tile) && TrackdirToExitdir(td) != GetRailDepotDirection(tile)) return;
2246  if (v->track == TRACK_BIT_DEPOT) {
2247  /* Front engine is in a depot. We enter if some part is not in the depot. */
2248  for (const Train *u = v; u != nullptr; u = u->Next()) {
2249  if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return;
2250  }
2251  }
2252  /* Don't free reservation if it's not ours. */
2254 
2256  while (ft.Follow(tile, td)) {
2257  tile = ft.m_new_tile;
2259  td = RemoveFirstTrackdir(&bits);
2260  assert(bits == TRACKDIR_BIT_NONE);
2261 
2262  if (!IsValidTrackdir(td)) break;
2263 
2264  if (IsTileType(tile, MP_RAILWAY)) {
2265  if (HasSignalOnTrackdir(tile, td) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td)))) {
2266  /* Conventional signal along trackdir: remove reservation and stop. */
2268  break;
2269  }
2270  if (HasPbsSignalOnTrackdir(tile, td)) {
2271  if (GetSignalStateByTrackdir(tile, td) == SIGNAL_STATE_RED) {
2272  /* Red PBS signal? Can't be our reservation, would be green then. */
2273  break;
2274  } else {
2275  /* Turn the signal back to red. */
2277  MarkTileDirtyByTile(tile);
2278  }
2279  } else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
2280  break;
2281  }
2282  }
2283 
2284  /* Don't free first station/bridge/tunnel if we are on it. */
2285  if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td);
2286 
2287  free_tile = true;
2288  }
2289 }
2290 
2291 static const byte _initial_tile_subcoord[6][4][3] = {
2292 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }},
2293 {{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
2294 {{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }},
2295 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
2296 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }},
2297 {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
2298 };
2299 
2312 static Track DoTrainPathfind(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool do_track_reservation, PBSTileInfo *dest)
2313 {
2315  case VPF_NPF: return NPFTrainChooseTrack(v, path_found, do_track_reservation, dest);
2316  case VPF_YAPF: return YapfTrainChooseTrack(v, tile, enterdir, tracks, path_found, do_track_reservation, dest);
2317 
2318  default: NOT_REACHED();
2319  }
2320 }
2321 
2327 static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir)
2328 {
2329  PBSTileInfo origin = FollowTrainReservation(v);
2330 
2331  CFollowTrackRail ft(v);
2332 
2333  TileIndex tile = origin.tile;
2334  Trackdir cur_td = origin.trackdir;
2335  while (ft.Follow(tile, cur_td)) {
2337  /* Possible signal tile. */
2339  }
2340 
2343  if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) break;
2344  }
2345 
2346  /* Station, depot or waypoint are a possible target. */
2347  bool target_seen = ft.m_is_station || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile));
2348  if (target_seen || KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
2349  /* Choice found or possible target encountered.
2350  * On finding a possible target, we need to stop and let the pathfinder handle the
2351  * remaining path. This is because we don't know if this target is in one of our
2352  * orders, so we might cause pathfinding to fail later on if we find a choice.
2353  * This failure would cause a bogous call to TryReserveSafePath which might reserve
2354  * a wrong path not leading to our next destination. */
2356 
2357  /* If we did skip some tiles, backtrack to the first skipped tile so the pathfinder
2358  * actually starts its search at the first unreserved tile. */
2360 
2361  /* Choice found, path valid but not okay. Save info about the choice tile as well. */
2362  if (new_tracks != nullptr) *new_tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
2363  if (enterdir != nullptr) *enterdir = ft.m_exitdir;
2364  return PBSTileInfo(ft.m_new_tile, ft.m_old_td, false);
2365  }
2366 
2367  tile = ft.m_new_tile;
2368  cur_td = FindFirstTrackdir(ft.m_new_td_bits);
2369 
2370  if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) {
2371  bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg);
2372  if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break;
2373  /* Safe position is all good, path valid and okay. */
2374  return PBSTileInfo(tile, cur_td, true);
2375  }
2376 
2377  if (!TryReserveRailTrack(tile, TrackdirToTrack(cur_td))) break;
2378  }
2379 
2380  if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
2381  /* End of line, path valid and okay. */
2382  return PBSTileInfo(ft.m_old_tile, ft.m_old_td, true);
2383  }
2384 
2385  /* Sorry, can't reserve path, back out. */
2386  tile = origin.tile;
2387  cur_td = origin.trackdir;
2388  TileIndex stopped = ft.m_old_tile;
2389  Trackdir stopped_td = ft.m_old_td;
2390  while (tile != stopped || cur_td != stopped_td) {
2391  if (!ft.Follow(tile, cur_td)) break;
2392 
2395  assert(ft.m_new_td_bits != TRACKDIR_BIT_NONE);
2396  }
2398 
2399  tile = ft.m_new_tile;
2400  cur_td = FindFirstTrackdir(ft.m_new_td_bits);
2401 
2402  UnreserveRailTrack(tile, TrackdirToTrack(cur_td));
2403  }
2404 
2405  /* Path invalid. */
2406  return PBSTileInfo();
2407 }
2408 
2419 static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
2420 {
2422  case VPF_NPF: return NPFTrainFindNearestSafeTile(v, tile, td, override_railtype);
2423  case VPF_YAPF: return YapfTrainFindNearestSafeTile(v, tile, td, override_railtype);
2424 
2425  default: NOT_REACHED();
2426  }
2427 }
2428 
2431 private:
2432  Train *v;
2433  Order old_order;
2434  TileIndex old_dest_tile;
2435  StationID old_last_station_visited;
2437  bool suppress_implicit_orders;
2438 
2439 public:
2440  VehicleOrderSaver(Train *_v) :
2441  v(_v),
2442  old_order(_v->current_order),
2443  old_dest_tile(_v->dest_tile),
2444  old_last_station_visited(_v->last_station_visited),
2446  suppress_implicit_orders(HasBit(_v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS))
2447  {
2448  }
2449 
2451  {
2452  this->v->current_order = this->old_order;
2453  this->v->dest_tile = this->old_dest_tile;
2454  this->v->last_station_visited = this->old_last_station_visited;
2455  SB(this->v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS, 1, suppress_implicit_orders ? 1: 0);
2456  }
2457 
2463  bool SwitchToNextOrder(bool skip_first)
2464  {
2465  if (this->v->GetNumOrders() == 0) return false;
2466 
2467  if (skip_first) ++this->index;
2468 
2469  int depth = 0;
2470 
2471  do {
2472  /* Wrap around. */
2473  if (this->index >= this->v->GetNumOrders()) this->index = 0;
2474 
2475  Order *order = this->v->GetOrder(this->index);
2476  assert(order != nullptr);
2477 
2478  switch (order->GetType()) {
2479  case OT_GOTO_DEPOT:
2480  /* Skip service in depot orders when the train doesn't need service. */
2481  if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !this->v->NeedsServicing()) break;
2482  FALLTHROUGH;
2483  case OT_GOTO_STATION:
2484  case OT_GOTO_WAYPOINT:
2485  this->v->current_order = *order;
2486  return UpdateOrderDest(this->v, order, 0, true);
2487  case OT_CONDITIONAL: {
2488  VehicleOrderID next = ProcessConditionalOrder(order, this->v);
2489  if (next != INVALID_VEH_ORDER_ID) {
2490  depth++;
2491  this->index = next;
2492  /* Don't increment next, so no break here. */
2493  continue;
2494  }
2495  break;
2496  }
2497  default:
2498  break;
2499  }
2500  /* Don't increment inside the while because otherwise conditional
2501  * orders can lead to an infinite loop. */
2502  ++this->index;
2503  depth++;
2504  } while (this->index != this->v->cur_real_order_index && depth < this->v->GetNumOrders());
2505 
2506  return false;
2507  }
2508 };
2509 
2510 /* choose a track */
2511 static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
2512 {
2513  Track best_track = INVALID_TRACK;
2514  bool do_track_reservation = _settings_game.pf.reserve_paths || force_res;
2515  bool changed_signal = false;
2516 
2517  assert((tracks & ~TRACK_BIT_MASK) == 0);
2518 
2519  if (got_reservation != nullptr) *got_reservation = false;
2520 
2521  /* Don't use tracks here as the setting to forbid 90 deg turns might have been switched between reservation and now. */
2522  TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir));
2523  /* Do we have a suitable reserved track? */
2524  if (res_tracks != TRACK_BIT_NONE) return FindFirstTrack(res_tracks);
2525 
2526  /* Quick return in case only one possible track is available */
2527  if (KillFirstBit(tracks) == TRACK_BIT_NONE) {
2528  Track track = FindFirstTrack(tracks);
2529  /* We need to check for signals only here, as a junction tile can't have signals. */
2530  if (track != INVALID_TRACK && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) {
2531  do_track_reservation = true;
2532  changed_signal = true;
2534  } else if (!do_track_reservation) {
2535  return track;
2536  }
2537  best_track = track;
2538  }
2539 
2540  PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false);
2541  DiagDirection dest_enterdir = enterdir;
2542  if (do_track_reservation) {
2543  res_dest = ExtendTrainReservation(v, &tracks, &dest_enterdir);
2544  if (res_dest.tile == INVALID_TILE) {
2545  /* Reservation failed? */
2546  if (mark_stuck) MarkTrainAsStuck(v);
2547  if (changed_signal) SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(best_track, enterdir), SIGNAL_STATE_RED);
2548  return FindFirstTrack(tracks);
2549  }
2550  if (res_dest.okay) {
2551  /* Got a valid reservation that ends at a safe target, quick exit. */
2552  if (got_reservation != nullptr) *got_reservation = true;
2553  if (changed_signal) MarkTileDirtyByTile(tile);
2555  return best_track;
2556  }
2557 
2558  /* Check if the train needs service here, so it has a chance to always find a depot.
2559  * Also check if the current order is a service order so we don't reserve a path to
2560  * the destination but instead to the next one if service isn't needed. */
2562  if (v->current_order.IsType(OT_DUMMY) || v->current_order.IsType(OT_CONDITIONAL) || v->current_order.IsType(OT_GOTO_DEPOT)) ProcessOrders(v);
2563  }
2564 
2565  /* Save the current train order. The destructor will restore the old order on function exit. */
2567 
2568  /* If the current tile is the destination of the current order and
2569  * a reservation was requested, advance to the next order.
2570  * Don't advance on a depot order as depots are always safe end points
2571  * for a path and no look-ahead is necessary. This also avoids a
2572  * problem with depot orders not part of the order list when the
2573  * order list itself is empty. */
2574  if (v->current_order.IsType(OT_LEAVESTATION)) {
2575  orders.SwitchToNextOrder(false);
2576  } else if (v->current_order.IsType(OT_LOADING) || (!v->current_order.IsType(OT_GOTO_DEPOT) && (
2577  v->current_order.IsType(OT_GOTO_STATION) ?
2579  v->tile == v->dest_tile))) {
2580  orders.SwitchToNextOrder(true);
2581  }
2582 
2583  if (res_dest.tile != INVALID_TILE && !res_dest.okay) {
2584  /* Pathfinders are able to tell that route was only 'guessed'. */
2585  bool path_found = true;
2586  TileIndex new_tile = res_dest.tile;
2587 
2588  Track next_track = DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
2589  if (new_tile == tile) best_track = next_track;
2590  v->HandlePathfindingResult(path_found);
2591  }
2592 
2593  /* No track reservation requested -> finished. */
2594  if (!do_track_reservation) return best_track;
2595 
2596  /* A path was found, but could not be reserved. */
2597  if (res_dest.tile != INVALID_TILE && !res_dest.okay) {
2598  if (mark_stuck) MarkTrainAsStuck(v);
2600  return best_track;
2601  }
2602 
2603  /* No possible reservation target found, we are probably lost. */
2604  if (res_dest.tile == INVALID_TILE) {
2605  /* Try to find any safe destination. */
2606  PBSTileInfo origin = FollowTrainReservation(v);
2607  if (TryReserveSafeTrack(v, origin.tile, origin.trackdir, false)) {
2609  best_track = FindFirstTrack(res);
2611  if (got_reservation != nullptr) *got_reservation = true;
2612  if (changed_signal) MarkTileDirtyByTile(tile);
2613  } else {
2615  if (mark_stuck) MarkTrainAsStuck(v);
2616  }
2617  return best_track;
2618  }
2619 
2620  if (got_reservation != nullptr) *got_reservation = true;
2621 
2622  /* Reservation target found and free, check if it is safe. */
2623  while (!IsSafeWaitingPosition(v, res_dest.tile, res_dest.trackdir, true, _settings_game.pf.forbid_90_deg)) {
2624  /* Extend reservation until we have found a safe position. */
2625  DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir);
2626  TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir);
2628  if (Rail90DegTurnDisallowed(GetTileRailType(res_dest.tile), GetTileRailType(next_tile))) {
2629  reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir));
2630  }
2631 
2632  /* Get next order with destination. */
2633  if (orders.SwitchToNextOrder(true)) {
2634  PBSTileInfo cur_dest;
2635  bool path_found;
2636  DoTrainPathfind(v, next_tile, exitdir, reachable, path_found, true, &cur_dest);
2637  if (cur_dest.tile != INVALID_TILE) {
2638  res_dest = cur_dest;
2639  if (res_dest.okay) continue;
2640  /* Path found, but could not be reserved. */
2642  if (mark_stuck) MarkTrainAsStuck(v);
2643  if (got_reservation != nullptr) *got_reservation = false;
2644  changed_signal = false;
2645  break;
2646  }
2647  }
2648  /* No order or no safe position found, try any position. */
2649  if (!TryReserveSafeTrack(v, res_dest.tile, res_dest.trackdir, true)) {
2651  if (mark_stuck) MarkTrainAsStuck(v);
2652  if (got_reservation != nullptr) *got_reservation = false;
2653  changed_signal = false;
2654  }
2655  break;
2656  }
2657 
2659 
2660  if (changed_signal) MarkTileDirtyByTile(tile);
2661 
2662  return best_track;
2663 }
2664 
2673 bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
2674 {
2675  assert(v->IsFrontEngine());
2676 
2677  /* We have to handle depots specially as the track follower won't look
2678  * at the depot tile itself but starts from the next tile. If we are still
2679  * inside the depot, a depot reservation can never be ours. */
2680  if (v->track == TRACK_BIT_DEPOT) {
2681  if (HasDepotReservation(v->tile)) {
2682  if (mark_as_stuck) MarkTrainAsStuck(v);
2683  return false;
2684  } else {
2685  /* Depot not reserved, but the next tile might be. */
2687  if (HasReservedTracks(next_tile, DiagdirReachesTracks(GetRailDepotDirection(v->tile)))) return false;
2688  }
2689  }
2690 
2691  Vehicle *other_train = nullptr;
2692  PBSTileInfo origin = FollowTrainReservation(v, &other_train);
2693  /* The path we are driving on is already blocked by some other train.
2694  * This can only happen in certain situations when mixing path and
2695  * block signals or when changing tracks and/or signals.
2696  * Exit here as doing any further reservations will probably just
2697  * make matters worse. */
2698  if (other_train != nullptr && other_train->index != v->index) {
2699  if (mark_as_stuck) MarkTrainAsStuck(v);
2700  return false;
2701  }
2702  /* If we have a reserved path and the path ends at a safe tile, we are finished already. */
2703  if (origin.okay && (v->tile != origin.tile || first_tile_okay)) {
2704  /* Can't be stuck then. */
2706  ClrBit(v->flags, VRF_TRAIN_STUCK);
2707  return true;
2708  }
2709 
2710  /* If we are in a depot, tentatively reserve the depot. */
2711  if (v->track == TRACK_BIT_DEPOT) {
2712  SetDepotReservation(v->tile, true);
2714  }
2715 
2716  DiagDirection exitdir = TrackdirToExitdir(origin.trackdir);
2717  TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir);
2719 
2721 
2722  bool res_made = false;
2723  ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck);
2724 
2725  if (!res_made) {
2726  /* Free the depot reservation as well. */
2727  if (v->track == TRACK_BIT_DEPOT) SetDepotReservation(v->tile, false);
2728  return false;
2729  }
2730 
2731  if (HasBit(v->flags, VRF_TRAIN_STUCK)) {
2732  v->wait_counter = 0;
2734  }
2735  ClrBit(v->flags, VRF_TRAIN_STUCK);
2736  return true;
2737 }
2738 
2739 
2740 static bool CheckReverseTrain(const Train *v)
2741 {
2743  v->track == TRACK_BIT_DEPOT || v->track == TRACK_BIT_WORMHOLE ||
2744  !(v->direction & 1)) {
2745  return false;
2746  }
2747 
2748  assert(v->track != TRACK_BIT_NONE);
2749 
2751  case VPF_NPF: return NPFTrainCheckReverse(v);
2752  case VPF_YAPF: return YapfTrainCheckReverse(v);
2753 
2754  default: NOT_REACHED();
2755  }
2756 }
2757 
2764 {
2765  if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
2766 
2767  const Station *st = Station::Get(station);
2768  if (!(st->facilities & FACIL_TRAIN)) {
2769  /* The destination station has no trainstation tiles. */
2770  this->IncrementRealOrderIndex();
2771  return 0;
2772  }
2773 
2774  return st->xy;
2775 }
2776 
2779 {
2780  Train *v = this;
2781  do {
2782  v->colourmap = PAL_NONE;
2783  v->UpdateViewport(true, false);
2784  } while ((v = v->Next()) != nullptr);
2785 
2786  /* need to update acceleration and cached values since the goods on the train changed. */
2787  this->CargoChanged();
2788  this->UpdateAcceleration();
2789 }
2790 
2799 {
2801  default: NOT_REACHED();
2802  case AM_ORIGINAL:
2803  return this->DoUpdateSpeed(this->acceleration * (this->GetAccelerationStatus() == AS_BRAKE ? -4 : 2), 0, this->GetCurrentMaxSpeed());
2804 
2805  case AM_REALISTIC:
2806  return this->DoUpdateSpeed(this->GetAcceleration(), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 2, this->GetCurrentMaxSpeed());
2807  }
2808 }
2809 
2815 static void TrainEnterStation(Train *v, StationID station)
2816 {
2817  v->last_station_visited = station;
2818 
2819  /* check if a train ever visited this station before */
2820  Station *st = Station::Get(station);
2821  if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
2822  st->had_vehicle_of_type |= HVOT_TRAIN;
2823  SetDParam(0, st->index);
2825  STR_NEWS_FIRST_TRAIN_ARRIVAL,
2827  v->index,
2828  st->index
2829  );
2830  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
2831  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
2832  }
2833 
2834  v->force_proceed = TFP_NONE;
2836 
2837  v->BeginLoading();
2838 
2840  TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
2841 }
2842 
2843 /* Check if the vehicle is compatible with the specified tile */
2844 static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
2845 {
2846  return IsTileOwner(tile, v->owner) &&
2847  (!v->IsFrontEngine() || HasBit(v->compatible_railtypes, GetRailType(tile)));
2848 }
2849 
2852  byte small_turn;
2853  byte large_turn;
2854  byte z_up;
2855  byte z_down;
2856 };
2857 
2860  /* normal accel */
2861  {256 / 4, 256 / 2, 256 / 4, 2},
2862  {256 / 4, 256 / 2, 256 / 4, 2},
2863  {0, 256 / 2, 256 / 4, 2},
2864 };
2865 
2871 static inline void AffectSpeedByZChange(Train *v, int old_z)
2872 {
2873  if (old_z == v->z_pos || _settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) return;
2874 
2875  const AccelerationSlowdownParams *asp = &_accel_slowdown[GetRailTypeInfo(v->railtype)->acceleration_type];
2876 
2877  if (old_z < v->z_pos) {
2878  v->cur_speed -= (v->cur_speed * asp->z_up >> 8);
2879  } else {
2880  uint16 spd = v->cur_speed + asp->z_down;
2881  if (spd <= v->gcache.cached_max_track_speed) v->cur_speed = spd;
2882  }
2883 }
2884 
2885 static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
2886 {
2887  if (IsTileType(tile, MP_RAILWAY) &&
2890  Trackdir trackdir = FindFirstTrackdir(tracks);
2892  /* A PBS block with a non-PBS signal facing us? */
2893  if (!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
2894  }
2895  }
2896  return false;
2897 }
2898 
2901 {
2902  for (const Train *u = this; u != nullptr; u = u->Next()) {
2903  switch (u->track) {
2904  case TRACK_BIT_WORMHOLE:
2906  break;
2907  case TRACK_BIT_DEPOT:
2908  break;
2909  default:
2910  TryReserveRailTrack(u->tile, TrackBitsToTrack(u->track));
2911  break;
2912  }
2913  }
2914 }
2915 
2922 uint Train::Crash(bool flooded)
2923 {
2924  uint pass = 0;
2925  if (this->IsFrontEngine()) {
2926  pass += 2; // driver
2927 
2928  /* Remove the reserved path in front of the train if it is not stuck.
2929  * Also clear all reserved tracks the train is currently on. */
2930  if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this);
2931  for (const Train *v = this; v != nullptr; v = v->Next()) {
2933  if (IsTileType(v->tile, MP_TUNNELBRIDGE)) {
2934  /* ClearPathReservation will not free the wormhole exit
2935  * if the train has just entered the wormhole. */
2937  }
2938  }
2939 
2940  /* we may need to update crossing we were approaching,
2941  * but must be updated after the train has been marked crashed */
2942  TileIndex crossing = TrainApproachingCrossingTile(this);
2943  if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
2944 
2945  /* Remove the loading indicators (if any) */
2947  }
2948 
2949  pass += this->GroundVehicleBase::Crash(flooded);
2950 
2951  this->crash_anim_pos = flooded ? 4000 : 1; // max 4440, disappear pretty fast when flooded
2952  return pass;
2953 }
2954 
2961 static uint TrainCrashed(Train *v)
2962 {
2963  uint num = 0;
2964 
2965  /* do not crash train twice */
2966  if (!(v->vehstatus & VS_CRASHED)) {
2967  num = v->Crash();
2968  AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN));
2969  Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN));
2970  }
2971 
2972  /* Try to re-reserve track under already crashed train too.
2973  * Crash() clears the reservation! */
2975 
2976  return num;
2977 }
2978 
2982  uint num;
2983 };
2984 
2991 static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data)
2992 {
2994 
2995  /* not a train or in depot */
2996  if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
2997 
2998  /* do not crash into trains of another company. */
2999  if (v->owner != tcc->v->owner) return nullptr;
3000 
3001  /* get first vehicle now to make most usual checks faster */
3002  Train *coll = Train::From(v)->First();
3003 
3004  /* can't collide with own wagons */
3005  if (coll == tcc->v) return nullptr;
3006 
3007  int x_diff = v->x_pos - tcc->v->x_pos;
3008  int y_diff = v->y_pos - tcc->v->y_pos;
3009 
3010  /* Do fast calculation to check whether trains are not in close vicinity
3011  * and quickly reject trains distant enough for any collision.
3012  * Differences are shifted by 7, mapping range [-7 .. 8] into [0 .. 15]
3013  * Differences are then ORed and then we check for any higher bits */
3014  uint hash = (y_diff + 7) | (x_diff + 7);
3015  if (hash & ~15) return nullptr;
3016 
3017  /* Slower check using multiplication */
3018  int min_diff = (Train::From(v)->gcache.cached_veh_length + 1) / 2 + (tcc->v->gcache.cached_veh_length + 1) / 2 - 1;
3019  if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff) return nullptr;
3020 
3021  /* Happens when there is a train under bridge next to bridge head */
3022  if (abs(v->z_pos - tcc->v->z_pos) > 5) return nullptr;
3023 
3024  /* crash both trains */
3025  tcc->num += TrainCrashed(tcc->v);
3026  tcc->num += TrainCrashed(coll);
3027 
3028  return nullptr; // continue searching
3029 }
3030 
3039 {
3040  /* can't collide in depot */
3041  if (v->track == TRACK_BIT_DEPOT) return false;
3042 
3043  assert(v->track == TRACK_BIT_WORMHOLE || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
3044 
3045  TrainCollideChecker tcc;
3046  tcc.v = v;
3047  tcc.num = 0;
3048 
3049  /* find colliding vehicles */
3050  if (v->track == TRACK_BIT_WORMHOLE) {
3053  } else {
3055  }
3056 
3057  /* any dead -> no crash */
3058  if (tcc.num == 0) return false;
3059 
3060  SetDParam(0, tcc.num);
3061  AddVehicleNewsItem(STR_NEWS_TRAIN_CRASH, NT_ACCIDENT, v->index);
3062 
3063  ModifyStationRatingAround(v->tile, v->owner, -160, 30);
3064  if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_BIG_CRASH, v);
3065  return true;
3066 }
3067 
3068 static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
3069 {
3070  if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return nullptr;
3071 
3072  Train *t = Train::From(v);
3073  DiagDirection exitdir = *(DiagDirection *)data;
3074 
3075  /* not front engine of a train, inside wormhole or depot, crashed */
3076  if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return nullptr;
3077 
3078  if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return nullptr;
3079 
3080  return t;
3081 }
3082 
3090 bool TrainController(Train *v, Vehicle *nomove, bool reverse)
3091 {
3092  Train *first = v->First();
3093  Train *prev;
3094  bool direction_changed = false; // has direction of any part changed?
3095 
3096  /* For every vehicle after and including the given vehicle */
3097  for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) {
3098  DiagDirection enterdir = DIAGDIR_BEGIN;
3099  bool update_signals_crossing = false; // will we update signals or crossing state?
3100 
3102  if (v->track != TRACK_BIT_WORMHOLE) {
3103  /* Not inside tunnel */
3104  if (gp.old_tile == gp.new_tile) {
3105  /* Staying in the old tile */
3106  if (v->track == TRACK_BIT_DEPOT) {
3107  /* Inside depot */
3108  gp.x = v->x_pos;
3109  gp.y = v->y_pos;
3110  } else {
3111  /* Not inside depot */
3112 
3113  /* Reverse when we are at the end of the track already, do not move to the new position */
3114  if (v->IsFrontEngine() && !TrainCheckIfLineEnds(v, reverse)) return false;
3115 
3116  uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
3117  if (HasBit(r, VETS_CANNOT_ENTER)) {
3118  goto invalid_rail;
3119  }
3120  if (HasBit(r, VETS_ENTERED_STATION)) {
3121  /* The new position is the end of the platform */
3123  }
3124  }
3125  } else {
3126  /* A new tile is about to be entered. */
3127 
3128  /* Determine what direction we're entering the new tile from */
3129  enterdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
3130  assert(IsValidDiagDirection(enterdir));
3131 
3132  /* Get the status of the tracks in the new tile and mask
3133  * away the bits that aren't reachable. */
3134  TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir));
3135  TrackdirBits reachable_trackdirs = DiagdirReachesTrackdirs(enterdir);
3136 
3137  TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts) & reachable_trackdirs;
3138  TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs);
3139 
3140  TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
3141  if (Rail90DegTurnDisallowed(GetTileRailType(gp.old_tile), GetTileRailType(gp.new_tile)) && prev == nullptr) {
3142  /* We allow wagons to make 90 deg turns, because forbid_90_deg
3143  * can be switched on halfway a turn */
3144  bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
3145  }
3146 
3147  if (bits == TRACK_BIT_NONE) goto invalid_rail;
3148 
3149  /* Check if the new tile constrains tracks that are compatible
3150  * with the current train, if not, bail out. */
3151  if (!CheckCompatibleRail(v, gp.new_tile)) goto invalid_rail;
3152 
3153  TrackBits chosen_track;
3154  if (prev == nullptr) {
3155  /* Currently the locomotive is active. Determine which one of the
3156  * available tracks to choose */
3157  chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits, false, nullptr, true));
3158  assert(chosen_track & (bits | GetReservedTrackbits(gp.new_tile)));
3159 
3160  if (v->force_proceed != TFP_NONE && IsPlainRailTile(gp.new_tile) && HasSignals(gp.new_tile)) {
3161  /* For each signal we find decrease the counter by one.
3162  * We start at two, so the first signal we pass decreases
3163  * this to one, then if we reach the next signal it is
3164  * decreased to zero and we won't pass that new signal. */
3165  Trackdir dir = FindFirstTrackdir(trackdirbits);
3166  if (HasSignalOnTrackdir(gp.new_tile, dir) ||
3168  GetSignalType(gp.new_tile, TrackdirToTrack(dir)) != SIGTYPE_PBS)) {
3169  /* However, we do not want to be stopped by PBS signals
3170  * entered via the back. */
3171  v->force_proceed = (v->force_proceed == TFP_SIGNAL) ? TFP_STUCK : TFP_NONE;
3172  SetWindowDirty(WC_VEHICLE_VIEW, v->index);
3173  }
3174  }
3175 
3176  /* Check if it's a red signal and that force proceed is not clicked. */
3177  if ((red_signals & chosen_track) && v->force_proceed == TFP_NONE) {
3178  /* In front of a red signal */
3179  Trackdir i = FindFirstTrackdir(trackdirbits);
3180 
3181  /* Don't handle stuck trains here. */
3182  if (HasBit(v->flags, VRF_TRAIN_STUCK)) return false;
3183 
3185  v->cur_speed = 0;
3186  v->subspeed = 0;
3187  v->progress = 255; // make sure that every bit of acceleration will hit the signal again, so speed stays 0.
3188  if (!_settings_game.pf.reverse_at_signals || ++v->wait_counter < _settings_game.pf.wait_oneway_signal * DAY_TICKS * 2) return false;
3189  } else if (HasSignalOnTrackdir(gp.new_tile, i)) {
3190  v->cur_speed = 0;
3191  v->subspeed = 0;
3192  v->progress = 255; // make sure that every bit of acceleration will hit the signal again, so speed stays 0.
3194  DiagDirection exitdir = TrackdirToExitdir(i);
3195  TileIndex o_tile = TileAddByDiagDir(gp.new_tile, exitdir);
3196 
3197  exitdir = ReverseDiagDir(exitdir);
3198 
3199  /* check if a train is waiting on the other side */
3200  if (!HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal)) return false;
3201  }
3202  }
3203 
3204  /* If we would reverse but are currently in a PBS block and
3205  * reversing of stuck trains is disabled, don't reverse.
3206  * This does not apply if the reason for reversing is a one-way
3207  * signal blocking us, because a train would then be stuck forever. */
3209  UpdateSignalsOnSegment(v->tile, enterdir, v->owner) == SIGSEG_PBS) {
3210  v->wait_counter = 0;
3211  return false;
3212  }
3213  goto reverse_train_direction;
3214  } else {
3215  TryReserveRailTrack(gp.new_tile, TrackBitsToTrack(chosen_track), false);
3216  }
3217  } else {
3218  /* The wagon is active, simply follow the prev vehicle. */
3219  if (prev->tile == gp.new_tile) {
3220  /* Choose the same track as prev */
3221  if (prev->track == TRACK_BIT_WORMHOLE) {
3222  /* Vehicles entering tunnels enter the wormhole earlier than for bridges.
3223  * However, just choose the track into the wormhole. */
3224  assert(IsTunnel(prev->tile));
3225  chosen_track = bits;
3226  } else {
3227  chosen_track = prev->track;
3228  }
3229  } else {
3230  /* Choose the track that leads to the tile where prev is.
3231  * This case is active if 'prev' is already on the second next tile, when 'v' just enters the next tile.
3232  * I.e. when the tile between them has only space for a single vehicle like
3233  * 1) horizontal/vertical track tiles and
3234  * 2) some orientations of tunnel entries, where the vehicle is already inside the wormhole at 8/16 from the tile edge.
3235  * Is also the train just reversing, the wagon inside the tunnel is 'on' the tile of the opposite tunnel entry.
3236  */
3237  static const TrackBits _connecting_track[DIAGDIR_END][DIAGDIR_END] = {
3242  };
3243  DiagDirection exitdir = DiagdirBetweenTiles(gp.new_tile, prev->tile);
3244  assert(IsValidDiagDirection(exitdir));
3245  chosen_track = _connecting_track[enterdir][exitdir];
3246  }
3247  chosen_track &= bits;
3248  }
3249 
3250  /* Make sure chosen track is a valid track */
3251  assert(
3252  chosen_track == TRACK_BIT_X || chosen_track == TRACK_BIT_Y ||
3253  chosen_track == TRACK_BIT_UPPER || chosen_track == TRACK_BIT_LOWER ||
3254  chosen_track == TRACK_BIT_LEFT || chosen_track == TRACK_BIT_RIGHT);
3255 
3256  /* Update XY to reflect the entrance to the new tile, and select the direction to use */
3257  const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir];
3258  gp.x = (gp.x & ~0xF) | b[0];
3259  gp.y = (gp.y & ~0xF) | b[1];
3260  Direction chosen_dir = (Direction)b[2];
3261 
3262  /* Call the landscape function and tell it that the vehicle entered the tile */
3263  uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
3264  if (HasBit(r, VETS_CANNOT_ENTER)) {
3265  goto invalid_rail;
3266  }
3267 
3268  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
3269  Track track = FindFirstTrack(chosen_track);
3270  Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir);
3271  if (v->IsFrontEngine() && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) {
3274  }
3275 
3276  /* Clear any track reservation when the last vehicle leaves the tile */
3277  if (v->Next() == nullptr) ClearPathReservation(v, v->tile, v->GetVehicleTrackdir());
3278 
3279  v->tile = gp.new_tile;
3280 
3282  v->First()->ConsistChanged(CCF_TRACK);
3283  }
3284 
3285  v->track = chosen_track;
3286  assert(v->track);
3287  }
3288 
3289  /* We need to update signal status, but after the vehicle position hash
3290  * has been updated by UpdateInclination() */
3291  update_signals_crossing = true;
3292 
3293  if (chosen_dir != v->direction) {
3294  if (prev == nullptr && _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) {
3295  const AccelerationSlowdownParams *asp = &_accel_slowdown[GetRailTypeInfo(v->railtype)->acceleration_type];
3296  DirDiff diff = DirDifference(v->direction, chosen_dir);
3297  v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? asp->small_turn : asp->large_turn) * v->cur_speed >> 8;
3298  }
3299  direction_changed = true;
3300  v->direction = chosen_dir;
3301  }
3302 
3303  if (v->IsFrontEngine()) {
3304  v->wait_counter = 0;
3305 
3306  /* If we are approaching a crossing that is reserved, play the sound now. */
3308  if (crossing != INVALID_TILE && HasCrossingReservation(crossing) && _settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, crossing);
3309 
3310  /* Always try to extend the reservation when entering a tile. */
3311  CheckNextTrainTile(v);
3312  }
3313 
3314  if (HasBit(r, VETS_ENTERED_STATION)) {
3315  /* The new position is the location where we want to stop */
3317  }
3318  }
3319  } else {
3321  /* Perform look-ahead on tunnel exit. */
3322  if (v->IsFrontEngine()) {
3324  CheckNextTrainTile(v);
3325  }
3326  /* Prevent v->UpdateInclination() being called with wrong parameters.
3327  * This could happen if the train was reversed inside the tunnel/bridge. */
3328  if (gp.old_tile == gp.new_tile) {
3330  }
3331  } else {
3332  v->x_pos = gp.x;
3333  v->y_pos = gp.y;
3334  v->UpdatePosition();
3335  if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
3336  continue;
3337  }
3338  }
3339 
3340  /* update image of train, as well as delta XY */
3341  v->UpdateDeltaXY();
3342 
3343  v->x_pos = gp.x;
3344  v->y_pos = gp.y;
3345  v->UpdatePosition();
3346 
3347  /* update the Z position of the vehicle */
3348  int old_z = v->UpdateInclination(gp.new_tile != gp.old_tile, false);
3349 
3350  if (prev == nullptr) {
3351  /* This is the first vehicle in the train */
3352  AffectSpeedByZChange(v, old_z);
3353  }
3354 
3355  if (update_signals_crossing) {
3356  if (v->IsFrontEngine()) {
3357  if (TrainMovedChangeSignals(gp.new_tile, enterdir)) {
3358  /* We are entering a block with PBS signals right now, but
3359  * not through a PBS signal. This means we don't have a
3360  * reservation right now. As a conventional signal will only
3361  * ever be green if no other train is in the block, getting
3362  * a path should always be possible. If the player built
3363  * such a strange network that it is not possible, the train
3364  * will be marked as stuck and the player has to deal with
3365  * the problem. */
3366  if ((!HasReservedTracks(gp.new_tile, v->track) &&
3367  !TryReserveRailTrack(gp.new_tile, FindFirstTrack(v->track))) ||
3368  !TryPathReserve(v)) {
3369  MarkTrainAsStuck(v);
3370  }
3371  }
3372  }
3373 
3374  /* Signals can only change when the first
3375  * (above) or the last vehicle moves. */
3376  if (v->Next() == nullptr) {
3377  TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
3379  }
3380  }
3381 
3382  /* Do not check on every tick to save some computing time. */
3383  if (v->IsFrontEngine() && v->tick_counter % _settings_game.pf.path_backoff_interval == 0) CheckNextTrainTile(v);
3384  }
3385 
3386  if (direction_changed) first->tcache.cached_max_curve_speed = first->GetCurveSpeedLimit();
3387 
3388  return true;
3389 
3390 invalid_rail:
3391  /* We've reached end of line?? */
3392  if (prev != nullptr) error("Disconnecting train");
3393 
3394 reverse_train_direction:
3395  if (reverse) {
3396  v->wait_counter = 0;
3397  v->cur_speed = 0;
3398  v->subspeed = 0;
3400  }
3401 
3402  return false;
3403 }
3404 
3412 {
3413  TrackBits *trackbits = (TrackBits *)data;
3414 
3415  if (v->type == VEH_TRAIN && (v->vehstatus & VS_CRASHED) != 0) {
3416  TrackBits train_tbits = Train::From(v)->track;
3417  if (train_tbits == TRACK_BIT_WORMHOLE) {
3418  /* Vehicle is inside a wormhole, v->track contains no useful value then. */
3420  } else if (train_tbits != TRACK_BIT_DEPOT) {
3421  *trackbits |= train_tbits;
3422  }
3423  }
3424 
3425  return nullptr;
3426 }
3427 
3435 static void DeleteLastWagon(Train *v)
3436 {
3437  Train *first = v->First();
3438 
3439  /* Go to the last wagon and delete the link pointing there
3440  * *u is then the one-before-last wagon, and *v the last
3441  * one which will physically be removed */
3442  Train *u = v;
3443  for (; v->Next() != nullptr; v = v->Next()) u = v;
3444  u->SetNext(nullptr);
3445 
3446  if (first != v) {
3447  /* Recalculate cached train properties */
3448  first->ConsistChanged(CCF_ARRANGE);
3449  /* Update the depot window if the first vehicle is in depot -
3450  * if v == first, then it is updated in PreDestructor() */
3451  if (first->track == TRACK_BIT_DEPOT) {
3453  }
3454  v->last_station_visited = first->last_station_visited; // for PreDestructor
3455  }
3456 
3457  /* 'v' shouldn't be accessed after it has been deleted */
3458  TrackBits trackbits = v->track;
3459  TileIndex tile = v->tile;
3460  Owner owner = v->owner;
3461 
3462  delete v;
3463  v = nullptr; // make sure nobody will try to read 'v' anymore
3464 
3465  if (trackbits == TRACK_BIT_WORMHOLE) {
3466  /* Vehicle is inside a wormhole, v->track contains no useful value then. */
3468  }
3469 
3470  Track track = TrackBitsToTrack(trackbits);
3471  if (HasReservedTracks(tile, trackbits)) {
3472  UnreserveRailTrack(tile, track);
3473 
3474  /* If there are still crashed vehicles on the tile, give the track reservation to them */
3475  TrackBits remaining_trackbits = TRACK_BIT_NONE;
3476  FindVehicleOnPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum);
3477 
3478  /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */
3479  assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1);
3480  Track t;
3481  FOR_EACH_SET_TRACK(t, remaining_trackbits) TryReserveRailTrack(tile, t);
3482  }
3483 
3484  /* check if the wagon was on a road/rail-crossing */
3485  if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
3486 
3487  /* Update signals */
3488  if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) {
3490  } else {
3491  SetSignalsOnBothDir(tile, track, owner);
3492  }
3493 }
3494 
3500 {
3501  static const DirDiff delta[] = {
3503  };
3504 
3505  do {
3506  /* We don't need to twist around vehicles if they're not visible */
3507  if (!(v->vehstatus & VS_HIDDEN)) {
3508  v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
3509  /* Refrain from updating the z position of the vehicle when on
3510  * a bridge, because UpdateInclination() will put the vehicle under
3511  * the bridge in that case */
3512  if (v->track != TRACK_BIT_WORMHOLE) {
3513  v->UpdatePosition();
3514  v->UpdateInclination(false, true);
3515  } else {
3516  v->UpdateViewport(false, true);
3517  }
3518  }
3519  } while ((v = v->Next()) != nullptr);
3520 }
3521 
3527 static bool HandleCrashedTrain(Train *v)
3528 {
3529  int state = ++v->crash_anim_pos;
3530 
3531  if (state == 4 && !(v->vehstatus & VS_HIDDEN)) {
3533  }
3534 
3535  uint32 r;
3536  if (state <= 200 && Chance16R(1, 7, r)) {
3537  int index = (r * 10 >> 16);
3538 
3539  Vehicle *u = v;
3540  do {
3541  if (--index < 0) {
3542  r = Random();
3543 
3545  GB(r, 8, 3) + 2,
3546  GB(r, 16, 3) + 2,
3547  GB(r, 0, 3) + 5,
3549  break;
3550  }
3551  } while ((u = u->Next()) != nullptr);
3552  }
3553 
3554  if (state <= 240 && !(v->tick_counter & 3)) ChangeTrainDirRandomly(v);
3555 
3556  if (state >= 4440 && !(v->tick_counter & 0x1F)) {
3557  bool ret = v->Next() != nullptr;
3558  DeleteLastWagon(v);
3559  return ret;
3560  }
3561 
3562  return true;
3563 }
3564 
3566 static const uint16 _breakdown_speeds[16] = {
3567  225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
3568 };
3569 
3570 
3579 static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse)
3580 {
3581  /* Calc position within the current tile */
3582  uint x = v->x_pos & 0xF;
3583  uint y = v->y_pos & 0xF;
3584 
3585  /* for diagonal directions, 'x' will be 0..15 -
3586  * for other directions, it will be 1, 3, 5, ..., 15 */
3587  switch (v->direction) {
3588  case DIR_N : x = ~x + ~y + 25; break;
3589  case DIR_NW: x = y; FALLTHROUGH;
3590  case DIR_NE: x = ~x + 16; break;
3591  case DIR_E : x = ~x + y + 9; break;
3592  case DIR_SE: x = y; break;
3593  case DIR_S : x = x + y - 7; break;
3594  case DIR_W : x = ~y + x + 9; break;
3595  default: break;
3596  }
3597 
3598  /* Do not reverse when approaching red signal. Make sure the vehicle's front
3599  * does not cross the tile boundary when we do reverse, but as the vehicle's
3600  * location is based on their center, use half a vehicle's length as offset.
3601  * Multiply the half-length by two for straight directions to compensate that
3602  * we only get odd x offsets there. */
3603  if (!signal && x + (v->gcache.cached_veh_length + 1) / 2 * (IsDiagonalDirection(v->direction) ? 1 : 2) >= TILE_SIZE) {
3604  /* we are too near the tile end, reverse now */
3605  v->cur_speed = 0;
3606  if (reverse) ReverseTrainDirection(v);
3607  return false;
3608  }
3609 
3610  /* slow down */
3612  uint16 break_speed = _breakdown_speeds[x & 0xF];
3613  if (break_speed < v->cur_speed) v->cur_speed = break_speed;
3614 
3615  return true;
3616 }
3617 
3618 
3624 static bool TrainCanLeaveTile(const Train *v)
3625 {
3626  /* Exit if inside a tunnel/bridge or a depot */
3627  if (v->track == TRACK_BIT_WORMHOLE || v->track == TRACK_BIT_DEPOT) return false;
3628 
3629  TileIndex tile = v->tile;
3630 
3631  /* entering a tunnel/bridge? */
3632  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
3634  if (DiagDirToDir(dir) == v->direction) return false;
3635  }
3636 
3637  /* entering a depot? */
3638  if (IsRailDepotTile(tile)) {
3640  if (DiagDirToDir(dir) == v->direction) return false;
3641  }
3642 
3643  return true;
3644 }
3645 
3646 
3655 {
3656  assert(v->IsFrontEngine());
3657  assert(!(v->vehstatus & VS_CRASHED));
3658 
3659  if (!TrainCanLeaveTile(v)) return INVALID_TILE;
3660 
3661  DiagDirection dir = VehicleExitDir(v->direction, v->track);
3662  TileIndex tile = v->tile + TileOffsByDiagDir(dir);
3663 
3664  /* not a crossing || wrong axis || unusable rail (wrong type or owner) */
3665  if (!IsLevelCrossingTile(tile) || DiagDirToAxis(dir) == GetCrossingRoadAxis(tile) ||
3666  !CheckCompatibleRail(v, tile)) {
3667  return INVALID_TILE;
3668  }
3669 
3670  return tile;
3671 }
3672 
3673 
3681 static bool TrainCheckIfLineEnds(Train *v, bool reverse)
3682 {
3683  /* First, handle broken down train */
3684 
3685  int t = v->breakdown_ctr;
3686  if (t > 1) {
3688 
3689  uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
3690  if (break_speed < v->cur_speed) v->cur_speed = break_speed;
3691  } else {
3692  v->vehstatus &= ~VS_TRAIN_SLOWING;
3693  }
3694 
3695  if (!TrainCanLeaveTile(v)) return true;
3696 
3697  /* Determine the non-diagonal direction in which we will exit this tile */
3698  DiagDirection dir = VehicleExitDir(v->direction, v->track);
3699  /* Calculate next tile */
3700  TileIndex tile = v->tile + TileOffsByDiagDir(dir);
3701 
3702  /* Determine the track status on the next tile */
3703  TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0, ReverseDiagDir(dir));
3704  TrackdirBits reachable_trackdirs = DiagdirReachesTrackdirs(dir);
3705 
3706  TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts) & reachable_trackdirs;
3707  TrackdirBits red_signals = TrackStatusToRedSignals(ts) & reachable_trackdirs;
3708 
3709  /* We are sure the train is not entering a depot, it is detected above */
3710 
3711  /* mask unreachable track bits if we are forbidden to do 90deg turns */
3712  TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
3714  bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
3715  }
3716 
3717  /* no suitable trackbits at all || unusable rail (wrong type or owner) */
3718  if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(v, tile)) {
3719  return TrainApproachingLineEnd(v, false, reverse);
3720  }
3721 
3722  /* approaching red signal */
3723  if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(v, true, reverse);
3724 
3725  /* approaching a rail/road crossing? then make it red */
3727 
3728  return true;
3729 }
3730 
3731 
3732 static bool TrainLocoHandler(Train *v, bool mode)
3733 {
3734  /* train has crashed? */
3735  if (v->vehstatus & VS_CRASHED) {
3736  return mode ? true : HandleCrashedTrain(v); // 'this' can be deleted here
3737  }
3738 
3739  if (v->force_proceed != TFP_NONE) {
3740  ClrBit(v->flags, VRF_TRAIN_STUCK);
3742  }
3743 
3744  /* train is broken down? */
3745  if (v->HandleBreakdown()) return true;
3746 
3747  if (HasBit(v->flags, VRF_REVERSING) && v->cur_speed == 0) {
3749  }
3750 
3751  /* exit if train is stopped */
3752  if ((v->vehstatus & VS_STOPPED) && v->cur_speed == 0) return true;
3753 
3754  bool valid_order = !v->current_order.IsType(OT_NOTHING) && v->current_order.GetType() != OT_CONDITIONAL;
3755  if (ProcessOrders(v) && CheckReverseTrain(v)) {
3756  v->wait_counter = 0;
3757  v->cur_speed = 0;
3758  v->subspeed = 0;
3759  ClrBit(v->flags, VRF_LEAVING_STATION);
3761  return true;
3762  } else if (HasBit(v->flags, VRF_LEAVING_STATION)) {
3763  /* Try to reserve a path when leaving the station as we
3764  * might not be marked as wanting a reservation, e.g.
3765  * when an overlength train gets turned around in a station. */
3766  DiagDirection dir = VehicleExitDir(v->direction, v->track);
3768 
3770  TryPathReserve(v, true, true);
3771  }
3772  ClrBit(v->flags, VRF_LEAVING_STATION);
3773  }
3774 
3775  v->HandleLoading(mode);
3776 
3777  if (v->current_order.IsType(OT_LOADING)) return true;
3778 
3779  if (CheckTrainStayInDepot(v)) return true;
3780 
3781  if (!mode) v->ShowVisualEffect();
3782 
3783  /* We had no order but have an order now, do look ahead. */
3784  if (!valid_order && !v->current_order.IsType(OT_NOTHING)) {
3785  CheckNextTrainTile(v);
3786  }
3787 
3788  /* Handle stuck trains. */
3789  if (!mode && HasBit(v->flags, VRF_TRAIN_STUCK)) {
3790  ++v->wait_counter;
3791 
3792  /* Should we try reversing this tick if still stuck? */
3794 
3795  if (!turn_around && v->wait_counter % _settings_game.pf.path_backoff_interval != 0 && v->force_proceed == TFP_NONE) return true;
3796  if (!TryPathReserve(v)) {
3797  /* Still stuck. */
3798  if (turn_around) ReverseTrainDirection(v);
3799 
3801  /* Show message to player. */
3803  SetDParam(0, v->index);
3804  AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_STUCK, v->index);
3805  }
3806  v->wait_counter = 0;
3807  }
3808  /* Exit if force proceed not pressed, else reset stuck flag anyway. */
3809  if (v->force_proceed == TFP_NONE) return true;
3810  ClrBit(v->flags, VRF_TRAIN_STUCK);
3811  v->wait_counter = 0;
3813  }
3814  }
3815 
3816  if (v->current_order.IsType(OT_LEAVESTATION)) {
3817  v->current_order.Free();
3819  return true;
3820  }
3821 
3822  int j = v->UpdateSpeed();
3823 
3824  /* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */
3825  if (v->cur_speed == 0 && (v->vehstatus & VS_STOPPED)) {
3826  /* If we manually stopped, we're not force-proceeding anymore. */
3827  v->force_proceed = TFP_NONE;
3829  }
3830 
3831  int adv_spd = v->GetAdvanceDistance();
3832  if (j < adv_spd) {
3833  /* if the vehicle has speed 0, update the last_speed field. */
3834  if (v->cur_speed == 0) v->SetLastSpeed();
3835  } else {
3837  /* Loop until the train has finished moving. */
3838  for (;;) {
3839  j -= adv_spd;
3840  TrainController(v, nullptr);
3841  /* Don't continue to move if the train crashed. */
3842  if (CheckTrainCollision(v)) break;
3843  /* Determine distance to next map position */
3844  adv_spd = v->GetAdvanceDistance();
3845 
3846  /* No more moving this tick */
3847  if (j < adv_spd || v->cur_speed == 0) break;
3848 
3849  OrderType order_type = v->current_order.GetType();
3850  /* Do not skip waypoints (incl. 'via' stations) when passing through at full speed. */
3851  if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
3853  IsTileType(v->tile, MP_STATION) &&
3855  ProcessOrders(v);
3856  }
3857  }
3858  v->SetLastSpeed();
3859  }
3860 
3861  for (Train *u = v; u != nullptr; u = u->Next()) {
3862  if ((u->vehstatus & VS_HIDDEN) != 0) continue;
3863 
3864  u->UpdateViewport(false, false);
3865  }
3866 
3867  if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress
3868 
3869  return true;
3870 }
3871 
3877 {
3878  Money cost = 0;
3879  const Train *v = this;
3880 
3881  do {
3882  const Engine *e = v->GetEngine();
3883  if (e->u.rail.running_cost_class == INVALID_PRICE) continue;
3884 
3885  uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost);
3886  if (cost_factor == 0) continue;
3887 
3888  /* Halve running cost for multiheaded parts */
3889  if (v->IsMultiheaded()) cost_factor /= 2;
3890 
3891  cost += GetPrice(e->u.rail.running_cost_class, cost_factor, e->GetGRF());
3892  } while ((v = v->GetNextVehicle()) != nullptr);
3893 
3894  return cost;
3895 }
3896 
3902 {
3904 
3905  this->tick_counter++;
3906 
3907  if (this->IsFrontEngine()) {
3908  if (!(this->vehstatus & VS_STOPPED) || this->cur_speed > 0) this->running_ticks++;
3909 
3910  this->current_order_time++;
3911 
3912  if (!TrainLocoHandler(this, false)) return false;
3913 
3914  return TrainLocoHandler(this, true);
3915  } else if (this->IsFreeWagon() && (this->vehstatus & VS_CRASHED)) {
3916  /* Delete flooded standalone wagon chain */
3917  if (++this->crash_anim_pos >= 4400) {
3918  delete this;
3919  return false;
3920  }
3921  }
3922 
3923  return true;
3924 }
3925 
3931 {
3932  if (Company::Get(v->owner)->settings.vehicle.servint_trains == 0 || !v->NeedsAutomaticServicing()) return;
3933  if (v->IsChainInDepot()) {
3935  return;
3936  }
3937 
3938  uint max_penalty;
3940  case VPF_NPF: max_penalty = _settings_game.pf.npf.maximum_go_to_depot_penalty; break;
3941  case VPF_YAPF: max_penalty = _settings_game.pf.yapf.maximum_go_to_depot_penalty; break;
3942  default: NOT_REACHED();
3943  }
3944 
3945  FindDepotData tfdd = FindClosestTrainDepot(v, max_penalty);
3946  /* Only go to the depot if it is not too far out of our way. */
3947  if (tfdd.best_length == UINT_MAX || tfdd.best_length > max_penalty) {
3948  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
3949  /* If we were already heading for a depot but it has
3950  * suddenly moved farther away, we continue our normal
3951  * schedule? */
3952  v->current_order.MakeDummy();
3954  }
3955  return;
3956  }
3957 
3958  DepotID depot = GetDepotIndex(tfdd.tile);
3959 
3960  if (v->current_order.IsType(OT_GOTO_DEPOT) &&
3961  v->current_order.GetDestination() != depot &&
3962  !Chance16(3, 16)) {
3963  return;
3964  }
3965 
3968  v->dest_tile = tfdd.tile;
3970 }
3971 
3974 {
3975  AgeVehicle(this);
3976 
3977  if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
3978 
3979  if (this->IsFrontEngine()) {
3980  CheckVehicleBreakdown(this);
3981 
3983 
3984  CheckOrders(this);
3985 
3986  /* update destination */
3987  if (this->current_order.IsType(OT_GOTO_STATION)) {
3988  TileIndex tile = Station::Get(this->current_order.GetDestination())->train_station.tile;
3989  if (tile != INVALID_TILE) this->dest_tile = tile;
3990  }
3991 
3992  if (this->running_ticks != 0) {
3993  /* running costs */
3995 
3996  this->profit_this_year -= cost.GetCost();
3997  this->running_ticks = 0;
3998 
3999  SubtractMoneyFromCompanyFract(this->owner, cost);
4000 
4003  }
4004  }
4005 }
4006 
4012 {
4013  if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
4014 
4015  if (this->track == TRACK_BIT_DEPOT) {
4016  /* We'll assume the train is facing outwards */
4017  return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot
4018  }
4019 
4020  if (this->track == TRACK_BIT_WORMHOLE) {
4021  /* train in tunnel or on bridge, so just use his direction and assume a diagonal track */
4023  }
4024 
4025  return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction);
4026 }
T * GetLastEnginePart()
Get the last part of an articulated engine.
bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
Try to reserve a path to a safe position.
Definition: train_cmd.cpp:2673
Functions related to OTTD&#39;s strings.
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
void ReverseTrainSwapVeh(Train *v, int l, int r)
Swap vehicles l and r in consist v, and reverse their direction.
Definition: train_cmd.cpp:1581
Owner
Enum for all companies/owners.
Definition: company_type.h:20
static Vehicle * TrainApproachingCrossingEnum(Vehicle *v, void *data)
Checks if a train is approaching a rail-road crossing.
Definition: train_cmd.cpp:1635
Normal operation.
Definition: train.h:40
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:513
VehicleSettings vehicle
options for vehicles
This vehicle is in the exclusive preview stage, either being used or being offered to a company...
Definition: engine_type.h:171
static bool HasPowerOnRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType got power on a tile with a given RailType.
Definition: rail.h:334
Functions/types related to NewGRF debugging.
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:277
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:27
Date max_age
Maximum age.
Definition: vehicle_base.h:259
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:20
StationFacility facilities
The facilities that this station has.
static bool HasSignalOnTrackdir(TileIndex tile, Trackdir trackdir)
Checks for the presence of signals along the given trackdir on the given rail tile.
Definition: rail_map.h:428
Vehicle is stopped by the player.
Definition: vehicle_base.h:33
First vehicle arrived for competitor.
Definition: news_type.h:25
bool cached_tilt
train can tilt; feature provides a bonus in curves
Definition: train.h:76
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:309
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:81
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:143
Definition of stuff that is very close to a company, like the company struct itself.
static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir)
Extend a train path as far as possible.
Definition: train_cmd.cpp:2327
static bool IsDiagonalDirection(Direction dir)
Checks if a given Direction is diagonal.
Money value
Value of the vehicle.
Definition: vehicle_base.h:241
int CalcNextVehicleOffset() const
Calculate the offset from this vehicle&#39;s center to the following center taking the vehicle lengths in...
Definition: train.h:169
bool _networking
are we in networking mode?
Definition: network.cpp:54
uint16 DepotID
Type for the unique identifier of depots.
Definition: depot_type.h:15
int GetAcceleration() const
Calculates the acceleration of the vehicle under its current conditions.
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:306
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1204
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:31
TrackdirBits
Enumeration of bitmasks for the TrackDirs.
Definition: track_type.h:103
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
No track build.
Definition: track_type.h:104
Direction direction
facing
Definition: vehicle_base.h:271
static void SetTunnelBridgeReservation(TileIndex t, bool b)
Set the reservation state of the rail tunnel/bridge.
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition: vehicle.cpp:2517
Occupied by a train.
Definition: signal_func.h:53
bool UsesWagonOverride(const Vehicle *v)
Check if a wagon is currently using a wagon override.
Flag for an invalid track.
Definition: track_type.h:30
bool Follow(TileIndex old_tile, Trackdir old_td)
main follower routine.
bool NPFTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype)
Try to extend the reserved path of a train to the nearest safe tile using NPF.
Definition: npf.cpp:1262
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3199
static DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Invalidate the inspect window for a given feature and index.
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:68
Yet Another PathFinder.
Definition: vehicle_type.h:63
Track along the x-axis (north-east to south-west)
Definition: track_type.h:23
TrackdirBits m_new_td_bits
the new set of available trackdirs
uint32 maximum_go_to_depot_penalty
What is the maximum penalty that may be endured for going to a depot.
bool m_is_tunnel
last turn passed tunnel
Train is just leaving a station.
Definition: train.h:35
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition: order_cmd.cpp:1726
void SetFrontEngine()
Set front engine state.
bool TrainController(Train *v, Vehicle *nomove, bool reverse=true)
Move a vehicle chain one movement stop forwards.
Definition: train_cmd.cpp:3090
void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
Mark bridge tiles dirty.
static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
Try to find a depot nearby.
Definition: train_cmd.cpp:1997
int TicksToLeaveDepot(const Train *v)
Compute number of ticks when next wagon will leave a depot.
Definition: rail_cmd.cpp:2932
ConsistChangeFlags
Flags for Train::ConsistChanged.
Definition: train.h:46
byte curve_speed
Multiplier for curve maximum speed advantage.
Definition: rail.h:205
Train vehicle type.
Definition: vehicle_type.h:26
union Vehicle::@49 orders
The orders currently assigned to the vehicle.
Max. speed: 1 unit = 1/1.6 mph = 1 km-ish/h.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
static bool TrainCheckIfLineEnds(Train *v, bool reverse=true)
Checks for line end.
Definition: train_cmd.cpp:3681
static bool IsBridgeTile(TileIndex t)
checks if there is a bridge on this tile
Definition: bridge_map.h:37
Capacity of vehicle changes when not refitting or arranging.
Definition: newgrf_config.h:49
void PlayLeaveStationSound() const
Play a sound for a train leaving the station.
Definition: train_cmd.cpp:2034
Angle of 45 degrees left.
static T ToggleBit(T &x, const uint8 y)
Toggles a bit in a variable.
uint DoUpdateSpeed(uint accel, int min_speed, int max_speed)
Update the speed of the vehicle.
static Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition: track_func.h:272
Vehicle composition was changed.
Definition: vehicle_gui.h:36
Trigger platform when train arrives.
static bool TrainApproachingCrossing(TileIndex tile)
Finds a vehicle approaching rail-road crossing.
Definition: train_cmd.cpp:1656
Bitmask for the first 6 bits.
Definition: track_type.h:56
Various explosions.
static CommandCost CheckTrainAttachment(Train *t)
Check whether the train parts can be attached.
Definition: train_cmd.cpp:965
Use default vehicle palette.
Definition: vehicle_base.h:35
Angle of 90 degrees right.
West.
static bool HasCrossingReservation(TileIndex t)
Get the reservation state of the rail crossing.
Definition: road_map.h:382
uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent)
Evaluate a newgrf callback for vehicles with a different vehicle for parent scope.
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition: order_type.h:23
static void NormaliseTrainHead(Train *head)
Normalise the head of the train again, i.e.
Definition: train_cmd.cpp:1122
Left track.
Definition: track_type.h:46
void AddArticulatedParts(Vehicle *first)
Add the remaining articulated parts to the given vehicle.
bool reverse
True if reversing is necessary for the train to get to this depot.
Used for iterations.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:72
Sprites to use for trains.
uint16 cur_speed
current speed
Definition: vehicle_base.h:293
Temporary data storage for testing collisions.
Definition: train_cmd.cpp:2980
static void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition: news_func.h:42
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:25
void ReserveTrackUnderConsist() const
Tries to reserve track under whole train consist.
Definition: train_cmd.cpp:2900
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:78
Depot view; Window numbers:
Definition: window_type.h:346
static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir)
Clear the reservation of tile that was just left by a wagon on track_dir.
Definition: train_cmd.cpp:2194
Rail vehicle can be flipped in the depot.
Definition: engine_type.h:159
Types for recording game performance data.
byte spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Definition: vehicle_base.h:279
CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
Build a railroad vehicle.
Definition: train_cmd.cpp:719
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:516
Both directions faces to the same direction.
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
OrderList * list
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:321
Train * GetNextUnit() const
Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consis...
Definition: train.h:145
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded...
Definition: vehicle_base.h:303
Yearly runningcost (if dualheaded: sum of both vehicles)
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:237
uint16 wait_counter
Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through sign...
Definition: train.h:102
static bool IsOnewaySignal(TileIndex t, Track track)
One-way signals can&#39;t be passed the &#39;wrong&#39; way.
Definition: rail_map.h:321
NPFSettings npf
pathfinder settings for the new pathfinder
X-axis track.
Definition: track_type.h:42
Proceed till next signal, but ignore being stuck till then. This includes force leaving depots...
Definition: train.h:41
Functions related to vehicles.
static TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track bits incidating with that diagdir. ...
Definition: track_func.h:534
Stop at the middle of the platform.
Definition: order_type.h:87
static void NormaliseDualHeads(Train *t)
Normalise the dual heads in the train, i.e.
Definition: train_cmd.cpp:887
bool lost_vehicle_warn
if a vehicle can&#39;t find its destination, show a warning
Definition: settings_type.h:86
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:824
uint32 current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:23
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:207
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it...
Definition: vehicle.cpp:1441
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Get the sprite to display the train.
Definition: train_cmd.cpp:465
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:128
PathfinderSettings pf
settings for all pathfinders
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
Process a conditional order and determine the next order.
Definition: order_cmd.cpp:1976
static TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition: map_func.h:384
Vehicle data structure.
Definition: vehicle_base.h:212
int UpdateSpeed()
This function looks at the vehicle and updates its speed (cur_speed and subspeed) variables...
Definition: train_cmd.cpp:2798
Station has seen a train.
Definition: station_type.h:66
static Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir)
Maps a track and an (4-way) dir to the trackdir that represents the track with the entry in the given...
Definition: track_func.h:496
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2188
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Definition: vehicle_base.h:163
DifficultySettings difficulty
settings related to the difficulty
Start or stop this vehicle, and show information about the current state.
bool ambient
Play ambient, industry and town sounds.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:382
static CommandCost CheckNewTrain(Train *original_dst, Train *dst, Train *original_src, Train *src)
Check/validate whether we may actually build a new train.
Definition: train_cmd.cpp:941
CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Reverse train.
Definition: train_cmd.cpp:1893
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:30
uint16 speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: bridge.h:48
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition: vehicle.cpp:2667
T * First() const
Get the first vehicle in the chain.
bool forbid_90_deg
forbid trains to make 90 deg turns
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
static bool IsRailWaypointTile(TileIndex t)
Is this tile a station tile and a rail waypoint?
Definition: station_map.h:125
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:302
Rail vehicle tilts in curves.
Definition: engine_type.h:155
uint16 reliability_spd_dec
Reliability decrease speed.
Definition: vehicle_base.h:262
static Track DiagDirToDiagTrack(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track incidating with that diagdir.
Definition: track_func.h:522
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition: order_cmd.cpp:1892
Determine whether a wagon can be attached to an already existing train.
TileIndex m_old_tile
the origin (vehicle moved from) before move
StringID GetGRFStringID(uint32 grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
A railway.
Definition: tile_type.h:44
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:84
RailTypes compatible_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel ...
Definition: rail.h:190
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition: vehicle.cpp:777
Number of ticks before carried cargo is aged.
static void InsertInConsist(Train *dst, Train *chain)
Inserts a chain into the train at dst.
Definition: train_cmd.cpp:873
T * GetFirstEnginePart()
Get the first part of an articulated engine.
bool IsChainInDepot() const override
Check whether the whole vehicle chain is in the depot.
Flag for an invalid DiagDirection.
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
Common return value for all commands.
Definition: command_type.h:25
static TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction...
Definition: track_func.h:565
uint32 cached_power
Total power of the consist (valid only for the first engine).
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:57
bool m_is_station
last turn passed station
static CommandCost ValidateTrains(Train *original_dst, Train *dst, Train *original_src, Train *src, bool check_limit)
Validate whether we are going to create valid trains.
Definition: train_cmd.cpp:1061
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
Follow a train reservation to the last tile.
Definition: pbs.cpp:291
byte vehstatus
Status.
Definition: vehicle_base.h:317
static void SwapTrainFlags(uint16 *swap_flag1, uint16 *swap_flag2)
Swap the two up/down flags in two ways:
Definition: train_cmd.cpp:1516
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:87
byte flags
Flags of the engine.
Definition: engine_base.h:35
static DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition: track_func.h:449
UnitID GetFreeUnitNumber(VehicleType type)
Get an unused unit number for a vehicle (if allowed).
Definition: vehicle.cpp:1731
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:26
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition: cargopacket.h:366
void CheckTrainsLengths()
Checks if lengths of all rail vehicles are valid.
Definition: train_cmd.cpp:74
static void SetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir, SignalState state)
Sets the state of the signal along the given trackdir.
Definition: rail_map.h:451
bool m_is_bridge
last turn passed bridge ramp
static Train * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
static void RestoreTrainBackup(TrainList &list)
Restore the train from the backup list.
Definition: train_cmd.cpp:833
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
Try to reserve a specific track on a tile.
Definition: pbs.cpp:82
uint16 cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition: vehicle_base.h:123
Money GetRunningCost() const
Get running cost for the train consist.
Definition: train_cmd.cpp:3876
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:253
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:745
Ignore next signal, after the signal ignore being stuck.
Definition: train.h:42
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:81
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
byte VehicleRandomBits()
Get a value for a vehicle&#39;s random_bits.
Definition: vehicle.cpp:363
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition: economy.cpp:966
Southwest.
Non-electrified rails.
Definition: rail_type.h:54
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:64
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:280
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
static void ArrangeTrains(Train **dst_head, Train *dst, Train **src_head, Train *src, bool move_chain)
Arrange the trains in the wanted way.
Definition: train_cmd.cpp:1081
North.
Various explosions.
The vehicle will stop at any station it passes except the destination.
Definition: order_type.h:77
int8 x_bb_offs
x offset of vehicle bounding box
Definition: vehicle_base.h:284
static Vehicle * FindTrainCollideEnum(Vehicle *v, void *data)
Collision test function.
Definition: train_cmd.cpp:2991
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the engine is tied to.
Definition: engine.cpp:162
when autoreplace/autorenew is in progress, this shall prevent truncating the amount of cargo in the v...
Definition: command_type.h:354
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:126
bool SwitchToNextOrder(bool skip_first)
Set the current vehicle order to the next order in the order list.
Definition: train_cmd.cpp:2463
Stop at the near end of the platform.
Definition: order_type.h:86
No rail types.
Definition: rail_type.h:53
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
Right track.
Definition: track_type.h:47
static void SetCrossingBarred(TileIndex t, bool barred)
Set the bar state of a level crossing.
Definition: road_map.h:430
Functions related to (drawing on) viewports.
Normal rail tile with signals.
Definition: rail_map.h:27
Pseudo random number generator.
uint Crash(bool flooded=false)
The train vehicle crashed! Update its status and other parts around it.
Definition: train_cmd.cpp:2922
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length)
Get the stop location of (the center) of the front vehicle of a train at a platform of a station...
Definition: train_cmd.cpp:259
int8 y_bb_offs
y offset of vehicle bounding box
Definition: vehicle_base.h:285
Angle of 45 degrees right.
byte breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:263
Stop at the far end of the platform.
Definition: order_type.h:88
static Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition: track_func.h:203
static bool CheckTrainCollision(Train *v)
Checks whether the specified train has a collision with another vehicle.
Definition: train_cmd.cpp:3038
static void MakeTrainBackup(TrainList &list, Train *t)
Make a backup of a train into a train list.
Definition: train_cmd.cpp:824
static const AccelerationSlowdownParams _accel_slowdown[]
Speed update fractions for each acceleration type.
Definition: train_cmd.cpp:2859
Train()
We don&#39;t want GCC to zero our struct! It already is zeroed and has an index!
Definition: train.h:105
TextEffectID fill_percent_te_id
a text-effect id to a loading indicator object
Definition: vehicle_base.h:290
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3318
static bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex station_tile)
Check if a tile is a valid continuation to a railstation tile.
Definition: station_map.h:380
bool reverse_at_signals
whether to reverse at signals at all
Critical errors, the MessageBox is shown in all cases.
Definition: error.h:26
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:2233
static void MaybeBarCrossingWithSound(TileIndex tile)
Bars crossing and plays ding-ding sound if not barred already.
Definition: train_cmd.cpp:1700
uint16 cargo_cap
total capacity
Definition: vehicle_base.h:307
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:331
static bool IsTileOwner(TileIndex tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:216
Header of Action 04 "universal holder" structure and functions.
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition: order_base.h:137
byte z_up
Fraction to remove when moving up.
Definition: train_cmd.cpp:2854
Vehicle orders; Window numbers:
Definition: window_type.h:207
User defined data for vehicle variable 0x42.
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a train sprite heading west, or both heads (used for lists)...
Definition: train_cmd.cpp:552
static const uint32 MAKE_ORDER_BACKUP_FLAG
Flag to pass to the vehicle construction command when an order should be preserved.
Definition: order_backup.h:31
uint8 freight_trains
value to multiply the weight of cargo by
Vehicle is crashed.
Definition: vehicle_base.h:39
Vehicle is a prototype (accepted as exclusive preview).
Definition: vehicle_base.h:46
static DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
Determines the DiagDirection to get from one tile to another.
Definition: map_func.h:396
byte acceleration
used by train & aircraft
Definition: vehicle_base.h:295
bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
Try to extend the reserved path of a train to the nearest safe tile using YAPF.
Definition: yapf_rail.cpp:628
static TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:343
uint16 reliability_spd_dec
Speed of reliability decay between services (per day).
Definition: engine_base.h:28
int traininfo_vehicle_pitch
Vertical offset for drawing train images in depot GUI and vehicle details.
Definition: newgrf.h:144
static bool IsValidTrackdir(Trackdir trackdir)
Checks if a Trackdir is valid for non-road vehicles.
Definition: track_func.h:62
bool Tick()
Update train vehicle data for a tick.
Definition: train_cmd.cpp:3901
void SubtractMoneyFromCompanyFract(CompanyID company, CommandCost cst)
Subtract money from a company, including the money fraction.
Track NPFTrainChooseTrack(const Train *v, bool &path_found, bool reserve_track, struct PBSTileInfo *target)
Finds the best path for given train using NPF.
Definition: npf.cpp:1302
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:152
bool IsWagon() const
Check if a vehicle is a wagon.
static void DeleteLastWagon(Train *v)
Deletes/Clears the last wagon of a crashed train.
Definition: train_cmd.cpp:3435
Functions related to errors.
static Vehicle * TrainOnTileEnum(Vehicle *v, void *)
Check if the vehicle is a train.
Definition: train_cmd.cpp:1623
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:291
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:78
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:443
byte cargo_subtype
Used for livery refits (NewGRF variations)
Definition: vehicle_base.h:306
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1332
void SetEngine()
Set engine status.
FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_penalty)
Used when user sends train to the nearest depot or if train needs servicing using NPF...
Definition: npf.cpp:1240
uint16 crash_anim_pos
Crash animation counter.
Definition: train.h:93
bool IsValid() const
Check whether the sequence contains any sprites.
Definition: vehicle_base.h:147
static void UpdateStatusAfterSwap(Train *v)
Updates some variables after swapping the vehicle.
Definition: train_cmd.cpp:1544
SoundSettings sound
sound effect settings
static bool IsRailStationTile(TileIndex t)
Is this tile a station tile and a rail station?
Definition: station_map.h:104
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
Definition: train_cmd.cpp:109
Segment is a PBS segment.
Definition: signal_func.h:54
YAPFSettings yapf
pathfinder settings for the yet another pathfinder
#define FIND_FIRST_BIT(x)
Returns the first non-zero bit in a 6-bit value (from right).
bool NeedsServicing() const
Check if the vehicle needs to go to a depot in near future (if a opportunity presents itself) for ser...
Definition: vehicle.cpp:185
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:134
int8 y_offs
y offset for vehicle sprite
Definition: vehicle_base.h:287
East.
void HideFillingPercent(TextEffectID *te_id)
Hide vehicle loading indicators.
Definition: misc_gui.cpp:653
We want to stop.
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:18
CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Force a train through a red signal.
Definition: train_cmd.cpp:1966
uint16 pow_wag_power
Extra power applied to consist if wagon should be powered.
Definition: engine_type.h:57
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:63
uint16 max_speed
Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: engine_type.h:49
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition: vehicle.cpp:568
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:180
Southeast.
static DiagDirection GetRailDepotDirection(TileIndex t)
Returns the direction the depot is facing to.
Definition: rail_map.h:173
static DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:344
T * Next() const
Get next vehicle in the chain.
byte callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:145
simple wagon, not motorized
Definition: engine_type.h:31
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:80
Standard non-electric rails.
Definition: rail_type.h:31
bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
Determine whether a certain track on a tile is a safe position to end a path.
Definition: pbs.cpp:383
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition: tile_cmd.h:24
Definition of base types and functions in a cross-platform compatible way.
Shift the VehicleEnterTileStatus this many bits to the right to get the station ID when VETS_ENTERED_...
Definition: tile_cmd.h:32
bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg)
Check if a safe position is free.
Definition: pbs.cpp:429
static const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition: bridge.h:67
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
Definition: vehicle_type.h:78
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:892
A number of safeguards to prevent using unsafe methods.
AccelStatus GetAccelerationStatus() const
Checks the current acceleration status of this vehicle.
Definition: train.h:264
byte x_extent
x-extent of vehicle bounding box
Definition: vehicle_base.h:281
#define FOR_EACH_SET_TRACK(var, track_bits)
Iterate through each set Track in a TrackBits value.
Definition: track_func.h:29
uint best_length
The distance towards the depot in penalty, or UINT_MAX if not found.
uint8 acceleration_type
Acceleration type of this rail type.
Definition: rail.h:225
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2134
Direction
Defines the 8 directions on the map.
Flag for an invalid trackdir.
Definition: track_type.h:91
std::vector< Train * > TrainList
Helper type for lists/vectors of trains.
Definition: train_cmd.cpp:817
void SetTrainGroupID(Train *v, GroupID grp)
Affect the groupID of a train to new_g.
Definition: group_cmd.cpp:747
static Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
Removes first Trackdir from TrackdirBits and returns it.
Definition: track_func.h:166
Vehicle refit; Window numbers:
Definition: window_type.h:201
Vehicle length (trains and road vehicles)
This class will save the current order of a vehicle and restore it on destruction.
Definition: train_cmd.cpp:2430
DirDiff
Enumeration for the difference between two directions.
byte z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:283
Vehicle starting, i.e. leaving, the station.
Definition: newgrf_sound.h:21
Valid changes for arranging the consist in a depot.
Definition: train.h:54
static Axis GetCrossingRailAxis(TileIndex t)
Get the rail axis of a level crossing.
Definition: road_map.h:339
static TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
Returns the red-signal-information of a TrackStatus.
Definition: track_func.h:386
static bool HasPbsSignalOnTrackdir(TileIndex tile, Trackdir td)
Is a pbs signal present along the trackdir?
Definition: rail_map.h:465
static void NormaliseSubtypes(Train *chain)
Normalise the sub types of the parts in this chain.
Definition: train_cmd.cpp:909
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:305
static Axis GetCrossingRoadAxis(TileIndex t)
Get the road axis of a level crossing.
Definition: road_map.h:327
static bool IsValidDiagDirection(DiagDirection d)
Checks if an integer value is a valid DiagDirection.
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition: vehicle.cpp:2696
byte capacity
Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
Definition: engine_type.h:55
Vehicle view; Window numbers:
Definition: window_type.h:334
byte large_turn
Speed change due to a large turn.
Definition: train_cmd.cpp:2853
uint traininfo_vehicle_width
Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details.
Definition: newgrf.h:145
TrackBits
Bitfield corresponding to Track.
Definition: track_type.h:40
Functions related to order backups.
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:883
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:144
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:498
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
South.
New PathFinder.
Definition: vehicle_type.h:62
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
byte shorten_factor
length on main map for this type is 8 - shorten_factor
Definition: engine_type.h:60
static Track DoTrainPathfind(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool do_track_reservation, PBSTileInfo *dest)
Perform pathfinding for a train.
Definition: train_cmd.cpp:2312
byte FreightWagonMult(CargoID cargo)
Return the cargo weight multiplier to use for a rail vehicle.
Definition: train_cmd.cpp:67
Functions to access the new pathfinder.
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
Definition: group_cmd.cpp:138
static Trackdir TrackDirectionToTrackdir(Track track, Direction dir)
Maps a track and a full (8-way) direction to the trackdir that represents the track running in the gi...
Definition: track_func.h:508
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:1940
Vehicle timetable; Window numbers:
Definition: window_type.h:219
static void CheckIfTrainNeedsService(Train *v)
Check whether a train needs service, and if so, find a depot or service it.
Definition: train_cmd.cpp:3930
static Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:547
VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition: vehicle.cpp:1679
void UpdateDeltaXY()
Updates the x and y offsets and the size of the sprite used for this vehicle.
Definition: train_cmd.cpp:1424
Basic functions/variables used all over the place.
static DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
bool IsRearDualheaded() const
Tell if we are dealing with the rear end of a multiheaded engine.
static Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
bool okay
True if tile is a safe waiting position, false otherwise.
Definition: pbs.h:31
int8 x_offs
x offset for vehicle sprite
Definition: vehicle_base.h:286
static void RemoveFromConsist(Train *part, bool chain=false)
Remove the given wagon from its consist.
Definition: train_cmd.cpp:856
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:130
static Track GetRailDepotTrack(TileIndex t)
Returns the track of a depot, ignoring direction.
Definition: rail_map.h:184
void UpdateTrainGroupID(Train *v)
Recalculates the groupID of a train.
Definition: group_cmd.cpp:775
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:534
static uint TrainCrashed(Train *v)
Marks train as crashed and creates an AI event.
Definition: train_cmd.cpp:2961
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
static TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir)
Maps a trackdir to the trackdirs that can be reached from it (ie, when entering the next tile...
Definition: track_func.h:594
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
bool NPFTrainCheckReverse(const Train *v)
Returns true if it is better to reverse the train before leaving station using NPF.
Definition: npf.cpp:1283
uint16 refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:308
byte random_bits
Bits used for determining which randomized variational spritegroups to use when drawing.
Definition: vehicle_base.h:299
Functions related to sound.
Add articulated engines (trains and road vehicles)
uint16 reliability
Reliability.
Definition: vehicle_base.h:261
Data structure for storing engine speed changes of an acceleration type.
Definition: train_cmd.cpp:2851
static void CheckNextTrainTile(Train *v)
Check if the train is on the last reserved tile and try to extend the path then.
Definition: train_cmd.cpp:2054
static DiagDirection GetTunnelBridgeDirection(TileIndex t)
Get the direction pointing to the other end.
static bool IsPlainRailTile(TileIndex t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition: rail_map.h:62
Vehicle is currently going uphill. (Cached track information for acceleration)
Track follower helper template class (can serve pathfinders and vehicle controllers).
Functions to cache sprites in memory.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
bool Failed() const
Did this command fail?
Definition: command_type.h:161
uint16 power
Power of engine (hp); For multiheaded engines the sum of both engine powers.
Definition: engine_type.h:50
byte tick_counter
Increased by one for each tick.
Definition: vehicle_base.h:314
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
void CheckCargoCapacity(Vehicle *v)
Check the capacity of all vehicles in a chain and spread cargo if needed.
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
Update the vehicle&#39;s destination tile from an order.
Definition: order_cmd.cpp:2006
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint32 user)
Sell a (single) train wagon/engine.
Definition: train_cmd.cpp:1349
static bool Chance16R(const uint a, const uint b, uint32 &r)
Flips a coin with a given probability and saves the randomize-number in a variable.
byte small_turn
Speed change due to a small turn.
Definition: train_cmd.cpp:2852
static void BarCrossing(TileIndex t)
Bar a level crossing.
Definition: road_map.h:449
Bitflag for a wormhole (used for tunnels)
Definition: track_type.h:57
static DepotID GetDepotIndex(TileIndex t)
Get the index of which depot is attached to the tile.
Definition: depot_map.h:54
Year build_year
Year the vehicle has been built.
Definition: vehicle_base.h:257
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event)
Checks whether a NewGRF wants to play a different vehicle sound effect.
static Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition: track_func.h:257
TileIndex tile
Tile the path ends, INVALID_TILE if no valid path was found.
Definition: pbs.h:29
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:35
Information about a rail vehicle.
Definition: engine_type.h:44
static const uint16 _breakdown_speeds[16]
Maximum speeds for train that is broken down or approaching line end.
Definition: train_cmd.cpp:3566
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:591
bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: train.h:115
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:238
void OnNewDay()
Update day counters of the train vehicle.
Definition: train_cmd.cpp:3973
static bool HasSignals(TileIndex t)
Checks if a rail tile has signals.
Definition: rail_map.h:74
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
Try to reserve any path to a safe tile, ignoring the vehicle&#39;s destination.
Definition: train_cmd.cpp:2419
autoreplace/autorenew is in progress, this shall disable vehicle limits when building, and ignore certain restrictions when undoing things (like vehicle attach callback)
Definition: command_type.h:353
static TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction...
Definition: track_func.h:583
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:87
static bool Chance16(const uint a, const uint b)
Flips a coin with given probability.
TileIndex tile
The tile of the depot.
This struct contains information about the end of a reserved path.
Definition: pbs.h:28
static RailTileType GetRailTileType(TileIndex t)
Returns the RailTileType (normal with or without signals, waypoint or depot).
Definition: rail_map.h:38
TileIndex old_tile
Current tile of the vehicle.
Definition: vehicle_func.h:79
static BridgeType GetBridgeType(TileIndex t)
Determines the type of bridge on a tile.
Definition: bridge_map.h:58
static bool CheckTrainStayInDepot(Train *v)
Will the train stay in the depot the next tick?
Definition: train_cmd.cpp:2116
FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_distance)
Used when user sends train to the nearest depot or if train needs servicing using YAPF...
Definition: yapf_rail.cpp:609
static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse)
Train is approaching line end, slow down and possibly reverse.
Definition: train_cmd.cpp:3579
static TrackBits GetTrackBits(TileIndex tile)
Gets the track bits of the given tile.
Definition: rail_map.h:138
CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Move a rail vehicle around inside the depot.
Definition: train_cmd.cpp:1155
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1146
Wagon is powered.
Definition: train.h:29
Bitflag for a depot.
Definition: track_type.h:58
static Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
uint Crash(bool flooded) override
Common code executed for crashed ground vehicles.
Lower track.
Definition: track_type.h:45
static TileIndex GetOtherTunnelBridgeEnd(TileIndex t)
Determines type of the wormhole and returns its other end.
Angle of 90 degrees left.
Transport by train.
execute the given command
Definition: command_type.h:346
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
Locate the closest depot for this consist, and return the information to the caller.
Definition: train_cmd.cpp:2021
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:176
static TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition: track_func.h:87
Open the refit window.
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:19
static void AdvanceWagonsAfterSwap(Train *v)
Advances wagons for train reversing, needed for variable length wagons.
Definition: train_cmd.cpp:1743
Functions related to companies.
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a train vehicle image in the GUI.
Definition: train_cmd.cpp:435
byte path_backoff_interval
ticks between checks for a free path.
RailType GetTileRailType(TileIndex tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition: rail.cpp:157
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing...
Definition: vehicle.cpp:1625
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1564
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:30
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition: map_func.h:196
void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
Checks whether the specs of freshly build articulated vehicles are consistent with the information sp...
OrderStopLocation
Where to stop the trains.
Definition: order_type.h:85
Vehicle is currently going downhill. (Cached track information for acceleration)
Allow vehicles to change length.
Definition: train.h:47
Electric train engine is allowed to run on normal rail. */.
Definition: train.h:32
No track.
Definition: track_type.h:41
static T KillFirstBit(T value)
Clear the first bit in an integer.
Functions related to articulated vehicles.
void ErrorUnknownCallbackResult(uint32 grfid, uint16 cbid, uint16 cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Trigger platform when train arrives.
Header file for NewGRF stations.
Track along the y-axis (north-west to south-east)
Definition: track_type.h:24
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
Train can&#39;t get a path reservation.
Definition: train.h:34
Trackdir GetVehicleTrackdir() const
Get the tracks of the train vehicle.
Definition: train_cmd.cpp:4011
static bool TrainCanLeaveTile(const Train *v)
Determines whether train would like to leave the tile.
Definition: train_cmd.cpp:3624
T * Previous() const
Get previous vehicle in the chain.
GUISettings gui
settings related to the GUI
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:52
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:96
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:140
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition: vehicle.cpp:164
Running costs trains.
Definition: economy_type.h:153
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3213
byte subspeed
fractional speed
Definition: vehicle_base.h:294
static bool IsRailDepotTile(TileIndex t)
Is this tile rail tile and a rail depot?
Definition: rail_map.h:107
void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoID cargo=CT_NO_REFIT)
Makes this order a Go To Depot order.
Definition: order_cmd.cpp:91
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds, and ending the breakdown when appropriate.
Definition: vehicle.cpp:1266
int cached_max_curve_speed
max consist speed limited by curves
Definition: train.h:81
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:19
OrderStopLocation GetStopLocation() const
Where must we stop at the platform?
Definition: order_base.h:135
Used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle ...
Definition: train.h:33
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:23
Upper track.
Definition: track_type.h:44
bool line_reverse_mode
reversing at stations or not
Definition: settings_type.h:69
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:119
T * Last()
Get the last vehicle in the chain.
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1589
The vehicle entered a station.
Definition: tile_cmd.h:23
uint GetAdvanceDistance()
Determines the vehicle "progress" needed for moving a step.
Definition: vehicle_base.h:414
Used for iterations.
Helper container to find a depot.
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2041
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:581
Date date_of_last_service
Last date the vehicle had a service at a depot.
Definition: vehicle_base.h:260
void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBugs bug_type, bool critical)
Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
Definition: vehicle.cpp:298
byte z_down
Fraction to add when moving down.
Definition: train_cmd.cpp:2855
Position information of a vehicle after it moved.
Definition: vehicle_func.h:77
Base includes/functions for YAPF.
static bool IsLevelCrossingTile(TileIndex t)
Return whether a tile is a level crossing tile.
Definition: road_map.h:96
First vehicle arrived for company.
Definition: news_type.h:24
Track
These are used to specify a single track.
Definition: track_type.h:21
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:438
static bool HandleCrashedTrain(Train *v)
Handle a crashed train.
Definition: train_cmd.cpp:3527
bool wagon_speed_limits
enable wagon speed limits
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:217
Train * v
Vehicle we are testing for collision.
Definition: train_cmd.cpp:2981
void Free()
&#39;Free&#39; the order
Definition: order_cmd.cpp:64
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:114
uint8 pathfinder_for_trains
the pathfinder to use for trains
SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner)
Update signals, starting at one side of a tile Will check tile next to this at opposite side too...
Definition: signal.cpp:640
static T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:83
indicates a combination of two locomotives
Definition: engine_type.h:30
TrackBits GetReservedTrackbits(TileIndex t)
Get the reserved trackbits for any tile, regardless of type.
Definition: pbs.cpp:26
TileIndex m_new_tile
the new tile (the vehicle has entered)
TileIndex xy
Base tile of the station.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
uint16 cached_total_length
Length of the whole vehicle (valid only for the first engine).
byte wait_twoway_signal
waitingtime in days before a twoway signal
Trains list; Window numbers:
Definition: window_type.h:303
Functions related to zooming.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:54
Vehicle * next
pointer to the next vehicle in the chain
Definition: vehicle_base.h:217
A tile of a station.
Definition: tile_type.h:48
static Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or INVALID_TRACK.
Definition: track_func.h:187
RAII class for measuring multi-step elements of performance.
OrderType
Order types.
Definition: order_type.h:37
Reverse the visible direction of the vehicle.
Definition: train.h:30
bool show_track_reservation
highlight reserved tracks.
void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool b)
Set the reservation for a complete station platform.
Definition: pbs.cpp:59
Northwest.
void CopyVehicleConfigAndStatistics(const Vehicle *src)
Copy certain configurations and statistics of a vehicle after successful autoreplace/renew The functi...
Definition: vehicle_base.h:712
int GetCurveSpeedLimit() const
Computes train speed limit caused by curves.
Definition: train_cmd.cpp:303
T * GetNextVehicle() const
Get the next real (non-articulated part) vehicle in the consist.
bool disaster
Play disaster and accident sounds.
SigSegState
State of the signal segment.
Definition: signal_func.h:51
uint16 cached_max_track_speed
Maximum consist speed (in internal units) limited by track type (valid only for the first engine)...
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
static bool IsCompatibleRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType can drive on a tile with a given RailType.
Definition: rail.h:321
RailTypes powered_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype generates power ...
Definition: rail.h:187
int32 z_pos
z coordinate.
Definition: vehicle_base.h:270
Vehicle is not visible.
Definition: vehicle_base.h:32
Vehicle details; Window numbers:
Definition: window_type.h:195
void UpdateLevelCrossing(TileIndex tile, bool sound)
Sets correct crossing state.
Definition: train_cmd.cpp:1678
static DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Definition: track_func.h:724
Used for iterations.
Definition: track_type.h:22
Base functions for all Games.
The signal is red.
Definition: signal_type.h:47
Functions related to commands.
static void AdvanceWagonsBeforeSwap(Train *v)
Advances wagons for train reversing, needed for variable length wagons.
Definition: train_cmd.cpp:1715
Coordinates of a point in 2D.
An accident or disaster has occurred.
Definition: news_type.h:26
Northeast.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
static void AffectSpeedByZChange(Train *v, int old_z)
Modify the speed of the vehicle due to a change in altitude.
Definition: train_cmd.cpp:2871
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:765
uint8 train_acceleration_model
realistic acceleration for trains
uint32 maximum_go_to_depot_penalty
What is the maximum penalty that may be endured for going to a depot.
UnitID max_trains
max trains in game per company
static void ChangeTrainDirRandomly(Train *v)
Rotate all vehicles of a (crashed) train chain randomly to animate the crash.
Definition: train_cmd.cpp:3499
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or nullptr when it doesn&#39;t exists.
Definition: vehicle_base.h:860
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:19
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Definition: vehicle_base.h:687
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
uint num
Total number of victims if train collided.
Definition: train_cmd.cpp:2982
void MarkDirty()
Goods at the consist have changed, update the graphics, cargo, and acceleration.
Definition: train_cmd.cpp:2778
DiagDirection m_exitdir
exit direction (leaving the old tile)
static void TrainEnterStation(Train *v, StationID station)
Trains enters a station, send out a news item if it is the first train, and start loading...
Definition: train_cmd.cpp:2815
void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner)
Update signals at segments that are at both ends of given (existent or non-existent) track...
Definition: signal.cpp:658
void SetLastSpeed()
Update the GUI variant of the current speed of the vehicle.
uint8 cached_veh_length
Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can b...
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
uint8 original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition: engine_base.h:41
byte running_ticks
Number of ticks this vehicle was not stopped this day.
Definition: vehicle_base.h:315
byte y_extent
y-extent of vehicle bounding box
Definition: vehicle_base.h:282
Flag to disable wagon power.
Definition: vehicle_base.h:92
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:288
Trackdir m_old_td
the trackdir (the vehicle was on) before move
static TrackBits TrackCrossesTracks(Track track)
Maps a track to all tracks that make 90 deg turns with it.
Definition: track_func.h:430
void RemoveVehicleFromGroup(const Vehicle *v)
Decrease the num_vehicle variable before delete an front engine from a group.
Definition: group_cmd.cpp:733
int GetCurrentMaxSpeed() const
Calculates the maximum speed of the vehicle under its current conditions.
Definition: train_cmd.cpp:372
int32 x_pos
x coordinate.
Definition: vehicle_base.h:268
Trackdir trackdir
The reserved trackdir on the tile.
Definition: pbs.h:30
byte VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition: order_type.h:17
uint16 vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:32
static bool HasReservedTracks(TileIndex tile, TrackBits tracks)
Check whether some of tracks is reserved on a tile.
Definition: pbs.h:60
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Functions related to NewGRF provided sounds.
DiagDirection
Enumeration for diagonal directions.
Base functions for all AIs.
static TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition: track_func.h:329
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
bool reserve_paths
always reserve paths regardless of signal type.
void SetFreeWagon()
Set a vehicle as a free wagon.
static bool IsCrossingBarred(TileIndex t)
Check if the level crossing is barred.
Definition: road_map.h:418
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:755
static void NormalizeTrainVehInDepot(const Train *u)
Move all free vehicles in the depot to the train.
Definition: train_cmd.cpp:663
byte progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition: vehicle_base.h:297
The vehicle cannot enter the tile.
Definition: tile_cmd.h:25
static bool IsPlainRail(TileIndex t)
Returns whether this is plain rails, with or without signals.
Definition: rail_map.h:51
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:69
Specification of a rectangle with absolute coordinates of all edges.
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
int32 y_pos
y coordinate.
Definition: vehicle_base.h:269
uint16 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:194
uint16 cargo_age_period
Number of ticks before carried cargo is aged.
Definition: engine_type.h:148
New vehicles.
Definition: economy_type.h:152
static Vehicle * CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data)
Collect trackbits of all crashed train vehicles on a tile.
Definition: train_cmd.cpp:3411
byte wait_for_pbs_path
how long to wait for a path reservation.
static TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition: track_func.h:318
Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, struct PBSTileInfo *target)
Finds the best path for given train using YAPF.
Definition: yapf_rail.cpp:535
std::vector< Train * > TrainList
Helper type for lists/vectors of trains.
Definition: rail_cmd.cpp:44
static bool HasDepotReservation(TileIndex t)
Get the reservation state of the depot.
Definition: rail_map.h:260
static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const Engine *e, Vehicle **ret)
Build a railroad wagon.
Definition: train_cmd.cpp:587
Station with train station.
Definition: station_type.h:54
static bool HasOnewaySignalBlockingTrackdir(TileIndex tile, Trackdir td)
Is a one-way signal blocking the trackdir? A one-way signal on the trackdir against will block...
Definition: rail_map.h:477
static void Backup(const Vehicle *v, uint32 user)
Create an order backup for the given vehicle.
static DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
Vehicle length, returns the amount of 1/8&#39;s the vehicle is shorter for trains and RVs...
bool YapfTrainCheckReverse(const Train *v)
Returns true if it is better to reverse the train before leaving station using YAPF.
Definition: yapf_rail.cpp:550
static SignalState GetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir)
Gets the state of the signal along the given trackdir.
Definition: rail_map.h:440
static TileIndex TrainApproachingCrossingTile(const Train *v)
Determines whether train is approaching a rail-road crossing (thus making it barred) ...
Definition: train_cmd.cpp:3654
int UpdateInclination(bool new_tile, bool update_delta)
Checks if the vehicle is in a slope and sets the required flags in that case.
move a rail vehicle (in the depot)
Definition: command_type.h:222
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition: vehicle_base.h:239
void SetMultiheaded()
Set a vehicle as a multiheaded engine.
byte running_cost
Running cost of engine; For multiheaded engines the sum of both running costs.
Definition: engine_type.h:52
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3227
uint DetermineCapacity(const Vehicle *v, uint16 *mail_capacity=nullptr) const
Determines capacity of a given vehicle from scratch.
Definition: engine.cpp:206
Functions related to news.
normal pbs signal
Definition: signal_type.h:30
TileIndex GetOrderStationLocation(StationID station)
Get the location of the next station to visit.
Definition: train_cmd.cpp:2763
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:330
static Station * Get(size_t index)
Gets station with given index.
int m_tiles_skipped
number of skipped tunnel or station tiles
Date _date
Current date in days (day counter)
Definition: date.cpp:28
void SetWagon()
Set a vehicle to be a wagon.
static Direction ReverseDir(Direction d)
Return the reverse of a direction.
byte wait_oneway_signal
waitingtime in days before a oneway signal
Company view; Window numbers:
Definition: window_type.h:364
static TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
Definition: track_func.h:616
TileIndex new_tile
Tile of the vehicle after moving.
Definition: vehicle_func.h:80
static bool Rail90DegTurnDisallowed(RailType rt1, RailType rt2, bool def=_settings_game.pf.forbid_90_deg)
Test if 90 degree turns are disallowed between two railtypes.
Definition: rail.h:356
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Definition: vehicle_base.h:219
uint GetPlatformLength(TileIndex tile, DiagDirection dir) const override
Determines the REMAINING length of a platform, starting at (and including) the given tile...
Definition: station.cpp:272
Allow vehicles to change capacity.
Definition: train.h:48
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Y-axis track.
Definition: track_type.h:43
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
This depot order is because of the servicing limit.
Definition: order_type.h:97
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:29
static bool IsTunnel(TileIndex t)
Is this a tunnel (entrance)?
Definition: tunnel_map.h:24
byte user_def_data
Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles.
Definition: engine_type.h:63
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:2250
Valid changes while vehicle is driving, and possibly changing tracks.
Definition: train.h:50
static TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition: track_func.h:362
SoundFx
Sound effects from baseset.
Definition: sound_type.h:39
void ReverseTrainDirection(Train *v)
Turn a train around.
Definition: train_cmd.cpp:1800
Station data structure.
Definition: station_base.h:452
Functions related to effect vehicles.
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition: order_base.h:133
Time spent processing trains.
void FreeTrainTrackReservation(const Train *v)
Free the reserved path in front of a vehicle.
Definition: train_cmd.cpp:2235
uint32 cached_weight
Total weight of the consist (valid only for the first engine).
void InvalidateNewGRFCache()
Invalidates cached NewGRF variables.
Definition: vehicle_base.h:451
Disable insertion and removal of automatic orders until the vehicle completes the real order...
A game paused because a (critical) error.
Definition: openttd.h:62
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:100
Date GetLifeLengthInDays() const
Returns the vehicle&#39;s (not model&#39;s!) life length in days.
Definition: engine.cpp:446
Train is slowing down.
Definition: vehicle_base.h:36
static void MarkTrainAsStuck(Train *v)
Mark a train as stuck and stop it if it isn&#39;t stopped right now.
Definition: train_cmd.cpp:1492
byte day_counter
Increased by one for each day.
Definition: vehicle_base.h:313
static RailType GetRailType(TileIndex t)
Gets the rail type of the given tile.
Definition: rail_map.h:117
static bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition: track_func.h:655
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:318
static bool IsBridge(TileIndex t)
Checks if this is a bridge, instead of a tunnel.
Definition: bridge_map.h:26
static Direction DiagDirToDir(DiagDirection dir)
Convert a DiagDirection to a Direction.
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:326
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:3300
bool IsEngine() const
Check if a vehicle is an engine (can be first in a consist).
void UpdateAcceleration()
Update acceleration of the train from the cached power and weight.
Definition: train_cmd.cpp:420
GroundVehicleCache gcache
Cache of often calculated values.
The signal is green.
Definition: signal_type.h:48
void UnreserveRailTrack(TileIndex tile, Track t)
Lift the reservation of a specific track on a tile.
Definition: pbs.cpp:143
static Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
Returns first Trackdir from TrackdirBits or INVALID_TRACKDIR.
Definition: track_func.h:221
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition: vehicle_base.h:254
static Train * GetIfValid(size_t index)
Returns vehicle if the index is a valid index for this vehicle type.
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
uint8 max_train_length
maximum length for trains
static void SetDepotReservation(TileIndex t, bool b)
Set the reservation state of the depot.
Definition: rail_map.h:272
static void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station=INVALID_STATION)
Adds a newsitem referencing a vehicle.
Definition: news_func.h:32
Base for the NewGRF implementation.
pause the game
Definition: command_type.h:256