OpenTTD
train_cmd.cpp
Go to the documentation of this file.
1 /* $Id: train_cmd.cpp 27893 2017-08-13 18:38:42Z frosch $ */
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 
39 #include "table/strings.h"
40 #include "table/train_cmd.h"
41 
42 #include "safeguards.h"
43 
44 static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
45 static bool TrainCheckIfLineEnds(Train *v, bool reverse = true);
46 bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // Also used in vehicle_sl.cpp.
48 static void CheckIfTrainNeedsService(Train *v);
49 static void CheckNextTrainTile(Train *v);
50 
51 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8};
52 static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
53 
54 template <>
55 bool IsValidImageIndex<VEH_TRAIN>(uint8 image_index)
56 {
57  return image_index < lengthof(_engine_sprite_base);
58 }
59 
68 {
70 
71  DiagDirection diagdir = DirToDiagDir(direction);
72 
73  /* Determine the diagonal direction in which we will exit this tile */
74  if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) {
75  diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT);
76  }
77 
78  return diagdir;
79 }
80 
81 
88 {
89  if (!CargoSpec::Get(cargo)->is_freight) return 1;
91 }
92 
95 {
96  const Train *v;
97  bool first = true;
98 
99  FOR_ALL_TRAINS(v) {
100  if (v->First() == v && !(v->vehstatus & VS_CRASHED)) {
101  for (const Train *u = v, *w = v->Next(); w != NULL; u = w, w = w->Next()) {
102  if (u->track != TRACK_BIT_DEPOT) {
103  if ((w->track != TRACK_BIT_DEPOT &&
104  max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->CalcNextVehicleOffset()) ||
105  (w->track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) {
106  SetDParam(0, v->index);
107  SetDParam(1, v->owner);
108  ShowErrorMessage(STR_BROKEN_VEHICLE_LENGTH, INVALID_STRING_ID, WL_CRITICAL);
109 
110  if (!_networking && first) {
111  first = false;
113  }
114  /* Break so we warn only once for each train. */
115  break;
116  }
117  }
118  }
119  }
120  }
121 }
122 
130 {
131  uint16 max_speed = UINT16_MAX;
132 
133  assert(this->IsFrontEngine() || this->IsFreeWagon());
134 
135  const RailVehicleInfo *rvi_v = RailVehInfo(this->engine_type);
136  EngineID first_engine = this->IsFrontEngine() ? this->engine_type : INVALID_ENGINE;
137  this->gcache.cached_total_length = 0;
138  this->compatible_railtypes = RAILTYPES_NONE;
139 
140  bool train_can_tilt = true;
141 
142  for (Train *u = this; u != NULL; u = u->Next()) {
143  const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
144 
145  /* Check the this->first cache. */
146  assert(u->First() == this);
147 
148  /* update the 'first engine' */
149  u->gcache.first_engine = this == u ? INVALID_ENGINE : first_engine;
150  u->railtype = rvi_u->railtype;
151 
152  if (u->IsEngine()) first_engine = u->engine_type;
153 
154  /* Set user defined data to its default value */
155  u->tcache.user_def_data = rvi_u->user_def_data;
156  this->InvalidateNewGRFCache();
157  u->InvalidateNewGRFCache();
158  }
159 
160  for (Train *u = this; u != NULL; u = u->Next()) {
161  /* Update user defined data (must be done before other properties) */
162  u->tcache.user_def_data = GetVehicleProperty(u, PROP_TRAIN_USER_DATA, u->tcache.user_def_data);
163  this->InvalidateNewGRFCache();
164  u->InvalidateNewGRFCache();
165  }
166 
167  for (Train *u = this; u != NULL; u = u->Next()) {
168  const Engine *e_u = u->GetEngine();
169  const RailVehicleInfo *rvi_u = &e_u->u.rail;
170 
171  if (!HasBit(e_u->info.misc_flags, EF_RAIL_TILTS)) train_can_tilt = false;
172 
173  /* Cache wagon override sprite group. NULL is returned if there is none */
174  u->tcache.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->gcache.first_engine);
175 
176  /* Reset colour map */
177  u->colourmap = PAL_NONE;
178 
179  /* Update powered-wagon-status and visual effect */
180  u->UpdateVisualEffect(true);
181 
182  if (rvi_v->pow_wag_power != 0 && rvi_u->railveh_type == RAILVEH_WAGON &&
183  UsesWagonOverride(u) && !HasBit(u->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
184  /* wagon is powered */
185  SetBit(u->flags, VRF_POWEREDWAGON); // cache 'powered' status
186  } else {
187  ClrBit(u->flags, VRF_POWEREDWAGON);
188  }
189 
190  if (!u->IsArticulatedPart()) {
191  /* Do not count powered wagons for the compatible railtypes, as wagons always
192  have railtype normal */
193  if (rvi_u->power > 0) {
194  this->compatible_railtypes |= GetRailTypeInfo(u->railtype)->powered_railtypes;
195  }
196 
197  /* Some electric engines can be allowed to run on normal rail. It happens to all
198  * existing electric engines when elrails are disabled and then re-enabled */
199  if (HasBit(u->flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
200  u->railtype = RAILTYPE_RAIL;
201  u->compatible_railtypes |= RAILTYPES_RAIL;
202  }
203 
204  /* max speed is the minimum of the speed limits of all vehicles in the consist */
205  if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings_game.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) {
206  uint16 speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed);
207  if (speed != 0) max_speed = min(speed, max_speed);
208  }
209  }
210 
211  uint16 new_cap = e_u->DetermineCapacity(u);
212  if (allowed_changes & CCF_CAPACITY) {
213  /* Update vehicle capacity. */
214  if (u->cargo_cap > new_cap) u->cargo.Truncate(new_cap);
215  u->refit_cap = min(new_cap, u->refit_cap);
216  u->cargo_cap = new_cap;
217  } else {
218  /* Verify capacity hasn't changed. */
219  if (new_cap != u->cargo_cap) ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_CAPACITY, GBUG_VEH_CAPACITY, true);
220  }
221  u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_TRAIN_CARGO_AGE_PERIOD, e_u->info.cargo_age_period);
222 
223  /* check the vehicle length (callback) */
224  uint16 veh_len = CALLBACK_FAILED;
225  if (e_u->GetGRF() != NULL && e_u->GetGRF()->grf_version >= 8) {
226  /* Use callback 36 */
227  veh_len = GetVehicleProperty(u, PROP_TRAIN_SHORTEN_FACTOR, CALLBACK_FAILED);
228 
229  if (veh_len != CALLBACK_FAILED && veh_len >= VEHICLE_LENGTH) {
231  }
232  } else if (HasBit(e_u->info.callback_mask, CBM_VEHICLE_LENGTH)) {
233  /* Use callback 11 */
234  veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
235  }
236  if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
237  veh_len = VEHICLE_LENGTH - Clamp(veh_len, 0, VEHICLE_LENGTH - 1);
238 
239  if (allowed_changes & CCF_LENGTH) {
240  /* Update vehicle length. */
241  u->gcache.cached_veh_length = veh_len;
242  } else {
243  /* Verify length hasn't changed. */
244  if (veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
245  }
246 
247  this->gcache.cached_total_length += u->gcache.cached_veh_length;
248  this->InvalidateNewGRFCache();
249  u->InvalidateNewGRFCache();
250  }
251 
252  /* store consist weight/max speed in cache */
253  this->vcache.cached_max_speed = max_speed;
254  this->tcache.cached_tilt = train_can_tilt;
255  this->tcache.cached_max_curve_speed = this->GetCurveSpeedLimit();
256 
257  /* 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) */
258  this->CargoChanged();
259 
260  if (this->IsFrontEngine()) {
261  this->UpdateAcceleration();
265  InvalidateNewGRFInspectWindow(GSF_TRAINS, this->index);
266  }
267 }
268 
279 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length)
280 {
281  const Station *st = Station::Get(station_id);
282  *station_ahead = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE;
283  *station_length = st->GetPlatformLength(tile) * TILE_SIZE;
284 
285  /* Default to the middle of the station for stations stops that are not in
286  * the order list like intermediate stations when non-stop is disabled */
288  if (v->gcache.cached_total_length >= *station_length) {
289  /* The train is longer than the station, make it stop at the far end of the platform */
290  osl = OSL_PLATFORM_FAR_END;
291  } else if (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == station_id) {
292  osl = v->current_order.GetStopLocation();
293  }
294 
295  /* The stop location of the FRONT! of the train */
296  int stop;
297  switch (osl) {
298  default: NOT_REACHED();
299 
301  stop = v->gcache.cached_total_length;
302  break;
303 
304  case OSL_PLATFORM_MIDDLE:
305  stop = *station_length - (*station_length - v->gcache.cached_total_length) / 2;
306  break;
307 
309  stop = *station_length;
310  break;
311  }
312 
313  /* Subtract half the front vehicle length of the train so we get the real
314  * stop location of the train. */
315  return stop - (v->gcache.cached_veh_length + 1) / 2;
316 }
317 
318 
324 {
325  assert(this->First() == this);
326 
327  static const int absolute_max_speed = UINT16_MAX;
328  int max_speed = absolute_max_speed;
329 
330  if (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) return max_speed;
331 
332  int curvecount[2] = {0, 0};
333 
334  /* first find the curve speed limit */
335  int numcurve = 0;
336  int sum = 0;
337  int pos = 0;
338  int lastpos = -1;
339  for (const Vehicle *u = this; u->Next() != NULL; u = u->Next(), pos++) {
340  Direction this_dir = u->direction;
341  Direction next_dir = u->Next()->direction;
342 
343  DirDiff dirdiff = DirDifference(this_dir, next_dir);
344  if (dirdiff == DIRDIFF_SAME) continue;
345 
346  if (dirdiff == DIRDIFF_45LEFT) curvecount[0]++;
347  if (dirdiff == DIRDIFF_45RIGHT) curvecount[1]++;
348  if (dirdiff == DIRDIFF_45LEFT || dirdiff == DIRDIFF_45RIGHT) {
349  if (lastpos != -1) {
350  numcurve++;
351  sum += pos - lastpos;
352  if (pos - lastpos == 1 && max_speed > 88) {
353  max_speed = 88;
354  }
355  }
356  lastpos = pos;
357  }
358 
359  /* if we have a 90 degree turn, fix the speed limit to 60 */
360  if (dirdiff == DIRDIFF_90LEFT || dirdiff == DIRDIFF_90RIGHT) {
361  max_speed = 61;
362  }
363  }
364 
365  if (numcurve > 0 && max_speed > 88) {
366  if (curvecount[0] == 1 && curvecount[1] == 1) {
367  max_speed = absolute_max_speed;
368  } else {
369  sum /= numcurve;
370  max_speed = 232 - (13 - Clamp(sum, 1, 12)) * (13 - Clamp(sum, 1, 12));
371  }
372  }
373 
374  if (max_speed != absolute_max_speed) {
375  /* Apply the engine's rail type curve speed advantage, if it slowed by curves */
376  const RailtypeInfo *rti = GetRailTypeInfo(this->railtype);
377  max_speed += (max_speed / 2) * rti->curve_speed;
378 
379  if (this->tcache.cached_tilt) {
380  /* Apply max_speed bonus of 20% for a tilting train */
381  max_speed += max_speed / 5;
382  }
383  }
384 
385  return max_speed;
386 }
387 
393 {
394  int max_speed = _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ?
396  this->tcache.cached_max_curve_speed;
397 
398  if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && IsRailStationTile(this->tile)) {
399  StationID sid = GetStationIndex(this->tile);
400  if (this->current_order.ShouldStopAtStation(this, sid)) {
401  int station_ahead;
402  int station_length;
403  int stop_at = GetTrainStopLocation(sid, this->tile, this, &station_ahead, &station_length);
404 
405  /* The distance to go is whatever is still ahead of the train minus the
406  * distance from the train's stop location to the end of the platform */
407  int distance_to_go = station_ahead / TILE_SIZE - (station_length - stop_at) / TILE_SIZE;
408 
409  if (distance_to_go > 0) {
410  int st_max_speed = 120;
411 
412  int delta_v = this->cur_speed / (distance_to_go + 1);
413  if (max_speed > (this->cur_speed - delta_v)) {
414  st_max_speed = this->cur_speed - (delta_v / 10);
415  }
416 
417  st_max_speed = max(st_max_speed, 25 * distance_to_go);
418  max_speed = min(max_speed, st_max_speed);
419  }
420  }
421  }
422 
423  for (const Train *u = this; u != NULL; u = u->Next()) {
424  if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == TRACK_BIT_DEPOT) {
425  max_speed = min(max_speed, 61);
426  break;
427  }
428 
429  /* Vehicle is on the middle part of a bridge. */
430  if (u->track == TRACK_BIT_WORMHOLE && !(u->vehstatus & VS_HIDDEN)) {
431  max_speed = min(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed);
432  }
433  }
434 
435  max_speed = min(max_speed, this->current_order.GetMaxSpeed());
436  return min(max_speed, this->gcache.cached_max_track_speed);
437 }
438 
441 {
442  assert(this->IsFrontEngine() || this->IsFreeWagon());
443 
444  uint power = this->gcache.cached_power;
445  uint weight = this->gcache.cached_weight;
446  assert(weight != 0);
447  this->acceleration = Clamp(power / weight * 4, 1, 255);
448 }
449 
456 {
457  int reference_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
458  int vehicle_pitch = 0;
459 
460  const Engine *e = this->GetEngine();
461  if (e->GetGRF() != NULL && is_custom_sprite(e->u.rail.image_index)) {
462  reference_width = e->GetGRF()->traininfo_vehicle_width;
463  vehicle_pitch = e->GetGRF()->traininfo_vehicle_pitch;
464  }
465 
466  if (offset != NULL) {
467  offset->x = ScaleGUITrad(reference_width) / 2;
468  offset->y = ScaleGUITrad(vehicle_pitch);
469  }
470  return ScaleGUITrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
471 }
472 
473 static SpriteID GetDefaultTrainSprite(uint8 spritenum, Direction direction)
474 {
475  assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
476  return ((direction + _engine_sprite_add[spritenum]) & _engine_sprite_and[spritenum]) + _engine_sprite_base[spritenum];
477 }
478 
486 {
487  uint8 spritenum = this->spritenum;
488 
489  if (HasBit(this->flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
490 
491  if (is_custom_sprite(spritenum)) {
492  GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
493  if (result->IsValid()) return;
494 
495  spritenum = this->GetEngine()->original_image_index;
496  }
497 
498  assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
499  SpriteID sprite = GetDefaultTrainSprite(spritenum, direction);
500 
501  if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _wagon_full_adder[spritenum];
502 
503  result->Set(sprite);
504 }
505 
506 static void GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType image_type, VehicleSpriteSeq *result)
507 {
508  const Engine *e = Engine::Get(engine);
509  Direction dir = rear_head ? DIR_E : DIR_W;
510  uint8 spritenum = e->u.rail.image_index;
511 
512  if (is_custom_sprite(spritenum)) {
513  GetCustomVehicleIcon(engine, dir, image_type, result);
514  if (result->IsValid()) {
515  if (e->GetGRF() != NULL) {
517  }
518  return;
519  }
520 
521  spritenum = Engine::Get(engine)->original_image_index;
522  }
523 
524  if (rear_head) spritenum++;
525 
526  result->Set(GetDefaultTrainSprite(spritenum, DIR_W));
527 }
528 
529 void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
530 {
531  if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
532  int yf = y;
533  int yr = y;
534 
535  VehicleSpriteSeq seqf, seqr;
536  GetRailIcon(engine, false, yf, image_type, &seqf);
537  GetRailIcon(engine, true, yr, image_type, &seqr);
538 
539  Rect rectf, rectr;
540  seqf.GetBounds(&rectf);
541  seqr.GetBounds(&rectr);
542 
543  preferred_x = Clamp(preferred_x,
544  left - UnScaleGUI(rectf.left) + ScaleGUITrad(14),
545  right - UnScaleGUI(rectr.right) - ScaleGUITrad(15));
546 
547  seqf.Draw(preferred_x - ScaleGUITrad(14), yf, pal, pal == PALETTE_CRASH);
548  seqr.Draw(preferred_x + ScaleGUITrad(15), yr, pal, pal == PALETTE_CRASH);
549  } else {
550  VehicleSpriteSeq seq;
551  GetRailIcon(engine, false, y, image_type, &seq);
552 
553  Rect rect;
554  seq.GetBounds(&rect);
555  preferred_x = Clamp(preferred_x,
556  left - UnScaleGUI(rect.left),
557  right - UnScaleGUI(rect.right));
558 
559  seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
560  }
561 }
562 
572 void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
573 {
574  int y = 0;
575 
576  VehicleSpriteSeq seq;
577  GetRailIcon(engine, false, y, image_type, &seq);
578 
579  Rect rect;
580  seq.GetBounds(&rect);
581 
582  width = UnScaleGUI(rect.right - rect.left + 1);
583  height = UnScaleGUI(rect.bottom - rect.top + 1);
584  xoffs = UnScaleGUI(rect.left);
585  yoffs = UnScaleGUI(rect.top);
586 
587  if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
588  GetRailIcon(engine, true, y, image_type, &seq);
589  seq.GetBounds(&rect);
590 
591  /* Calculate values relative to an imaginary center between the two sprites. */
592  width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(rect.right) - xoffs;
593  height = max<uint>(height, UnScaleGUI(rect.bottom - rect.top + 1));
594  xoffs = xoffs - ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
595  yoffs = min(yoffs, UnScaleGUI(rect.top));
596  }
597 }
598 
608 {
609  const RailVehicleInfo *rvi = &e->u.rail;
610 
611  /* Check that the wagon can drive on the track in question */
612  if (!IsCompatibleRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
613 
614  if (flags & DC_EXEC) {
615  Train *v = new Train();
616  *ret = v;
617  v->spritenum = rvi->image_index;
618 
619  v->engine_type = e->index;
620  v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
621 
623 
624  v->direction = DiagDirToDir(dir);
625  v->tile = tile;
626 
627  int x = TileX(tile) * TILE_SIZE | _vehicle_initial_x_fract[dir];
628  int y = TileY(tile) * TILE_SIZE | _vehicle_initial_y_fract[dir];
629 
630  v->x_pos = x;
631  v->y_pos = y;
632  v->z_pos = GetSlopePixelZ(x, y);
633  v->owner = _current_company;
634  v->track = TRACK_BIT_DEPOT;
636 
637  v->SetWagon();
638 
639  v->SetFreeWagon();
641 
643  v->cargo_cap = rvi->capacity;
644  v->refit_cap = 0;
645 
646  v->railtype = rvi->railtype;
647 
649  v->build_year = _cur_year;
650  v->sprite_seq.Set(SPR_IMG_QUERY);
652 
653  v->group_id = DEFAULT_GROUP;
654 
656 
657  _new_vehicle_id = v->index;
658 
659  v->UpdatePosition();
662 
664 
665  /* Try to connect the vehicle to one of free chains of wagons. */
666  Train *w;
667  FOR_ALL_TRAINS(w) {
668  if (w->tile == tile &&
669  w->IsFreeWagon() &&
670  w->engine_type == e->index &&
671  w->First() != v &&
672  !(w->vehstatus & VS_CRASHED)) {
673  DoCommand(0, v->index | 1 << 20, w->Last()->index, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
674  break;
675  }
676  }
677  }
678 
679  return CommandCost();
680 }
681 
683 static void NormalizeTrainVehInDepot(const Train *u)
684 {
685  const Train *v;
686  FOR_ALL_TRAINS(v) {
687  if (v->IsFreeWagon() && v->tile == u->tile &&
688  v->track == TRACK_BIT_DEPOT) {
689  if (DoCommand(0, v->index | 1 << 20, u->index, DC_EXEC,
691  break;
692  }
693  }
694 }
695 
696 static void AddRearEngineToMultiheadedTrain(Train *v)
697 {
698  Train *u = new Train();
699  v->value >>= 1;
700  u->value = v->value;
701  u->direction = v->direction;
702  u->owner = v->owner;
703  u->tile = v->tile;
704  u->x_pos = v->x_pos;
705  u->y_pos = v->y_pos;
706  u->z_pos = v->z_pos;
707  u->track = TRACK_BIT_DEPOT;
708  u->vehstatus = v->vehstatus & ~VS_STOPPED;
709  u->spritenum = v->spritenum + 1;
710  u->cargo_type = v->cargo_type;
712  u->cargo_cap = v->cargo_cap;
713  u->refit_cap = v->refit_cap;
714  u->railtype = v->railtype;
715  u->engine_type = v->engine_type;
717  u->build_year = v->build_year;
718  u->sprite_seq.Set(SPR_IMG_QUERY);
720  v->SetMultiheaded();
721  u->SetMultiheaded();
722  v->SetNext(u);
723  u->UpdatePosition();
724 
725  /* Now we need to link the front and rear engines together */
726  v->other_multiheaded_part = u;
727  u->other_multiheaded_part = v;
728 }
729 
740 {
741  const RailVehicleInfo *rvi = &e->u.rail;
742 
743  if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(tile, flags, e, ret);
744 
745  /* Check if depot and new engine uses the same kind of tracks *
746  * We need to see if the engine got power on the tile to avoid electric engines in non-electric depots */
747  if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
748 
749  if (flags & DC_EXEC) {
751  int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
752  int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
753 
754  Train *v = new Train();
755  *ret = v;
756  v->direction = DiagDirToDir(dir);
757  v->tile = tile;
758  v->owner = _current_company;
759  v->x_pos = x;
760  v->y_pos = y;
761  v->z_pos = GetSlopePixelZ(x, y);
762  v->track = TRACK_BIT_DEPOT;
764  v->spritenum = rvi->image_index;
766  v->cargo_cap = rvi->capacity;
767  v->refit_cap = 0;
768  v->last_station_visited = INVALID_STATION;
769  v->last_loading_station = INVALID_STATION;
770 
771  v->engine_type = e->index;
772  v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
773 
774  v->reliability = e->reliability;
776  v->max_age = e->GetLifeLengthInDays();
777 
778  v->railtype = rvi->railtype;
779  _new_vehicle_id = v->index;
780 
781  v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains);
783  v->build_year = _cur_year;
784  v->sprite_seq.Set(SPR_IMG_QUERY);
786 
788  v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
789 
790  v->group_id = DEFAULT_GROUP;
791 
792  v->SetFrontEngine();
793  v->SetEngine();
794 
795  v->UpdatePosition();
796 
797  if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
798  AddRearEngineToMultiheadedTrain(v);
799  } else {
801  }
802 
805 
806  if (!HasBit(data, 0) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
808  }
809 
811  }
812 
813  return CommandCost();
814 }
815 
816 static Train *FindGoodVehiclePos(const Train *src)
817 {
818  EngineID eng = src->engine_type;
819  TileIndex tile = src->tile;
820 
821  Train *dst;
822  FOR_ALL_TRAINS(dst) {
823  if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED)) {
824  /* check so all vehicles in the line have the same engine. */
825  Train *t = dst;
826  while (t->engine_type == eng) {
827  t = t->Next();
828  if (t == NULL) return dst;
829  }
830  }
831  }
832 
833  return NULL;
834 }
835 
838 
845 {
846  for (; t != NULL; t = t->Next()) *list.Append() = t;
847 }
848 
854 {
855  /* No train, nothing to do. */
856  if (list.Length() == 0) return;
857 
858  Train *prev = NULL;
859  /* Iterate over the list and rebuild it. */
860  for (Train **iter = list.Begin(); iter != list.End(); iter++) {
861  Train *t = *iter;
862  if (prev != NULL) {
863  prev->SetNext(t);
864  } else if (t->Previous() != NULL) {
865  /* Make sure the head of the train is always the first in the chain. */
866  t->Previous()->SetNext(NULL);
867  }
868  prev = t;
869  }
870 }
871 
877 static void RemoveFromConsist(Train *part, bool chain = false)
878 {
879  Train *tail = chain ? part->Last() : part->GetLastEnginePart();
880 
881  /* Unlink at the front, but make it point to the next
882  * vehicle after the to be remove part. */
883  if (part->Previous() != NULL) part->Previous()->SetNext(tail->Next());
884 
885  /* Unlink at the back */
886  tail->SetNext(NULL);
887 }
888 
894 static void InsertInConsist(Train *dst, Train *chain)
895 {
896  /* We do not want to add something in the middle of an articulated part. */
897  assert(dst->Next() == NULL || !dst->Next()->IsArticulatedPart());
898 
899  chain->Last()->SetNext(dst->Next());
900  dst->SetNext(chain);
901 }
902 
908 static void NormaliseDualHeads(Train *t)
909 {
910  for (; t != NULL; t = t->GetNextVehicle()) {
911  if (!t->IsMultiheaded() || !t->IsEngine()) continue;
912 
913  /* Make sure that there are no free cars before next engine */
914  Train *u;
915  for (u = t; u->Next() != NULL && !u->Next()->IsEngine(); u = u->Next()) {}
916 
917  if (u == t->other_multiheaded_part) continue;
918 
919  /* Remove the part from the 'wrong' train */
920  RemoveFromConsist(t->other_multiheaded_part);
921  /* And add it to the 'right' train */
922  InsertInConsist(u, t->other_multiheaded_part);
923  }
924 }
925 
930 static void NormaliseSubtypes(Train *chain)
931 {
932  /* Nothing to do */
933  if (chain == NULL) return;
934 
935  /* We must be the first in the chain. */
936  assert(chain->Previous() == NULL);
937 
938  /* Set the appropriate bits for the first in the chain. */
939  if (chain->IsWagon()) {
940  chain->SetFreeWagon();
941  } else {
942  assert(chain->IsEngine());
943  chain->SetFrontEngine();
944  }
945 
946  /* Now clear the bits for the rest of the chain */
947  for (Train *t = chain->Next(); t != NULL; t = t->Next()) {
948  t->ClearFreeWagon();
949  t->ClearFrontEngine();
950  }
951 }
952 
962 static CommandCost CheckNewTrain(Train *original_dst, Train *dst, Train *original_src, Train *src)
963 {
964  /* Just add 'new' engines and subtract the original ones.
965  * If that's less than or equal to 0 we can be sure we did
966  * not add any engines (read: trains) along the way. */
967  if ((src != NULL && src->IsEngine() ? 1 : 0) +
968  (dst != NULL && dst->IsEngine() ? 1 : 0) -
969  (original_src != NULL && original_src->IsEngine() ? 1 : 0) -
970  (original_dst != NULL && original_dst->IsEngine() ? 1 : 0) <= 0) {
971  return CommandCost();
972  }
973 
974  /* Get a free unit number and check whether it's within the bounds.
975  * There will always be a maximum of one new train. */
977 
978  return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
979 }
980 
987 {
988  /* No multi-part train, no need to check. */
989  if (t == NULL || t->Next() == NULL || !t->IsEngine()) return CommandCost();
990 
991  /* The maximum length for a train. For each part we decrease this by one
992  * and if the result is negative the train is simply too long. */
994 
995  Train *head = t;
996  Train *prev = t;
997 
998  /* Break the prev -> t link so it always holds within the loop. */
999  t = t->Next();
1000  prev->SetNext(NULL);
1001 
1002  /* Make sure the cache is cleared. */
1003  head->InvalidateNewGRFCache();
1004 
1005  while (t != NULL) {
1006  allowed_len -= t->gcache.cached_veh_length;
1007 
1008  Train *next = t->Next();
1009 
1010  /* Unlink the to-be-added piece; it is already unlinked from the previous
1011  * part due to the fact that the prev -> t link is broken. */
1012  t->SetNext(NULL);
1013 
1014  /* Don't check callback for articulated or rear dual headed parts */
1015  if (!t->IsArticulatedPart() && !t->IsRearDualheaded()) {
1016  /* Back up and clear the first_engine data to avoid using wagon override group */
1017  EngineID first_engine = t->gcache.first_engine;
1019 
1020  /* We don't want the cache to interfere. head's cache is cleared before
1021  * the loop and after each callback does not need to be cleared here. */
1022  t->InvalidateNewGRFCache();
1023 
1024  uint16 callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, head->engine_type, t, head);
1025 
1026  /* Restore original first_engine data */
1027  t->gcache.first_engine = first_engine;
1028 
1029  /* We do not want to remember any cached variables from the test run */
1030  t->InvalidateNewGRFCache();
1031  head->InvalidateNewGRFCache();
1032 
1033  if (callback != CALLBACK_FAILED) {
1034  /* A failing callback means everything is okay */
1035  StringID error = STR_NULL;
1036 
1037  if (head->GetGRF()->grf_version < 8) {
1038  if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1039  if (callback < 0xFD) error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback);
1040  if (callback >= 0x100) ErrorUnknownCallbackResult(head->GetGRFID(), CBID_TRAIN_ALLOW_WAGON_ATTACH, callback);
1041  } else {
1042  if (callback < 0x400) {
1043  error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback);
1044  } else {
1045  switch (callback) {
1046  case 0x400: // allow if railtypes match (always the case for OpenTTD)
1047  case 0x401: // allow
1048  break;
1049 
1050  default: // unknown reason -> disallow
1051  case 0x402: // disallow attaching
1052  error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1053  break;
1054  }
1055  }
1056  }
1057 
1058  if (error != STR_NULL) return_cmd_error(error);
1059  }
1060  }
1061 
1062  /* And link it to the new part. */
1063  prev->SetNext(t);
1064  prev = t;
1065  t = next;
1066  }
1067 
1068  if (allowed_len < 0) return_cmd_error(STR_ERROR_TRAIN_TOO_LONG);
1069  return CommandCost();
1070 }
1071 
1082 static CommandCost ValidateTrains(Train *original_dst, Train *dst, Train *original_src, Train *src, bool check_limit)
1083 {
1084  /* Check whether we may actually construct the trains. */
1085  CommandCost ret = CheckTrainAttachment(src);
1086  if (ret.Failed()) return ret;
1087  ret = CheckTrainAttachment(dst);
1088  if (ret.Failed()) return ret;
1089 
1090  /* Check whether we need to build a new train. */
1091  return check_limit ? CheckNewTrain(original_dst, dst, original_src, src) : CommandCost();
1092 }
1093 
1102 static void ArrangeTrains(Train **dst_head, Train *dst, Train **src_head, Train *src, bool move_chain)
1103 {
1104  /* First determine the front of the two resulting trains */
1105  if (*src_head == *dst_head) {
1106  /* If we aren't moving part(s) to a new train, we are just moving the
1107  * front back and there is not destination head. */
1108  *dst_head = NULL;
1109  } else if (*dst_head == NULL) {
1110  /* If we are moving to a new train the head of the move train would become
1111  * the head of the new vehicle. */
1112  *dst_head = src;
1113  }
1114 
1115  if (src == *src_head) {
1116  /* If we are moving the front of a train then we are, in effect, creating
1117  * a new head for the train. Point to that. Unless we are moving the whole
1118  * train in which case there is not 'source' train anymore.
1119  * In case we are a multiheaded part we want the complete thing to come
1120  * with us, so src->GetNextUnit(), however... when we are e.g. a wagon
1121  * that is followed by a rear multihead we do not want to include that. */
1122  *src_head = move_chain ? NULL :
1123  (src->IsMultiheaded() ? src->GetNextUnit() : src->GetNextVehicle());
1124  }
1125 
1126  /* Now it's just simply removing the part that we are going to move from the
1127  * source train and *if* the destination is a not a new train add the chain
1128  * at the destination location. */
1129  RemoveFromConsist(src, move_chain);
1130  if (*dst_head != src) InsertInConsist(dst, src);
1131 
1132  /* Now normalise the dual heads, that is move the dual heads around in such
1133  * a way that the head and rear of a dual head are in the same train */
1134  NormaliseDualHeads(*src_head);
1135  NormaliseDualHeads(*dst_head);
1136 }
1137 
1143 static void NormaliseTrainHead(Train *head)
1144 {
1145  /* Not much to do! */
1146  if (head == NULL) return;
1147 
1148  /* Tell the 'world' the train changed. */
1149  head->ConsistChanged(CCF_ARRANGE);
1150  UpdateTrainGroupID(head);
1151 
1152  /* Not a front engine, i.e. a free wagon chain. No need to do more. */
1153  if (!head->IsFrontEngine()) return;
1154 
1155  /* Update the refit button and window */
1158 
1159  /* If we don't have a unit number yet, set one. */
1160  if (head->unitnumber != 0) return;
1162 }
1163 
1176 CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1177 {
1178  VehicleID s = GB(p1, 0, 20);
1179  VehicleID d = GB(p2, 0, 20);
1180  bool move_chain = HasBit(p1, 20);
1181 
1182  Train *src = Train::GetIfValid(s);
1183  if (src == NULL) return CMD_ERROR;
1184 
1185  CommandCost ret = CheckOwnership(src->owner);
1186  if (ret.Failed()) return ret;
1187 
1188  /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */
1189  if (src->vehstatus & VS_CRASHED) return CMD_ERROR;
1190 
1191  /* if nothing is selected as destination, try and find a matching vehicle to drag to. */
1192  Train *dst;
1193  if (d == INVALID_VEHICLE) {
1194  dst = src->IsEngine() ? NULL : FindGoodVehiclePos(src);
1195  } else {
1196  dst = Train::GetIfValid(d);
1197  if (dst == NULL) return CMD_ERROR;
1198 
1199  CommandCost ret = CheckOwnership(dst->owner);
1200  if (ret.Failed()) return ret;
1201 
1202  /* Do not allow appending to crashed vehicles, too */
1203  if (dst->vehstatus & VS_CRASHED) return CMD_ERROR;
1204  }
1205 
1206  /* if an articulated part is being handled, deal with its parent vehicle */
1207  src = src->GetFirstEnginePart();
1208  if (dst != NULL) {
1209  dst = dst->GetFirstEnginePart();
1210  }
1211 
1212  /* don't move the same vehicle.. */
1213  if (src == dst) return CommandCost();
1214 
1215  /* locate the head of the two chains */
1216  Train *src_head = src->First();
1217  Train *dst_head;
1218  if (dst != NULL) {
1219  dst_head = dst->First();
1220  if (dst_head->tile != src_head->tile) return CMD_ERROR;
1221  /* Now deal with articulated part of destination wagon */
1222  dst = dst->GetLastEnginePart();
1223  } else {
1224  dst_head = NULL;
1225  }
1226 
1227  if (src->IsRearDualheaded()) return_cmd_error(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT);
1228 
1229  /* When moving all wagons, we can't have the same src_head and dst_head */
1230  if (move_chain && src_head == dst_head) return CommandCost();
1231 
1232  /* When moving a multiheaded part to be place after itself, bail out. */
1233  if (!move_chain && dst != NULL && dst->IsRearDualheaded() && src == dst->other_multiheaded_part) return CommandCost();
1234 
1235  /* Check if all vehicles in the source train are stopped inside a depot. */
1236  if (!src_head->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1237 
1238  /* Check if all vehicles in the destination train are stopped inside a depot. */
1239  if (dst_head != NULL && !dst_head->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1240 
1241  /* First make a backup of the order of the trains. That way we can do
1242  * whatever we want with the order and later on easily revert. */
1243  TrainList original_src;
1244  TrainList original_dst;
1245 
1246  MakeTrainBackup(original_src, src_head);
1247  MakeTrainBackup(original_dst, dst_head);
1248 
1249  /* Also make backup of the original heads as ArrangeTrains can change them.
1250  * For the destination head we do not care if it is the same as the source
1251  * head because in that case it's just a copy. */
1252  Train *original_src_head = src_head;
1253  Train *original_dst_head = (dst_head == src_head ? NULL : dst_head);
1254 
1255  /* We want this information from before the rearrangement, but execute this after the validation.
1256  * original_src_head can't be NULL; src is by definition != NULL, so src_head can't be NULL as
1257  * src->GetFirst() always yields non-NULL, so eventually original_src_head != NULL as well. */
1258  bool original_src_head_front_engine = original_src_head->IsFrontEngine();
1259  bool original_dst_head_front_engine = original_dst_head != NULL && original_dst_head->IsFrontEngine();
1260 
1261  /* (Re)arrange the trains in the wanted arrangement. */
1262  ArrangeTrains(&dst_head, dst, &src_head, src, move_chain);
1263 
1264  if ((flags & DC_AUTOREPLACE) == 0) {
1265  /* If the autoreplace flag is set we do not need to test for the validity
1266  * because we are going to revert the train to its original state. As we
1267  * assume the original state was correct autoreplace can skip this. */
1268  CommandCost ret = ValidateTrains(original_dst_head, dst_head, original_src_head, src_head, true);
1269  if (ret.Failed()) {
1270  /* Restore the train we had. */
1271  RestoreTrainBackup(original_src);
1272  RestoreTrainBackup(original_dst);
1273  return ret;
1274  }
1275  }
1276 
1277  /* do it? */
1278  if (flags & DC_EXEC) {
1279  /* Remove old heads from the statistics */
1280  if (original_src_head_front_engine) GroupStatistics::CountVehicle(original_src_head, -1);
1281  if (original_dst_head_front_engine) GroupStatistics::CountVehicle(original_dst_head, -1);
1282 
1283  /* First normalise the sub types of the chains. */
1284  NormaliseSubtypes(src_head);
1285  NormaliseSubtypes(dst_head);
1286 
1287  /* There are 14 different cases:
1288  * 1) front engine gets moved to a new train, it stays a front engine.
1289  * a) the 'next' part is a wagon that becomes a free wagon chain.
1290  * b) the 'next' part is an engine that becomes a front engine.
1291  * c) there is no 'next' part, nothing else happens
1292  * 2) front engine gets moved to another train, it is not a front engine anymore
1293  * a) the 'next' part is a wagon that becomes a free wagon chain.
1294  * b) the 'next' part is an engine that becomes a front engine.
1295  * c) there is no 'next' part, nothing else happens
1296  * 3) front engine gets moved to later in the current train, it is not a front engine anymore.
1297  * a) the 'next' part is a wagon that becomes a free wagon chain.
1298  * b) the 'next' part is an engine that becomes a front engine.
1299  * 4) free wagon gets moved
1300  * a) the 'next' part is a wagon that becomes a free wagon chain.
1301  * b) the 'next' part is an engine that becomes a front engine.
1302  * c) there is no 'next' part, nothing else happens
1303  * 5) non front engine gets moved and becomes a new train, nothing else happens
1304  * 6) non front engine gets moved within a train / to another train, nothing hapens
1305  * 7) wagon gets moved, nothing happens
1306  */
1307  if (src == original_src_head && src->IsEngine() && !src->IsFrontEngine()) {
1308  /* Cases #2 and #3: the front engine gets trashed. */
1314  DeleteNewGRFInspectWindow(GSF_TRAINS, src->index);
1316 
1317  /* Delete orders, group stuff and the unit number as we're not the
1318  * front of any vehicle anymore. */
1319  DeleteVehicleOrders(src);
1321  src->unitnumber = 0;
1322  }
1323 
1324  /* We weren't a front engine but are becoming one. So
1325  * we should be put in the default group. */
1326  if (original_src_head != src && dst_head == src) {
1329  }
1330 
1331  /* Add new heads to statistics */
1332  if (src_head != NULL && src_head->IsFrontEngine()) GroupStatistics::CountVehicle(src_head, 1);
1333  if (dst_head != NULL && dst_head->IsFrontEngine()) GroupStatistics::CountVehicle(dst_head, 1);
1334 
1335  /* Handle 'new engine' part of cases #1b, #2b, #3b, #4b and #5 in NormaliseTrainHead. */
1336  NormaliseTrainHead(src_head);
1337  NormaliseTrainHead(dst_head);
1338 
1339  if ((flags & DC_NO_CARGO_CAP_CHECK) == 0) {
1340  CheckCargoCapacity(src_head);
1341  CheckCargoCapacity(dst_head);
1342  }
1343 
1344  if (src_head != NULL) src_head->First()->MarkDirty();
1345  if (dst_head != NULL) dst_head->First()->MarkDirty();
1346 
1347  /* We are undoubtedly changing something in the depot and train list. */
1350  } else {
1351  /* We don't want to execute what we're just tried. */
1352  RestoreTrainBackup(original_src);
1353  RestoreTrainBackup(original_dst);
1354  }
1355 
1356  return CommandCost();
1357 }
1358 
1370 CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint32 user)
1371 {
1372  /* Sell a chain of vehicles or not? */
1373  bool sell_chain = HasBit(data, 0);
1374 
1376  Train *first = v->First();
1377 
1378  if (v->IsRearDualheaded()) return_cmd_error(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT);
1379 
1380  /* First make a backup of the order of the train. That way we can do
1381  * whatever we want with the order and later on easily revert. */
1382  TrainList original;
1383  MakeTrainBackup(original, first);
1384 
1385  /* We need to keep track of the new head and the head of what we're going to sell. */
1386  Train *new_head = first;
1387  Train *sell_head = NULL;
1388 
1389  /* Split the train in the wanted way. */
1390  ArrangeTrains(&sell_head, NULL, &new_head, v, sell_chain);
1391 
1392  /* We don't need to validate the second train; it's going to be sold. */
1393  CommandCost ret = ValidateTrains(NULL, NULL, first, new_head, (flags & DC_AUTOREPLACE) == 0);
1394  if (ret.Failed()) {
1395  /* Restore the train we had. */
1396  RestoreTrainBackup(original);
1397  return ret;
1398  }
1399 
1400  if (first->orders.list == NULL && !OrderList::CanAllocateItem()) {
1401  /* Restore the train we had. */
1402  RestoreTrainBackup(original);
1403  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1404  }
1405 
1407  for (Train *t = sell_head; t != NULL; t = t->Next()) cost.AddCost(-t->value);
1408 
1409  /* do it? */
1410  if (flags & DC_EXEC) {
1411  /* First normalise the sub types of the chain. */
1412  NormaliseSubtypes(new_head);
1413 
1414  if (v == first && v->IsEngine() && !sell_chain && new_head != NULL && new_head->IsFrontEngine()) {
1415  /* We are selling the front engine. In this case we want to
1416  * 'give' the order, unit number and such to the new head. */
1417  new_head->orders.list = first->orders.list;
1418  new_head->AddToShared(first);
1419  DeleteVehicleOrders(first);
1420 
1421  /* Copy other important data from the front engine */
1422  new_head->CopyVehicleConfigAndStatistics(first);
1423  GroupStatistics::CountVehicle(new_head, 1); // after copying over the profit
1424  } else if (v->IsPrimaryVehicle() && data & (MAKE_ORDER_BACKUP_FLAG >> 20)) {
1425  OrderBackup::Backup(v, user);
1426  }
1427 
1428  /* We need to update the information about the train. */
1429  NormaliseTrainHead(new_head);
1430 
1431  /* We are undoubtedly changing something in the depot and train list. */
1434 
1435  /* Actually delete the sold 'goods' */
1436  delete sell_head;
1437  } else {
1438  /* We don't want to execute what we're just tried. */
1439  RestoreTrainBackup(original);
1440  }
1441 
1442  return cost;
1443 }
1444 
1446 {
1447  /* Set common defaults. */
1448  this->x_offs = -1;
1449  this->y_offs = -1;
1450  this->x_extent = 3;
1451  this->y_extent = 3;
1452  this->z_extent = 6;
1453  this->x_bb_offs = 0;
1454  this->y_bb_offs = 0;
1455 
1456  if (!IsDiagonalDirection(direction)) {
1457  static const int _sign_table[] =
1458  {
1459  /* x, y */
1460  -1, -1, // DIR_N
1461  -1, 1, // DIR_E
1462  1, 1, // DIR_S
1463  1, -1, // DIR_W
1464  };
1465 
1466  int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length) / 2;
1467 
1468  /* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
1469  this->x_offs -= half_shorten * _sign_table[direction];
1470  this->y_offs -= half_shorten * _sign_table[direction + 1];
1471  this->x_extent += this->x_bb_offs = half_shorten * _sign_table[direction];
1472  this->y_extent += this->y_bb_offs = half_shorten * _sign_table[direction + 1];
1473  } else {
1474  switch (direction) {
1475  /* Shorten southern corner of the bounding box according the vehicle length
1476  * and center the bounding box on the vehicle. */
1477  case DIR_NE:
1478  this->x_offs = 1 - (this->gcache.cached_veh_length + 1) / 2;
1479  this->x_extent = this->gcache.cached_veh_length - 1;
1480  this->x_bb_offs = -1;
1481  break;
1482 
1483  case DIR_NW:
1484  this->y_offs = 1 - (this->gcache.cached_veh_length + 1) / 2;
1485  this->y_extent = this->gcache.cached_veh_length - 1;
1486  this->y_bb_offs = -1;
1487  break;
1488 
1489  /* Move northern corner of the bounding box down according to vehicle length
1490  * and center the bounding box on the vehicle. */
1491  case DIR_SW:
1492  this->x_offs = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH;
1493  this->x_extent = VEHICLE_LENGTH - 1;
1494  this->x_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
1495  break;
1496 
1497  case DIR_SE:
1498  this->y_offs = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH;
1499  this->y_extent = VEHICLE_LENGTH - 1;
1500  this->y_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
1501  break;
1502 
1503  default:
1504  NOT_REACHED();
1505  }
1506  }
1507 }
1508 
1513 static void MarkTrainAsStuck(Train *v)
1514 {
1515  if (!HasBit(v->flags, VRF_TRAIN_STUCK)) {
1516  /* It is the first time the problem occurred, set the "train stuck" flag. */
1517  SetBit(v->flags, VRF_TRAIN_STUCK);
1518 
1519  v->wait_counter = 0;
1520 
1521  /* Stop train */
1522  v->cur_speed = 0;
1523  v->subspeed = 0;
1524  v->SetLastSpeed();
1525 
1527  }
1528 }
1529 
1537 static void SwapTrainFlags(uint16 *swap_flag1, uint16 *swap_flag2)
1538 {
1539  uint16 flag1 = *swap_flag1;
1540  uint16 flag2 = *swap_flag2;
1541 
1542  /* Clear the flags */
1543  ClrBit(*swap_flag1, GVF_GOINGUP_BIT);
1544  ClrBit(*swap_flag1, GVF_GOINGDOWN_BIT);
1545  ClrBit(*swap_flag2, GVF_GOINGUP_BIT);
1546  ClrBit(*swap_flag2, GVF_GOINGDOWN_BIT);
1547 
1548  /* Reverse the rail-flags (if needed) */
1549  if (HasBit(flag1, GVF_GOINGUP_BIT)) {
1550  SetBit(*swap_flag2, GVF_GOINGDOWN_BIT);
1551  } else if (HasBit(flag1, GVF_GOINGDOWN_BIT)) {
1552  SetBit(*swap_flag2, GVF_GOINGUP_BIT);
1553  }
1554  if (HasBit(flag2, GVF_GOINGUP_BIT)) {
1555  SetBit(*swap_flag1, GVF_GOINGDOWN_BIT);
1556  } else if (HasBit(flag2, GVF_GOINGDOWN_BIT)) {
1557  SetBit(*swap_flag1, GVF_GOINGUP_BIT);
1558  }
1559 }
1560 
1566 {
1567  /* Reverse the direction. */
1568  if (v->track != TRACK_BIT_DEPOT) v->direction = ReverseDir(v->direction);
1569 
1570  /* Call the proper EnterTile function unless we are in a wormhole. */
1571  if (v->track != TRACK_BIT_WORMHOLE) {
1572  VehicleEnterTile(v, v->tile, v->x_pos, v->y_pos);
1573  } else {
1574  /* VehicleEnter_TunnelBridge() sets TRACK_BIT_WORMHOLE when the vehicle
1575  * is on the last bit of the bridge head (frame == TILE_SIZE - 1).
1576  * If we were swapped with such a vehicle, we have set TRACK_BIT_WORMHOLE,
1577  * when we shouldn't have. Check if this is the case. */
1578  TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
1579  if (IsTileType(vt, MP_TUNNELBRIDGE)) {
1580  VehicleEnterTile(v, vt, v->x_pos, v->y_pos);
1581  if (v->track != TRACK_BIT_WORMHOLE && IsBridgeTile(v->tile)) {
1582  /* We have just left the wormhole, possibly set the
1583  * "goingdown" bit. UpdateInclination() can be used
1584  * because we are at the border of the tile. */
1585  v->UpdatePosition();
1586  v->UpdateInclination(true, true);
1587  return;
1588  }
1589  }
1590  }
1591 
1592  v->UpdatePosition();
1593  v->UpdateViewport(true, true);
1594 }
1595 
1602 void ReverseTrainSwapVeh(Train *v, int l, int r)
1603 {
1604  Train *a, *b;
1605 
1606  /* locate vehicles to swap */
1607  for (a = v; l != 0; l--) a = a->Next();
1608  for (b = v; r != 0; r--) b = b->Next();
1609 
1610  if (a != b) {
1611  /* swap the hidden bits */
1612  {
1613  uint16 tmp = (a->vehstatus & ~VS_HIDDEN) | (b->vehstatus & VS_HIDDEN);
1614  b->vehstatus = (b->vehstatus & ~VS_HIDDEN) | (a->vehstatus & VS_HIDDEN);
1615  a->vehstatus = tmp;
1616  }
1617 
1618  Swap(a->track, b->track);
1619  Swap(a->direction, b->direction);
1620  Swap(a->x_pos, b->x_pos);
1621  Swap(a->y_pos, b->y_pos);
1622  Swap(a->tile, b->tile);
1623  Swap(a->z_pos, b->z_pos);
1624 
1625  SwapTrainFlags(&a->gv_flags, &b->gv_flags);
1626 
1629  } else {
1630  /* Swap GVF_GOINGUP_BIT/GVF_GOINGDOWN_BIT.
1631  * This is a little bit redundant way, a->gv_flags will
1632  * be (re)set twice, but it reduces code duplication */
1633  SwapTrainFlags(&a->gv_flags, &a->gv_flags);
1635  }
1636 }
1637 
1638 
1644 static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
1645 {
1646  return (v->type == VEH_TRAIN) ? v : NULL;
1647 }
1648 
1649 
1657 {
1658  if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return NULL;
1659 
1660  Train *t = Train::From(v);
1661  if (!t->IsFrontEngine()) return NULL;
1662 
1663  TileIndex tile = *(TileIndex *)data;
1664 
1665  if (TrainApproachingCrossingTile(t) != tile) return NULL;
1666 
1667  return t;
1668 }
1669 
1670 
1678 {
1679  assert(IsLevelCrossingTile(tile));
1680 
1682  TileIndex tile_from = tile + TileOffsByDiagDir(dir);
1683 
1684  if (HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum)) return true;
1685 
1686  dir = ReverseDiagDir(dir);
1687  tile_from = tile + TileOffsByDiagDir(dir);
1688 
1689  return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum);
1690 }
1691 
1692 
1700 {
1701  assert(IsLevelCrossingTile(tile));
1702 
1703  /* reserved || train on crossing || train approaching crossing */
1704  bool new_state = HasCrossingReservation(tile) || HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
1705 
1706  if (new_state != IsCrossingBarred(tile)) {
1707  if (new_state && sound) {
1708  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
1709  }
1710  SetCrossingBarred(tile, new_state);
1711  MarkTileDirtyByTile(tile);
1712  }
1713 }
1714 
1715 
1722 {
1723  if (!IsCrossingBarred(tile)) {
1724  BarCrossing(tile);
1725  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
1726  MarkTileDirtyByTile(tile);
1727  }
1728 }
1729 
1730 
1737 {
1738  Train *base = v;
1739  Train *first = base; // first vehicle to move
1740  Train *last = v->Last(); // last vehicle to move
1741  uint length = CountVehiclesInChain(v);
1742 
1743  while (length > 2) {
1744  last = last->Previous();
1745  first = first->Next();
1746 
1747  int differential = base->CalcNextVehicleOffset() - last->CalcNextVehicleOffset();
1748 
1749  /* do not update images now
1750  * negative differential will be handled in AdvanceWagonsAfterSwap() */
1751  for (int i = 0; i < differential; i++) TrainController(first, last->Next());
1752 
1753  base = first; // == base->Next()
1754  length -= 2;
1755  }
1756 }
1757 
1758 
1765 {
1766  /* first of all, fix the situation when the train was entering a depot */
1767  Train *dep = v; // last vehicle in front of just left depot
1768  while (dep->Next() != NULL && (dep->track == TRACK_BIT_DEPOT || dep->Next()->track != TRACK_BIT_DEPOT)) {
1769  dep = dep->Next(); // find first vehicle outside of a depot, with next vehicle inside a depot
1770  }
1771 
1772  Train *leave = dep->Next(); // first vehicle in a depot we are leaving now
1773 
1774  if (leave != NULL) {
1775  /* 'pull' next wagon out of the depot, so we won't miss it (it could stay in depot forever) */
1776  int d = TicksToLeaveDepot(dep);
1777 
1778  if (d <= 0) {
1779  leave->vehstatus &= ~VS_HIDDEN; // move it out of the depot
1780  leave->track = TrackToTrackBits(GetRailDepotTrack(leave->tile));
1781  for (int i = 0; i >= d; i--) TrainController(leave, NULL); // maybe move it, and maybe let another wagon leave
1782  }
1783  } else {
1784  dep = NULL; // no vehicle in a depot, so no vehicle leaving a depot
1785  }
1786 
1787  Train *base = v;
1788  Train *first = base; // first vehicle to move
1789  Train *last = v->Last(); // last vehicle to move
1790  uint length = CountVehiclesInChain(v);
1791 
1792  /* We have to make sure all wagons that leave a depot because of train reversing are moved correctly
1793  * they have already correct spacing, so we have to make sure they are moved how they should */
1794  bool nomove = (dep == NULL); // If there is no vehicle leaving a depot, limit the number of wagons moved immediately.
1795 
1796  while (length > 2) {
1797  /* we reached vehicle (originally) in front of a depot, stop now
1798  * (we would move wagons that are already moved with new wagon length). */
1799  if (base == dep) break;
1800 
1801  /* the last wagon was that one leaving a depot, so do not move it anymore */
1802  if (last == dep) nomove = true;
1803 
1804  last = last->Previous();
1805  first = first->Next();
1806 
1807  int differential = last->CalcNextVehicleOffset() - base->CalcNextVehicleOffset();
1808 
1809  /* do not update images now */
1810  for (int i = 0; i < differential; i++) TrainController(first, (nomove ? last->Next() : NULL));
1811 
1812  base = first; // == base->Next()
1813  length -= 2;
1814  }
1815 }
1816 
1822 {
1823  if (IsRailDepotTile(v->tile)) {
1825  }
1826 
1827  /* Clear path reservation in front if train is not stuck. */
1828  if (!HasBit(v->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v);
1829 
1830  /* Check if we were approaching a rail/road-crossing */
1832 
1833  /* count number of vehicles */
1834  int r = CountVehiclesInChain(v) - 1; // number of vehicles - 1
1835 
1837 
1838  /* swap start<>end, start+1<>end-1, ... */
1839  int l = 0;
1840  do {
1841  ReverseTrainSwapVeh(v, l++, r--);
1842  } while (l <= r);
1843 
1845 
1846  if (IsRailDepotTile(v->tile)) {
1848  }
1849 
1850  ToggleBit(v->flags, VRF_TOGGLE_REVERSE);
1851 
1852  ClrBit(v->flags, VRF_REVERSING);
1853 
1854  /* recalculate cached data */
1856 
1857  /* update all images */
1858  for (Train *u = v; u != NULL; u = u->Next()) u->UpdateViewport(false, false);
1859 
1860  /* update crossing we were approaching */
1861  if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
1862 
1863  /* maybe we are approaching crossing now, after reversal */
1864  crossing = TrainApproachingCrossingTile(v);
1865  if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing);
1866 
1867  /* If we are inside a depot after reversing, don't bother with path reserving. */
1868  if (v->track == TRACK_BIT_DEPOT) {
1869  /* Can't be stuck here as inside a depot is always a safe tile. */
1871  ClrBit(v->flags, VRF_TRAIN_STUCK);
1872  return;
1873  }
1874 
1875  /* TrainExitDir does not always produce the desired dir for depots and
1876  * tunnels/bridges that is needed for UpdateSignalsOnSegment. */
1877  DiagDirection dir = TrainExitDir(v->direction, v->track);
1879 
1881  /* If we are currently on a tile with conventional signals, we can't treat the
1882  * current tile as a safe tile or we would enter a PBS block without a reservation. */
1883  bool first_tile_okay = !(IsTileType(v->tile, MP_RAILWAY) &&
1885  !IsPbsSignal(GetSignalType(v->tile, FindFirstTrack(v->track))));
1886 
1887  /* If we are on a depot tile facing outwards, do not treat the current tile as safe. */
1888  if (IsRailDepotTile(v->tile) && TrackdirToExitdir(v->GetVehicleTrackdir()) == GetRailDepotDirection(v->tile)) first_tile_okay = false;
1889 
1891  if (TryPathReserve(v, false, first_tile_okay)) {
1892  /* Do a look-ahead now in case our current tile was already a safe tile. */
1893  CheckNextTrainTile(v);
1894  } else if (v->current_order.GetType() != OT_LOADING) {
1895  /* Do not wait for a way out when we're still loading */
1896  MarkTrainAsStuck(v);
1897  }
1898  } else if (HasBit(v->flags, VRF_TRAIN_STUCK)) {
1899  /* A train not inside a PBS block can't be stuck. */
1900  ClrBit(v->flags, VRF_TRAIN_STUCK);
1901  v->wait_counter = 0;
1902  }
1903 }
1904 
1914 CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1915 {
1916  Train *v = Train::GetIfValid(p1);
1917  if (v == NULL) return CMD_ERROR;
1918 
1919  CommandCost ret = CheckOwnership(v->owner);
1920  if (ret.Failed()) return ret;
1921 
1922  if (p2 != 0) {
1923  /* turn a single unit around */
1924 
1925  if (v->IsMultiheaded() || HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) {
1926  return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
1927  }
1928  if (!HasBit(EngInfo(v->engine_type)->misc_flags, EF_RAIL_FLIPS)) return CMD_ERROR;
1929 
1930  Train *front = v->First();
1931  /* make sure the vehicle is stopped in the depot */
1932  if (!front->IsStoppedInDepot()) {
1933  return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1934  }
1935 
1936  if (flags & DC_EXEC) {
1937  ToggleBit(v->flags, VRF_REVERSE_DIRECTION);
1938 
1939  front->ConsistChanged(CCF_ARRANGE);
1944  }
1945  } else {
1946  /* turn the whole train around */
1947  if ((v->vehstatus & VS_CRASHED) || v->breakdown_ctr != 0) return CMD_ERROR;
1948 
1949  if (flags & DC_EXEC) {
1950  /* Properly leave the station if we are loading and won't be loading anymore */
1951  if (v->current_order.IsType(OT_LOADING)) {
1952  const Vehicle *last = v;
1953  while (last->Next() != NULL) last = last->Next();
1954 
1955  /* not a station || different station --> leave the station */
1956  if (!IsTileType(last->tile, MP_STATION) || GetStationIndex(last->tile) != GetStationIndex(v->tile)) {
1957  v->LeaveStation();
1958  }
1959  }
1960 
1961  /* We cancel any 'skip signal at dangers' here */
1962  v->force_proceed = TFP_NONE;
1964 
1965  if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && v->cur_speed != 0) {
1966  ToggleBit(v->flags, VRF_REVERSING);
1967  } else {
1968  v->cur_speed = 0;
1969  v->SetLastSpeed();
1972  }
1973  }
1974  }
1975  return CommandCost();
1976 }
1977 
1987 CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1988 {
1989  Train *t = Train::GetIfValid(p1);
1990  if (t == NULL) return CMD_ERROR;
1991 
1992  if (!t->IsPrimaryVehicle()) return CMD_ERROR;
1993 
1994  CommandCost ret = CheckOwnership(t->owner);
1995  if (ret.Failed()) return ret;
1996 
1997 
1998  if (flags & DC_EXEC) {
1999  /* If we are forced to proceed, cancel that order.
2000  * If we are marked stuck we would want to force the train
2001  * to proceed to the next signal. In the other cases we
2002  * would like to pass the signal at danger and run till the
2003  * next signal we encounter. */
2004  t->force_proceed = t->force_proceed == TFP_SIGNAL ? TFP_NONE : HasBit(t->flags, VRF_TRAIN_STUCK) || t->IsChainInDepot() ? TFP_STUCK : TFP_SIGNAL;
2006  }
2007 
2008  return CommandCost();
2009 }
2010 
2018 static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
2019 {
2020  assert(!(v->vehstatus & VS_CRASHED));
2021 
2022  if (IsRailDepotTile(v->tile)) return FindDepotData(v->tile, 0);
2023 
2024  PBSTileInfo origin = FollowTrainReservation(v);
2025  if (IsRailDepotTile(origin.tile)) return FindDepotData(origin.tile, 0);
2026 
2028  case VPF_NPF: return NPFTrainFindNearestDepot(v, max_distance);
2029  case VPF_YAPF: return YapfTrainFindNearestDepot(v, max_distance);
2030 
2031  default: NOT_REACHED();
2032  }
2033 }
2034 
2042 bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
2043 {
2044  FindDepotData tfdd = FindClosestTrainDepot(this, 0);
2045  if (tfdd.best_length == UINT_MAX) return false;
2046 
2047  if (location != NULL) *location = tfdd.tile;
2048  if (destination != NULL) *destination = GetDepotIndex(tfdd.tile);
2049  if (reverse != NULL) *reverse = tfdd.reverse;
2050 
2051  return true;
2052 }
2053 
2056 {
2057  static const SoundFx sfx[] = {
2058  SND_04_TRAIN,
2059  SND_0A_TRAIN_HORN,
2060  SND_0A_TRAIN_HORN,
2061  SND_47_MAGLEV_2,
2062  SND_41_MAGLEV
2063  };
2064 
2065  if (PlayVehicleSound(this, VSE_START)) return;
2066 
2067  EngineID engtype = this->engine_type;
2068  SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
2069 }
2070 
2075 static void CheckNextTrainTile(Train *v)
2076 {
2077  /* Don't do any look-ahead if path_backoff_interval is 255. */
2078  if (_settings_game.pf.path_backoff_interval == 255) return;
2079 
2080  /* Exit if we are inside a depot. */
2081  if (v->track == TRACK_BIT_DEPOT) return;
2082 
2083  switch (v->current_order.GetType()) {
2084  /* Exit if we reached our destination depot. */
2085  case OT_GOTO_DEPOT:
2086  if (v->tile == v->dest_tile) return;
2087  break;
2088 
2089  case OT_GOTO_WAYPOINT:
2090  /* If we reached our waypoint, make sure we see that. */
2092  break;
2093 
2094  case OT_NOTHING:
2095  case OT_LEAVESTATION:
2096  case OT_LOADING:
2097  /* Exit if the current order doesn't have a destination, but the train has orders. */
2098  if (v->GetNumOrders() > 0) return;
2099  break;
2100 
2101  default:
2102  break;
2103  }
2104  /* Exit if we are on a station tile and are going to stop. */
2106 
2107  Trackdir td = v->GetVehicleTrackdir();
2108 
2109  /* On a tile with a red non-pbs signal, don't look ahead. */
2110  if (IsTileType(v->tile, MP_RAILWAY) && HasSignalOnTrackdir(v->tile, td) &&
2111  !IsPbsSignal(GetSignalType(v->tile, TrackdirToTrack(td))) &&
2112  GetSignalStateByTrackdir(v->tile, td) == SIGNAL_STATE_RED) return;
2113 
2114  CFollowTrackRail ft(v);
2115  if (!ft.Follow(v->tile, td)) return;
2116 
2118  /* Next tile is not reserved. */
2121  /* If the next tile is a PBS signal, try to make a reservation. */
2125  }
2126  ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, NULL, false);
2127  }
2128  }
2129  }
2130 }
2131 
2138 {
2139  /* bail out if not all wagons are in the same depot or not in a depot at all */
2140  for (const Train *u = v; u != NULL; u = u->Next()) {
2141  if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
2142  }
2143 
2144  /* if the train got no power, then keep it in the depot */
2145  if (v->gcache.cached_power == 0) {
2146  v->vehstatus |= VS_STOPPED;
2148  return true;
2149  }
2150 
2151  SigSegState seg_state;
2152 
2153  if (v->force_proceed == TFP_NONE) {
2154  /* force proceed was not pressed */
2155  if (++v->wait_counter < 37) {
2157  return true;
2158  }
2159 
2160  v->wait_counter = 0;
2161 
2163  if (seg_state == SIGSEG_FULL || HasDepotReservation(v->tile)) {
2164  /* Full and no PBS signal in block or depot reserved, can't exit. */
2166  return true;
2167  }
2168  } else {
2170  }
2171 
2172  /* We are leaving a depot, but have to go to the exact same one; re-enter */
2173  if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
2174  /* We need to have a reservation for this to work. */
2175  if (HasDepotReservation(v->tile)) return true;
2176  SetDepotReservation(v->tile, true);
2177  VehicleEnterDepot(v);
2178  return true;
2179  }
2180 
2181  /* Only leave when we can reserve a path to our destination. */
2182  if (seg_state == SIGSEG_PBS && !TryPathReserve(v) && v->force_proceed == TFP_NONE) {
2183  /* No path and no force proceed. */
2185  MarkTrainAsStuck(v);
2186  return true;
2187  }
2188 
2189  SetDepotReservation(v->tile, true);
2191 
2194  v->PlayLeaveStationSound();
2195 
2196  v->track = TRACK_BIT_X;
2197  if (v->direction & 2) v->track = TRACK_BIT_Y;
2198 
2199  v->vehstatus &= ~VS_HIDDEN;
2200  v->cur_speed = 0;
2201 
2202  v->UpdateViewport(true, true);
2203  v->UpdatePosition();
2205  v->UpdateAcceleration();
2207 
2208  return false;
2209 }
2210 
2217 static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir)
2218 {
2219  DiagDirection dir = TrackdirToExitdir(track_dir);
2220 
2221  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
2222  /* Are we just leaving a tunnel/bridge? */
2223  if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
2224  TileIndex end = GetOtherTunnelBridgeEnd(tile);
2225 
2226  if (TunnelBridgeIsFree(tile, end, v).Succeeded()) {
2227  /* Free the reservation only if no other train is on the tiles. */
2228  SetTunnelBridgeReservation(tile, false);
2229  SetTunnelBridgeReservation(end, false);
2230 
2232  if (IsBridge(tile)) {
2233  MarkBridgeDirty(tile);
2234  } else {
2235  MarkTileDirtyByTile(tile);
2236  MarkTileDirtyByTile(end);
2237  }
2238  }
2239  }
2240  }
2241  } else if (IsRailStationTile(tile)) {
2242  TileIndex new_tile = TileAddByDiagDir(tile, dir);
2243  /* If the new tile is not a further tile of the same station, we
2244  * clear the reservation for the whole platform. */
2245  if (!IsCompatibleTrainStationTile(new_tile, tile)) {
2247  }
2248  } else {
2249  /* Any other tile */
2250  UnreserveRailTrack(tile, TrackdirToTrack(track_dir));
2251  }
2252 }
2253 
2259 {
2260  assert(v->IsFrontEngine());
2261 
2262  TileIndex tile = v->tile;
2263  Trackdir td = v->GetVehicleTrackdir();
2264  bool free_tile = !(IsRailStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
2265  StationID station_id = IsRailStationTile(v->tile) ? GetStationIndex(v->tile) : INVALID_STATION;
2266 
2267  /* Can't be holding a reservation if we enter a depot. */
2268  if (IsRailDepotTile(tile) && TrackdirToExitdir(td) != GetRailDepotDirection(tile)) return;
2269  if (v->track == TRACK_BIT_DEPOT) {
2270  /* Front engine is in a depot. We enter if some part is not in the depot. */
2271  for (const Train *u = v; u != NULL; u = u->Next()) {
2272  if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return;
2273  }
2274  }
2275  /* Don't free reservation if it's not ours. */
2277 
2279  while (ft.Follow(tile, td)) {
2280  tile = ft.m_new_tile;
2282  td = RemoveFirstTrackdir(&bits);
2283  assert(bits == TRACKDIR_BIT_NONE);
2284 
2285  if (!IsValidTrackdir(td)) break;
2286 
2287  if (IsTileType(tile, MP_RAILWAY)) {
2288  if (HasSignalOnTrackdir(tile, td) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td)))) {
2289  /* Conventional signal along trackdir: remove reservation and stop. */
2291  break;
2292  }
2293  if (HasPbsSignalOnTrackdir(tile, td)) {
2294  if (GetSignalStateByTrackdir(tile, td) == SIGNAL_STATE_RED) {
2295  /* Red PBS signal? Can't be our reservation, would be green then. */
2296  break;
2297  } else {
2298  /* Turn the signal back to red. */
2300  MarkTileDirtyByTile(tile);
2301  }
2302  } else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
2303  break;
2304  }
2305  }
2306 
2307  /* Don't free first station/bridge/tunnel if we are on it. */
2308  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);
2309 
2310  free_tile = true;
2311  }
2312 }
2313 
2314 static const byte _initial_tile_subcoord[6][4][3] = {
2315 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }},
2316 {{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
2317 {{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }},
2318 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
2319 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }},
2320 {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
2321 };
2322 
2335 static Track DoTrainPathfind(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool do_track_reservation, PBSTileInfo *dest)
2336 {
2338  case VPF_NPF: return NPFTrainChooseTrack(v, tile, enterdir, tracks, path_found, do_track_reservation, dest);
2339  case VPF_YAPF: return YapfTrainChooseTrack(v, tile, enterdir, tracks, path_found, do_track_reservation, dest);
2340 
2341  default: NOT_REACHED();
2342  }
2343 }
2344 
2350 static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir)
2351 {
2352  PBSTileInfo origin = FollowTrainReservation(v);
2353 
2354  CFollowTrackRail ft(v);
2355 
2356  TileIndex tile = origin.tile;
2357  Trackdir cur_td = origin.trackdir;
2358  while (ft.Follow(tile, cur_td)) {
2360  /* Possible signal tile. */
2362  }
2363 
2366  if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) break;
2367  }
2368 
2369  /* Station, depot or waypoint are a possible target. */
2370  bool target_seen = ft.m_is_station || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile));
2371  if (target_seen || KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
2372  /* Choice found or possible target encountered.
2373  * On finding a possible target, we need to stop and let the pathfinder handle the
2374  * remaining path. This is because we don't know if this target is in one of our
2375  * orders, so we might cause pathfinding to fail later on if we find a choice.
2376  * This failure would cause a bogous call to TryReserveSafePath which might reserve
2377  * a wrong path not leading to our next destination. */
2379 
2380  /* If we did skip some tiles, backtrack to the first skipped tile so the pathfinder
2381  * actually starts its search at the first unreserved tile. */
2383 
2384  /* Choice found, path valid but not okay. Save info about the choice tile as well. */
2385  if (new_tracks != NULL) *new_tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
2386  if (enterdir != NULL) *enterdir = ft.m_exitdir;
2387  return PBSTileInfo(ft.m_new_tile, ft.m_old_td, false);
2388  }
2389 
2390  tile = ft.m_new_tile;
2391  cur_td = FindFirstTrackdir(ft.m_new_td_bits);
2392 
2393  if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) {
2394  bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg);
2395  if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break;
2396  /* Safe position is all good, path valid and okay. */
2397  return PBSTileInfo(tile, cur_td, true);
2398  }
2399 
2400  if (!TryReserveRailTrack(tile, TrackdirToTrack(cur_td))) break;
2401  }
2402 
2403  if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
2404  /* End of line, path valid and okay. */
2405  return PBSTileInfo(ft.m_old_tile, ft.m_old_td, true);
2406  }
2407 
2408  /* Sorry, can't reserve path, back out. */
2409  tile = origin.tile;
2410  cur_td = origin.trackdir;
2411  TileIndex stopped = ft.m_old_tile;
2412  Trackdir stopped_td = ft.m_old_td;
2413  while (tile != stopped || cur_td != stopped_td) {
2414  if (!ft.Follow(tile, cur_td)) break;
2415 
2418  assert(ft.m_new_td_bits != TRACKDIR_BIT_NONE);
2419  }
2421 
2422  tile = ft.m_new_tile;
2423  cur_td = FindFirstTrackdir(ft.m_new_td_bits);
2424 
2425  UnreserveRailTrack(tile, TrackdirToTrack(cur_td));
2426  }
2427 
2428  /* Path invalid. */
2429  return PBSTileInfo();
2430 }
2431 
2442 static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_tailtype)
2443 {
2445  case VPF_NPF: return NPFTrainFindNearestSafeTile(v, tile, td, override_tailtype);
2446  case VPF_YAPF: return YapfTrainFindNearestSafeTile(v, tile, td, override_tailtype);
2447 
2448  default: NOT_REACHED();
2449  }
2450 }
2451 
2454 private:
2455  Train *v;
2456  Order old_order;
2457  TileIndex old_dest_tile;
2458  StationID old_last_station_visited;
2460  bool suppress_implicit_orders;
2461 
2462 public:
2463  VehicleOrderSaver(Train *_v) :
2464  v(_v),
2465  old_order(_v->current_order),
2466  old_dest_tile(_v->dest_tile),
2467  old_last_station_visited(_v->last_station_visited),
2469  suppress_implicit_orders(HasBit(_v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS))
2470  {
2471  }
2472 
2474  {
2475  this->v->current_order = this->old_order;
2476  this->v->dest_tile = this->old_dest_tile;
2477  this->v->last_station_visited = this->old_last_station_visited;
2478  SB(this->v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS, 1, suppress_implicit_orders ? 1: 0);
2479  }
2480 
2486  bool SwitchToNextOrder(bool skip_first)
2487  {
2488  if (this->v->GetNumOrders() == 0) return false;
2489 
2490  if (skip_first) ++this->index;
2491 
2492  int depth = 0;
2493 
2494  do {
2495  /* Wrap around. */
2496  if (this->index >= this->v->GetNumOrders()) this->index = 0;
2497 
2498  Order *order = this->v->GetOrder(this->index);
2499  assert(order != NULL);
2500 
2501  switch (order->GetType()) {
2502  case OT_GOTO_DEPOT:
2503  /* Skip service in depot orders when the train doesn't need service. */
2504  if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !this->v->NeedsServicing()) break;
2505  FALLTHROUGH;
2506  case OT_GOTO_STATION:
2507  case OT_GOTO_WAYPOINT:
2508  this->v->current_order = *order;
2509  return UpdateOrderDest(this->v, order, 0, true);
2510  case OT_CONDITIONAL: {
2511  VehicleOrderID next = ProcessConditionalOrder(order, this->v);
2512  if (next != INVALID_VEH_ORDER_ID) {
2513  depth++;
2514  this->index = next;
2515  /* Don't increment next, so no break here. */
2516  continue;
2517  }
2518  break;
2519  }
2520  default:
2521  break;
2522  }
2523  /* Don't increment inside the while because otherwise conditional
2524  * orders can lead to an infinite loop. */
2525  ++this->index;
2526  depth++;
2527  } while (this->index != this->v->cur_real_order_index && depth < this->v->GetNumOrders());
2528 
2529  return false;
2530  }
2531 };
2532 
2533 /* choose a track */
2534 static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
2535 {
2536  Track best_track = INVALID_TRACK;
2537  bool do_track_reservation = _settings_game.pf.reserve_paths || force_res;
2538  bool changed_signal = false;
2539 
2540  assert((tracks & ~TRACK_BIT_MASK) == 0);
2541 
2542  if (got_reservation != NULL) *got_reservation = false;
2543 
2544  /* Don't use tracks here as the setting to forbid 90 deg turns might have been switched between reservation and now. */
2545  TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir));
2546  /* Do we have a suitable reserved track? */
2547  if (res_tracks != TRACK_BIT_NONE) return FindFirstTrack(res_tracks);
2548 
2549  /* Quick return in case only one possible track is available */
2550  if (KillFirstBit(tracks) == TRACK_BIT_NONE) {
2551  Track track = FindFirstTrack(tracks);
2552  /* We need to check for signals only here, as a junction tile can't have signals. */
2553  if (track != INVALID_TRACK && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) {
2554  do_track_reservation = true;
2555  changed_signal = true;
2557  } else if (!do_track_reservation) {
2558  return track;
2559  }
2560  best_track = track;
2561  }
2562 
2563  PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false);
2564  DiagDirection dest_enterdir = enterdir;
2565  if (do_track_reservation) {
2566  res_dest = ExtendTrainReservation(v, &tracks, &dest_enterdir);
2567  if (res_dest.tile == INVALID_TILE) {
2568  /* Reservation failed? */
2569  if (mark_stuck) MarkTrainAsStuck(v);
2570  if (changed_signal) SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(best_track, enterdir), SIGNAL_STATE_RED);
2571  return FindFirstTrack(tracks);
2572  }
2573  if (res_dest.okay) {
2574  /* Got a valid reservation that ends at a safe target, quick exit. */
2575  if (got_reservation != NULL) *got_reservation = true;
2576  if (changed_signal) MarkTileDirtyByTile(tile);
2578  return best_track;
2579  }
2580 
2581  /* Check if the train needs service here, so it has a chance to always find a depot.
2582  * Also check if the current order is a service order so we don't reserve a path to
2583  * the destination but instead to the next one if service isn't needed. */
2585  if (v->current_order.IsType(OT_DUMMY) || v->current_order.IsType(OT_CONDITIONAL) || v->current_order.IsType(OT_GOTO_DEPOT)) ProcessOrders(v);
2586  }
2587 
2588  /* Save the current train order. The destructor will restore the old order on function exit. */
2590 
2591  /* If the current tile is the destination of the current order and
2592  * a reservation was requested, advance to the next order.
2593  * Don't advance on a depot order as depots are always safe end points
2594  * for a path and no look-ahead is necessary. This also avoids a
2595  * problem with depot orders not part of the order list when the
2596  * order list itself is empty. */
2597  if (v->current_order.IsType(OT_LEAVESTATION)) {
2598  orders.SwitchToNextOrder(false);
2599  } else if (v->current_order.IsType(OT_LOADING) || (!v->current_order.IsType(OT_GOTO_DEPOT) && (
2600  v->current_order.IsType(OT_GOTO_STATION) ?
2602  v->tile == v->dest_tile))) {
2603  orders.SwitchToNextOrder(true);
2604  }
2605 
2606  if (res_dest.tile != INVALID_TILE && !res_dest.okay) {
2607  /* Pathfinders are able to tell that route was only 'guessed'. */
2608  bool path_found = true;
2609  TileIndex new_tile = res_dest.tile;
2610 
2611  Track next_track = DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
2612  if (new_tile == tile) best_track = next_track;
2613  v->HandlePathfindingResult(path_found);
2614  }
2615 
2616  /* No track reservation requested -> finished. */
2617  if (!do_track_reservation) return best_track;
2618 
2619  /* A path was found, but could not be reserved. */
2620  if (res_dest.tile != INVALID_TILE && !res_dest.okay) {
2621  if (mark_stuck) MarkTrainAsStuck(v);
2623  return best_track;
2624  }
2625 
2626  /* No possible reservation target found, we are probably lost. */
2627  if (res_dest.tile == INVALID_TILE) {
2628  /* Try to find any safe destination. */
2629  PBSTileInfo origin = FollowTrainReservation(v);
2630  if (TryReserveSafeTrack(v, origin.tile, origin.trackdir, false)) {
2632  best_track = FindFirstTrack(res);
2634  if (got_reservation != NULL) *got_reservation = true;
2635  if (changed_signal) MarkTileDirtyByTile(tile);
2636  } else {
2638  if (mark_stuck) MarkTrainAsStuck(v);
2639  }
2640  return best_track;
2641  }
2642 
2643  if (got_reservation != NULL) *got_reservation = true;
2644 
2645  /* Reservation target found and free, check if it is safe. */
2646  while (!IsSafeWaitingPosition(v, res_dest.tile, res_dest.trackdir, true, _settings_game.pf.forbid_90_deg)) {
2647  /* Extend reservation until we have found a safe position. */
2648  DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir);
2649  TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir);
2652  reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir));
2653  }
2654 
2655  /* Get next order with destination. */
2656  if (orders.SwitchToNextOrder(true)) {
2657  PBSTileInfo cur_dest;
2658  bool path_found;
2659  DoTrainPathfind(v, next_tile, exitdir, reachable, path_found, true, &cur_dest);
2660  if (cur_dest.tile != INVALID_TILE) {
2661  res_dest = cur_dest;
2662  if (res_dest.okay) continue;
2663  /* Path found, but could not be reserved. */
2665  if (mark_stuck) MarkTrainAsStuck(v);
2666  if (got_reservation != NULL) *got_reservation = false;
2667  changed_signal = false;
2668  break;
2669  }
2670  }
2671  /* No order or no safe position found, try any position. */
2672  if (!TryReserveSafeTrack(v, res_dest.tile, res_dest.trackdir, true)) {
2674  if (mark_stuck) MarkTrainAsStuck(v);
2675  if (got_reservation != NULL) *got_reservation = false;
2676  changed_signal = false;
2677  }
2678  break;
2679  }
2680 
2682 
2683  if (changed_signal) MarkTileDirtyByTile(tile);
2684 
2685  return best_track;
2686 }
2687 
2696 bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
2697 {
2698  assert(v->IsFrontEngine());
2699 
2700  /* We have to handle depots specially as the track follower won't look
2701  * at the depot tile itself but starts from the next tile. If we are still
2702  * inside the depot, a depot reservation can never be ours. */
2703  if (v->track == TRACK_BIT_DEPOT) {
2704  if (HasDepotReservation(v->tile)) {
2705  if (mark_as_stuck) MarkTrainAsStuck(v);
2706  return false;
2707  } else {
2708  /* Depot not reserved, but the next tile might be. */
2710  if (HasReservedTracks(next_tile, DiagdirReachesTracks(GetRailDepotDirection(v->tile)))) return false;
2711  }
2712  }
2713 
2714  Vehicle *other_train = NULL;
2715  PBSTileInfo origin = FollowTrainReservation(v, &other_train);
2716  /* The path we are driving on is already blocked by some other train.
2717  * This can only happen in certain situations when mixing path and
2718  * block signals or when changing tracks and/or signals.
2719  * Exit here as doing any further reservations will probably just
2720  * make matters worse. */
2721  if (other_train != NULL && other_train->index != v->index) {
2722  if (mark_as_stuck) MarkTrainAsStuck(v);
2723  return false;
2724  }
2725  /* If we have a reserved path and the path ends at a safe tile, we are finished already. */
2726  if (origin.okay && (v->tile != origin.tile || first_tile_okay)) {
2727  /* Can't be stuck then. */
2729  ClrBit(v->flags, VRF_TRAIN_STUCK);
2730  return true;
2731  }
2732 
2733  /* If we are in a depot, tentatively reserve the depot. */
2734  if (v->track == TRACK_BIT_DEPOT) {
2735  SetDepotReservation(v->tile, true);
2737  }
2738 
2739  DiagDirection exitdir = TrackdirToExitdir(origin.trackdir);
2740  TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir);
2742 
2744 
2745  bool res_made = false;
2746  ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck);
2747 
2748  if (!res_made) {
2749  /* Free the depot reservation as well. */
2750  if (v->track == TRACK_BIT_DEPOT) SetDepotReservation(v->tile, false);
2751  return false;
2752  }
2753 
2754  if (HasBit(v->flags, VRF_TRAIN_STUCK)) {
2755  v->wait_counter = 0;
2757  }
2758  ClrBit(v->flags, VRF_TRAIN_STUCK);
2759  return true;
2760 }
2761 
2762 
2763 static bool CheckReverseTrain(const Train *v)
2764 {
2766  v->track == TRACK_BIT_DEPOT || v->track == TRACK_BIT_WORMHOLE ||
2767  !(v->direction & 1)) {
2768  return false;
2769  }
2770 
2771  assert(v->track != TRACK_BIT_NONE);
2772 
2774  case VPF_NPF: return NPFTrainCheckReverse(v);
2775  case VPF_YAPF: return YapfTrainCheckReverse(v);
2776 
2777  default: NOT_REACHED();
2778  }
2779 }
2780 
2787 {
2788  if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
2789 
2790  const Station *st = Station::Get(station);
2791  if (!(st->facilities & FACIL_TRAIN)) {
2792  /* The destination station has no trainstation tiles. */
2793  this->IncrementRealOrderIndex();
2794  return 0;
2795  }
2796 
2797  return st->xy;
2798 }
2799 
2802 {
2803  Train *v = this;
2804  do {
2805  v->colourmap = PAL_NONE;
2806  v->UpdateViewport(true, false);
2807  } while ((v = v->Next()) != NULL);
2808 
2809  /* need to update acceleration and cached values since the goods on the train changed. */
2810  this->CargoChanged();
2811  this->UpdateAcceleration();
2812 }
2813 
2822 {
2824  default: NOT_REACHED();
2825  case AM_ORIGINAL:
2826  return this->DoUpdateSpeed(this->acceleration * (this->GetAccelerationStatus() == AS_BRAKE ? -4 : 2), 0, this->GetCurrentMaxSpeed());
2827 
2828  case AM_REALISTIC:
2829  return this->DoUpdateSpeed(this->GetAcceleration(), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 2, this->GetCurrentMaxSpeed());
2830  }
2831 }
2832 
2838 static void TrainEnterStation(Train *v, StationID station)
2839 {
2840  v->last_station_visited = station;
2841 
2842  /* check if a train ever visited this station before */
2843  Station *st = Station::Get(station);
2844  if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
2845  st->had_vehicle_of_type |= HVOT_TRAIN;
2846  SetDParam(0, st->index);
2848  STR_NEWS_FIRST_TRAIN_ARRIVAL,
2850  v->index,
2851  st->index
2852  );
2853  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
2854  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
2855  }
2856 
2857  v->force_proceed = TFP_NONE;
2859 
2860  v->BeginLoading();
2861 
2863  TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
2864 }
2865 
2866 /* Check if the vehicle is compatible with the specified tile */
2867 static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
2868 {
2869  return IsTileOwner(tile, v->owner) &&
2870  (!v->IsFrontEngine() || HasBit(v->compatible_railtypes, GetRailType(tile)));
2871 }
2872 
2875  byte small_turn;
2876  byte large_turn;
2877  byte z_up;
2878  byte z_down;
2879 };
2880 
2883  /* normal accel */
2884  {256 / 4, 256 / 2, 256 / 4, 2},
2885  {256 / 4, 256 / 2, 256 / 4, 2},
2886  {0, 256 / 2, 256 / 4, 2},
2887 };
2888 
2894 static inline void AffectSpeedByZChange(Train *v, int old_z)
2895 {
2896  if (old_z == v->z_pos || _settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) return;
2897 
2898  const AccelerationSlowdownParams *asp = &_accel_slowdown[GetRailTypeInfo(v->railtype)->acceleration_type];
2899 
2900  if (old_z < v->z_pos) {
2901  v->cur_speed -= (v->cur_speed * asp->z_up >> 8);
2902  } else {
2903  uint16 spd = v->cur_speed + asp->z_down;
2904  if (spd <= v->gcache.cached_max_track_speed) v->cur_speed = spd;
2905  }
2906 }
2907 
2908 static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
2909 {
2910  if (IsTileType(tile, MP_RAILWAY) &&
2913  Trackdir trackdir = FindFirstTrackdir(tracks);
2915  /* A PBS block with a non-PBS signal facing us? */
2916  if (!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
2917  }
2918  }
2919  return false;
2920 }
2921 
2924 {
2925  for (const Train *u = this; u != NULL; u = u->Next()) {
2926  switch (u->track) {
2927  case TRACK_BIT_WORMHOLE:
2929  break;
2930  case TRACK_BIT_DEPOT:
2931  break;
2932  default:
2933  TryReserveRailTrack(u->tile, TrackBitsToTrack(u->track));
2934  break;
2935  }
2936  }
2937 }
2938 
2945 uint Train::Crash(bool flooded)
2946 {
2947  uint pass = 0;
2948  if (this->IsFrontEngine()) {
2949  pass += 2; // driver
2950 
2951  /* Remove the reserved path in front of the train if it is not stuck.
2952  * Also clear all reserved tracks the train is currently on. */
2953  if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this);
2954  for (const Train *v = this; v != NULL; v = v->Next()) {
2956  if (IsTileType(v->tile, MP_TUNNELBRIDGE)) {
2957  /* ClearPathReservation will not free the wormhole exit
2958  * if the train has just entered the wormhole. */
2960  }
2961  }
2962 
2963  /* we may need to update crossing we were approaching,
2964  * but must be updated after the train has been marked crashed */
2965  TileIndex crossing = TrainApproachingCrossingTile(this);
2966  if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
2967 
2968  /* Remove the loading indicators (if any) */
2970  }
2971 
2972  pass += this->GroundVehicleBase::Crash(flooded);
2973 
2974  this->crash_anim_pos = flooded ? 4000 : 1; // max 4440, disappear pretty fast when flooded
2975  return pass;
2976 }
2977 
2984 static uint TrainCrashed(Train *v)
2985 {
2986  uint num = 0;
2987 
2988  /* do not crash train twice */
2989  if (!(v->vehstatus & VS_CRASHED)) {
2990  num = v->Crash();
2991  AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN));
2992  Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN));
2993  }
2994 
2995  /* Try to re-reserve track under already crashed train too.
2996  * Crash() clears the reservation! */
2998 
2999  return num;
3000 }
3001 
3005  uint num;
3006 };
3007 
3014 static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data)
3015 {
3017 
3018  /* not a train or in depot */
3019  if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return NULL;
3020 
3021  /* do not crash into trains of another company. */
3022  if (v->owner != tcc->v->owner) return NULL;
3023 
3024  /* get first vehicle now to make most usual checks faster */
3025  Train *coll = Train::From(v)->First();
3026 
3027  /* can't collide with own wagons */
3028  if (coll == tcc->v) return NULL;
3029 
3030  int x_diff = v->x_pos - tcc->v->x_pos;
3031  int y_diff = v->y_pos - tcc->v->y_pos;
3032 
3033  /* Do fast calculation to check whether trains are not in close vicinity
3034  * and quickly reject trains distant enough for any collision.
3035  * Differences are shifted by 7, mapping range [-7 .. 8] into [0 .. 15]
3036  * Differences are then ORed and then we check for any higher bits */
3037  uint hash = (y_diff + 7) | (x_diff + 7);
3038  if (hash & ~15) return NULL;
3039 
3040  /* Slower check using multiplication */
3041  int min_diff = (Train::From(v)->gcache.cached_veh_length + 1) / 2 + (tcc->v->gcache.cached_veh_length + 1) / 2 - 1;
3042  if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff) return NULL;
3043 
3044  /* Happens when there is a train under bridge next to bridge head */
3045  if (abs(v->z_pos - tcc->v->z_pos) > 5) return NULL;
3046 
3047  /* crash both trains */
3048  tcc->num += TrainCrashed(tcc->v);
3049  tcc->num += TrainCrashed(coll);
3050 
3051  return NULL; // continue searching
3052 }
3053 
3062 {
3063  /* can't collide in depot */
3064  if (v->track == TRACK_BIT_DEPOT) return false;
3065 
3066  assert(v->track == TRACK_BIT_WORMHOLE || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
3067 
3068  TrainCollideChecker tcc;
3069  tcc.v = v;
3070  tcc.num = 0;
3071 
3072  /* find colliding vehicles */
3073  if (v->track == TRACK_BIT_WORMHOLE) {
3076  } else {
3078  }
3079 
3080  /* any dead -> no crash */
3081  if (tcc.num == 0) return false;
3082 
3083  SetDParam(0, tcc.num);
3084  AddVehicleNewsItem(STR_NEWS_TRAIN_CRASH, NT_ACCIDENT, v->index);
3085 
3086  ModifyStationRatingAround(v->tile, v->owner, -160, 30);
3087  if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_BIG_CRASH, v);
3088  return true;
3089 }
3090 
3091 static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
3092 {
3093  if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return NULL;
3094 
3095  Train *t = Train::From(v);
3096  DiagDirection exitdir = *(DiagDirection *)data;
3097 
3098  /* not front engine of a train, inside wormhole or depot, crashed */
3099  if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return NULL;
3100 
3101  if (t->cur_speed > 5 || TrainExitDir(t->direction, t->track) != exitdir) return NULL;
3102 
3103  return t;
3104 }
3105 
3113 bool TrainController(Train *v, Vehicle *nomove, bool reverse)
3114 {
3115  Train *first = v->First();
3116  Train *prev;
3117  bool direction_changed = false; // has direction of any part changed?
3118 
3119  /* For every vehicle after and including the given vehicle */
3120  for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) {
3121  DiagDirection enterdir = DIAGDIR_BEGIN;
3122  bool update_signals_crossing = false; // will we update signals or crossing state?
3123 
3125  if (v->track != TRACK_BIT_WORMHOLE) {
3126  /* Not inside tunnel */
3127  if (gp.old_tile == gp.new_tile) {
3128  /* Staying in the old tile */
3129  if (v->track == TRACK_BIT_DEPOT) {
3130  /* Inside depot */
3131  gp.x = v->x_pos;
3132  gp.y = v->y_pos;
3133  } else {
3134  /* Not inside depot */
3135 
3136  /* Reverse when we are at the end of the track already, do not move to the new position */
3137  if (v->IsFrontEngine() && !TrainCheckIfLineEnds(v, reverse)) return false;
3138 
3139  uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
3140  if (HasBit(r, VETS_CANNOT_ENTER)) {
3141  goto invalid_rail;
3142  }
3143  if (HasBit(r, VETS_ENTERED_STATION)) {
3144  /* The new position is the end of the platform */
3146  }
3147  }
3148  } else {
3149  /* A new tile is about to be entered. */
3150 
3151  /* Determine what direction we're entering the new tile from */
3152  enterdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
3153  assert(IsValidDiagDirection(enterdir));
3154 
3155  /* Get the status of the tracks in the new tile and mask
3156  * away the bits that aren't reachable. */
3157  TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir));
3158  TrackdirBits reachable_trackdirs = DiagdirReachesTrackdirs(enterdir);
3159 
3160  TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts) & reachable_trackdirs;
3161  TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs);
3162 
3163  TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
3164  if (_settings_game.pf.forbid_90_deg && prev == NULL) {
3165  /* We allow wagons to make 90 deg turns, because forbid_90_deg
3166  * can be switched on halfway a turn */
3167  bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
3168  }
3169 
3170  if (bits == TRACK_BIT_NONE) goto invalid_rail;
3171 
3172  /* Check if the new tile constrains tracks that are compatible
3173  * with the current train, if not, bail out. */
3174  if (!CheckCompatibleRail(v, gp.new_tile)) goto invalid_rail;
3175 
3176  TrackBits chosen_track;
3177  if (prev == NULL) {
3178  /* Currently the locomotive is active. Determine which one of the
3179  * available tracks to choose */
3180  chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits, false, NULL, true));
3181  assert(chosen_track & (bits | GetReservedTrackbits(gp.new_tile)));
3182 
3183  if (v->force_proceed != TFP_NONE && IsPlainRailTile(gp.new_tile) && HasSignals(gp.new_tile)) {
3184  /* For each signal we find decrease the counter by one.
3185  * We start at two, so the first signal we pass decreases
3186  * this to one, then if we reach the next signal it is
3187  * decreased to zero and we won't pass that new signal. */
3188  Trackdir dir = FindFirstTrackdir(trackdirbits);
3189  if (HasSignalOnTrackdir(gp.new_tile, dir) ||
3191  GetSignalType(gp.new_tile, TrackdirToTrack(dir)) != SIGTYPE_PBS)) {
3192  /* However, we do not want to be stopped by PBS signals
3193  * entered via the back. */
3194  v->force_proceed = (v->force_proceed == TFP_SIGNAL) ? TFP_STUCK : TFP_NONE;
3195  SetWindowDirty(WC_VEHICLE_VIEW, v->index);
3196  }
3197  }
3198 
3199  /* Check if it's a red signal and that force proceed is not clicked. */
3200  if ((red_signals & chosen_track) && v->force_proceed == TFP_NONE) {
3201  /* In front of a red signal */
3202  Trackdir i = FindFirstTrackdir(trackdirbits);
3203 
3204  /* Don't handle stuck trains here. */
3205  if (HasBit(v->flags, VRF_TRAIN_STUCK)) return false;
3206 
3208  v->cur_speed = 0;
3209  v->subspeed = 0;
3210  v->progress = 255 - 100;
3211  if (!_settings_game.pf.reverse_at_signals || ++v->wait_counter < _settings_game.pf.wait_oneway_signal * 20) return false;
3212  } else if (HasSignalOnTrackdir(gp.new_tile, i)) {
3213  v->cur_speed = 0;
3214  v->subspeed = 0;
3215  v->progress = 255 - 10;
3216  if (!_settings_game.pf.reverse_at_signals || ++v->wait_counter < _settings_game.pf.wait_twoway_signal * 73) {
3217  DiagDirection exitdir = TrackdirToExitdir(i);
3218  TileIndex o_tile = TileAddByDiagDir(gp.new_tile, exitdir);
3219 
3220  exitdir = ReverseDiagDir(exitdir);
3221 
3222  /* check if a train is waiting on the other side */
3223  if (!HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal)) return false;
3224  }
3225  }
3226 
3227  /* If we would reverse but are currently in a PBS block and
3228  * reversing of stuck trains is disabled, don't reverse.
3229  * This does not apply if the reason for reversing is a one-way
3230  * signal blocking us, because a train would then be stuck forever. */
3232  UpdateSignalsOnSegment(v->tile, enterdir, v->owner) == SIGSEG_PBS) {
3233  v->wait_counter = 0;
3234  return false;
3235  }
3236  goto reverse_train_direction;
3237  } else {
3238  TryReserveRailTrack(gp.new_tile, TrackBitsToTrack(chosen_track), false);
3239  }
3240  } else {
3241  /* The wagon is active, simply follow the prev vehicle. */
3242  if (prev->tile == gp.new_tile) {
3243  /* Choose the same track as prev */
3244  if (prev->track == TRACK_BIT_WORMHOLE) {
3245  /* Vehicles entering tunnels enter the wormhole earlier than for bridges.
3246  * However, just choose the track into the wormhole. */
3247  assert(IsTunnel(prev->tile));
3248  chosen_track = bits;
3249  } else {
3250  chosen_track = prev->track;
3251  }
3252  } else {
3253  /* Choose the track that leads to the tile where prev is.
3254  * This case is active if 'prev' is already on the second next tile, when 'v' just enters the next tile.
3255  * I.e. when the tile between them has only space for a single vehicle like
3256  * 1) horizontal/vertical track tiles and
3257  * 2) some orientations of tunnel entries, where the vehicle is already inside the wormhole at 8/16 from the tile edge.
3258  * Is also the train just reversing, the wagon inside the tunnel is 'on' the tile of the opposite tunnel entry.
3259  */
3260  static const TrackBits _connecting_track[DIAGDIR_END][DIAGDIR_END] = {
3265  };
3266  DiagDirection exitdir = DiagdirBetweenTiles(gp.new_tile, prev->tile);
3267  assert(IsValidDiagDirection(exitdir));
3268  chosen_track = _connecting_track[enterdir][exitdir];
3269  }
3270  chosen_track &= bits;
3271  }
3272 
3273  /* Make sure chosen track is a valid track */
3274  assert(
3275  chosen_track == TRACK_BIT_X || chosen_track == TRACK_BIT_Y ||
3276  chosen_track == TRACK_BIT_UPPER || chosen_track == TRACK_BIT_LOWER ||
3277  chosen_track == TRACK_BIT_LEFT || chosen_track == TRACK_BIT_RIGHT);
3278 
3279  /* Update XY to reflect the entrance to the new tile, and select the direction to use */
3280  const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir];
3281  gp.x = (gp.x & ~0xF) | b[0];
3282  gp.y = (gp.y & ~0xF) | b[1];
3283  Direction chosen_dir = (Direction)b[2];
3284 
3285  /* Call the landscape function and tell it that the vehicle entered the tile */
3286  uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
3287  if (HasBit(r, VETS_CANNOT_ENTER)) {
3288  goto invalid_rail;
3289  }
3290 
3291  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
3292  Track track = FindFirstTrack(chosen_track);
3293  Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir);
3294  if (v->IsFrontEngine() && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) {
3297  }
3298 
3299  /* Clear any track reservation when the last vehicle leaves the tile */
3300  if (v->Next() == NULL) ClearPathReservation(v, v->tile, v->GetVehicleTrackdir());
3301 
3302  v->tile = gp.new_tile;
3303 
3305  v->First()->ConsistChanged(CCF_TRACK);
3306  }
3307 
3308  v->track = chosen_track;
3309  assert(v->track);
3310  }
3311 
3312  /* We need to update signal status, but after the vehicle position hash
3313  * has been updated by UpdateInclination() */
3314  update_signals_crossing = true;
3315 
3316  if (chosen_dir != v->direction) {
3317  if (prev == NULL && _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) {
3318  const AccelerationSlowdownParams *asp = &_accel_slowdown[GetRailTypeInfo(v->railtype)->acceleration_type];
3319  DirDiff diff = DirDifference(v->direction, chosen_dir);
3320  v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? asp->small_turn : asp->large_turn) * v->cur_speed >> 8;
3321  }
3322  direction_changed = true;
3323  v->direction = chosen_dir;
3324  }
3325 
3326  if (v->IsFrontEngine()) {
3327  v->wait_counter = 0;
3328 
3329  /* If we are approaching a crossing that is reserved, play the sound now. */
3331  if (crossing != INVALID_TILE && HasCrossingReservation(crossing) && _settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, crossing);
3332 
3333  /* Always try to extend the reservation when entering a tile. */
3334  CheckNextTrainTile(v);
3335  }
3336 
3337  if (HasBit(r, VETS_ENTERED_STATION)) {
3338  /* The new position is the location where we want to stop */
3340  }
3341  }
3342  } else {
3344  /* Perform look-ahead on tunnel exit. */
3345  if (v->IsFrontEngine()) {
3347  CheckNextTrainTile(v);
3348  }
3349  /* Prevent v->UpdateInclination() being called with wrong parameters.
3350  * This could happen if the train was reversed inside the tunnel/bridge. */
3351  if (gp.old_tile == gp.new_tile) {
3353  }
3354  } else {
3355  v->x_pos = gp.x;
3356  v->y_pos = gp.y;
3357  v->UpdatePosition();
3358  if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
3359  continue;
3360  }
3361  }
3362 
3363  /* update image of train, as well as delta XY */
3364  v->UpdateDeltaXY(v->direction);
3365 
3366  v->x_pos = gp.x;
3367  v->y_pos = gp.y;
3368  v->UpdatePosition();
3369 
3370  /* update the Z position of the vehicle */
3371  int old_z = v->UpdateInclination(gp.new_tile != gp.old_tile, false);
3372 
3373  if (prev == NULL) {
3374  /* This is the first vehicle in the train */
3375  AffectSpeedByZChange(v, old_z);
3376  }
3377 
3378  if (update_signals_crossing) {
3379  if (v->IsFrontEngine()) {
3380  if (TrainMovedChangeSignals(gp.new_tile, enterdir)) {
3381  /* We are entering a block with PBS signals right now, but
3382  * not through a PBS signal. This means we don't have a
3383  * reservation right now. As a conventional signal will only
3384  * ever be green if no other train is in the block, getting
3385  * a path should always be possible. If the player built
3386  * such a strange network that it is not possible, the train
3387  * will be marked as stuck and the player has to deal with
3388  * the problem. */
3389  if ((!HasReservedTracks(gp.new_tile, v->track) &&
3390  !TryReserveRailTrack(gp.new_tile, FindFirstTrack(v->track))) ||
3391  !TryPathReserve(v)) {
3392  MarkTrainAsStuck(v);
3393  }
3394  }
3395  }
3396 
3397  /* Signals can only change when the first
3398  * (above) or the last vehicle moves. */
3399  if (v->Next() == NULL) {
3400  TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
3402  }
3403  }
3404 
3405  /* Do not check on every tick to save some computing time. */
3406  if (v->IsFrontEngine() && v->tick_counter % _settings_game.pf.path_backoff_interval == 0) CheckNextTrainTile(v);
3407  }
3408 
3409  if (direction_changed) first->tcache.cached_max_curve_speed = first->GetCurveSpeedLimit();
3410 
3411  return true;
3412 
3413 invalid_rail:
3414  /* We've reached end of line?? */
3415  if (prev != NULL) error("Disconnecting train");
3416 
3417 reverse_train_direction:
3418  if (reverse) {
3419  v->wait_counter = 0;
3420  v->cur_speed = 0;
3421  v->subspeed = 0;
3423  }
3424 
3425  return false;
3426 }
3427 
3435 {
3436  TrackBits *trackbits = (TrackBits *)data;
3437 
3438  if (v->type == VEH_TRAIN && (v->vehstatus & VS_CRASHED) != 0) {
3439  TrackBits train_tbits = Train::From(v)->track;
3440  if (train_tbits == TRACK_BIT_WORMHOLE) {
3441  /* Vehicle is inside a wormhole, v->track contains no useful value then. */
3443  } else if (train_tbits != TRACK_BIT_DEPOT) {
3444  *trackbits |= train_tbits;
3445  }
3446  }
3447 
3448  return NULL;
3449 }
3450 
3458 static void DeleteLastWagon(Train *v)
3459 {
3460  Train *first = v->First();
3461 
3462  /* Go to the last wagon and delete the link pointing there
3463  * *u is then the one-before-last wagon, and *v the last
3464  * one which will physically be removed */
3465  Train *u = v;
3466  for (; v->Next() != NULL; v = v->Next()) u = v;
3467  u->SetNext(NULL);
3468 
3469  if (first != v) {
3470  /* Recalculate cached train properties */
3471  first->ConsistChanged(CCF_ARRANGE);
3472  /* Update the depot window if the first vehicle is in depot -
3473  * if v == first, then it is updated in PreDestructor() */
3474  if (first->track == TRACK_BIT_DEPOT) {
3476  }
3477  v->last_station_visited = first->last_station_visited; // for PreDestructor
3478  }
3479 
3480  /* 'v' shouldn't be accessed after it has been deleted */
3481  TrackBits trackbits = v->track;
3482  TileIndex tile = v->tile;
3483  Owner owner = v->owner;
3484 
3485  delete v;
3486  v = NULL; // make sure nobody will try to read 'v' anymore
3487 
3488  if (trackbits == TRACK_BIT_WORMHOLE) {
3489  /* Vehicle is inside a wormhole, v->track contains no useful value then. */
3491  }
3492 
3493  Track track = TrackBitsToTrack(trackbits);
3494  if (HasReservedTracks(tile, trackbits)) {
3495  UnreserveRailTrack(tile, track);
3496 
3497  /* If there are still crashed vehicles on the tile, give the track reservation to them */
3498  TrackBits remaining_trackbits = TRACK_BIT_NONE;
3499  FindVehicleOnPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum);
3500 
3501  /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */
3502  assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1);
3503  Track t;
3504  FOR_EACH_SET_TRACK(t, remaining_trackbits) TryReserveRailTrack(tile, t);
3505  }
3506 
3507  /* check if the wagon was on a road/rail-crossing */
3508  if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
3509 
3510  /* Update signals */
3511  if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) {
3513  } else {
3514  SetSignalsOnBothDir(tile, track, owner);
3515  }
3516 }
3517 
3523 {
3524  static const DirDiff delta[] = {
3526  };
3527 
3528  do {
3529  /* We don't need to twist around vehicles if they're not visible */
3530  if (!(v->vehstatus & VS_HIDDEN)) {
3531  v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
3532  /* Refrain from updating the z position of the vehicle when on
3533  * a bridge, because UpdateInclination() will put the vehicle under
3534  * the bridge in that case */
3535  if (v->track != TRACK_BIT_WORMHOLE) {
3536  v->UpdatePosition();
3537  v->UpdateInclination(false, true);
3538  } else {
3539  v->UpdateViewport(false, true);
3540  }
3541  }
3542  } while ((v = v->Next()) != NULL);
3543 }
3544 
3550 static bool HandleCrashedTrain(Train *v)
3551 {
3552  int state = ++v->crash_anim_pos;
3553 
3554  if (state == 4 && !(v->vehstatus & VS_HIDDEN)) {
3556  }
3557 
3558  uint32 r;
3559  if (state <= 200 && Chance16R(1, 7, r)) {
3560  int index = (r * 10 >> 16);
3561 
3562  Vehicle *u = v;
3563  do {
3564  if (--index < 0) {
3565  r = Random();
3566 
3568  GB(r, 8, 3) + 2,
3569  GB(r, 16, 3) + 2,
3570  GB(r, 0, 3) + 5,
3572  break;
3573  }
3574  } while ((u = u->Next()) != NULL);
3575  }
3576 
3577  if (state <= 240 && !(v->tick_counter & 3)) ChangeTrainDirRandomly(v);
3578 
3579  if (state >= 4440 && !(v->tick_counter & 0x1F)) {
3580  bool ret = v->Next() != NULL;
3581  DeleteLastWagon(v);
3582  return ret;
3583  }
3584 
3585  return true;
3586 }
3587 
3589 static const uint16 _breakdown_speeds[16] = {
3590  225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
3591 };
3592 
3593 
3602 static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse)
3603 {
3604  /* Calc position within the current tile */
3605  uint x = v->x_pos & 0xF;
3606  uint y = v->y_pos & 0xF;
3607 
3608  /* for diagonal directions, 'x' will be 0..15 -
3609  * for other directions, it will be 1, 3, 5, ..., 15 */
3610  switch (v->direction) {
3611  case DIR_N : x = ~x + ~y + 25; break;
3612  case DIR_NW: x = y; FALLTHROUGH;
3613  case DIR_NE: x = ~x + 16; break;
3614  case DIR_E : x = ~x + y + 9; break;
3615  case DIR_SE: x = y; break;
3616  case DIR_S : x = x + y - 7; break;
3617  case DIR_W : x = ~y + x + 9; break;
3618  default: break;
3619  }
3620 
3621  /* Do not reverse when approaching red signal. Make sure the vehicle's front
3622  * does not cross the tile boundary when we do reverse, but as the vehicle's
3623  * location is based on their center, use half a vehicle's length as offset.
3624  * Multiply the half-length by two for straight directions to compensate that
3625  * we only get odd x offsets there. */
3626  if (!signal && x + (v->gcache.cached_veh_length + 1) / 2 * (IsDiagonalDirection(v->direction) ? 1 : 2) >= TILE_SIZE) {
3627  /* we are too near the tile end, reverse now */
3628  v->cur_speed = 0;
3629  if (reverse) ReverseTrainDirection(v);
3630  return false;
3631  }
3632 
3633  /* slow down */
3635  uint16 break_speed = _breakdown_speeds[x & 0xF];
3636  if (break_speed < v->cur_speed) v->cur_speed = break_speed;
3637 
3638  return true;
3639 }
3640 
3641 
3647 static bool TrainCanLeaveTile(const Train *v)
3648 {
3649  /* Exit if inside a tunnel/bridge or a depot */
3650  if (v->track == TRACK_BIT_WORMHOLE || v->track == TRACK_BIT_DEPOT) return false;
3651 
3652  TileIndex tile = v->tile;
3653 
3654  /* entering a tunnel/bridge? */
3655  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
3657  if (DiagDirToDir(dir) == v->direction) return false;
3658  }
3659 
3660  /* entering a depot? */
3661  if (IsRailDepotTile(tile)) {
3663  if (DiagDirToDir(dir) == v->direction) return false;
3664  }
3665 
3666  return true;
3667 }
3668 
3669 
3678 {
3679  assert(v->IsFrontEngine());
3680  assert(!(v->vehstatus & VS_CRASHED));
3681 
3682  if (!TrainCanLeaveTile(v)) return INVALID_TILE;
3683 
3684  DiagDirection dir = TrainExitDir(v->direction, v->track);
3685  TileIndex tile = v->tile + TileOffsByDiagDir(dir);
3686 
3687  /* not a crossing || wrong axis || unusable rail (wrong type or owner) */
3688  if (!IsLevelCrossingTile(tile) || DiagDirToAxis(dir) == GetCrossingRoadAxis(tile) ||
3689  !CheckCompatibleRail(v, tile)) {
3690  return INVALID_TILE;
3691  }
3692 
3693  return tile;
3694 }
3695 
3696 
3704 static bool TrainCheckIfLineEnds(Train *v, bool reverse)
3705 {
3706  /* First, handle broken down train */
3707 
3708  int t = v->breakdown_ctr;
3709  if (t > 1) {
3711 
3712  uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
3713  if (break_speed < v->cur_speed) v->cur_speed = break_speed;
3714  } else {
3715  v->vehstatus &= ~VS_TRAIN_SLOWING;
3716  }
3717 
3718  if (!TrainCanLeaveTile(v)) return true;
3719 
3720  /* Determine the non-diagonal direction in which we will exit this tile */
3721  DiagDirection dir = TrainExitDir(v->direction, v->track);
3722  /* Calculate next tile */
3723  TileIndex tile = v->tile + TileOffsByDiagDir(dir);
3724 
3725  /* Determine the track status on the next tile */
3726  TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0, ReverseDiagDir(dir));
3727  TrackdirBits reachable_trackdirs = DiagdirReachesTrackdirs(dir);
3728 
3729  TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts) & reachable_trackdirs;
3730  TrackdirBits red_signals = TrackStatusToRedSignals(ts) & reachable_trackdirs;
3731 
3732  /* We are sure the train is not entering a depot, it is detected above */
3733 
3734  /* mask unreachable track bits if we are forbidden to do 90deg turns */
3735  TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
3737  bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
3738  }
3739 
3740  /* no suitable trackbits at all || unusable rail (wrong type or owner) */
3741  if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(v, tile)) {
3742  return TrainApproachingLineEnd(v, false, reverse);
3743  }
3744 
3745  /* approaching red signal */
3746  if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(v, true, reverse);
3747 
3748  /* approaching a rail/road crossing? then make it red */
3750 
3751  return true;
3752 }
3753 
3754 
3755 static bool TrainLocoHandler(Train *v, bool mode)
3756 {
3757  /* train has crashed? */
3758  if (v->vehstatus & VS_CRASHED) {
3759  return mode ? true : HandleCrashedTrain(v); // 'this' can be deleted here
3760  }
3761 
3762  if (v->force_proceed != TFP_NONE) {
3763  ClrBit(v->flags, VRF_TRAIN_STUCK);
3765  }
3766 
3767  /* train is broken down? */
3768  if (v->HandleBreakdown()) return true;
3769 
3770  if (HasBit(v->flags, VRF_REVERSING) && v->cur_speed == 0) {
3772  }
3773 
3774  /* exit if train is stopped */
3775  if ((v->vehstatus & VS_STOPPED) && v->cur_speed == 0) return true;
3776 
3777  bool valid_order = !v->current_order.IsType(OT_NOTHING) && v->current_order.GetType() != OT_CONDITIONAL;
3778  if (ProcessOrders(v) && CheckReverseTrain(v)) {
3779  v->wait_counter = 0;
3780  v->cur_speed = 0;
3781  v->subspeed = 0;
3782  ClrBit(v->flags, VRF_LEAVING_STATION);
3784  return true;
3785  } else if (HasBit(v->flags, VRF_LEAVING_STATION)) {
3786  /* Try to reserve a path when leaving the station as we
3787  * might not be marked as wanting a reservation, e.g.
3788  * when an overlength train gets turned around in a station. */
3789  DiagDirection dir = TrainExitDir(v->direction, v->track);
3791 
3793  TryPathReserve(v, true, true);
3794  }
3795  ClrBit(v->flags, VRF_LEAVING_STATION);
3796  }
3797 
3798  v->HandleLoading(mode);
3799 
3800  if (v->current_order.IsType(OT_LOADING)) return true;
3801 
3802  if (CheckTrainStayInDepot(v)) return true;
3803 
3804  if (!mode) v->ShowVisualEffect();
3805 
3806  /* We had no order but have an order now, do look ahead. */
3807  if (!valid_order && !v->current_order.IsType(OT_NOTHING)) {
3808  CheckNextTrainTile(v);
3809  }
3810 
3811  /* Handle stuck trains. */
3812  if (!mode && HasBit(v->flags, VRF_TRAIN_STUCK)) {
3813  ++v->wait_counter;
3814 
3815  /* Should we try reversing this tick if still stuck? */
3817 
3818  if (!turn_around && v->wait_counter % _settings_game.pf.path_backoff_interval != 0 && v->force_proceed == TFP_NONE) return true;
3819  if (!TryPathReserve(v)) {
3820  /* Still stuck. */
3821  if (turn_around) ReverseTrainDirection(v);
3822 
3824  /* Show message to player. */
3826  SetDParam(0, v->index);
3827  AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_STUCK, v->index);
3828  }
3829  v->wait_counter = 0;
3830  }
3831  /* Exit if force proceed not pressed, else reset stuck flag anyway. */
3832  if (v->force_proceed == TFP_NONE) return true;
3833  ClrBit(v->flags, VRF_TRAIN_STUCK);
3834  v->wait_counter = 0;
3836  }
3837  }
3838 
3839  if (v->current_order.IsType(OT_LEAVESTATION)) {
3840  v->current_order.Free();
3842  return true;
3843  }
3844 
3845  int j = v->UpdateSpeed();
3846 
3847  /* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */
3848  if (v->cur_speed == 0 && (v->vehstatus & VS_STOPPED)) {
3849  /* If we manually stopped, we're not force-proceeding anymore. */
3850  v->force_proceed = TFP_NONE;
3852  }
3853 
3854  int adv_spd = v->GetAdvanceDistance();
3855  if (j < adv_spd) {
3856  /* if the vehicle has speed 0, update the last_speed field. */
3857  if (v->cur_speed == 0) v->SetLastSpeed();
3858  } else {
3860  /* Loop until the train has finished moving. */
3861  for (;;) {
3862  j -= adv_spd;
3863  TrainController(v, NULL);
3864  /* Don't continue to move if the train crashed. */
3865  if (CheckTrainCollision(v)) break;
3866  /* Determine distance to next map position */
3867  adv_spd = v->GetAdvanceDistance();
3868 
3869  /* No more moving this tick */
3870  if (j < adv_spd || v->cur_speed == 0) break;
3871 
3872  OrderType order_type = v->current_order.GetType();
3873  /* Do not skip waypoints (incl. 'via' stations) when passing through at full speed. */
3874  if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
3876  IsTileType(v->tile, MP_STATION) &&
3878  ProcessOrders(v);
3879  }
3880  }
3881  v->SetLastSpeed();
3882  }
3883 
3884  for (Train *u = v; u != NULL; u = u->Next()) {
3885  if ((u->vehstatus & VS_HIDDEN) != 0) continue;
3886 
3887  u->UpdateViewport(false, false);
3888  }
3889 
3890  if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress
3891 
3892  return true;
3893 }
3894 
3900 {
3901  Money cost = 0;
3902  const Train *v = this;
3903 
3904  do {
3905  const Engine *e = v->GetEngine();
3906  if (e->u.rail.running_cost_class == INVALID_PRICE) continue;
3907 
3908  uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost);
3909  if (cost_factor == 0) continue;
3910 
3911  /* Halve running cost for multiheaded parts */
3912  if (v->IsMultiheaded()) cost_factor /= 2;
3913 
3914  cost += GetPrice(e->u.rail.running_cost_class, cost_factor, e->GetGRF());
3915  } while ((v = v->GetNextVehicle()) != NULL);
3916 
3917  return cost;
3918 }
3919 
3925 {
3926  this->tick_counter++;
3927 
3928  if (this->IsFrontEngine()) {
3929  if (!(this->vehstatus & VS_STOPPED) || this->cur_speed > 0) this->running_ticks++;
3930 
3931  this->current_order_time++;
3932 
3933  if (!TrainLocoHandler(this, false)) return false;
3934 
3935  return TrainLocoHandler(this, true);
3936  } else if (this->IsFreeWagon() && (this->vehstatus & VS_CRASHED)) {
3937  /* Delete flooded standalone wagon chain */
3938  if (++this->crash_anim_pos >= 4400) {
3939  delete this;
3940  return false;
3941  }
3942  }
3943 
3944  return true;
3945 }
3946 
3952 {
3953  if (Company::Get(v->owner)->settings.vehicle.servint_trains == 0 || !v->NeedsAutomaticServicing()) return;
3954  if (v->IsChainInDepot()) {
3956  return;
3957  }
3958 
3959  uint max_penalty;
3961  case VPF_NPF: max_penalty = _settings_game.pf.npf.maximum_go_to_depot_penalty; break;
3962  case VPF_YAPF: max_penalty = _settings_game.pf.yapf.maximum_go_to_depot_penalty; break;
3963  default: NOT_REACHED();
3964  }
3965 
3966  FindDepotData tfdd = FindClosestTrainDepot(v, max_penalty);
3967  /* Only go to the depot if it is not too far out of our way. */
3968  if (tfdd.best_length == UINT_MAX || tfdd.best_length > max_penalty) {
3969  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
3970  /* If we were already heading for a depot but it has
3971  * suddenly moved farther away, we continue our normal
3972  * schedule? */
3973  v->current_order.MakeDummy();
3975  }
3976  return;
3977  }
3978 
3979  DepotID depot = GetDepotIndex(tfdd.tile);
3980 
3981  if (v->current_order.IsType(OT_GOTO_DEPOT) &&
3982  v->current_order.GetDestination() != depot &&
3983  !Chance16(3, 16)) {
3984  return;
3985  }
3986 
3989  v->dest_tile = tfdd.tile;
3991 }
3992 
3995 {
3996  AgeVehicle(this);
3997 
3998  if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
3999 
4000  if (this->IsFrontEngine()) {
4001  CheckVehicleBreakdown(this);
4002 
4004 
4005  CheckOrders(this);
4006 
4007  /* update destination */
4008  if (this->current_order.IsType(OT_GOTO_STATION)) {
4009  TileIndex tile = Station::Get(this->current_order.GetDestination())->train_station.tile;
4010  if (tile != INVALID_TILE) this->dest_tile = tile;
4011  }
4012 
4013  if (this->running_ticks != 0) {
4014  /* running costs */
4016 
4017  this->profit_this_year -= cost.GetCost();
4018  this->running_ticks = 0;
4019 
4020  SubtractMoneyFromCompanyFract(this->owner, cost);
4021 
4024  }
4025  }
4026 }
4027 
4033 {
4034  if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
4035 
4036  if (this->track == TRACK_BIT_DEPOT) {
4037  /* We'll assume the train is facing outwards */
4038  return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot
4039  }
4040 
4041  if (this->track == TRACK_BIT_WORMHOLE) {
4042  /* train in tunnel or on bridge, so just use his direction and assume a diagonal track */
4044  }
4045 
4046  return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction);
4047 }
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:2696
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:1602
static Vehicle * TrainApproachingCrossingEnum(Vehicle *v, void *data)
Checks if a train is approaching a rail-road crossing.
Definition: train_cmd.cpp:1656
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:512
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:169
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:324
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
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:427
Vehicle is stopped by the player.
Definition: vehicle_base.h:33
First vehicle arrived for competitor.
Definition: news_type.h:38
bool cached_tilt
train can tilt; feature provides a bonus in curves
Definition: train.h:77
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:77
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:134
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:2350
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:170
bool _networking
are we in networking mode?
Definition: network.cpp:56
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:296
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1195
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:31
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
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:2481
Occupied by a train.
Definition: signal_func.h:53
bool UsesWagonOverride(const Vehicle *v)
Check if a wagon is currently using a wagon override.
bool Follow(TileIndex old_tile, Trackdir old_td)
main follower routine.
void UpdateDeltaXY(Direction direction)
Updates the x and y offsets and the size of the sprite used for this vehicle.
Definition: train_cmd.cpp:1445
Used for iterations.
Definition: track_type.h:22
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:1220
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3120
static DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
DirectionByte direction
facing
Definition: vehicle_base.h:271
void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Invalidate the inspect window for a given feature and index.
Bitmask for the first 6 bits.
Definition: track_type.h:57
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:72
Yet Another PathFinder.
Definition: vehicle_type.h:63
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
East.
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:1762
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:3113
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:2018
int TicksToLeaveDepot(const Train *v)
Compute number of ticks when next wagon will leave a depot.
Definition: rail_cmd.cpp:2889
ConsistChangeFlags
Flags for Train::ConsistChanged.
Definition: train.h:47
byte curve_speed
Multiplier for curve maximum speed advantage.
Definition: rail.h:195
Flag for an invalid DiagDirection.
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:3704
static bool IsBridgeTile(TileIndex t)
checks if there is a bridge on this tile
Definition: bridge_map.h:35
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:2055
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:1677
Various explosions.
static CommandCost CheckTrainAttachment(Train *t)
Check whether the train parts can be attached.
Definition: train_cmd.cpp:986
Use default vehicle palette.
Definition: vehicle_base.h:35
Angle of 90 degrees right.
static bool HasCrossingReservation(TileIndex t)
Get the reservation state of the rail crossing.
Definition: road_map.h:350
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:1143
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.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Sprites to use for trains.
Track
These are used to specify a single track.
Definition: track_type.h:21
uint16 cur_speed
current speed
Definition: vehicle_base.h:293
Temporary data storage for testing collisions.
Definition: train_cmd.cpp:3003
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:2923
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:82
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:2217
Rail vehicle can be flipped in the depot.
Definition: engine_type.h:157
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:739
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:517
Both directions faces to the same direction.
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:146
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:103
static bool IsOnewaySignal(TileIndex t, Track track)
One-way signals can&#39;t be passed the &#39;wrong&#39; way.
Definition: rail_map.h:320
NPFSettings npf
pathfinder settings for the new pathfinder
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:512
Stop at the middle of the platform.
Definition: order_type.h:91
static void NormaliseDualHeads(Train *t)
Normalise the dual heads in the train, i.e.
Definition: train_cmd.cpp:908
bool lost_vehicle_warn
if a vehicle can&#39;t find its destination, show a warning
Definition: settings_type.h:77
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:823
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:1426
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Get the sprite to display the train.
Definition: train_cmd.cpp:485
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:127
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:2010
static TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition: map_func.h:372
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:2821
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:474
const T * Begin() const
Get the pointer to the first item (const)
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2152
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
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:962
CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Reverse train.
Definition: train_cmd.cpp:1914
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:2631
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:124
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:302
Rail vehicle tilts in curves.
Definition: engine_type.h:153
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:500
Simple vector template class.
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition: order_cmd.cpp:1925
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
A game paused because a (critical) error.
Definition: openttd.h:62
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:180
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition: vehicle.cpp:775
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:894
Standard non-electric rails.
Definition: rail_type.h:31
T * GetFirstEnginePart()
Get the first part of an articulated engine.
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:543
uint32 cached_power
Total power of the consist (valid only for the first engine).
Used for iterations.
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:1082
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:1537
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:427
UnitID GetFreeUnitNumber(VehicleType type)
Get an unused unit number for a vehicle (if allowed).
Definition: vehicle.cpp:1714
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:94
static void SetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir, SignalState state)
Sets the state of the signal along the given trackdir.
Definition: rail_map.h:450
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:853
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
const T * End() const
Get the pointer behind the last valid item (const)
Money GetRunningCost() const
Get running cost for the train consist.
Definition: train_cmd.cpp:3899
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:252
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:743
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:362
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition: economy.cpp:958
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:64
Running costs trains.
Definition: economy_type.h:153
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:280
Direction
Defines the 8 directions on the map.
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:1102
Various explosions.
The vehicle will stop at any station it passes except the destination.
Definition: order_type.h:81
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:3014
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:350
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:116
bool SwitchToNextOrder(bool skip_first)
Set the current vehicle order to the next order in the order list.
Definition: train_cmd.cpp:2486
Stop at the near end of the platform.
Definition: order_type.h:90
Southeast.
T * Append(uint to_add=1)
Append an item and return it.
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
static void SetCrossingBarred(TileIndex t, bool barred)
Set the bar state of a level crossing.
Definition: road_map.h:398
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Functions related to (drawing on) viewports.
Normal rail tile with signals.
Definition: rail_map.h:26
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:2945
Northeast.
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:279
int8 y_bb_offs
y offset of vehicle bounding box
Definition: vehicle_base.h:285
Angle of 45 degrees right.
Right track.
Definition: track_type.h:48
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:92
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:3061
static void MakeTrainBackup(TrainList &list, Train *t)
Make a backup of a train into a train list.
Definition: train_cmd.cpp:844
static const AccelerationSlowdownParams _accel_slowdown[]
Speed update fractions for each acceleration type.
Definition: train_cmd.cpp:2882
Train()
We don&#39;t want GCC to zero our struct! It already is zeroed and has an index!
Definition: train.h:106
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:3238
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:379
bool reverse_at_signals
whether to reverse at signals at all
TrackBits
Bitfield corresponding to Track.
Definition: track_type.h:41
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:2259
static void MaybeBarCrossingWithSound(TileIndex tile)
Bars crossing and plays ding-ding sound if not barred already.
Definition: train_cmd.cpp:1721
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:330
static bool IsTileOwner(TileIndex tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:207
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
Definition: error_gui.cpp:378
Non-electrified rails.
Definition: rail_type.h:54
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:2877
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:572
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:384
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:626
static TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:343
Track NPFTrainChooseTrack(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 NPF.
Definition: npf.cpp:1260
uint16 reliability_spd_dec
Speed of reliability decay between services (per day).
Definition: engine_base.h:28
int traininfo_vehicle_pitch
Vertical offset for draing train images in depot GUI and vehicle details.
Definition: newgrf.h:135
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:3924
void SubtractMoneyFromCompanyFract(CompanyID company, CommandCost cst)
Subtract money from a company, including the money fraction.
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a give tiletype.
Definition: tile_map.h:143
bool IsWagon() const
Check if a vehicle is a wagon.
Normal operation.
Definition: train.h:40
static void DeleteLastWagon(Train *v)
Deletes/Clears the last wagon of a crashed train.
Definition: train_cmd.cpp:3458
Functions related to errors.
static Vehicle * TrainOnTileEnum(Vehicle *v, void *)
Check if the vehicle is a train.
Definition: train_cmd.cpp:1644
SmallVector< Train *, 16 > TrainList
Helper type for lists/vectors of trains.
Definition: train_cmd.cpp:837
Track along the y-axis (north-west to south-east)
Definition: track_type.h:24
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:436
byte cargo_subtype
Used for livery refits (NewGRF variations)
Definition: vehicle_base.h:306
uint Length() const
Get the number of items in the list.
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1320
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:1198
uint16 crash_anim_pos
Crash animation counter.
Definition: train.h:94
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:1565
West.
SoundSettings sound
sound effect settings
static bool IsRailStationTile(TileIndex t)
Is this tile a station tile and a rail station?
Definition: station_map.h:103
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
Definition: train_cmd.cpp:129
X-axis track.
Definition: track_type.h:43
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:184
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
void HideFillingPercent(TextEffectID *te_id)
Hide vehicle loading indicators.
Definition: misc_gui.cpp:629
We want to stop.
North.
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:1987
uint16 pow_wag_power
Extra power applied to consist if wagon should be powered.
Definition: engine_type.h:56
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:48
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition: vehicle.cpp:567
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:171
static DiagDirection GetRailDepotDirection(TileIndex t)
Returns the direction the depot is facing to.
Definition: rail_map.h:172
static DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:340
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:143
simple wagon, not motorized
Definition: engine_type.h:30
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
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:891
A number of safeguards to prevent using unsafe methods.
AccelStatus GetAccelerationStatus() const
Checks the current acceleration status of this vehicle.
Definition: train.h:265
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:215
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2160
void SetTrainGroupID(Train *v, GroupID grp)
Affect the groupID of a train to new_g.
Definition: group_cmd.cpp:644
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:2453
DirDiff
Enumeration for the difference between two directions.
byte z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:283
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:74
Vehicle starting, i.e. leaving, the station.
Definition: newgrf_sound.h:21
Used for iterations.
Valid changes for arranging the consist in a depot.
Definition: train.h:55
static Axis GetCrossingRailAxis(TileIndex t)
Get the rail axis of a level crossing.
Definition: road_map.h:307
static TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
Returns the red-signal-information of a TrackStatus.
Definition: track_func.h:364
static bool HasPbsSignalOnTrackdir(TileIndex tile, Trackdir td)
Is a pbs signal present along the trackdir?
Definition: rail_map.h:464
static void NormaliseSubtypes(Train *chain)
Normalise the sub types of the parts in this chain.
Definition: train_cmd.cpp:930
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:295
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:2660
byte capacity
Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
Definition: engine_type.h:54
Vehicle view; Window numbers:
Definition: window_type.h:334
byte large_turn
Speed change due to a large turn.
Definition: train_cmd.cpp:2876
uint traininfo_vehicle_width
Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details.
Definition: newgrf.h:136
static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_tailtype)
Try to reserve any path to a safe tile, ignoring the vehicle&#39;s destination.
Definition: train_cmd.cpp:2442
Functions related to order backups.
static DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:882
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:142
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:497
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
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:59
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:2335
byte FreightWagonMult(CargoID cargo)
Return the cargo weight multiplier to use for a rail vehicle.
Definition: train_cmd.cpp:87
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:486
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:3951
static Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:525
VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition: vehicle.cpp:1662
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
StationFacilityByte facilities
The facilities that this station has.
static void RemoveFromConsist(Train *part, bool chain=false)
Remove the given wagon from its consist.
Definition: train_cmd.cpp:877
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:183
void UpdateTrainGroupID(Train *v)
Recalculates the groupID of a train.
Definition: group_cmd.cpp:669
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:527
static uint TrainCrashed(Train *v)
Marks train as crashed and creates an AI event.
Definition: train_cmd.cpp:2984
DiagDirection
Enumeration for diagonal directions.
#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:572
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:1241
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:2874
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:2075
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:61
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:49
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:2039
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint32 user)
Sell a (single) train wagon/engine.
Definition: train_cmd.cpp:1370
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:2875
int GetDisplayImageWidth(Point *offset=NULL) const
Get the width of a train vehicle image in the GUI.
Definition: train_cmd.cpp:455
static void BarCrossing(TileIndex t)
Bar a level crossing.
Definition: road_map.h:417
OrderType
Order types.
Definition: order_type.h:37
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:43
static const uint16 _breakdown_speeds[16]
Maximum speeds for train that is broken down or approaching line end.
Definition: train_cmd.cpp:3589
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:509
bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: train.h:116
uint DetermineCapacity(const Vehicle *v, uint16 *mail_capacity=NULL) const
Determines capacity of a given vehicle from scratch.
Definition: engine.cpp:206
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:233
void OnNewDay()
Update day counters of the train vehicle.
Definition: train_cmd.cpp:3994
static bool HasSignals(TileIndex t)
Checks if a rail tile has signals.
Definition: rail_map.h:73
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
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:349
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:561
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:88
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:37
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:56
static bool CheckTrainStayInDepot(Train *v)
Will the train stay in the depot the next tick?
Definition: train_cmd.cpp:2137
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:1904
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:607
static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse)
Train is approaching line end, slow down and possibly reverse.
Definition: train_cmd.cpp:3602
static TrackBits GetTrackBits(TileIndex tile)
Gets the track bits of the given tile.
Definition: rail_map.h:137
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:1176
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1137
Wagon is powered.
Definition: train.h:29
static Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
Bitflag for a wormhole (used for tunnels)
Definition: track_type.h:58
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:342
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:2042
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:174
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:1764
Functions related to companies.
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:1608
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1547
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:29
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:89
Vehicle is currently going downhill. (Cached track information for acceleration)
Allow vehicles to change length.
Definition: train.h:48
Electric train engine is allowed to run on normal rail. */.
Definition: train.h:32
static DiagDirection TrainExitDir(Direction direction, TrackBits track)
Determine the side in which the train will leave the tile.
Definition: train_cmd.cpp:67
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.
Flag for an invalid track.
Definition: track_type.h:30
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:4032
static bool TrainCanLeaveTile(const Train *v)
Determines whether train would like to leave the tile.
Definition: train_cmd.cpp:3647
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:163
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:3134
Lower track.
Definition: track_type.h:46
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:106
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:1254
Upper track.
Definition: track_type.h:45
int cached_max_curve_speed
max consist speed limited by curves
Definition: train.h:82
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:22
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:118
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
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:1569
The vehicle entered a station.
Definition: tile_cmd.h:23
Bitflag for a depot.
Definition: track_type.h:59
uint GetAdvanceDistance()
Determines the vehicle "progress" needed for moving a step.
Definition: vehicle_base.h:415
Helper container to find a depot.
Station has seen a train.
Definition: station_type.h:68
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2005
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:582
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:297
byte z_down
Fraction to add when moving down.
Definition: train_cmd.cpp:2878
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:78
First vehicle arrived for company.
Definition: news_type.h:37
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:437
static bool HandleCrashedTrain(Train *v)
Handle a crashed train.
Definition: train_cmd.cpp:3550
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:3004
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:110
OwnerByte owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
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:29
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.
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
No rail types.
Definition: rail_type.h:53
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
void CopyVehicleConfigAndStatistics(const Vehicle *src)
Copy certain configurations and statistics of a vehicle after successful autoreplace/renew The functi...
Definition: vehicle_base.h:713
int GetCurveSpeedLimit() const
Computes train speed limit caused by curves.
Definition: train_cmd.cpp:323
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 limited by track type (valid only for the first engine).
Station with train station.
Definition: station_type.h:55
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:311
RailTypes powered_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype generates power ...
Definition: rail.h:177
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:1699
TrackdirBits
Enumeration of bitmasks for the TrackDirs.
Definition: track_type.h:106
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:1736
Coordinates of a point in 2D.
An accident or disaster has occurred.
Definition: news_type.h:39
static void AffectSpeedByZChange(Train *v, int old_z)
Modify the speed of the vehicle due to a change in altitude.
Definition: train_cmd.cpp:2894
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:763
Proceed till next signal, but ignore being stuck till then. This includes force leaving depots...
Definition: train.h:41
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.
Ignore next signal, after the signal ignore being stuck.
Definition: train.h:42
New vehicles.
Definition: economy_type.h:152
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:3522
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or NULL when it doesn&#39;t exists.
Definition: vehicle_base.h:859
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:688
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:3005
void MarkDirty()
Goods at the consist have changed, update the graphics, cargo, and acceleration.
Definition: train_cmd.cpp:2801
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:2838
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
Northwest.
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
South.
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:408
void RemoveVehicleFromGroup(const Vehicle *v)
Decrease the num_vehicle variable before delete an front engine from a group.
Definition: group_cmd.cpp:630
int GetCurrentMaxSpeed() const
Calculates the maximum speed of the vehicle under its current conditions.
Definition: train_cmd.cpp:392
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.
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:386
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:753
static void NormalizeTrainVehInDepot(const Train *u)
Move all free vehicles in the depot to the train.
Definition: train_cmd.cpp:683
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
No track build.
Definition: track_type.h:107
static bool IsPlainRail(TileIndex t)
Returns whether this is plain rails, with or without signals.
Definition: rail_map.h:50
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
Left track.
Definition: track_type.h:47
uint16 cargo_age_period
Number of ticks before carried cargo is aged.
Definition: engine_type.h:146
static Vehicle * CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data)
Collect trackbits of all crashed train vehicles on a tile.
Definition: train_cmd.cpp:3434
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:533
static bool HasDepotReservation(TileIndex t)
Get the reservation state of the depot.
Definition: rail_map.h:259
Owner
Enum for all companies/owners.
Definition: company_type.h:20
static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const Engine *e, Vehicle **ret)
Build a railroad wagon.
Definition: train_cmd.cpp:607
Flag for an invalid trackdir.
Definition: track_type.h:93
uint Crash(bool flooded)
Common code executed for crashed ground vehicles.
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:476
static void Backup(const Vehicle *v, uint32 user)
Create an order backup for the given vehicle.
Track along the x-axis (north-east to south-west)
Definition: track_type.h:23
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:548
union Vehicle::@46 orders
The orders currently assigned to the vehicle.
static SignalState GetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir)
Gets the state of the signal along the given trackdir.
Definition: rail_map.h:439
static TileIndex TrainApproachingCrossingTile(const Train *v)
Determines whether train is approaching a rail-road crossing (thus making it barred) ...
Definition: train_cmd.cpp:3677
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:221
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.