OpenTTD Source 20260917-master-gec444f7315
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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 "strings_func.h"
23#include "window_func.h"
26#include "vehicle_func.h"
27#include "sound_func.h"
28#include "ai/ai.hpp"
29#include "game/game.hpp"
30#include "engine_base.h"
31#include "company_base.h"
32#include "tunnelbridge_map.h"
33#include "zoom_func.h"
34#include "framerate_type.h"
35#include "industry.h"
36#include "industry_map.h"
37#include "ship_cmd.h"
38#include "script/api/script_event_types.hpp"
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);
59 return WaterClass::Canal;
60 }
61 if (IsTileType(tile, TileType::Railway)) {
63 return WaterClass::Sea;
64 }
65 NOT_REACHED();
66}
67
68static const uint16_t _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
69
71template <>
72bool IsValidImageIndex<VehicleType::Ship>(uint8_t image_index)
73{
74 return image_index < lengthof(_ship_sprites);
75}
76
77static inline TrackBits GetTileShipTrackStatus(TileIndex tile)
78{
80}
81
82static void GetShipIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
83{
84 const Engine *e = Engine::Get(engine);
85 uint8_t spritenum = e->VehInfo<ShipVehicleInfo>().image_index;
86
87 if (IsCustomVehicleSpriteNum(spritenum)) {
88 GetCustomVehicleIcon(engine, Direction::W, image_type, result);
89 if (result->IsValid()) return;
90
91 spritenum = e->original_image_index;
92 }
93
94 assert(IsValidImageIndex<VehicleType::Ship>(spritenum));
95 result->Set(to_underlying(Direction::W) + _ship_sprites[spritenum]);
96}
97
98void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
99{
101 GetShipIcon(engine, image_type, &seq);
102
103 Rect rect;
104 seq.GetBounds(&rect);
105 preferred_x = Clamp(preferred_x,
106 left - UnScaleGUI(rect.left),
107 right - UnScaleGUI(rect.right));
108
109 seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
110}
111
121void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
122{
124 GetShipIcon(engine, image_type, &seq);
125
126 Rect rect;
127 seq.GetBounds(&rect);
128
129 width = UnScaleGUI(rect.Width());
130 height = UnScaleGUI(rect.Height());
131 xoffs = UnScaleGUI(rect.left);
132 yoffs = UnScaleGUI(rect.top);
133}
134
136{
137 uint8_t spritenum = this->spritenum;
138
139 if (image_type == EngineImageType::OnMap) direction = this->rotation;
140
141 /* Reverse the ship's visual direction if the ship is double-ended and the second end is used as the bow.
142 * The ship's sprites might not be symmetrical, this avoids them flipping around visually. */
144
145 if (IsCustomVehicleSpriteNum(spritenum)) {
146 GetCustomVehicleSprite(this, direction, image_type, result);
147 if (result->IsValid()) return;
148
150 }
151
153 result->Set(_ship_sprites[spritenum] + to_underlying(direction));
154}
155
156static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
157{
158 const int max_region_distance = (max_distance / WATER_REGION_EDGE_LENGTH) + 1;
159
160 static std::unordered_set<int> visited_patch_hashes;
161 static std::deque<WaterRegionPatchDesc> patches_to_search;
162 visited_patch_hashes.clear();
163 patches_to_search.clear();
164
165 /* Step 1: find a set of reachable Water Region Patches using BFS. */
166 const WaterRegionPatchDesc start_patch = GetWaterRegionPatchInfo(v->tile);
167 patches_to_search.push_back(start_patch);
168 visited_patch_hashes.insert(CalculateWaterRegionPatchHash(start_patch));
169
170 while (!patches_to_search.empty()) {
171 /* Remove first patch from the queue and make it the current patch. */
172 const WaterRegionPatchDesc current_node = patches_to_search.front();
173 patches_to_search.pop_front();
174
175 /* Add neighbours of the current patch to the search queue. */
176 VisitWaterRegionPatchCallback visit_func = [&](const WaterRegionPatchDesc &water_region_patch) {
177 /* Note that we check the max distance per axis, not the total distance. */
178 if (std::abs(water_region_patch.x - start_patch.x) > max_region_distance ||
179 std::abs(water_region_patch.y - start_patch.y) > max_region_distance) return;
180
181 const int hash = CalculateWaterRegionPatchHash(water_region_patch);
182 if (visited_patch_hashes.count(hash) == 0) {
183 visited_patch_hashes.insert(hash);
184 patches_to_search.push_back(water_region_patch);
185 }
186 };
187
188 VisitWaterRegionPatchNeighbours(current_node, visit_func);
189 }
190
191 /* Step 2: Find the closest depot within the reachable Water Region Patches. */
192 const Depot *best_depot = nullptr;
193 uint best_dist_sq = std::numeric_limits<uint>::max();
194 for (const Depot *depot : Depot::Iterate()) {
195 const TileIndex tile = depot->xy;
196 if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
197 const uint dist_sq = DistanceSquare(tile, v->tile);
198 if (dist_sq < best_dist_sq && dist_sq <= max_distance * max_distance &&
199 visited_patch_hashes.count(CalculateWaterRegionPatchHash(GetWaterRegionPatchInfo(tile))) > 0) {
200 best_dist_sq = dist_sq;
201 best_depot = depot;
202 }
203 }
204 }
205
206 return best_depot;
207}
208
209static void CheckIfShipNeedsService(Vehicle *v)
210{
211 if (Company::Get(v->owner)->settings.vehicle.servint_ships == 0 || !v->NeedsAutomaticServicing()) return;
212 if (v->IsChainInDepot()) {
214 return;
215 }
216
217 uint max_distance = _settings_game.pf.yapf.maximum_go_to_depot_penalty / YAPF_TILE_LENGTH;
218
219 const Depot *depot = FindClosestShipDepot(v, max_distance);
220
221 if (depot == nullptr) {
222 if (v->current_order.IsType(OT_GOTO_DEPOT)) {
224 SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
225 }
226 return;
227 }
228
230 v->SetDestTile(depot->xy);
231 SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
232}
233
238{
239 const ShipVehicleInfo *svi = ShipVehInfo(this->engine_type);
240
241 /* Get speed fraction for the current water type. Aqueducts are always canals. */
242 bool is_ocean = GetEffectiveWaterClass(this->tile) == WaterClass::Sea;
243 uint raw_speed = GetVehicleProperty(this, PROP_SHIP_SPEED, svi->max_speed);
244 this->vcache.cached_max_speed = svi->ApplyWaterClassSpeedFrac(raw_speed, is_ocean);
245
246 /* Update cargo aging period. */
247 this->vcache.cached_cargo_age_period = GetVehicleProperty(this, PROP_SHIP_CARGO_AGE_PERIOD, EngInfo(this->engine_type)->cargo_age_period);
248
249 this->UpdateVisualEffect();
250}
251
253{
254 const Engine *e = this->GetEngine();
255 uint cost_factor = GetVehicleProperty(this, PROP_SHIP_RUNNING_COST_FACTOR, e->VehInfo<ShipVehicleInfo>().running_cost);
256 return GetPrice(Price::RunningShip, cost_factor, e->GetGRF());
257}
258
261{
262 AgeVehicle(this);
263}
264
267{
268 EconomyAgeVehicle(this);
269
270 if ((++this->day_counter & 7) == 0) {
272 }
273
275 CheckIfShipNeedsService(this);
276
277 CheckOrders(this);
278
279 if (this->running_ticks == 0) return;
280
282
283 this->profit_this_year -= cost.GetCost();
284 this->running_ticks = 0;
285
287
288 SetWindowDirty(WindowClass::VehicleDetails, this->index);
289 /* we need this for the profit */
290 SetWindowClassesDirty(WindowClass::ShipList);
291}
292
294{
295 if (this->vehstatus.Test(VehState::Crashed)) return Trackdir::Invalid;
296
297 if (this->IsInDepot()) {
298 /* We'll assume the ship is facing outwards */
300 }
301
302 if (this->state == Track::Wormhole) {
303 /* ship on aqueduct, so just use its direction and assume a diagonal track */
305 }
306
308}
309
311{
312 this->colourmap = PAL_NONE;
313 this->UpdateViewport(true, false);
314 this->UpdateCache();
315}
316
317void Ship::PlayLeaveStationSound(bool force) const
318{
319 if (PlayVehicleSound(this, VSE_START, force)) return;
320 SndPlayVehicleFx(ShipVehInfo(this->engine_type)->sfx, this);
321}
322
324{
325 if (station == this->last_station_visited) this->last_station_visited = StationID::Invalid();
326
327 const Station *st = Station::Get(station);
328 if (CanVehicleUseStation(this, st)) {
329 return st->xy;
330 } else {
332 return TileIndex{};
333 }
334}
335
337{
338 static constexpr DirectionIndexArray<SpriteBounds> ship_bounds{{{
339 {{ -3, -3, 0}, { 6, 6, 6}, {}}, // N
340 {{-16, -3, 0}, {32, 6, 6}, {}}, // NE
341 {{ -3, -3, 0}, { 6, 6, 6}, {}}, // E
342 {{ -3, -16, 0}, { 6, 32, 6}, {}}, // SE
343 {{ -3, -3, 0}, { 6, 6, 6}, {}}, // S
344 {{-16, -3, 0}, {32, 6, 6}, {}}, // SW
345 {{ -3, -3, 0}, { 6, 6, 6}, {}}, // W
346 {{ -3, -16, 0}, { 6, 32, 6}, {}}, // NW
347 }}};
348
349 this->bounds = ship_bounds[this->rotation];
350
351 if (this->direction != this->rotation) {
352 /* If we are rotating, then it is possible the ship was moved to its next position. In that
353 * case, because we are still showing the old direction, the ship will appear to glitch sideways
354 * slightly. We can work around this by applying an additional offset to make the ship appear
355 * where it was before it moved. */
356 this->bounds.origin.x -= this->x_pos - this->rotation_x_pos;
357 this->bounds.origin.y -= this->y_pos - this->rotation_y_pos;
358 }
359}
360
361static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr)
362{
363 /* Ask pathfinder for best direction */
364 return YapfShipCheckReverse(v, trackdir);
365}
366
373{
374 if (!v->IsChainInDepot()) return false;
375
376 /* Check if we should wait here for unbunching. */
377 if (v->IsWaitingForUnbunching()) return true;
378
379 /* We are leaving a depot, but have to go to the exact same one; re-enter */
380 if (v->current_order.IsType(OT_GOTO_DEPOT) &&
383 return true;
384 }
385
386 /* Don't leave depot if no destination set */
387 if (v->dest_tile == INVALID_TILE) return true;
388
389 /* Don't leave depot if another vehicle is already entering/leaving */
390 /* This helps avoid CPU load if many ships are set to start at the same time */
391 if (HasVehicleOnTile(v->tile, [](const Vehicle *u) {
392 return u->type == VehicleType::Ship && u->cur_speed != 0;
393 })) return true;
394
397 if (CheckReverseShip(v)) v->direction = ReverseDir(v->direction);
398
399 /* Double-ended always exit a depot with the first end facing forward, consistent with train reversal behaviour. */
401
403 v->rotation = v->direction;
405 v->cur_speed = 0;
406 v->UpdateViewport(true, true);
407 SetWindowDirty(WindowClass::VehicleDepot, v->tile);
408
412 InvalidateWindowData(WindowClass::VehicleDepot, v->tile);
413 SetWindowClassesDirty(WindowClass::ShipList);
414
415 return false;
416}
417
423static uint ShipAccelerate(Vehicle *v)
424{
425 uint speed;
426 speed = std::min<uint>(v->cur_speed + v->acceleration, v->vcache.cached_max_speed);
427 speed = std::min<uint>(speed, v->current_order.GetMaxSpeed() * 2);
428
429 /* updates statusbar only if speed have changed to save CPU time */
430 if (speed != v->cur_speed) {
431 v->cur_speed = speed;
432 SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
433 }
434
435 const uint advance_speed = v->GetAdvanceSpeed(speed);
436 const uint number_of_steps = (advance_speed + v->progress) / v->GetAdvanceDistance();
437 const uint remainder = (advance_speed + v->progress) % v->GetAdvanceDistance();
438 assert(remainder <= std::numeric_limits<uint8_t>::max());
439 v->progress = static_cast<uint8_t>(remainder);
440 return number_of_steps;
441}
442
448static void ShipArrivesAt(const Vehicle *v, Station *st)
449{
450 /* Check if station was ever visited before */
451 if (!st->had_vehicle_of_type.Test(StationVehicleType::Ship)) {
452 st->had_vehicle_of_type.Set(StationVehicleType::Ship);
453
455 GetEncodedString(STR_NEWS_FIRST_SHIP_ARRIVAL, st->index),
457 v->index,
458 st->index
459 );
460 AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
461 Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
462 }
463}
464
465
475{
476 bool path_found = true;
477 Track track;
478
479 if (v->dest_tile == INVALID_TILE) {
480 /* No destination, don't invoke pathfinder. */
481 track = TrackBitsToTrack(v->state);
482 if (!IsDiagonalTrack(track)) track = TrackToOppositeTrack(track);
483 if (!tracks.Test(track)) track = FindFirstTrack(tracks);
484 path_found = false;
485 } else {
486 /* Attempt to follow cached path. */
487 if (!v->path.empty()) {
488 track = TrackdirToTrack(v->path.back().trackdir);
489
490 if (tracks.Test(track)) {
491 v->path.pop_back();
492 /* HandlePathfindResult() is not called here because this is not a new pathfinder result. */
493 return track;
494 }
495
496 /* Cached path is invalid so continue with pathfinder. */
497 v->path.clear();
498 }
499
500 track = YapfShipChooseTrack(v, tile, path_found, v->path);
501 }
502
503 v->HandlePathfindingResult(path_found);
504 return track;
505}
506
514{
515 TrackBits tracks = GetTileShipTrackStatus(tile) & DiagdirReachesTracks(dir);
516
517 return tracks;
518}
519
525static int ShipTestUpDownOnLock(const Ship *v)
526{
527 /* Suitable tile? */
528 if (!IsTileType(v->tile, TileType::Water) || !IsLock(v->tile) || GetLockPart(v->tile) != LockPart::Middle) return 0;
529
530 /* Must be at the centre of the lock */
531 if ((v->x_pos & 0xF) != 8 || (v->y_pos & 0xF) != 8) return 0;
532
534 assert(IsValidDiagDirection(diagdir));
535
536 if (DirToDiagDir(v->direction) == diagdir) {
537 /* Move up */
538 return (v->z_pos < GetTileMaxZ(v->tile) * (int)TILE_HEIGHT) ? 1 : 0;
539 } else {
540 /* Move down */
541 return (v->z_pos > GetTileZ(v->tile) * (int)TILE_HEIGHT) ? -1 : 0;
542 }
543}
544
551{
552 /* Moving up/down through lock */
553 int dz = ShipTestUpDownOnLock(v);
554 if (dz == 0) return false;
555
556 if (v->cur_speed != 0) {
557 v->cur_speed = 0;
558 SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
559 }
560
561 if ((v->tick_counter & 7) == 0) {
562 v->z_pos += dz;
563 v->UpdatePosition();
564 v->UpdateViewport(true, true);
565 }
566
567 return true;
568}
569
576bool IsShipDestinationTile(TileIndex tile, StationID station)
577{
578 assert(IsDockingTile(tile));
579 /* Check each tile adjacent to docking tile. */
581 TileIndex t = tile + TileOffsByDiagDir(d);
582 if (!IsValidTile(t)) continue;
583 if (IsDockTile(t) && GetStationIndex(t) == station && IsDockWaterPart(t)) return true;
585 const Industry *i = Industry::GetByTile(t);
586 if (i->neutral_station != nullptr && i->neutral_station->index == station) return true;
587 }
588 if (IsTileType(t, TileType::Station) && IsOilRig(t) && GetStationIndex(t) == station) return true;
589 }
590 return false;
591}
592
593static void ReverseShipIntoTrackdir(Ship *v, Trackdir trackdir)
594{
595 static constexpr TrackdirIndexArray<Direction> _trackdir_to_direction{
598 };
599
600 v->direction = _trackdir_to_direction[trackdir];
601 assert(v->direction != Direction::Invalid);
603
604 /* Double-ended ships can instantly "turn" 180 degrees by switching which end is forward-facing. */
605 if (v->GetEngine()->info.extra_flags.Test(ExtraEngineFlag::IsDoubleEnded)) {
608 }
609
610 /* Remember our current location to avoid movement glitch */
611 v->rotation_x_pos = v->x_pos;
612 v->rotation_y_pos = v->y_pos;
613 v->cur_speed = 0;
614 v->path.clear();
615
616 v->UpdatePosition();
617 v->UpdateViewport(true, true);
618}
619
620static void ReverseShip(Ship *v)
621{
623
624 /* Double-ended ships can instantly "turn" 180 degrees by switching which end is forward-facing. */
625 if (v->GetEngine()->info.extra_flags.Test(ExtraEngineFlag::IsDoubleEnded)) {
628 }
629
630 /* Remember our current location to avoid movement glitch */
631 v->rotation_x_pos = v->x_pos;
632 v->rotation_y_pos = v->y_pos;
633 v->cur_speed = 0;
634 v->path.clear();
635
636 v->UpdatePosition();
637 v->UpdateViewport(true, true);
638}
639
640static void ShipController(Ship *v)
641{
642 v->tick_counter++;
644
645 if (v->HandleBreakdown()) return;
646
647 if (v->vehstatus.Test(VehState::Stopped)) return;
648
649 if (ProcessOrders(v) && CheckReverseShip(v)) return ReverseShip(v);
650
651 v->HandleLoading();
652
653 if (v->current_order.IsType(OT_LOADING)) return;
654
655 if (CheckShipStayInDepot(v)) return;
656
657 v->ShowVisualEffect();
658
659 /* Rotating on spot */
660 if (v->direction != v->rotation) {
661 if ((v->tick_counter & 7) == 0) {
663 v->rotation = ChangeDir(v->rotation, LimitDirDiff(diff));
664 /* Invalidate the sprite cache direction to force recalculation of viewport */
666 v->UpdateViewport(true, true);
667 }
668 return;
669 }
670
671 if (ShipMoveUpDownOnLock(v)) return;
672
673 const uint number_of_steps = ShipAccelerate(v);
674 for (uint i = 0; i < number_of_steps; ++i) {
675 if (ShipMoveUpDownOnLock(v)) return;
676
678 if (v->state != Track::Wormhole) {
679 /* Not on a bridge */
680 if (gp.old_tile == gp.new_tile) {
681 /* Staying in tile */
682 if (v->IsInDepot()) {
683 gp.x = v->x_pos;
684 gp.y = v->y_pos;
685 } else {
686 /* Not inside depot */
687 auto vets = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
688 if (vets.Test(VehicleEnterTileState::CannotEnter)) return ReverseShip(v);
689
690 /* A leave station order only needs one tick to get processed, so we can
691 * always skip ahead. */
692 if (v->current_order.IsType(OT_LEAVESTATION)) {
693 v->current_order.Free();
694 SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
695 /* Test if continuing forward would lead to a dead-end, moving into the dock. */
696 const DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
697 const TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
698 if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TransportType::Water, RoadTramType::Invalid, exitdir).trackdirs).None()) return ReverseShip(v);
699 } else if (v->dest_tile != INVALID_TILE) {
700 /* We have a target, let's see if we reached it... */
701 if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
702 DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
703 /* We got within 3 tiles of our target buoy, so let's skip to our
704 * next order */
705 UpdateVehicleTimetable(v, true);
708 } else if (v->current_order.IsType(OT_GOTO_DEPOT) &&
709 v->dest_tile == gp.new_tile) {
710 /* Depot orders really need to reach the tile */
711 if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
713 return;
714 }
715 } else if (v->current_order.IsType(OT_GOTO_STATION) && IsDockingTile(gp.new_tile)) {
716 /* Process station in the orderlist. */
717 Station *st = Station::Get(v->current_order.GetDestination().ToStationID());
718 if (st->docking_station.Contains(gp.new_tile) && IsShipDestinationTile(gp.new_tile, st->index)) {
719 v->last_station_visited = st->index;
720 if (st->facilities.Test(StationFacility::Dock)) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
721 ShipArrivesAt(v, st);
722 v->BeginLoading();
723 } else { // leave stations without docks right away
726 }
727 }
728 }
729 }
730 }
731 } else {
732 /* New tile */
733 if (!IsValidTile(gp.new_tile)) return ReverseShip(v);
734
735 const DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
736 assert(diagdir != DiagDirection::Invalid);
737 const TrackBits tracks = GetAvailShipTracks(gp.new_tile, diagdir);
738 if (tracks.None()) {
739 Trackdir trackdir = Trackdir::Invalid;
740 CheckReverseShip(v, &trackdir);
741 if (trackdir == Trackdir::Invalid) return ReverseShip(v);
742 return ReverseShipIntoTrackdir(v, trackdir);
743 }
744
745 /* Choose a direction, and continue if we find one */
746 const Track track = ChooseShipTrack(v, gp.new_tile, tracks);
747 if (!IsValidTrack(track)) return ReverseShip(v);
748
749 /* Update XY to reflect the entrance to the new tile, and select the direction to use */
750 Direction chosen_dir = VehicleEnterTileCoordinates(gp, diagdir, track);
751
752 /* Call the landscape function and tell it that the vehicle entered the tile */
753 auto vets = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
754 if (vets.Test(VehicleEnterTileState::CannotEnter)) return ReverseShip(v);
755
757 v->tile = gp.new_tile;
758 v->state = track;
759
760 /* Update ship cache when the water class changes. Aqueducts are always canals. */
762 }
763
764 const Direction new_direction = chosen_dir;
765 const DirDiff diff = DirDifference(new_direction, v->direction);
766 switch (diff) {
767 case DirDiff::Same:
768 case DirDiff::Right45:
769 case DirDiff::Left45:
770 /* Continue at speed */
771 v->rotation = v->direction = new_direction;
772 break;
773
774 default:
775 /* Stop for rotation */
776 v->cur_speed = 0;
777 v->direction = new_direction;
778 /* Remember our current location to avoid movement glitch */
779 v->rotation_x_pos = v->x_pos;
780 v->rotation_y_pos = v->y_pos;
781 break;
782 }
783 }
784 } else {
785 /* On a bridge */
787 v->x_pos = gp.x;
788 v->y_pos = gp.y;
789 v->UpdatePosition();
790 if (!v->vehstatus.Test(VehState::Hidden)) v->Vehicle::UpdateViewport(true);
791 continue;
792 }
793
794 /* Ship is back on the bridge head, we need to consume its path
795 * cache entry here as we didn't have to choose a ship track. */
796 if (!v->path.empty()) v->path.pop_back();
797 }
798
799 /* update image of ship, as well as delta XY */
800 v->x_pos = gp.x;
801 v->y_pos = gp.y;
802
803 v->UpdatePosition();
804 v->UpdateViewport(true, true);
805 }
806}
807
809{
811
812 if (!this->vehstatus.Test(VehState::Stopped)) this->running_ticks++;
813
814 ShipController(this);
815
816 return true;
817}
818
820{
821 if (tile == this->dest_tile) return;
822 this->path.clear();
823 this->dest_tile = tile;
824}
825
835{
836 tile = GetShipDepotNorthTile(tile);
837 if (flags.Test(DoCommandFlag::Execute)) {
838 int x;
839 int y;
840
841 const ShipVehicleInfo *svi = &e->VehInfo<ShipVehicleInfo>();
842
843 Ship *v = Ship::Create();
844 *ret = v;
845
847 v->tile = tile;
848 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
849 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
850 v->x_pos = x;
851 v->y_pos = y;
852 v->z_pos = GetSlopePixelZ(x, y);
853
854 v->direction = DiagDirToDir(GetShipDepotDirection(tile));
855
856 /* UpdateDeltaXY() requires rotation to be initialised as well. */
857 v->rotation = v->direction;
858 v->UpdateDeltaXY();
859
861
862 v->spritenum = svi->image_index;
863 v->cargo_type = e->GetDefaultCargoType();
864 assert(IsValidCargoType(v->cargo_type));
865 v->cargo_cap = svi->capacity;
866 v->refit_cap = 0;
867
868 v->last_station_visited = StationID::Invalid();
869 v->last_loading_station = StationID::Invalid();
870 v->engine_type = e->index;
871
872 v->reliability = e->reliability;
873 v->reliability_spd_dec = e->reliability_spd_dec;
874 v->max_age = e->GetLifeLengthInDays();
875
876 v->state = Track::Depot;
877
878 v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships);
879 v->date_of_last_service = TimerGameEconomy::date;
880 v->date_of_last_service_newgrf = TimerGameCalendar::date;
881 v->build_year = TimerGameCalendar::year;
882 v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
883 v->random_bits = Random();
884
885 v->acceleration = svi->acceleration;
886 v->UpdateCache();
887
889 v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
890
891 v->InvalidateNewGRFCacheOfChain();
892
893 v->cargo_cap = e->DetermineCapacity(v);
894
895 v->InvalidateNewGRFCacheOfChain();
896
897 v->UpdatePosition();
898 }
899
900 return CommandCost();
901}
902
904{
905 const Depot *depot = FindClosestShipDepot(this, MAX_SHIP_DEPOT_SEARCH_DISTANCE);
906 if (depot == nullptr) return ClosestDepot();
907
908 return ClosestDepot(depot->xy, depot->index);
909}
Base functions for all AIs.
@ None
Tile is not animated.
@ BuiltAsPrototype
Vehicle is a prototype (accepted as exclusive preview).
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:110
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:231
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Flip()
Flip all bits.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
Common return value for all commands.
Money GetCost() const
The costs as made up to this moment.
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition engine_base.h:52
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:227
EngineFlags flags
Flags of the engine.
Definition engine_base.h:59
uint8_t original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition engine_base.h:63
TimerGameCalendar::Date GetLifeLengthInDays() const
Returns the vehicle's (not model's!) life length in days.
Definition engine.cpp:469
CargoType GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition engine_base.h:96
uint16_t reliability
Current reliability of the engine.
Definition engine_base.h:51
Iterate a range of enum values.
static void NewEvent(class ScriptEvent *event)
Queue a new event for the 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 Date date
Current date in days (day counter).
@ Execute
execute the given command
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
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:56
DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Direction DiagDirToDir(DiagDirection dir)
Convert a DiagDirection to a Direction.
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.
DirDiff LimitDirDiff(DirDiff d)
Limit a direction difference to up to 45 degrees.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
DirDiff
Enumeration for the difference between two directions.
@ Left45
Angle of 45 degrees left.
@ Same
Both directions faces to the same direction.
@ Right45
Angle of 45 degrees right.
Direction
Defines the 8 directions on the map.
@ Invalid
Flag for an invalid direction.
@ SW
Southwest.
@ NW
Northwest.
@ NE
Northeast.
@ SE
Southeast.
EnumIndexArray< T, Direction, Direction::End > DirectionIndexArray
Array with Direction as index.
DiagDirection
Enumeration for diagonal directions.
@ Invalid
Flag for an invalid DiagDirection.
@ End
Used for iterations.
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition economy.cpp:937
@ ShipRun
Running costs ships.
@ RunningShip
Running cost of ships.
Base class for engines.
@ IsDoubleEnded
Ship is double-ended, it can reverse direction without having to turn around.
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF > EngineID
Unique identification number of an engine.
Definition engine_type.h:26
@ ExclusivePreview
This vehicle is in the exclusive preview stage, either being used or being offered to a company.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
fluid_settings_t * settings
FluidSynth settings handle.
Types for recording game performance data.
@ GameLoopShips
Time spent processing ships.
Base functions for all Games.
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
Base of all industries.
Accessors to map for industries.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, RoadTramType 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.
#define Rect
Macro that prevents name conflicts between included headers.
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:186
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:169
DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
Determines the DiagDirection to get from one tile to another.
Definition map_func.h:627
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:615
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:574
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(EncodedString &&headline, NewsType type, VehicleID vehicle, StationID station=StationID::Invalid())
Adds a newsitem referencing a vehicle.
Definition news_func.h:32
@ ArrivalCompany
First vehicle arrived for company.
Definition news_type.h:30
@ ArrivalOther
First vehicle arrived for competitor.
Definition news_type.h:31
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.
@ Service
This depot order is because of the servicing limit.
Definition order_type.h:109
static const int YAPF_TILE_LENGTH
Length (penalty) of one tile with YAPF.
RailGroundType GetRailGroundType(Tile t)
Get the ground type for rail tiles.
Definition rail_map.h:601
@ HalfTileWater
Grass with a fence and shore or water on the free halftile.
Definition rail_map.h:582
@ Invalid
Invalid marker.
Definition road_type.h:42
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:61
Base for ships.
@ SecondEndFacingForward
Whether the other end is facing forward. Only applies to dual-ended ships.
Definition ship.h:31
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Definition ship_cmd.cpp:576
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
CommandCost CmdBuildShip(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a ship.
Definition ship_cmd.cpp:834
static uint ShipAccelerate(Vehicle *v)
Accelerates the ship towards its target speed.
Definition ship_cmd.cpp:423
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:513
static bool ShipMoveUpDownOnLock(Ship *v)
Test and move a ship up or down in a lock.
Definition ship_cmd.cpp:550
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Definition ship_cmd.cpp:576
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:121
static void ShipArrivesAt(const Vehicle *v, Station *st)
Ship arrives at a dock.
Definition ship_cmd.cpp:448
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:525
static bool CheckShipStayInDepot(Ship *v)
Checks whether a ship should stay in the depot.
Definition ship_cmd.cpp:372
static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
Runs the pathfinder to choose a track to continue along.
Definition ship_cmd.cpp:474
bool IsValidImageIndex< VehicleType::Ship >(uint8_t image_index)
Helper to check whether an image index is valid for a particular vehicle.
Definition ship_cmd.cpp:72
Command definitions related to ships.
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition slope_func.h:249
Functions related to sound.
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1794
static const SpriteID SPR_IMG_QUERY
Definition sprites.h:1275
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.
@ Dock
Station with a dock.
@ Ship
Station has seen a ship.
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:261
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
Functions related to OTTD's strings.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
TileIndex xy
Base tile of the station.
StationFacilities facilities
The facilities that this station has.
Structure to return information about the closest depot location, and whether it could be found.
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:64
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition industry.h:253
Station * neutral_station
Associated neutral station.
Definition industry.h:110
Direction last_direction
Last direction we obtained sprites for.
uint16_t GetMaxSpeed() const
Get the maximum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition order_base.h:307
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:100
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
void MakeDummy()
Makes this order a Dummy order.
void MakeLeaveStation()
Makes this order a Leave Station order.
void Free()
'Free' the order
Definition order_cmd.cpp:48
void MakeGoToDepot(DestinationID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=OrderNonStopFlag::NonStop, OrderDepotActionFlags action={}, CargoType cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition order_cmd.cpp:74
bool Contains(TileIndex tile) const
Does this tile area contain a tile?
Definition tilearea.cpp:104
static Pool::IterateWrapper< Depot > Iterate(size_t from=0)
static T * Create(Targs &&... args)
static Engine * Get(auto index)
int Width() const
Get width of Rect.
int Height() const
Get height of Rect.
Information about a ship vehicle.
Definition engine_type.h:99
uint ApplyWaterClassSpeedFrac(uint raw_speed, bool is_ocean) const
Apply ocean/canal speed fraction to a velocity.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h).
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick).
All ships have this type.
Definition ship.h:39
bool Tick() override
Calls the tick handler of the vehicle.
Definition ship_cmd.cpp:808
Money GetRunningCost() const override
Gets the running cost of a vehicle.
Definition ship_cmd.cpp:252
TileIndex GetOrderStationLocation(StationID station) override
Determine the location for the station where the vehicle goes to next.
Definition ship_cmd.cpp:323
void SetDestTile(TileIndex tile) override
Set the destination of this vehicle.
Definition ship_cmd.cpp:819
TrackBits state
The "track" the ship is following.
Definition ship.h:41
int16_t rotation_x_pos
NOSAVE: X Position before rotation.
Definition ship.h:44
VehicleShipFlags flags
Ship-specific flags.
Definition ship.h:43
Direction rotation
Visible direction.
Definition ship.h:42
void UpdateDeltaXY() override
Updates the x and y offsets and the size of the sprite used for this vehicle.
Definition ship_cmd.cpp:336
void OnNewCalendarDay() override
Calendar day handler.
Definition ship_cmd.cpp:260
int16_t rotation_y_pos
NOSAVE: Y Position before rotation.
Definition ship.h:45
ShipPathCache path
Cached path.
Definition ship.h:40
ClosestDepot FindClosestDepot() override
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
Definition ship_cmd.cpp:903
void MarkDirty() override
Marks the vehicles to be redrawn and updates cached variables.
Definition ship_cmd.cpp:310
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
Definition ship_cmd.cpp:293
bool IsInDepot() const override
Check whether the vehicle is in the depot.
Definition ship.h:61
void PlayLeaveStationSound(bool force=false) const override
Play the sound associated with leaving the station.
Definition ship_cmd.cpp:317
void OnNewEconomyDay() override
Economy day handler.
Definition ship_cmd.cpp:266
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override
Gets the sprite to show for the given direction.
Definition ship_cmd.cpp:135
void UpdateCache()
Update the caches of this ship.
Definition ship_cmd.cpp:237
static Station * Get(auto index)
void UpdateViewport(bool force_update, bool update_delta)
Station data structure.
TileArea docking_station
Tile area the docking tiles cover.
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:124
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:152
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:749
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.
virtual void SetDestTile(TileIndex tile)
Set the destination of this vehicle.
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:2453
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.
VehStates vehstatus
Status.
void UpdateVisualEffect(bool allow_power_change=true)
Update the cached visual effect.
Definition vehicle.cpp:2681
void LeaveUnbunchingDepot()
Leave an unbunching depot and calculate the next departure time for shared order vehicles.
Definition vehicle.cpp:2533
uint8_t acceleration
used by train & aircraft
Order current_order
The current order (+ status, like: loading).
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition vehicle.cpp:793
int32_t y_pos
y coordinate.
int32_t x_pos
x coordinate.
VehicleCache vcache
Cache of often used vehicle values.
SpriteBounds bounds
Bounding box of vehicle.
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition vehicle.cpp:2228
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:2580
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds,...
Definition vehicle.cpp:1375
uint8_t progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
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:1700
StationID last_station_visited
The last station we stopped at.
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition vehicle.cpp:2835
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:293
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.
@ CannotEnter
The vehicle cannot enter the tile.
Definition tile_cmd.h:27
@ EnteredWormhole
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition tile_cmd.h:26
VehicleEnterTileStates VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition vehicle.cpp:1864
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:135
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:115
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
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
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
@ TunnelBridge
Tunnel entry/exit and bridge heads.
Definition tile_type.h:58
@ Water
Water tile.
Definition tile_type.h:55
@ Station
A tile of a station or airport.
Definition tile_type.h:54
@ Industry
Part of an industry.
Definition tile_type.h:57
@ Railway
A tile with railway.
Definition tile_type.h:50
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:235
Track TrackToOppositeTrack(Track t)
Find the opposite track to a given track.
Definition track_func.h:204
bool IsDiagonalTrack(Track track)
Checks if a given Track is diagonal.
Definition track_func.h:514
DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Definition track_func.h:609
Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition track_func.h:166
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:405
bool IsValidTrack(Track track)
Checks if a Track is valid.
Definition track_func.h:24
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or Track::Invalid.
Definition track_func.h:150
TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:468
Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition track_func.h:432
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition track_func.h:86
Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track Axis::X -> Track::X Axis::Y -> Track::Y Uses the fact that...
Definition track_func.h:62
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition track_func.h:343
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition track_func.h:281
EnumBitSet< Track, uint8_t > TrackBits
Bitset of Track elements.
Definition track_type.h:43
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:63
@ X_NE
X-axis and direction to north-east.
Definition track_type.h:64
@ Invalid
Flag for an invalid trackdir.
Definition track_type.h:82
@ Y_NW
Y-axis and direction to north-west.
Definition track_type.h:73
EnumIndexArray< T, Trackdir, Trackdir::End > TrackdirIndexArray
Array with Trackdir as index.
Definition track_type.h:90
Track
These are used to specify a single track.
Definition track_type.h:19
@ Depot
Special flag indicating a vehicle is inside a depot.
Definition track_type.h:30
@ Wormhole
Special flag indicating vehicle is inside a bridge or tunnel.
Definition track_type.h:29
@ 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:1563
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition vehicle.cpp:188
void CheckVehicleBreakdown(Vehicle *v)
Periodic check for a vehicle to maybe break down.
Definition vehicle.cpp:1319
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition vehicle.cpp:1803
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition vehicle.cpp:1298
void EconomyAgeVehicle(Vehicle *v)
Update economy age of a vehicle.
Definition vehicle.cpp:1441
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition vehicle.cpp:3114
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition vehicle.cpp:1453
Direction VehicleEnterTileCoordinates(GetNewVehiclePosResult &gp, DiagDirection enterdir, Track track)
Lookup new subposition coordinates and direction to use when entering a new tile, applying the subcoo...
Definition vehicle.cpp:3401
@ Crashed
Vehicle is crashed.
@ Hidden
Vehicle is not visible.
@ DefaultPalette
Use default vehicle palette.
@ Stopped
Vehicle is stopped by the player.
Functions related to vehicles.
bool IsValidImageIndex(uint8_t image_index)
Helper to check whether an image index is valid for a particular vehicle.
bool HasVehicleOnTile(TileIndex tile, UnaryPred &&predicate)
Loop over vehicles on a tile, and check whether a predicate is true for any of them.
EngineImageType
Visualisation contexts of vehicles and engines.
@ OnMap
Vehicle drawn in viewport.
@ 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:294
WaterClass
classes of water (for WaterTileType::Clear water tile type).
Definition water_map.h:41
@ Canal
Canal.
Definition water_map.h:43
@ Sea
Sea.
Definition water_map.h:42
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:105
bool IsShipDepotTile(Tile t)
Is it a ship depot tile?
Definition water_map.h:237
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:116
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:378
@ Middle
Middle part of a lock.
Definition water_map.h:68
bool IsLock(Tile t)
Is there a lock on a given water tile?
Definition water_map.h:308
DiagDirection GetShipDepotDirection(Tile t)
Get the direction of the ship depot.
Definition water_map.h:272
LockPart GetLockPart(Tile t)
Get the part of a lock.
Definition water_map.h:331
Axis GetShipDepotAxis(Tile t)
Get the axis of the ship depot.
Definition water_map.h:248
WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
Returns basic water region patch information for the provided tile.
int CalculateWaterRegionPatchHash(const WaterRegionPatchDesc &water_region_patch)
Calculates a number that uniquely identifies the provided water region patch.
void VisitWaterRegionPatchNeighbours(const WaterRegionPatchDesc &water_region_patch, VisitWaterRegionPatchCallback &callback)
Calls the provided callback function on all accessible water region patches in each cardinal directio...
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting).
Definition window.cpp:3242
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:3334
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:3228
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting).
Definition window.cpp:3212
Window functions not directly related to making/drawing windows.
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