OpenTTD Source 20241224-master-gee860a5c8e
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"
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
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
68static const uint16_t _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
69
70template <>
71bool IsValidImageIndex<VEH_SHIP>(uint8_t image_index)
72{
73 return image_index < lengthof(_ship_sprites);
74}
75
76static inline TrackBits GetTileShipTrackStatus(TileIndex tile)
77{
79}
80
81static 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
97void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
98{
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
120void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
121{
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
134void 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
151static 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
204static 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) {
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 */
295 }
296
297 if (this->state == TRACK_BIT_WORMHOLE) {
298 /* ship on aqueduct, so just use its direction and assume a diagonal track */
300 }
301
303}
304
306{
307 this->colourmap = PAL_NONE;
308 this->UpdateViewport(true, false);
309 this->UpdateCache();
310}
311
312void Ship::PlayLeaveStationSound(bool force) const
313{
314 if (PlayVehicleSound(this, VSE_START, force)) return;
315 SndPlayVehicleFx(ShipVehInfo(this->engine_type)->sfx, this);
316}
317
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 {
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
370static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr)
371{
372 /* Ask pathfinder for best direction */
373 return YapfShipCheckReverse(v, trackdir);
374}
375
376static 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
434
435 return false;
436}
437
443static 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
468static 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
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.back().trackdir);
510
511 if (HasBit(tracks, track)) {
512 v->path.pop_back();
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
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
596static 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
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
647bool 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
664static 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
685static void ReverseShip(Ship *v)
686{
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
699static void ShipController(Ship *v)
700{
701 v->tick_counter++;
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) {
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. */
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_back();
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
880void 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
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;
931
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.
debug_inline constexpr 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.
Money GetCost() const
The costs as made up to this moment.
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
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.
@ DC_EXEC
execute the given command
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.
CompanyID _current_company
Company currently doing an action.
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:966
@ EXPENSES_SHIP_RUN
Running costs ships.
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.
fluid_settings_t * settings
FluidSynth settings handle.
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.
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
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 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.
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.
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
@ 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.
WaterClass GetEffectiveWaterClass(TileIndex tile)
Determine the effective WaterClass for a ship travelling on a tile.
Definition ship_cmd.cpp:54
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 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
static Vehicle * EnsureNoMovingShipProc(Vehicle *v, void *)
Test-procedure for HasVehicleOnPos to check for any ships which are moving.
Definition ship_cmd.cpp:365
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?
bool IsOilRig(Tile t)
Is tile t part of an oilrig?
bool IsDockWaterPart(Tile t)
Check whether a dock tile is the tile on water.
@ HVOT_SHIP
Station has seen a ship.
@ FACIL_DOCK
Station with a dock.
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.
uint16_t vehicle_flags
Used for gradual loading and other miscellaneous things (.
StationFacility facilities
The facilities that this station has.
TileIndex xy
Base tile of the station.
VehicleType type
Type of vehicle.
Structure to return information about the closest depot location, and whether it could be found.
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition engine_base.h:48
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
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:59
TimerGameCalendar::Date GetLifeLengthInDays() const
Returns the vehicle's (not model's!) life length in days.
Definition engine.cpp:443
uint16_t reliability
Current reliability of the engine.
Definition engine_base.h:47
uint8_t flags
Flags of the engine.
Definition engine_base.h:55
PathfinderSettings pf
settings for all pathfinders
Position information of a vehicle after it moved.
TileIndex new_tile
Tile of the vehicle after moving.
int y
x and y position of the vehicle after moving
TileIndex old_tile
Current tile of the vehicle.
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.
Direction last_direction
Last direction we obtained sprites for.
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.
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.
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.
static Titem * Get(size_t index)
Returns Titem with given index.
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:72
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
Definition engine_type.h:71
All ships have this type.
Definition ship.h:32
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
TileIndex GetOrderStationLocation(StationID station) override
Determine the location for the station where the vehicle goes to next.
Definition ship_cmd.cpp:318
TrackBits state
The "track" the ship is following.
Definition ship.h:34
int16_t rotation_x_pos
NOSAVE: X Position before rotation.
Definition ship.h:36
Direction rotation
Visible direction.
Definition ship.h:35
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:37
ShipPathCache path
Cached path.
Definition ship.h:33
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:54
void PlayLeaveStationSound(bool force=false) const override
Play the sound associated with leaving the station.
Definition ship_cmd.cpp:312
void OnNewEconomyDay() override
Economy day handler.
Definition ship_cmd.cpp:261
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override
Gets the sprite to show for the given direction.
Definition ship_cmd.cpp:134
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.
TileArea docking_station
Tile area the docking tiles cover.
uint16_t cached_cargo_age_period
Number of ticks before carried cargo is aged.
uint16_t cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Sprite sequence for a vehicle part.
bool IsValid() const
Check whether the sequence contains any sprites.
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.
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition vehicle.cpp:131
Vehicle data structure.
EngineID engine_type
The type of engine used for this vehicle.
static uint GetAdvanceSpeed(uint speed)
Determines the effective vehicle movement speed.
int32_t z_pos
z coordinate.
Direction direction
facing
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...
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
uint8_t x_extent
x-extent of vehicle bounding box
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
uint16_t cargo_cap
total capacity
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
uint16_t random_bits
Bits used for randomized variational spritegroups.
uint8_t day_counter
Increased by one for each day.
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.
SpriteID colourmap
NOSAVE: cached colour mapping.
uint GetAdvanceDistance()
Determines the vehicle "progress" needed for moving a step.
uint8_t z_extent
z-extent of vehicle bounding box
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...
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
uint8_t acceleration
used by train & aircraft
Order current_order
The current order (+ status, like: loading)
CargoID cargo_type
type of cargo this vehicle is carrying
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
int32_t y_pos
y coordinate.
int32_t x_pos
x coordinate.
uint8_t y_extent
y-extent of vehicle bounding box
uint16_t refit_cap
Capacity left over from before last refit.
uint8_t vehstatus
Status.
VehicleCache vcache
Cache of often used vehicle values.
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...
uint16_t cur_speed
current speed
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition vehicle.cpp:2561
TimerGameCalendar::Date max_age
Maximum age.
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
uint16_t reliability
Reliability.
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.
uint16_t reliability_spd_dec
Reliability decrease speed.
uint8_t tick_counter
Increased by one for each tick.
TileIndex tile
Current tile index.
TileIndex dest_tile
Heading for this tile.
void UpdatePosition()
Update the position of the vehicle.
Definition vehicle.cpp:1693
StationID last_station_visited
The last station we stopped at.
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle)
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.
Owner owner
Which company owns the vehicle?
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.
Describes a single interconnected patch of water within a particular water region.
int y
The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis.
int x
The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis.
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).
@ VS_STOPPED
Vehicle is stopped by the player.
@ VS_HIDDEN
Vehicle is not visible.
@ VS_CRASHED
Vehicle is crashed.
@ VS_DEFPAL
Use default vehicle palette.
Functions related to vehicles.
EngineImageType
Visualisation contexts of vehicles and engines.
@ EIT_ON_MAP
Vehicle drawn in viewport.
@ VEH_SHIP
Ship vehicle type.
@ 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:3127
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:3219
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:3114
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
Window functions not directly related to making/drawing windows.
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
@ WC_SHIPS_LIST
Ships list; Window numbers:
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
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.
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
Finds the best path for given ship using YAPF.
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