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