OpenTTD Source  20241108-master-g80f628063a
ship_cmd.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "ship.h"
12 #include "landscape.h"
13 #include "timetable.h"
14 #include "news_func.h"
15 #include "company_func.h"
16 #include "depot_base.h"
17 #include "station_base.h"
18 #include "newgrf_engine.h"
19 #include "pathfinder/yapf/yapf.h"
21 #include "newgrf_sound.h"
22 #include "spritecache.h"
23 #include "strings_func.h"
24 #include "window_func.h"
27 #include "vehicle_func.h"
28 #include "sound_func.h"
29 #include "ai/ai.hpp"
30 #include "game/game.hpp"
31 #include "engine_base.h"
32 #include "company_base.h"
33 #include "tunnelbridge_map.h"
34 #include "zoom_func.h"
35 #include "framerate_type.h"
36 #include "industry.h"
37 #include "industry_map.h"
38 #include "ship_cmd.h"
39 
40 #include "table/strings.h"
41 
42 #include <unordered_set>
43 
44 #include "safeguards.h"
45 
47 constexpr int MAX_SHIP_DEPOT_SEARCH_DISTANCE = 80;
48 
55 {
56  if (HasTileWaterClass(tile)) return GetWaterClass(tile);
57  if (IsTileType(tile, MP_TUNNELBRIDGE)) {
59  return WATER_CLASS_CANAL;
60  }
61  if (IsTileType(tile, MP_RAILWAY)) {
62  assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
63  return WATER_CLASS_SEA;
64  }
65  NOT_REACHED();
66 }
67 
68 static const uint16_t _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
69 
70 template <>
71 bool IsValidImageIndex<VEH_SHIP>(uint8_t image_index)
72 {
73  return image_index < lengthof(_ship_sprites);
74 }
75 
76 static inline TrackBits GetTileShipTrackStatus(TileIndex tile)
77 {
79 }
80 
81 static void GetShipIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
82 {
83  const Engine *e = Engine::Get(engine);
84  uint8_t spritenum = e->u.ship.image_index;
85 
86  if (is_custom_sprite(spritenum)) {
87  GetCustomVehicleIcon(engine, DIR_W, image_type, result);
88  if (result->IsValid()) return;
89 
90  spritenum = e->original_image_index;
91  }
92 
93  assert(IsValidImageIndex<VEH_SHIP>(spritenum));
94  result->Set(DIR_W + _ship_sprites[spritenum]);
95 }
96 
97 void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
98 {
99  VehicleSpriteSeq seq;
100  GetShipIcon(engine, image_type, &seq);
101 
102  Rect rect;
103  seq.GetBounds(&rect);
104  preferred_x = Clamp(preferred_x,
105  left - UnScaleGUI(rect.left),
106  right - UnScaleGUI(rect.right));
107 
108  seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
109 }
110 
120 void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
121 {
122  VehicleSpriteSeq seq;
123  GetShipIcon(engine, image_type, &seq);
124 
125  Rect rect;
126  seq.GetBounds(&rect);
127 
128  width = UnScaleGUI(rect.Width());
129  height = UnScaleGUI(rect.Height());
130  xoffs = UnScaleGUI(rect.left);
131  yoffs = UnScaleGUI(rect.top);
132 }
133 
134 void Ship::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
135 {
136  uint8_t spritenum = this->spritenum;
137 
138  if (image_type == EIT_ON_MAP) direction = this->rotation;
139 
140  if (is_custom_sprite(spritenum)) {
141  GetCustomVehicleSprite(this, direction, image_type, result);
142  if (result->IsValid()) return;
143 
145  }
146 
147  assert(IsValidImageIndex<VEH_SHIP>(spritenum));
148  result->Set(_ship_sprites[spritenum] + direction);
149 }
150 
151 static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
152 {
153  const int max_region_distance = (max_distance / WATER_REGION_EDGE_LENGTH) + 1;
154 
155  static std::unordered_set<int> visited_patch_hashes;
156  static std::deque<WaterRegionPatchDesc> patches_to_search;
157  visited_patch_hashes.clear();
158  patches_to_search.clear();
159 
160  /* Step 1: find a set of reachable Water Region Patches using BFS. */
161  const WaterRegionPatchDesc start_patch = GetWaterRegionPatchInfo(v->tile);
162  patches_to_search.push_back(start_patch);
163  visited_patch_hashes.insert(CalculateWaterRegionPatchHash(start_patch));
164 
165  while (!patches_to_search.empty()) {
166  /* Remove first patch from the queue and make it the current patch. */
167  const WaterRegionPatchDesc current_node = patches_to_search.front();
168  patches_to_search.pop_front();
169 
170  /* Add neighbors of the current patch to the search queue. */
171  TVisitWaterRegionPatchCallBack visitFunc = [&](const WaterRegionPatchDesc &water_region_patch) {
172  /* Note that we check the max distance per axis, not the total distance. */
173  if (std::abs(water_region_patch.x - start_patch.x) > max_region_distance ||
174  std::abs(water_region_patch.y - start_patch.y) > max_region_distance) return;
175 
176  const int hash = CalculateWaterRegionPatchHash(water_region_patch);
177  if (visited_patch_hashes.count(hash) == 0) {
178  visited_patch_hashes.insert(hash);
179  patches_to_search.push_back(water_region_patch);
180  }
181  };
182 
183  VisitWaterRegionPatchNeighbors(current_node, visitFunc);
184  }
185 
186  /* Step 2: Find the closest depot within the reachable Water Region Patches. */
187  const Depot *best_depot = nullptr;
188  uint best_dist_sq = std::numeric_limits<uint>::max();
189  for (const Depot *depot : Depot::Iterate()) {
190  const TileIndex tile = depot->xy;
191  if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
192  const uint dist_sq = DistanceSquare(tile, v->tile);
193  if (dist_sq < best_dist_sq && dist_sq <= max_distance * max_distance &&
194  visited_patch_hashes.count(CalculateWaterRegionPatchHash(GetWaterRegionPatchInfo(tile))) > 0) {
195  best_dist_sq = dist_sq;
196  best_depot = depot;
197  }
198  }
199  }
200 
201  return best_depot;
202 }
203 
204 static void CheckIfShipNeedsService(Vehicle *v)
205 {
206  if (Company::Get(v->owner)->settings.vehicle.servint_ships == 0 || !v->NeedsAutomaticServicing()) return;
207  if (v->IsChainInDepot()) {
209  return;
210  }
211 
213 
214  const Depot *depot = FindClosestShipDepot(v, max_distance);
215 
216  if (depot == nullptr) {
217  if (v->current_order.IsType(OT_GOTO_DEPOT)) {
220  }
221  return;
222  }
223 
225  v->SetDestTile(depot->xy);
227 }
228 
233 {
234  const ShipVehicleInfo *svi = ShipVehInfo(this->engine_type);
235 
236  /* Get speed fraction for the current water type. Aqueducts are always canals. */
237  bool is_ocean = GetEffectiveWaterClass(this->tile) == WATER_CLASS_SEA;
238  uint raw_speed = GetVehicleProperty(this, PROP_SHIP_SPEED, svi->max_speed);
239  this->vcache.cached_max_speed = svi->ApplyWaterClassSpeedFrac(raw_speed, is_ocean);
240 
241  /* Update cargo aging period. */
242  this->vcache.cached_cargo_age_period = GetVehicleProperty(this, PROP_SHIP_CARGO_AGE_PERIOD, EngInfo(this->engine_type)->cargo_age_period);
243 
244  this->UpdateVisualEffect();
245 }
246 
248 {
249  const Engine *e = this->GetEngine();
250  uint cost_factor = GetVehicleProperty(this, PROP_SHIP_RUNNING_COST_FACTOR, e->u.ship.running_cost);
251  return GetPrice(PR_RUNNING_SHIP, cost_factor, e->GetGRF());
252 }
253 
256 {
257  AgeVehicle(this);
258 }
259 
262 {
263  EconomyAgeVehicle(this);
264 
265  if ((++this->day_counter & 7) == 0) {
266  DecreaseVehicleValue(this);
267  }
268 
269  CheckVehicleBreakdown(this);
270  CheckIfShipNeedsService(this);
271 
272  CheckOrders(this);
273 
274  if (this->running_ticks == 0) return;
275 
277 
278  this->profit_this_year -= cost.GetCost();
279  this->running_ticks = 0;
280 
282 
284  /* we need this for the profit */
286 }
287 
289 {
290  if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
291 
292  if (this->IsInDepot()) {
293  /* We'll assume the ship is facing outwards */
294  return DiagDirToDiagTrackdir(GetShipDepotDirection(this->tile));
295  }
296 
297  if (this->state == TRACK_BIT_WORMHOLE) {
298  /* ship on aqueduct, so just use its direction and assume a diagonal track */
299  return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
300  }
301 
302  return TrackDirectionToTrackdir(FindFirstTrack(this->state), this->direction);
303 }
304 
306 {
307  this->colourmap = PAL_NONE;
308  this->UpdateViewport(true, false);
309  this->UpdateCache();
310 }
311 
312 void Ship::PlayLeaveStationSound(bool force) const
313 {
314  if (PlayVehicleSound(this, VSE_START, force)) return;
315  SndPlayVehicleFx(ShipVehInfo(this->engine_type)->sfx, this);
316 }
317 
318 TileIndex Ship::GetOrderStationLocation(StationID station)
319 {
320  if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
321 
322  const Station *st = Station::Get(station);
323  if (CanVehicleUseStation(this, st)) {
324  return st->xy;
325  } else {
326  this->IncrementRealOrderIndex();
327  return 0;
328  }
329 }
330 
332 {
333  static const int8_t _delta_xy_table[8][4] = {
334  /* y_extent, x_extent, y_offs, x_offs */
335  { 6, 6, -3, -3}, // N
336  { 6, 32, -3, -16}, // NE
337  { 6, 6, -3, -3}, // E
338  {32, 6, -16, -3}, // SE
339  { 6, 6, -3, -3}, // S
340  { 6, 32, -3, -16}, // SW
341  { 6, 6, -3, -3}, // W
342  {32, 6, -16, -3}, // NW
343  };
344 
345  const int8_t *bb = _delta_xy_table[this->rotation];
346  this->x_offs = bb[3];
347  this->y_offs = bb[2];
348  this->x_extent = bb[1];
349  this->y_extent = bb[0];
350  this->z_extent = 6;
351 
352  if (this->direction != this->rotation) {
353  /* If we are rotating, then it is possible the ship was moved to its next position. In that
354  * case, because we are still showing the old direction, the ship will appear to glitch sideways
355  * slightly. We can work around this by applying an additional offset to make the ship appear
356  * where it was before it moved. */
357  this->x_offs -= this->x_pos - this->rotation_x_pos;
358  this->y_offs -= this->y_pos - this->rotation_y_pos;
359  }
360 }
361 
366 {
367  return v->type == VEH_SHIP && v->cur_speed != 0 ? v : nullptr;
368 }
369 
370 static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr)
371 {
372  /* Ask pathfinder for best direction */
373  return YapfShipCheckReverse(v, trackdir);
374 }
375 
376 static bool CheckShipLeaveDepot(Ship *v)
377 {
378  if (!v->IsChainInDepot()) return false;
379 
380  /* Check if we should wait here for unbunching. */
381  if (v->IsWaitingForUnbunching()) return true;
382 
383  /* We are leaving a depot, but have to go to the exact same one; re-enter */
384  if (v->current_order.IsType(OT_GOTO_DEPOT) &&
387  return true;
388  }
389 
390  /* Don't leave depot if no destination set */
391  if (v->dest_tile == 0) return true;
392 
393  /* Don't leave depot if another vehicle is already entering/leaving */
394  /* This helps avoid CPU load if many ships are set to start at the same time */
395  if (HasVehicleOnPos(v->tile, nullptr, &EnsureNoMovingShipProc)) return true;
396 
397  TileIndex tile = v->tile;
398  Axis axis = GetShipDepotAxis(tile);
399 
400  DiagDirection north_dir = ReverseDiagDir(AxisToDiagDir(axis));
401  TileIndex north_neighbour = TileAdd(tile, TileOffsByDiagDir(north_dir));
402  DiagDirection south_dir = AxisToDiagDir(axis);
403  TileIndex south_neighbour = TileAdd(tile, 2 * TileOffsByDiagDir(south_dir));
404 
405  TrackBits north_tracks = DiagdirReachesTracks(north_dir) & GetTileShipTrackStatus(north_neighbour);
406  TrackBits south_tracks = DiagdirReachesTracks(south_dir) & GetTileShipTrackStatus(south_neighbour);
407  if (north_tracks && south_tracks) {
408  if (CheckReverseShip(v)) north_tracks = TRACK_BIT_NONE;
409  }
410 
411  if (north_tracks) {
412  /* Leave towards north */
413  v->rotation = v->direction = DiagDirToDir(north_dir);
414  } else if (south_tracks) {
415  /* Leave towards south */
416  v->rotation = v->direction = DiagDirToDir(south_dir);
417  } else {
418  /* Both ways blocked */
419  return false;
420  }
421 
422  v->state = AxisToTrackBits(axis);
423  v->vehstatus &= ~VS_HIDDEN;
424 
425  v->cur_speed = 0;
426  v->UpdateViewport(true, true);
428 
431  v->PlayLeaveStationSound();
434 
435  return false;
436 }
437 
443 static uint ShipAccelerate(Vehicle *v)
444 {
445  uint speed;
446  speed = std::min<uint>(v->cur_speed + v->acceleration, v->vcache.cached_max_speed);
447  speed = std::min<uint>(speed, v->current_order.GetMaxSpeed() * 2);
448 
449  /* updates statusbar only if speed have changed to save CPU time */
450  if (speed != v->cur_speed) {
451  v->cur_speed = speed;
453  }
454 
455  const uint advance_speed = v->GetAdvanceSpeed(speed);
456  const uint number_of_steps = (advance_speed + v->progress) / v->GetAdvanceDistance();
457  const uint remainder = (advance_speed + v->progress) % v->GetAdvanceDistance();
458  assert(remainder <= std::numeric_limits<uint8_t>::max());
459  v->progress = static_cast<uint8_t>(remainder);
460  return number_of_steps;
461 }
462 
468 static void ShipArrivesAt(const Vehicle *v, Station *st)
469 {
470  /* Check if station was ever visited before */
471  if (!(st->had_vehicle_of_type & HVOT_SHIP)) {
472  st->had_vehicle_of_type |= HVOT_SHIP;
473 
474  SetDParam(0, st->index);
476  STR_NEWS_FIRST_SHIP_ARRIVAL,
478  v->index,
479  st->index
480  );
481  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
482  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
483  }
484 }
485 
486 
495 static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
496 {
497  bool path_found = true;
498  Track track;
499 
500  if (v->dest_tile == 0) {
501  /* No destination, don't invoke pathfinder. */
502  track = TrackBitsToTrack(v->state);
503  if (!IsDiagonalTrack(track)) track = TrackToOppositeTrack(track);
504  if (!HasBit(tracks, track)) track = FindFirstTrack(tracks);
505  path_found = false;
506  } else {
507  /* Attempt to follow cached path. */
508  if (!v->path.empty()) {
509  track = TrackdirToTrack(v->path.front());
510 
511  if (HasBit(tracks, track)) {
512  v->path.pop_front();
513  /* HandlePathfindResult() is not called here because this is not a new pathfinder result. */
514  return track;
515  }
516 
517  /* Cached path is invalid so continue with pathfinder. */
518  v->path.clear();
519  }
520 
521  track = YapfShipChooseTrack(v, tile, path_found, v->path);
522  }
523 
524  v->HandlePathfindingResult(path_found);
525  return track;
526 }
527 
535 {
536  TrackBits tracks = GetTileShipTrackStatus(tile) & DiagdirReachesTracks(dir);
537 
538  return tracks;
539 }
540 
543  uint8_t x_subcoord;
544  uint8_t y_subcoord;
546 };
553  // DIAGDIR_NE
554  {
555  {15, 8, DIR_NE}, // TRACK_X
556  { 0, 0, INVALID_DIR}, // TRACK_Y
557  { 0, 0, INVALID_DIR}, // TRACK_UPPER
558  {15, 8, DIR_E}, // TRACK_LOWER
559  {15, 7, DIR_N}, // TRACK_LEFT
560  { 0, 0, INVALID_DIR}, // TRACK_RIGHT
561  },
562  // DIAGDIR_SE
563  {
564  { 0, 0, INVALID_DIR}, // TRACK_X
565  { 8, 0, DIR_SE}, // TRACK_Y
566  { 7, 0, DIR_E}, // TRACK_UPPER
567  { 0, 0, INVALID_DIR}, // TRACK_LOWER
568  { 8, 0, DIR_S}, // TRACK_LEFT
569  { 0, 0, INVALID_DIR}, // TRACK_RIGHT
570  },
571  // DIAGDIR_SW
572  {
573  { 0, 8, DIR_SW}, // TRACK_X
574  { 0, 0, INVALID_DIR}, // TRACK_Y
575  { 0, 7, DIR_W}, // TRACK_UPPER
576  { 0, 0, INVALID_DIR}, // TRACK_LOWER
577  { 0, 0, INVALID_DIR}, // TRACK_LEFT
578  { 0, 8, DIR_S}, // TRACK_RIGHT
579  },
580  // DIAGDIR_NW
581  {
582  { 0, 0, INVALID_DIR}, // TRACK_X
583  { 8, 15, DIR_NW}, // TRACK_Y
584  { 0, 0, INVALID_DIR}, // TRACK_UPPER
585  { 8, 15, DIR_W}, // TRACK_LOWER
586  { 0, 0, INVALID_DIR}, // TRACK_LEFT
587  { 7, 15, DIR_N}, // TRACK_RIGHT
588  }
589 };
590 
596 static int ShipTestUpDownOnLock(const Ship *v)
597 {
598  /* Suitable tile? */
599  if (!IsTileType(v->tile, MP_WATER) || !IsLock(v->tile) || GetLockPart(v->tile) != LOCK_PART_MIDDLE) return 0;
600 
601  /* Must be at the centre of the lock */
602  if ((v->x_pos & 0xF) != 8 || (v->y_pos & 0xF) != 8) return 0;
603 
605  assert(IsValidDiagDirection(diagdir));
606 
607  if (DirToDiagDir(v->direction) == diagdir) {
608  /* Move up */
609  return (v->z_pos < GetTileMaxZ(v->tile) * (int)TILE_HEIGHT) ? 1 : 0;
610  } else {
611  /* Move down */
612  return (v->z_pos > GetTileZ(v->tile) * (int)TILE_HEIGHT) ? -1 : 0;
613  }
614 }
615 
621 static bool ShipMoveUpDownOnLock(Ship *v)
622 {
623  /* Moving up/down through lock */
624  int dz = ShipTestUpDownOnLock(v);
625  if (dz == 0) return false;
626 
627  if (v->cur_speed != 0) {
628  v->cur_speed = 0;
630  }
631 
632  if ((v->tick_counter & 7) == 0) {
633  v->z_pos += dz;
634  v->UpdatePosition();
635  v->UpdateViewport(true, true);
636  }
637 
638  return true;
639 }
640 
647 bool IsShipDestinationTile(TileIndex tile, StationID station)
648 {
649  assert(IsDockingTile(tile));
650  /* Check each tile adjacent to docking tile. */
651  for (DiagDirection d = DIAGDIR_BEGIN; d != DIAGDIR_END; d++) {
652  TileIndex t = tile + TileOffsByDiagDir(d);
653  if (!IsValidTile(t)) continue;
654  if (IsDockTile(t) && GetStationIndex(t) == station && IsDockWaterPart(t)) return true;
655  if (IsTileType(t, MP_INDUSTRY)) {
656  const Industry *i = Industry::GetByTile(t);
657  if (i->neutral_station != nullptr && i->neutral_station->index == station) return true;
658  }
659  if (IsTileType(t, MP_STATION) && IsOilRig(t) && GetStationIndex(t) == station) return true;
660  }
661  return false;
662 }
663 
664 static void ReverseShipIntoTrackdir(Ship *v, Trackdir trackdir)
665 {
666  static constexpr Direction _trackdir_to_direction[] = {
669  };
670 
671  v->direction = _trackdir_to_direction[trackdir];
672  assert(v->direction != INVALID_DIR);
674 
675  /* Remember our current location to avoid movement glitch */
676  v->rotation_x_pos = v->x_pos;
677  v->rotation_y_pos = v->y_pos;
678  v->cur_speed = 0;
679  v->path.clear();
680 
681  v->UpdatePosition();
682  v->UpdateViewport(true, true);
683 }
684 
685 static void ReverseShip(Ship *v)
686 {
687  v->direction = ReverseDir(v->direction);
688 
689  /* Remember our current location to avoid movement glitch */
690  v->rotation_x_pos = v->x_pos;
691  v->rotation_y_pos = v->y_pos;
692  v->cur_speed = 0;
693  v->path.clear();
694 
695  v->UpdatePosition();
696  v->UpdateViewport(true, true);
697 }
698 
699 static void ShipController(Ship *v)
700 {
701  v->tick_counter++;
702  v->current_order_time++;
703 
704  if (v->HandleBreakdown()) return;
705 
706  if (v->vehstatus & VS_STOPPED) return;
707 
708  if (ProcessOrders(v) && CheckReverseShip(v)) return ReverseShip(v);
709 
710  v->HandleLoading();
711 
712  if (v->current_order.IsType(OT_LOADING)) return;
713 
714  if (CheckShipLeaveDepot(v)) return;
715 
716  v->ShowVisualEffect();
717 
718  /* Rotating on spot */
719  if (v->direction != v->rotation) {
720  if ((v->tick_counter & 7) == 0) {
721  DirDiff diff = DirDifference(v->direction, v->rotation);
723  /* Invalidate the sprite cache direction to force recalculation of viewport */
725  v->UpdateViewport(true, true);
726  }
727  return;
728  }
729 
730  if (ShipMoveUpDownOnLock(v)) return;
731 
732  const uint number_of_steps = ShipAccelerate(v);
733  for (uint i = 0; i < number_of_steps; ++i) {
734  if (ShipMoveUpDownOnLock(v)) return;
735 
737  if (v->state != TRACK_BIT_WORMHOLE) {
738  /* Not on a bridge */
739  if (gp.old_tile == gp.new_tile) {
740  /* Staying in tile */
741  if (v->IsInDepot()) {
742  gp.x = v->x_pos;
743  gp.y = v->y_pos;
744  } else {
745  /* Not inside depot */
746  const VehicleEnterTileStatus r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
747  if (HasBit(r, VETS_CANNOT_ENTER)) return ReverseShip(v);
748 
749  /* A leave station order only needs one tick to get processed, so we can
750  * always skip ahead. */
751  if (v->current_order.IsType(OT_LEAVESTATION)) {
752  v->current_order.Free();
754  /* Test if continuing forward would lead to a dead-end, moving into the dock. */
755  const DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
756  const TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
757  if (TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) return ReverseShip(v);
758  } else if (v->dest_tile != 0) {
759  /* We have a target, let's see if we reached it... */
760  if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
761  DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
762  /* We got within 3 tiles of our target buoy, so let's skip to our
763  * next order */
764  UpdateVehicleTimetable(v, true);
767  } else if (v->current_order.IsType(OT_GOTO_DEPOT) &&
768  v->dest_tile == gp.new_tile) {
769  /* Depot orders really need to reach the tile */
770  if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
772  return;
773  }
774  } else if (v->current_order.IsType(OT_GOTO_STATION) && IsDockingTile(gp.new_tile)) {
775  /* Process station in the orderlist. */
778  v->last_station_visited = st->index;
779  if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
780  ShipArrivesAt(v, st);
781  v->BeginLoading();
782  } else { // leave stations without docks right away
785  }
786  }
787  }
788  }
789  }
790  } else {
791  /* New tile */
792  if (!IsValidTile(gp.new_tile)) return ReverseShip(v);
793 
794  const DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
795  assert(diagdir != INVALID_DIAGDIR);
796  const TrackBits tracks = GetAvailShipTracks(gp.new_tile, diagdir);
797  if (tracks == TRACK_BIT_NONE) {
798  Trackdir trackdir = INVALID_TRACKDIR;
799  CheckReverseShip(v, &trackdir);
800  if (trackdir == INVALID_TRACKDIR) return ReverseShip(v);
801  return ReverseShipIntoTrackdir(v, trackdir);
802  }
803 
804  /* Choose a direction, and continue if we find one */
805  const Track track = ChooseShipTrack(v, gp.new_tile, tracks);
806  if (track == INVALID_TRACK) return ReverseShip(v);
807 
808  const ShipSubcoordData &b = _ship_subcoord[diagdir][track];
809 
810  gp.x = (gp.x & ~0xF) | b.x_subcoord;
811  gp.y = (gp.y & ~0xF) | b.y_subcoord;
812 
813  /* Call the landscape function and tell it that the vehicle entered the tile */
814  const VehicleEnterTileStatus r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
815  if (HasBit(r, VETS_CANNOT_ENTER)) return ReverseShip(v);
816 
817  if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
818  v->tile = gp.new_tile;
819  v->state = TrackToTrackBits(track);
820 
821  /* Update ship cache when the water class changes. Aqueducts are always canals. */
823  }
824 
825  const Direction new_direction = b.dir;
826  const DirDiff diff = DirDifference(new_direction, v->direction);
827  switch (diff) {
828  case DIRDIFF_SAME:
829  case DIRDIFF_45RIGHT:
830  case DIRDIFF_45LEFT:
831  /* Continue at speed */
832  v->rotation = v->direction = new_direction;
833  break;
834 
835  default:
836  /* Stop for rotation */
837  v->cur_speed = 0;
838  v->direction = new_direction;
839  /* Remember our current location to avoid movement glitch */
840  v->rotation_x_pos = v->x_pos;
841  v->rotation_y_pos = v->y_pos;
842  break;
843  }
844  }
845  } else {
846  /* On a bridge */
848  v->x_pos = gp.x;
849  v->y_pos = gp.y;
850  v->UpdatePosition();
851  if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
852  continue;
853  }
854 
855  /* Ship is back on the bridge head, we need to consume its path
856  * cache entry here as we didn't have to choose a ship track. */
857  if (!v->path.empty()) v->path.pop_front();
858  }
859 
860  /* update image of ship, as well as delta XY */
861  v->x_pos = gp.x;
862  v->y_pos = gp.y;
863 
864  v->UpdatePosition();
865  v->UpdateViewport(true, true);
866  }
867 }
868 
870 {
872 
873  if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
874 
875  ShipController(this);
876 
877  return true;
878 }
879 
880 void Ship::SetDestTile(TileIndex tile)
881 {
882  if (tile == this->dest_tile) return;
883  this->path.clear();
884  this->dest_tile = tile;
885 }
886 
896 {
897  tile = GetShipDepotNorthTile(tile);
898  if (flags & DC_EXEC) {
899  int x;
900  int y;
901 
902  const ShipVehicleInfo *svi = &e->u.ship;
903 
904  Ship *v = new Ship();
905  *ret = v;
906 
907  v->owner = _current_company;
908  v->tile = tile;
909  x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
910  y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
911  v->x_pos = x;
912  v->y_pos = y;
913  v->z_pos = GetSlopePixelZ(x, y);
914 
915  v->UpdateDeltaXY();
917 
918  v->spritenum = svi->image_index;
920  assert(IsValidCargoID(v->cargo_type));
921  v->cargo_cap = svi->capacity;
922  v->refit_cap = 0;
923 
924  v->last_station_visited = INVALID_STATION;
925  v->last_loading_station = INVALID_STATION;
926  v->engine_type = e->index;
927 
928  v->reliability = e->reliability;
930  v->max_age = e->GetLifeLengthInDays();
931 
932  v->state = TRACK_BIT_DEPOT;
933 
934  v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships);
938  v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
939  v->random_bits = Random();
940 
941  v->acceleration = svi->acceleration;
942  v->UpdateCache();
943 
945  v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
946 
948 
949  v->cargo_cap = e->DetermineCapacity(v);
950 
952 
953  v->UpdatePosition();
954  }
955 
956  return CommandCost();
957 }
958 
960 {
961  const Depot *depot = FindClosestShipDepot(this, MAX_SHIP_DEPOT_SEARCH_DISTANCE);
962  if (depot == nullptr) return ClosestDepot();
963 
964  return ClosestDepot(depot->xy, depot->index);
965 }
Base functions for all AIs.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:243
Common return value for all commands.
Definition: command_type.h:23
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:146
RAII class for measuring multi-step elements of performance.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static constexpr int DAYS_IN_YEAR
days per year
static Date date
Current date in days (day counter).
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_EXEC
execute the given command
Definition: command_type.h:376
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
Subtract money from a company, including the money fraction.
Functions related to companies.
Base for all depots (except hangars)
DepotID GetDepotIndex(Tile t)
Get the index of which depot is attached to the tile.
Definition: depot_map.h:52
DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Direction DiagDirToDir(DiagDirection dir)
Convert a DiagDirection to a Direction.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Direction ReverseDir(Direction d)
Return the reverse of a direction.
bool IsValidDiagDirection(DiagDirection d)
Checks if an integer value is a valid DiagDirection.
Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
Direction
Defines the 8 directions on the map.
@ DIR_SW
Southwest.
@ DIR_NW
Northwest.
@ INVALID_DIR
Flag for an invalid direction.
@ DIR_N
North.
@ DIR_SE
Southeast.
@ DIR_S
South.
@ DIR_NE
Northeast.
@ DIR_W
West.
@ DIR_E
East.
Axis
Allow incrementing of DiagDirDiff variables.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
DirDiff
Allow incrementing of Direction variables.
@ DIRDIFF_45LEFT
Angle of 45 degrees left.
@ DIRDIFF_REVERSE
One direction is the opposite of the other one.
@ DIRDIFF_45RIGHT
Angle of 45 degrees right.
@ DIRDIFF_SAME
Both directions faces to the same direction.
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition: economy.cpp:969
@ EXPENSES_SHIP_RUN
Running costs ships.
Definition: economy_type.h:178
Base class for engines.
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
@ ENGINE_EXCLUSIVE_PREVIEW
This vehicle is in the exclusive preview stage, either being used or being offered to a company.
Definition: engine_type.h:184
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
Types for recording game performance data.
@ PFE_GL_SHIPS
Time spent processing ships.
Base functions for all Games.
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:19
Base of all industries.
Accessors for industries.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition: landscape.cpp:303
Functions related to OTTD's landscape.
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition: map.cpp:163
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition: map.cpp:146
DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
Determines the DiagDirection to get from one tile to another.
Definition: map_func.h:620
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition: map_func.h:608
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition: map_func.h:454
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
Functions for NewGRF engines.
@ PROP_SHIP_SPEED
Max. speed: 1 unit = 1/3.2 mph = 0.5 km-ish/h.
@ PROP_SHIP_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_SHIP_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event, bool force)
Checks whether a NewGRF wants to play a different vehicle sound effect.
Functions related to NewGRF provided sounds.
@ VSE_START
Vehicle starting, i.e. leaving, the station.
Definition: newgrf_sound.h:19
Functions related to news.
void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station=INVALID_STATION)
Adds a newsitem referencing a vehicle.
Definition: news_func.h:30
@ NT_ARRIVAL_COMPANY
First vehicle arrived for company.
Definition: news_type.h:24
@ NT_ARRIVAL_OTHER
First vehicle arrived for competitor.
Definition: news_type.h:25
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2127
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition: order_cmd.cpp:1711
@ ODTFB_SERVICE
This depot order is because of the servicing limit.
Definition: order_type.h:95
static const int YAPF_TILE_LENGTH
Length (penalty) of one tile with YAPF.
@ RAIL_GROUND_WATER
Grass with a fence and shore or water on the free halftile.
Definition: rail_map.h:499
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
Base for ships.
constexpr int MAX_SHIP_DEPOT_SEARCH_DISTANCE
Max distance in tiles (as the crow flies) to search for depots when user clicks "go to depot".
Definition: ship_cmd.cpp:47
static const ShipSubcoordData _ship_subcoord[DIAGDIR_END][TRACK_END]
Ship sub-coordinate data for moving into a new tile via a Diagdir onto a Track.
Definition: ship_cmd.cpp:552
static Vehicle * EnsureNoMovingShipProc(Vehicle *v, void *)
Test-procedure for HasVehicleOnPos to check for any ships which are moving.
Definition: ship_cmd.cpp:365
static uint ShipAccelerate(Vehicle *v)
Accelerates the ship towards its target speed.
Definition: ship_cmd.cpp:443
static TrackBits GetAvailShipTracks(TileIndex tile, DiagDirection dir)
Get the available water tracks on a tile for a ship entering a tile.
Definition: ship_cmd.cpp:534
static bool ShipMoveUpDownOnLock(Ship *v)
Test and move a ship up or down in a lock.
Definition: ship_cmd.cpp:621
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Definition: ship_cmd.cpp:647
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a ship sprite heading west (used for lists).
Definition: ship_cmd.cpp:120
static void ShipArrivesAt(const Vehicle *v, Station *st)
Ship arrives at a dock.
Definition: ship_cmd.cpp:468
WaterClass GetEffectiveWaterClass(TileIndex tile)
Determine the effective WaterClass for a ship travelling on a tile.
Definition: ship_cmd.cpp:54
static int ShipTestUpDownOnLock(const Ship *v)
Test if a ship is in the centre of a lock and should move up or down.
Definition: ship_cmd.cpp:596
CommandCost CmdBuildShip(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a ship.
Definition: ship_cmd.cpp:895
static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
Runs the pathfinder to choose a track to continue along.
Definition: ship_cmd.cpp:495
Command definitions related to ships.
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition: slope_func.h:239
Functions related to sound.
Functions to cache sprites in memory.
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1605
Base classes/functions for stations.
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
bool IsDockTile(Tile t)
Is tile t a dock tile?
Definition: station_map.h:389
bool IsOilRig(Tile t)
Is tile t part of an oilrig?
Definition: station_map.h:368
bool IsDockWaterPart(Tile t)
Check whether a dock tile is the tile on water.
Definition: station_map.h:605
@ HVOT_SHIP
Station has seen a ship.
Definition: station_type.h:70
@ FACIL_DOCK
Station with a dock.
Definition: station_type.h:58
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
Functions related to OTTD's strings.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:21
uint16_t vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:34
StationFacility facilities
The facilities that this station has.
TileIndex xy
Base tile of the station.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Structure to return information about the closest depot location, and whether it could be found.
Definition: vehicle_base.h:230
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:96
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition: engine_base.h:42
uint DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity=nullptr) const
Determines capacity of a given vehicle from scratch.
Definition: engine.cpp:201
uint8_t original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition: engine_base.h:55
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:167
TimerGameCalendar::Date GetLifeLengthInDays() const
Returns the vehicle's (not model's!) life length in days.
Definition: engine.cpp:443
uint16_t reliability
Current reliability of the engine.
Definition: engine_base.h:41
uint8_t flags
Flags of the engine.
Definition: engine_base.h:49
PathfinderSettings pf
settings for all pathfinders
Position information of a vehicle after it moved.
Definition: vehicle_func.h:77
TileIndex new_tile
Tile of the vehicle after moving.
Definition: vehicle_func.h:80
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:78
TileIndex old_tile
Current tile of the vehicle.
Definition: vehicle_func.h:79
Defines the internal data of a functional industry.
Definition: industry.h:66
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition: industry.h:238
Station * neutral_station
Associated neutral station.
Definition: industry.h:96
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:200
Direction last_direction
Last direction we obtained sprites for.
Definition: vehicle_base.h:196
uint16_t GetMaxSpeed() const
Get the maxmimum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition: order_base.h:201
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:103
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:70
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:133
void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoID cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition: order_cmd.cpp:90
void MakeLeaveStation()
Makes this order a Leave Station order.
Definition: order_cmd.cpp:124
void Free()
'Free' the order
Definition: order_cmd.cpp:63
bool Contains(TileIndex tile) const
Does this tile area contain a tile?
Definition: tilearea.cpp:104
YAPFSettings yapf
pathfinder settings for the yet another pathfinder
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
int Height() const
Get height of Rect.
Structure for ship sub-coordinate data for moving into a new tile via a Diagdir onto a Track.
Definition: ship_cmd.cpp:542
uint8_t y_subcoord
New Y sub-coordinate on the new tile.
Definition: ship_cmd.cpp:544
Direction dir
New Direction to move in on the new track.
Definition: ship_cmd.cpp:545
uint8_t x_subcoord
New X sub-coordinate on the new tile.
Definition: ship_cmd.cpp:543
Information about a ship vehicle.
Definition: engine_type.h:67
uint ApplyWaterClassSpeedFrac(uint raw_speed, bool is_ocean) const
Apply ocean/canal speed fraction to a velocity.
Definition: engine_type.h:81
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
Definition: engine_type.h:71
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
Definition: engine_type.h:70
All ships have this type.
Definition: ship.h:24
bool Tick() override
Calls the tick handler of the vehicle.
Definition: ship_cmd.cpp:869
Money GetRunningCost() const override
Gets the running cost of a vehicle.
Definition: ship_cmd.cpp:247
TrackBits state
The "track" the ship is following.
Definition: ship.h:26
int16_t rotation_x_pos
NOSAVE: X Position before rotation.
Definition: ship.h:28
Direction rotation
Visible direction.
Definition: ship.h:27
void UpdateDeltaXY() override
Updates the x and y offsets and the size of the sprite used for this vehicle.
Definition: ship_cmd.cpp:331
void OnNewCalendarDay() override
Calendar day handler.
Definition: ship_cmd.cpp:255
int16_t rotation_y_pos
NOSAVE: Y Position before rotation.
Definition: ship.h:29
ShipPathCache path
Cached path.
Definition: ship.h:25
ClosestDepot FindClosestDepot() override
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
Definition: ship_cmd.cpp:959
void MarkDirty() override
Marks the vehicles to be redrawn and updates cached variables.
Definition: ship_cmd.cpp:305
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
Definition: ship_cmd.cpp:288
bool IsInDepot() const override
Check whether the vehicle is in the depot.
Definition: ship.h:46
void OnNewEconomyDay() override
Economy day handler.
Definition: ship_cmd.cpp:261
void UpdateCache()
Update the caches of this ship.
Definition: ship_cmd.cpp:232
static Station * Get(size_t index)
Gets station with given index.
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
Station data structure.
Definition: station_base.h:439
TileArea docking_station
Tile area the docking tiles cover.
Definition: station_base.h:455
uint16_t cached_cargo_age_period
Number of ticks before carried cargo is aged.
Definition: vehicle_base.h:127
uint16_t cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition: vehicle_base.h:126
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:135
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:103
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Definition: vehicle_base.h:168
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:131
Vehicle data structure.
Definition: vehicle_base.h:244
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
static uint GetAdvanceSpeed(uint speed)
Determines the effective vehicle movement speed.
Definition: vehicle_base.h:445
int32_t z_pos
z coordinate.
Definition: vehicle_base.h:306
Direction direction
facing
Definition: vehicle_base.h:307
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:747
void IncrementRealOrderIndex()
Advanced cur_real_order_index to the next real order, keeps care of the wrap-around and invalidates t...
Definition: vehicle_base.h:886
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition: vehicle_base.h:554
uint8_t x_extent
x-extent of vehicle bounding box
Definition: vehicle_base.h:316
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
Definition: vehicle_base.h:295
uint16_t cargo_cap
total capacity
Definition: vehicle_base.h:344
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
Definition: vehicle_base.h:338
uint16_t random_bits
Bits used for randomized variational spritegroups.
Definition: vehicle_base.h:335
uint8_t day_counter
Increased by one for each day.
Definition: vehicle_base.h:349
void HandleLoading(bool mode=false)
Handle the loading of the vehicle; when not it skips through dummy orders and does nothing in all oth...
Definition: vehicle.cpp:2430
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition: vehicle_base.h:273
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition: vehicle_base.h:288
uint GetAdvanceDistance()
Determines the vehicle "progress" needed for moving a step.
Definition: vehicle_base.h:457
uint8_t z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:318
TimerGameCalendar::Date date_of_last_service_newgrf
Last calendar date the vehicle had a service at a depot, unchanged by the date cheat to protect again...
Definition: vehicle_base.h:296
void UpdateVisualEffect(bool allow_power_change=true)
Update the cached visual effect.
Definition: vehicle.cpp:2664
void LeaveUnbunchingDepot()
Leave an unbunching depot and calculate the next departure time for shared order vehicles.
Definition: vehicle.cpp:2514
int8_t y_offs
y offset for vehicle sprite
Definition: vehicle_base.h:322
uint8_t acceleration
used by train & aircraft
Definition: vehicle_base.h:330
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:356
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:342
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition: vehicle.cpp:791
int8_t x_offs
x offset for vehicle sprite
Definition: vehicle_base.h:321
int32_t y_pos
y coordinate.
Definition: vehicle_base.h:305
int32_t x_pos
x coordinate.
Definition: vehicle_base.h:304
uint8_t y_extent
y-extent of vehicle bounding box
Definition: vehicle_base.h:317
uint16_t refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:345
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:364
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2203
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Definition: vehicle_base.h:315
uint16_t cur_speed
current speed
Definition: vehicle_base.h:328
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition: vehicle.cpp:2561
TimerGameCalendar::Date max_age
Maximum age.
Definition: vehicle_base.h:294
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
Definition: vehicle_base.h:368
uint16_t reliability
Reliability.
Definition: vehicle_base.h:297
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds,...
Definition: vehicle.cpp:1363
uint8_t progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition: vehicle_base.h:332
uint16_t reliability_spd_dec
Reliability decrease speed.
Definition: vehicle_base.h:298
uint8_t tick_counter
Increased by one for each tick.
Definition: vehicle_base.h:350
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:271
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1693
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:337
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle)
Definition: vehicle_base.h:504
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition: vehicle.cpp:2787
TimerGameCalendar::Year build_year
Year the vehicle has been built.
Definition: vehicle_base.h:291
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:309
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:272
uint8_t running_ticks
Number of ticks this vehicle was not stopped this day.
Definition: vehicle_base.h:351
Describes a single interconnected patch of water within a particular water region.
Definition: water_regions.h:27
int y
The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis.
Definition: water_regions.h:29
int x
The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis.
Definition: water_regions.h:28
uint32_t maximum_go_to_depot_penalty
What is the maximum penalty that may be endured for going to a depot.
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition: tile_cmd.h:21
@ VETS_CANNOT_ENTER
The vehicle cannot enter the tile.
Definition: tile_cmd.h:24
@ VETS_ENTERED_WORMHOLE
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition: tile_cmd.h:23
VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition: vehicle.cpp:1838
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition: tile_map.cpp:136
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition: tile_map.cpp:116
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:214
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition: tile_map.h:161
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition: tile_map.h:279
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_BASE.
Definition: tile_type.h:18
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
@ MP_STATION
A tile of a station.
Definition: tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:57
@ MP_WATER
Water tile.
Definition: tile_type.h:54
@ MP_RAILWAY
A railway.
Definition: tile_type.h:49
@ MP_INDUSTRY
Part of an industry.
Definition: tile_type.h:56
Definition of the game-calendar-timer.
Definition of the game-economy-timer.
Functions related to time tabling.
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition: track_func.h:262
Track TrackToOppositeTrack(Track t)
Find the opposite track to a given track.
Definition: track_func.h:231
bool IsDiagonalTrack(Track track)
Checks if a given Track is diagonal.
Definition: track_func.h:619
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition: track_func.h:77
DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Definition: track_func.h:714
Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition: track_func.h:193
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:498
TrackBits AxisToTrackBits(Axis a)
Maps an Axis to the corresponding TrackBits value.
Definition: track_func.h:88
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or INVALID_TRACK.
Definition: track_func.h:177
TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction.
Definition: track_func.h:573
Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:537
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition: track_func.h:111
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition: track_func.h:363
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition: track_func.h:308
TrackBits
Allow incrementing of Track variables.
Definition: track_type.h:35
@ TRACK_BIT_WORMHOLE
Bitflag for a wormhole (used for tunnels)
Definition: track_type.h:52
@ TRACK_BIT_DEPOT
Bitflag for a depot.
Definition: track_type.h:53
@ TRACK_BIT_NONE
No track.
Definition: track_type.h:36
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:67
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition: track_type.h:86
Track
These are used to specify a single track.
Definition: track_type.h:19
@ INVALID_TRACK
Flag for an invalid track.
Definition: track_type.h:28
@ TRACK_END
Used for iterations.
Definition: track_type.h:27
@ TRANSPORT_WATER
Transport over water.
Functions that have tunnels and bridges in common.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition: vehicle.cpp:1552
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition: vehicle.cpp:167
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition: vehicle.cpp:1784
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:520
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1301
void EconomyAgeVehicle(Vehicle *v)
Update economy age of a vehicle.
Definition: vehicle.cpp:1429
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:3058
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1441
@ VF_BUILT_AS_PROTOTYPE
Vehicle is a prototype (accepted as exclusive preview).
Definition: vehicle_base.h:47
@ VS_STOPPED
Vehicle is stopped by the player.
Definition: vehicle_base.h:34
@ VS_HIDDEN
Vehicle is not visible.
Definition: vehicle_base.h:33
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
@ VS_DEFPAL
Use default vehicle palette.
Definition: vehicle_base.h:36
Functions related to vehicles.
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:78
@ EIT_ON_MAP
Vehicle drawn in viewport.
Definition: vehicle_type.h:79
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
TileIndex GetShipDepotNorthTile(Tile t)
Get the most northern tile of a ship depot.
Definition: water_map.h:289
WaterClass
classes of water (for WATER_TILE_CLEAR water tile type).
Definition: water_map.h:39
@ WATER_CLASS_SEA
Sea.
Definition: water_map.h:40
@ WATER_CLASS_CANAL
Canal.
Definition: water_map.h:41
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition: water_map.h:101
bool IsShipDepotTile(Tile t)
Is it a ship depot tile?
Definition: water_map.h:232
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition: water_map.h:112
uint8_t GetLockPart(Tile t)
Get the part of a lock.
Definition: water_map.h:326
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition: water_map.h:371
bool IsLock(Tile t)
Is there a lock on a given water tile?
Definition: water_map.h:303
DiagDirection GetShipDepotDirection(Tile t)
Get the direction of the ship depot.
Definition: water_map.h:267
@ LOCK_PART_MIDDLE
Middle part of a lock.
Definition: water_map.h:66
Axis GetShipDepotAxis(Tile t)
Get the axis of the ship depot.
Definition: water_map.h:243
WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
Returns basic water region patch information for the provided tile.
void VisitWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_patch, TVisitWaterRegionPatchCallBack &callback)
Calls the provided callback function on all accessible water region patches in each cardinal directio...
int CalculateWaterRegionPatchHash(const WaterRegionPatchDesc &water_region_patch)
Calculates a number that uniquely identifies the provided water region patch.
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3119
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3211
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3106
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3093
Window functions not directly related to making/drawing windows.
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition: window_type.h:351
@ WC_SHIPS_LIST
Ships list; Window numbers:
Definition: window_type.h:320
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition: window_type.h:200
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition: window_type.h:339
Entry point for OpenTTD to YAPF.
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
Returns true if it is better to reverse the ship before leaving depot using YAPF.
Definition: yapf_ship.cpp:435
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
Finds the best path for given ship using YAPF.
Definition: yapf_ship.cpp:427
Implementation of YAPF for water regions, which are used for finding intermediate ship destinations.
Functions related to zooming.
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:77