OpenTTD Source 20250205-master-gfd85ab1e2c
roadveh_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 "roadveh.h"
12#include "command_func.h"
13#include "error_func.h"
14#include "news_func.h"
15#include "station_base.h"
16#include "company_func.h"
18#include "newgrf_sound.h"
20#include "strings_func.h"
21#include "tunnelbridge_map.h"
24#include "vehicle_func.h"
25#include "sound_func.h"
26#include "ai/ai.hpp"
27#include "game/game.hpp"
28#include "depot_map.h"
29#include "effectvehicle_func.h"
30#include "roadstop_base.h"
31#include "spritecache.h"
32#include "core/random_func.hpp"
33#include "company_base.h"
34#include "core/backup_type.hpp"
35#include "newgrf.h"
36#include "zoom_func.h"
37#include "framerate_type.h"
38#include "roadveh_cmd.h"
39#include "road_cmd.h"
40
41#include "table/strings.h"
42
43#include "safeguards.h"
44
45static const uint16_t _roadveh_images[] = {
46 0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14,
47 0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74,
48 0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C,
49 0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC,
50 0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC,
51 0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4,
52 0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C,
53 0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4
54};
55
56static const uint16_t _roadveh_full_adder[] = {
57 0, 88, 0, 0, 0, 0, 48, 48,
58 48, 48, 0, 0, 64, 64, 0, 16,
59 16, 0, 88, 0, 0, 0, 0, 48,
60 48, 48, 48, 0, 0, 64, 64, 0,
61 16, 16, 0, 88, 0, 0, 0, 0,
62 48, 48, 48, 48, 0, 0, 64, 64,
63 0, 16, 16, 0, 8, 8, 8, 8,
64 0, 0, 0, 8, 8, 8, 8
65};
66static_assert(lengthof(_roadveh_images) == lengthof(_roadveh_full_adder));
67
68template <>
69bool IsValidImageIndex<VEH_ROAD>(uint8_t image_index)
70{
71 return image_index < lengthof(_roadveh_images);
72}
73
74static const Trackdir _road_reverse_table[DIAGDIR_END] = {
76};
77
83{
84 assert(this->IsFrontEngine());
86}
87
94{
95 int reference_width = ROADVEHINFO_DEFAULT_VEHICLE_WIDTH;
96
97 if (offset != nullptr) {
98 offset->x = ScaleSpriteTrad(reference_width) / 2;
99 offset->y = 0;
100 }
101 return ScaleSpriteTrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
102}
103
104static void GetRoadVehIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
105{
106 const Engine *e = Engine::Get(engine);
107 uint8_t spritenum = e->u.road.image_index;
108
109 if (is_custom_sprite(spritenum)) {
110 GetCustomVehicleIcon(engine, DIR_W, image_type, result);
111 if (result->IsValid()) return;
112
113 spritenum = e->original_image_index;
114 }
115
116 assert(IsValidImageIndex<VEH_ROAD>(spritenum));
117 result->Set(DIR_W + _roadveh_images[spritenum]);
118}
119
120void RoadVehicle::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
121{
122 uint8_t spritenum = this->spritenum;
123
124 if (is_custom_sprite(spritenum)) {
125 GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
126 if (result->IsValid()) return;
127
129 }
130
131 assert(IsValidImageIndex<VEH_ROAD>(spritenum));
132 SpriteID sprite = direction + _roadveh_images[spritenum];
133
134 if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
135
136 result->Set(sprite);
137}
138
148void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
149{
151 GetRoadVehIcon(engine, image_type, &seq);
152
153 Rect rect;
154 seq.GetBounds(&rect);
155 preferred_x = Clamp(preferred_x,
156 left - UnScaleGUI(rect.left),
157 right - UnScaleGUI(rect.right));
158
159 seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
160}
161
171void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
172{
174 GetRoadVehIcon(engine, image_type, &seq);
175
176 Rect rect;
177 seq.GetBounds(&rect);
178
179 width = UnScaleGUI(rect.Width());
180 height = UnScaleGUI(rect.Height());
181 xoffs = UnScaleGUI(rect.left);
182 yoffs = UnScaleGUI(rect.top);
183}
184
190static uint GetRoadVehLength(const RoadVehicle *v)
191{
192 const Engine *e = v->GetEngine();
193 uint length = VEHICLE_LENGTH;
194
195 uint16_t veh_len = CALLBACK_FAILED;
196 if (e->GetGRF() != nullptr && e->GetGRF()->grf_version >= 8) {
197 /* Use callback 36 */
198 veh_len = GetVehicleProperty(v, PROP_ROADVEH_SHORTEN_FACTOR, CALLBACK_FAILED);
199 if (veh_len != CALLBACK_FAILED && veh_len >= VEHICLE_LENGTH) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_LENGTH, veh_len);
200 } else {
201 /* Use callback 11 */
202 veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
203 }
204 if (veh_len == CALLBACK_FAILED) veh_len = e->u.road.shorten_factor;
205 if (veh_len != 0) {
206 length -= Clamp(veh_len, 0, VEHICLE_LENGTH - 1);
207 }
208
209 return length;
210}
211
218void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
219{
220 assert(v->type == VEH_ROAD);
221 assert(v->IsFrontEngine());
222
224
226
227 for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
228 /* Check the v->first cache. */
229 assert(u->First() == v);
230
231 /* Update the 'first engine' */
232 u->gcache.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
233
234 /* Update the length of the vehicle. */
235 uint veh_len = GetRoadVehLength(u);
236 /* Verify length hasn't changed. */
237 if (same_length && veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
238
239 u->gcache.cached_veh_length = veh_len;
240 v->gcache.cached_total_length += u->gcache.cached_veh_length;
241
242 /* Update visual effect */
243 u->UpdateVisualEffect();
244
245 /* Update cargo aging period. */
246 u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_ROADVEH_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
247 }
248
249 uint max_speed = GetVehicleProperty(v, PROP_ROADVEH_SPEED, 0);
250 v->vcache.cached_max_speed = (max_speed != 0) ? max_speed * 4 : RoadVehInfo(v->engine_type)->max_speed;
251}
252
262{
263 /* Check that the vehicle can drive on the road in question */
264 RoadType rt = e->u.road.roadtype;
265 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
266 if (!HasTileAnyRoadType(tile, rti->powered_roadtypes)) return CommandCost(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
267
268 if (flags & DC_EXEC) {
269 const RoadVehicleInfo *rvi = &e->u.road;
270
271 RoadVehicle *v = new RoadVehicle();
272 *ret = v;
275
276 v->tile = tile;
277 int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
278 int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
279 v->x_pos = x;
280 v->y_pos = y;
281 v->z_pos = GetSlopePixelZ(x, y, true);
282
283 v->state = RVSB_IN_DEPOT;
285
286 v->spritenum = rvi->image_index;
288 assert(IsValidCargoType(v->cargo_type));
289 v->cargo_cap = rvi->capacity;
290 v->refit_cap = 0;
291
292 v->last_station_visited = INVALID_STATION;
293 v->last_loading_station = INVALID_STATION;
294 v->engine_type = e->index;
295 v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
296
297 v->reliability = e->reliability;
300
301 v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh);
302
306
307 v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
308 v->random_bits = Random();
309 v->SetFrontEngine();
310
311 v->roadtype = rt;
314
316 v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
317
320
321 /* Call various callbacks after the whole consist has been constructed */
322 for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
323 u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
324 u->refit_cap = 0;
326 u->InvalidateNewGRFCache();
327 }
329 /* Initialize cached values for realistic acceleration. */
331
332 v->UpdatePosition();
333
335 }
336
337 return CommandCost();
338}
339
340static FindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance)
341{
342 if (IsRoadDepotTile(v->tile)) return FindDepotData(v->tile, 0);
343
344 return YapfRoadVehicleFindNearestDepot(v, max_distance);
345}
346
348{
349 FindDepotData rfdd = FindClosestRoadDepot(this, 0);
350 if (rfdd.best_length == UINT_MAX) return ClosestDepot();
351
352 return ClosestDepot(rfdd.tile, GetDepotIndex(rfdd.tile));
353}
354
362{
364 if (v == nullptr) return CMD_ERROR;
365
366 if (!v->IsPrimaryVehicle()) return CMD_ERROR;
367
369 if (ret.Failed()) return ret;
370
371 if ((v->vehstatus & VS_STOPPED) ||
372 (v->vehstatus & VS_CRASHED) ||
373 v->breakdown_ctr != 0 ||
374 v->overtaking != 0 ||
375 v->state == RVSB_WORMHOLE ||
376 v->IsInDepot() ||
377 v->current_order.IsType(OT_LOADING)) {
378 return CMD_ERROR;
379 }
380
382
384
385 if (flags & DC_EXEC) {
386 v->reverse_ctr = 180;
387
388 /* Unbunching data is no longer valid. */
390 }
391
392 return CommandCost();
393}
394
395
397{
398 for (RoadVehicle *v = this; v != nullptr; v = v->Next()) {
399 v->colourmap = PAL_NONE;
400 v->UpdateViewport(true, false);
401 }
402 this->CargoChanged();
403}
404
406{
407 static const int8_t _delta_xy_table[8][10] = {
408 /* y_extent, x_extent, y_offs, x_offs, y_bb_offs, x_bb_offs, y_extent_shorten, x_extent_shorten, y_bb_offs_shorten, x_bb_offs_shorten */
409 {3, 3, -1, -1, 0, 0, -1, -1, -1, -1}, // N
410 {3, 7, -1, -3, 0, -1, 0, -1, 0, 0}, // NE
411 {3, 3, -1, -1, 0, 0, 1, -1, 1, -1}, // E
412 {7, 3, -3, -1, -1, 0, 0, 0, 1, 0}, // SE
413 {3, 3, -1, -1, 0, 0, 1, 1, 1, 1}, // S
414 {3, 7, -1, -3, 0, -1, 0, 0, 0, 1}, // SW
415 {3, 3, -1, -1, 0, 0, -1, 1, -1, 1}, // W
416 {7, 3, -3, -1, -1, 0, -1, 0, 0, 0}, // NW
417 };
418
419 int shorten = VEHICLE_LENGTH - this->gcache.cached_veh_length;
420 if (!IsDiagonalDirection(this->direction)) shorten >>= 1;
421
422 const int8_t *bb = _delta_xy_table[this->direction];
423 this->x_bb_offs = bb[5] + bb[9] * shorten;
424 this->y_bb_offs = bb[4] + bb[8] * shorten;;
425 this->x_offs = bb[3];
426 this->y_offs = bb[2];
427 this->x_extent = bb[1] + bb[7] * shorten;
428 this->y_extent = bb[0] + bb[6] * shorten;
429 this->z_extent = 6;
430}
431
437{
438 int max_speed = this->gcache.cached_max_track_speed;
439
440 /* Limit speed to 50% while reversing, 75% in curves. */
441 for (const RoadVehicle *u = this; u != nullptr; u = u->Next()) {
444 max_speed = this->gcache.cached_max_track_speed / 2;
445 break;
446 } else if ((u->direction & 1) == 0) {
447 max_speed = this->gcache.cached_max_track_speed * 3 / 4;
448 }
449 }
450
451 /* Vehicle is on the middle part of a bridge. */
452 if (u->state == RVSB_WORMHOLE && !(u->vehstatus & VS_HIDDEN)) {
453 max_speed = std::min(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed * 2);
454 }
455 }
456
457 return std::min(max_speed, this->current_order.GetMaxSpeed() * 2);
458}
459
465{
466 RoadVehicle *first = v->First();
467 Vehicle *u = v;
468 for (; v->Next() != nullptr; v = v->Next()) u = v;
469 u->SetNext(nullptr);
470 v->last_station_visited = first->last_station_visited; // for PreDestructor
471
472 /* Only leave the road stop when we're really gone. */
473 if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
474
475 delete v;
476}
477
478static void RoadVehSetRandomDirection(RoadVehicle *v)
479{
480 static const DirDiff delta[] = {
482 };
483
484 do {
485 uint32_t r = Random();
486
487 v->direction = ChangeDir(v->direction, delta[r & 3]);
488 v->UpdateViewport(true, true);
489 } while ((v = v->Next()) != nullptr);
490}
491
498{
499 v->crashed_ctr++;
500 if (v->crashed_ctr == 2) {
502 } else if (v->crashed_ctr <= 45) {
503 if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
504 } else if (v->crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
505 bool ret = v->Next() != nullptr;
507 return ret;
508 }
509
510 return true;
511}
512
520{
521 const Vehicle *u = (Vehicle*)data;
522
523 return (v->type == VEH_TRAIN &&
524 abs(v->z_pos - u->z_pos) <= 6 &&
525 abs(v->x_pos - u->x_pos) <= 4 &&
526 abs(v->y_pos - u->y_pos) <= 4) ? v : nullptr;
527}
528
529uint RoadVehicle::Crash(bool flooded)
530{
531 uint victims = this->GroundVehicleBase::Crash(flooded);
532 if (this->IsFrontEngine()) {
533 victims += 1; // driver
534
535 /* If we're in a drive through road stop we ought to leave it */
536 if (IsInsideMM(this->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
537 RoadStop::GetByTile(this->tile, GetRoadStopType(this->tile))->Leave(this);
538 }
539 }
540 this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
541 return victims;
542}
543
544static void RoadVehCrash(RoadVehicle *v)
545{
546 uint victims = v->Crash();
547
548 AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
549 Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
550
551 SetDParam(0, victims);
552 StringID newsitem = (victims == 1) ? STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH;
553 NewsType newstype = NT_ACCIDENT;
554
555 if (v->owner != _local_company) {
556 newstype = NT_ACCIDENT_OTHER;
557 }
558
559 AddTileNewsItem(newsitem, newstype, v->tile);
560
561 ModifyStationRatingAround(v->tile, v->owner, -160, 22);
562 if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
563}
564
565static bool RoadVehCheckTrainCrash(RoadVehicle *v)
566{
567 for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
568 if (u->state == RVSB_WORMHOLE) continue;
569
570 TileIndex tile = u->tile;
571
572 if (!IsLevelCrossingTile(tile)) continue;
573
575 RoadVehCrash(v);
576 return true;
577 }
578 }
579
580 return false;
581}
582
584{
585 if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
586
587 const Station *st = Station::Get(station);
588 if (!CanVehicleUseStation(this, st)) {
589 /* There is no stop left at the station, so don't even TRY to go there */
591 return TileIndex{};
592 }
593
594 return st->xy;
595}
596
597static void StartRoadVehSound(const RoadVehicle *v)
598{
599 if (!PlayVehicleSound(v, VSE_START)) {
600 SoundID s = RoadVehInfo(v->engine_type)->sfx;
601 if (s == SND_19_DEPARTURE_OLD_RV_1 && (v->tick_counter & 3) == 0) {
603 }
604 SndPlayVehicleFx(s, v);
605 }
606}
607
609 int x;
610 int y;
611 const Vehicle *veh;
612 Vehicle *best;
613 uint best_diff;
614 Direction dir;
615};
616
617static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
618{
619 static const int8_t dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
620 static const int8_t dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
621
622 RoadVehFindData *rvf = (RoadVehFindData*)data;
623
624 short x_diff = v->x_pos - rvf->x;
625 short y_diff = v->y_pos - rvf->y;
626
627 if (v->type == VEH_ROAD &&
628 !v->IsInDepot() &&
629 abs(v->z_pos - rvf->veh->z_pos) < 6 &&
630 v->direction == rvf->dir &&
631 rvf->veh->First() != v->First() &&
632 (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
633 (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
634 (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
635 (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0))) {
636 uint diff = abs(x_diff) + abs(y_diff);
637
638 if (diff < rvf->best_diff || (diff == rvf->best_diff && v->index < rvf->best->index)) {
639 rvf->best = v;
640 rvf->best_diff = diff;
641 }
642 }
643
644 return nullptr;
645}
646
647static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction dir, bool update_blocked_ctr = true)
648{
649 RoadVehFindData rvf;
650 RoadVehicle *front = v->First();
651
652 if (front->reverse_ctr != 0) return nullptr;
653
654 rvf.x = x;
655 rvf.y = y;
656 rvf.dir = dir;
657 rvf.veh = v;
658 rvf.best_diff = UINT_MAX;
659
660 if (front->state == RVSB_WORMHOLE) {
661 FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
662 FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
663 } else {
664 FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
665 }
666
667 /* This code protects a roadvehicle from being blocked for ever
668 * If more than 1480 / 74 days a road vehicle is blocked, it will
669 * drive just through it. The ultimate backup-code of TTD.
670 * It can be disabled. */
671 if (rvf.best_diff == UINT_MAX) {
672 front->blocked_ctr = 0;
673 return nullptr;
674 }
675
676 if (update_blocked_ctr && ++front->blocked_ctr > 1480) return nullptr;
677
678 return RoadVehicle::From(rvf.best);
679}
680
686static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
687{
688 if (v->IsBus()) {
689 /* Check if station was ever visited before */
690 if (!(st->had_vehicle_of_type & HVOT_BUS)) {
691 st->had_vehicle_of_type |= HVOT_BUS;
692 SetDParam(0, st->index);
694 RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
696 v->index,
697 st->index
698 );
699 AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
700 Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
701 }
702 } else {
703 /* Check if station was ever visited before */
704 if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
705 st->had_vehicle_of_type |= HVOT_TRUCK;
706 SetDParam(0, st->index);
708 RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
710 v->index,
711 st->index
712 );
713 AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
714 Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
715 }
716 }
717}
718
727{
729 default: NOT_REACHED();
730 case AM_ORIGINAL:
731 return this->DoUpdateSpeed(this->overtaking != 0 ? 512 : 256, 0, this->GetCurrentMaxSpeed());
732
733 case AM_REALISTIC:
734 return this->DoUpdateSpeed(this->GetAcceleration() + (this->overtaking != 0 ? 256 : 0), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 4, this->GetCurrentMaxSpeed());
735 }
736}
737
738static Direction RoadVehGetNewDirection(const RoadVehicle *v, int x, int y)
739{
740 static const Direction _roadveh_new_dir[] = {
744 };
745
746 x = x - v->x_pos + 1;
747 y = y - v->y_pos + 1;
748
749 if ((uint)x > 2 || (uint)y > 2) return v->direction;
750 return _roadveh_new_dir[y * 4 + x];
751}
752
753static Direction RoadVehGetSlidingDirection(const RoadVehicle *v, int x, int y)
754{
755 Direction new_dir = RoadVehGetNewDirection(v, x, y);
756 Direction old_dir = v->direction;
757 DirDiff delta;
758
759 if (new_dir == old_dir) return old_dir;
760 delta = (DirDifference(new_dir, old_dir) > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
761 return ChangeDir(old_dir, delta);
762}
763
765 const RoadVehicle *u;
766 const RoadVehicle *v;
767 TileIndex tile;
768 Trackdir trackdir;
769};
770
771static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
772{
773 const OvertakeData *od = (OvertakeData*)data;
774
775 return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : nullptr;
776}
777
785{
786 if (!HasTileAnyRoadType(od->tile, od->v->compatible_roadtypes)) return true;
787 TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, GetRoadTramType(od->v->roadtype));
788 TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
789 TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
790 TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
791
792 /* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
793 if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
794
795 /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
796 return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
797}
798
799static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
800{
801 OvertakeData od;
802
803 od.v = v;
804 od.u = u;
805
806 /* Trams can't overtake other trams */
807 if (RoadTypeIsTram(v->roadtype)) return;
808
809 /* Don't overtake in stations */
810 if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
811
812 /* For now, articulated road vehicles can't overtake anything. */
813 if (v->HasArticulatedPart()) return;
814
815 /* Vehicles are not driving in same direction || direction is not a diagonal direction */
816 if (v->direction != u->direction || !(v->direction & 1)) return;
817
818 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
820
821 /* Can't overtake a vehicle that is moving faster than us. If the vehicle in front is
822 * accelerating, take the maximum speed for the comparison, else the current speed.
823 * Original acceleration always accelerates, so always use the maximum speed. */
824 int u_speed = (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL || u->GetAcceleration() > 0) ? u->GetCurrentMaxSpeed() : u->cur_speed;
825 if (u_speed >= v->GetCurrentMaxSpeed() &&
826 !(u->vehstatus & VS_STOPPED) &&
827 u->cur_speed != 0) {
828 return;
829 }
830
832
833 /* Are the current and the next tile suitable for overtaking?
834 * - Does the track continue along od.trackdir
835 * - No junctions
836 * - No barred levelcrossing
837 * - No other vehicles in the way
838 */
839 od.tile = v->tile;
840 if (CheckRoadBlockedForOvertaking(&od)) return;
841
842 od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
843 if (CheckRoadBlockedForOvertaking(&od)) return;
844
845 /* When the vehicle in front of us is stopped we may only take
846 * half the time to pass it than when the vehicle is moving. */
847 v->overtaking_ctr = (od.u->cur_speed == 0 || (od.u->vehstatus & VS_STOPPED)) ? RV_OVERTAKE_TIMEOUT / 2 : 0;
849}
850
851static void RoadZPosAffectSpeed(RoadVehicle *v, int old_z)
852{
853 if (old_z == v->z_pos || _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) return;
854
855 if (old_z < v->z_pos) {
856 v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
857 } else {
858 uint16_t spd = v->cur_speed + 2;
859 if (spd <= v->gcache.cached_max_track_speed) v->cur_speed = spd;
860 }
861}
862
863static int PickRandomBit(uint bits)
864{
865 uint i;
866 uint num = RandomRange(CountBits(bits));
867
868 for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
869 return i;
870}
871
881{
882#define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
883
884 TileIndex desttile;
885 Trackdir best_track;
886 bool path_found = true;
887
888 TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype));
889 TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
891
892 if (IsTileType(tile, MP_ROAD)) {
893 if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) {
894 /* Road depot owned by another company or with the wrong orientation */
895 trackdirs = TRACKDIR_BIT_NONE;
896 }
897 } else if (IsTileType(tile, MP_STATION) && IsBayRoadStopTile(tile)) {
898 /* Standard road stop (drive-through stops are treated as normal road) */
899
900 if (!IsTileOwner(tile, v->owner) || GetBayRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
901 /* different station owner or wrong orientation or the vehicle has articulated parts */
902 trackdirs = TRACKDIR_BIT_NONE;
903 } else {
904 /* Our station */
906
907 if (GetRoadStopType(tile) != rstype) {
908 /* Wrong station type */
909 trackdirs = TRACKDIR_BIT_NONE;
910 } else {
911 /* Proper station type, check if there is free loading bay */
913 !RoadStop::GetByTile(tile, rstype)->HasFreeBay()) {
914 /* Station is full and RV queuing is off */
915 trackdirs = TRACKDIR_BIT_NONE;
916 }
917 }
918 }
919 }
920 /* The above lookups should be moved to GetTileTrackStatus in the
921 * future, but that requires more changes to the pathfinder and other
922 * stuff, probably even more arguments to GTTS.
923 */
924
925 /* Remove tracks unreachable from the enter dir */
926 trackdirs &= DiagdirReachesTrackdirs(enterdir);
927 if (trackdirs == TRACKDIR_BIT_NONE) {
928 /* If vehicle expected a path, it no longer exists, so invalidate it. */
929 if (!v->path.empty()) v->path.clear();
930 /* No reachable tracks, so we'll reverse */
931 return_track(_road_reverse_table[enterdir]);
932 }
933
934 if (v->reverse_ctr != 0) {
935 bool reverse = true;
936 if (RoadTypeIsTram(v->roadtype)) {
937 /* Trams may only reverse on a tile if it contains at least the straight
938 * trackbits or when it is a valid turning tile (i.e. one roadbit) */
939 RoadBits rb = GetAnyRoadBits(tile, RTT_TRAM);
940 RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
941 reverse = ((rb & straight) == straight) ||
942 (rb == DiagDirToRoadBits(enterdir));
943 }
944 if (reverse) {
945 v->reverse_ctr = 0;
946 if (v->tile != tile) {
947 return_track(_road_reverse_table[enterdir]);
948 }
949 }
950 }
951
952 desttile = v->dest_tile;
953 if (desttile == 0) {
954 /* We've got no destination, pick a random track */
955 return_track(PickRandomBit(trackdirs));
956 }
957
958 /* Only one track to choose between? */
959 if (KillFirstBit(trackdirs) == TRACKDIR_BIT_NONE) {
960 if (!v->path.empty() && v->path.back().tile == tile) {
961 /* Vehicle expected a choice here, invalidate its path. */
962 v->path.clear();
963 }
964 return_track(FindFirstBit(trackdirs));
965 }
966
967 /* Attempt to follow cached path. */
968 if (!v->path.empty()) {
969 if (v->path.back().tile != tile) {
970 /* Vehicle didn't expect a choice here, invalidate its path. */
971 v->path.clear();
972 } else {
973 Trackdir trackdir = v->path.back().trackdir;
974
975 if (HasBit(trackdirs, trackdir)) {
976 v->path.pop_back();
977 return_track(trackdir);
978 }
979
980 /* Vehicle expected a choice which is no longer available. */
981 v->path.clear();
982 }
983 }
984
985 best_track = YapfRoadVehicleChooseTrack(v, tile, enterdir, trackdirs, path_found, v->path);
986
987 v->HandlePathfindingResult(path_found);
988
989found_best_track:;
990
991 if (HasBit(red_signals, best_track)) return INVALID_TRACKDIR;
992
993 return best_track;
994}
995
997 uint8_t x, y;
998};
999
1000#include "table/roadveh_movement.h"
1001
1002bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
1003{
1004 /* Don't leave unless v and following wagons are in the depot. */
1005 for (const RoadVehicle *u = v; u != nullptr; u = u->Next()) {
1006 if (u->state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
1007 }
1008
1010 v->direction = DiagDirToDir(dir);
1011
1012 Trackdir tdir = DiagDirToDiagTrackdir(dir);
1013 const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
1014
1015 int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
1016 int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
1017
1018 if (first) {
1019 /* We are leaving a depot, but have to go to the exact same one; re-enter */
1020 if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
1022 return true;
1023 }
1024
1025 if (RoadVehFindCloseTo(v, x, y, v->direction, false) != nullptr) return true;
1026
1029
1030 StartRoadVehSound(v);
1031
1032 /* Vehicle is about to leave a depot */
1033 v->cur_speed = 0;
1034 }
1035
1036 v->vehstatus &= ~VS_HIDDEN;
1037 v->state = tdir;
1038 v->frame = RVC_DEPOT_START_FRAME;
1039
1040 v->x_pos = x;
1041 v->y_pos = y;
1042 v->UpdatePosition();
1043 v->UpdateInclination(true, true);
1044
1046
1047 return true;
1048}
1049
1050static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
1051{
1052 if (prev->tile == v->tile && !already_reversed) {
1053 /* If the previous vehicle is on the same tile as this vehicle is
1054 * then it must have reversed. */
1055 return _road_reverse_table[entry_dir];
1056 }
1057
1058 uint8_t prev_state = prev->state;
1059 Trackdir dir;
1060
1061 if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
1062 DiagDirection diag_dir = INVALID_DIAGDIR;
1063
1064 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1065 diag_dir = GetTunnelBridgeDirection(tile);
1066 } else if (IsRoadDepotTile(tile)) {
1067 diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
1068 }
1069
1070 if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
1071 dir = DiagDirToDiagTrackdir(diag_dir);
1072 } else {
1073 if (already_reversed && prev->tile != tile) {
1074 /*
1075 * The vehicle has reversed, but did not go straight back.
1076 * It immediately turn onto another tile. This means that
1077 * the roadstate of the previous vehicle cannot be used
1078 * as the direction we have to go with this vehicle.
1079 *
1080 * Next table is build in the following way:
1081 * - first row for when the vehicle in front went to the northern or
1082 * western tile, second for southern and eastern.
1083 * - columns represent the entry direction.
1084 * - cell values are determined by the Trackdir one has to take from
1085 * the entry dir (column) to the tile in north or south by only
1086 * going over the trackdirs used for turning 90 degrees, i.e.
1087 * TRACKDIR_{UPPER,RIGHT,LOWER,LEFT}_{N,E,S,W}.
1088 */
1089 static const Trackdir reversed_turn_lookup[2][DIAGDIR_END] = {
1092 dir = reversed_turn_lookup[prev->tile < tile ? 0 : 1][ReverseDiagDir(entry_dir)];
1093 } else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
1094 dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
1095 } else if (prev_state < TRACKDIR_END) {
1096 dir = (Trackdir)prev_state;
1097 } else {
1098 return INVALID_TRACKDIR;
1099 }
1100 }
1101
1102 /* Do some sanity checking. */
1103 static const RoadBits required_roadbits[] = {
1106 };
1107 RoadBits required = required_roadbits[dir & 0x07];
1108
1109 if ((required & GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true)) == ROAD_NONE) {
1110 dir = INVALID_TRACKDIR;
1111 }
1112
1113 return dir;
1114}
1115
1125{
1126 /* The 'current' company is not necessarily the owner of the vehicle. */
1127 Backup<CompanyID> cur_company(_current_company, c);
1128
1129 CommandCost ret = Command<CMD_BUILD_ROAD>::Do(DC_NO_WATER, t, r, rt, DRD_NONE, INVALID_TOWN);
1130
1131 cur_company.Restore();
1132 return ret.Succeeded();
1133}
1134
1135bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
1136{
1137 if (v->overtaking != 0) {
1138 if (IsTileType(v->tile, MP_STATION)) {
1139 /* Force us to be not overtaking! */
1140 v->overtaking = 0;
1141 } else if (++v->overtaking_ctr >= RV_OVERTAKE_TIMEOUT) {
1142 /* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
1143 * if the vehicle started a corner. To protect that, only allow an abort of
1144 * overtake if we are on straight roads */
1146 v->overtaking = 0;
1147 }
1148 }
1149 }
1150
1151 /* If this vehicle is in a depot and we've reached this point it must be
1152 * one of the articulated parts. It will stay in the depot until activated
1153 * by the previous vehicle in the chain when it gets to the right place. */
1154 if (v->IsInDepot()) return true;
1155
1156 if (v->state == RVSB_WORMHOLE) {
1157 /* Vehicle is entering a depot or is on a bridge or in a tunnel */
1159
1160 if (v->IsFrontEngine()) {
1161 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
1162 if (u != nullptr) {
1163 v->cur_speed = u->First()->cur_speed;
1164 return false;
1165 }
1166 }
1167
1169 /* Vehicle has just entered a bridge or tunnel */
1170 v->x_pos = gp.x;
1171 v->y_pos = gp.y;
1172 v->UpdatePosition();
1173 v->UpdateInclination(true, true);
1174 return true;
1175 }
1176
1177 v->x_pos = gp.x;
1178 v->y_pos = gp.y;
1179 v->UpdatePosition();
1180 if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
1181 return true;
1182 }
1183
1184 /* Get move position data for next frame.
1185 * For a drive-through road stop use 'straight road' move data.
1186 * In this case v->state is masked to give the road stop entry direction. */
1187 RoadDriveEntry rd = _road_drive_data[GetRoadTramType(v->roadtype)][(
1189 (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
1190
1191 if (rd.x & RDE_NEXT_TILE) {
1192 TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
1193 Trackdir dir;
1194
1195 if (v->IsFrontEngine()) {
1196 /* If this is the front engine, look for the right path. */
1198 dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
1199 } else {
1200 dir = _road_reverse_table[(DiagDirection)(rd.x & 3)];
1201 }
1202 } else {
1203 dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
1204 }
1205
1206 if (dir == INVALID_TRACKDIR) {
1207 if (!v->IsFrontEngine()) FatalError("Disconnecting road vehicle.");
1208 v->cur_speed = 0;
1209 return false;
1210 }
1211
1212again:
1213 uint start_frame = RVC_DEFAULT_START_FRAME;
1214 if (IsReversingRoadTrackdir(dir)) {
1215 /* When turning around we can't be overtaking. */
1216 v->overtaking = 0;
1217
1218 /* Turning around */
1219 if (RoadTypeIsTram(v->roadtype)) {
1220 /* Determine the road bits the tram needs to be able to turn around
1221 * using the 'big' corner loop. */
1222 RoadBits needed;
1223 switch (dir) {
1224 default: NOT_REACHED();
1225 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
1226 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
1227 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
1228 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
1229 }
1230 if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
1231 (v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
1233 (needed & GetRoadBits(tile, RTT_TRAM)) != ROAD_NONE)) {
1234 /*
1235 * Taking the 'big' corner for trams only happens when:
1236 * - The previous vehicle in this (articulated) tram chain is
1237 * already on the 'next' tile, we just follow them regardless of
1238 * anything. When it is NOT on the 'next' tile, the tram started
1239 * doing a reversing turn when the piece of tram track on the next
1240 * tile did not exist yet. Do not use the big tram loop as that is
1241 * going to cause the tram to split up.
1242 * - Or the front of the tram can drive over the next tile.
1243 */
1244 } else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RTT_TRAM, false)) == ROAD_NONE)) {
1245 /*
1246 * Taking the 'small' corner for trams only happens when:
1247 * - We are not the from vehicle of an articulated tram.
1248 * - Or when the company cannot build on the next tile.
1249 *
1250 * The 'small' corner means that the vehicle is on the end of a
1251 * tram track and needs to start turning there. To do this properly
1252 * the tram needs to start at an offset in the tram turning 'code'
1253 * for 'big' corners. It furthermore does not go to the next tile,
1254 * so that needs to be fixed too.
1255 */
1256 tile = v->tile;
1257 start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
1258 } else {
1259 /* The company can build on the next tile, so wait till they do. */
1260 v->cur_speed = 0;
1261 return false;
1262 }
1264 v->cur_speed = 0;
1265 return false;
1266 } else {
1267 tile = v->tile;
1268 }
1269 }
1270
1271 /* Get position data for first frame on the new tile */
1272 const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
1273
1274 int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
1275 int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
1276
1277 Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1278 if (v->IsFrontEngine()) {
1279 const Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1280 if (u != nullptr) {
1281 v->cur_speed = u->First()->cur_speed;
1282 /* We might be blocked, prevent pathfinding rerun as we already know where we are heading to. */
1283 v->path.emplace_back(dir, tile);
1284 return false;
1285 }
1286 }
1287
1288 uint32_t r = VehicleEnterTile(v, tile, x, y);
1289 if (HasBit(r, VETS_CANNOT_ENTER)) {
1290 if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
1291 v->cur_speed = 0;
1292 return false;
1293 }
1294 /* Try an about turn to re-enter the previous tile */
1295 dir = _road_reverse_table[rd.x & 3];
1296 goto again;
1297 }
1298
1299 if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
1300 if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
1301 /* New direction is trying to turn vehicle around.
1302 * We can't turn at the exit of a road stop so wait.*/
1303 v->cur_speed = 0;
1304 return false;
1305 }
1306
1307 /* If we are a drive through road stop and the next tile is of
1308 * the same road stop and the next tile isn't this one (i.e. we
1309 * are not reversing), then keep the reservation and state.
1310 * This way we will not be shortly unregister from the road
1311 * stop. It also makes it possible to load when on the edge of
1312 * two road stops; otherwise you could get vehicles that should
1313 * be loading but are not actually loading. */
1314 if (IsDriveThroughStopTile(v->tile) &&
1316 v->tile != tile) {
1317 /* So, keep 'our' state */
1318 dir = (Trackdir)v->state;
1319 } else if (IsStationRoadStop(v->tile)) {
1320 /* We're not continuing our drive through road stop, so leave. */
1322 }
1323 }
1324
1325 if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
1326 TileIndex old_tile = v->tile;
1327
1328 v->tile = tile;
1329 v->state = (uint8_t)dir;
1330 v->frame = start_frame;
1331 RoadTramType rtt = GetRoadTramType(v->roadtype);
1332 if (GetRoadType(old_tile, rtt) != GetRoadType(tile, rtt)) {
1333 if (v->IsFrontEngine()) {
1335 }
1336 v->First()->CargoChanged();
1337 }
1338 }
1339 if (new_dir != v->direction) {
1340 v->direction = new_dir;
1341 if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1342 }
1343 v->x_pos = x;
1344 v->y_pos = y;
1345 v->UpdatePosition();
1346 RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
1347 return true;
1348 }
1349
1350 if (rd.x & RDE_TURNED) {
1351 /* Vehicle has finished turning around, it will now head back onto the same tile */
1352 Trackdir dir;
1353 uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
1354
1355 if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RTT_TRAM, true))) {
1356 /*
1357 * The tram is turning around with one tram 'roadbit'. This means that
1358 * it is using the 'big' corner 'drive data'. However, to support the
1359 * trams to take a small corner, there is a 'turned' marker in the middle
1360 * of the turning 'drive data'. When the tram took the long corner, we
1361 * will still use the 'big' corner drive data, but we advance it one
1362 * frame. We furthermore set the driving direction so the turning is
1363 * going to be properly shown.
1364 */
1365 turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
1366 switch (rd.x & 0x3) {
1367 default: NOT_REACHED();
1368 case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
1369 case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
1370 case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
1371 case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
1372 }
1373 } else {
1374 if (v->IsFrontEngine()) {
1375 /* If this is the front engine, look for the right path. */
1376 dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
1377 } else {
1378 dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
1379 }
1380 }
1381
1382 if (dir == INVALID_TRACKDIR) {
1383 v->cur_speed = 0;
1384 return false;
1385 }
1386
1387 const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
1388
1389 int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
1390 int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
1391
1392 Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1393 if (v->IsFrontEngine()) {
1394 const Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1395 if (u != nullptr) {
1396 v->cur_speed = u->First()->cur_speed;
1397 /* We might be blocked, prevent pathfinding rerun as we already know where we are heading to. */
1398 v->path.emplace_back(dir, v->tile);
1399 return false;
1400 }
1401 }
1402
1403 uint32_t r = VehicleEnterTile(v, v->tile, x, y);
1404 if (HasBit(r, VETS_CANNOT_ENTER)) {
1405 v->cur_speed = 0;
1406 return false;
1407 }
1408
1409 v->state = dir;
1410 v->frame = turn_around_start_frame;
1411
1412 if (new_dir != v->direction) {
1413 v->direction = new_dir;
1414 if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1415 }
1416
1417 v->x_pos = x;
1418 v->y_pos = y;
1419 v->UpdatePosition();
1420 RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
1421 return true;
1422 }
1423
1424 /* This vehicle is not in a wormhole and it hasn't entered a new tile. If
1425 * it's on a depot tile, check if it's time to activate the next vehicle in
1426 * the chain yet. */
1427 if (v->Next() != nullptr && IsRoadDepotTile(v->tile)) {
1428 if (v->frame == v->gcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
1429 RoadVehLeaveDepot(v->Next(), false);
1430 }
1431 }
1432
1433 /* Calculate new position for the vehicle */
1434 int x = (v->x_pos & ~15) + (rd.x & 15);
1435 int y = (v->y_pos & ~15) + (rd.y & 15);
1436
1437 Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1438
1439 if (v->IsFrontEngine() && !IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
1440 /* Vehicle is not in a road stop.
1441 * Check for another vehicle to overtake */
1442 RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1443
1444 if (u != nullptr) {
1445 u = u->First();
1446 /* There is a vehicle in front overtake it if possible */
1447 if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
1448 if (v->overtaking == 0) v->cur_speed = u->cur_speed;
1449
1450 /* In case an RV is stopped in a road stop, why not try to load? */
1451 if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
1453 v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
1454 GetRoadStopType(v->tile) == (v->IsBus() ? RoadStopType::Bus : RoadStopType::Truck)) {
1456 v->last_station_visited = st->index;
1457 RoadVehArrivesAt(v, st);
1458 v->BeginLoading();
1459 }
1460 return false;
1461 }
1462 }
1463
1464 Direction old_dir = v->direction;
1465 if (new_dir != old_dir) {
1466 v->direction = new_dir;
1467 if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) v->cur_speed -= v->cur_speed >> 2;
1468
1469 /* Delay the vehicle in curves by making it require one additional frame per turning direction (two in total).
1470 * A vehicle has to spend at least 9 frames on a tile, so the following articulated part can follow.
1471 * (The following part may only be one tile behind, and the front part is moved before the following ones.)
1472 * The short (inner) curve has 8 frames, this elongates it to 10. */
1473 v->UpdateViewport(true, true);
1474 return true;
1475 }
1476
1477 /* If the vehicle is in a normal road stop and the frame equals the stop frame OR
1478 * if the vehicle is in a drive-through road stop and this is the destination station
1479 * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
1480 * (the station test and stop type test ensure that other vehicles, using the road stop as
1481 * a through route, do not stop) */
1482 if (v->IsFrontEngine() && ((IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
1484 (IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
1486 v->owner == GetTileOwner(v->tile) &&
1487 GetRoadStopType(v->tile) == (v->IsBus() ? RoadStopType::Bus : RoadStopType::Truck) &&
1488 v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
1489
1492
1493 /* Vehicle is at the stop position (at a bay) in a road stop.
1494 * Note, if vehicle is loading/unloading it has already been handled,
1495 * so if we get here the vehicle has just arrived or is just ready to leave. */
1496 if (!HasBit(v->state, RVS_ENTERED_STOP)) {
1497 /* Vehicle has arrived at a bay in a road stop */
1498
1499 if (IsDriveThroughStopTile(v->tile)) {
1500 TileIndex next_tile = TileAddByDir(v->tile, v->direction);
1501
1502 /* Check if next inline bay is free and has compatible road. */
1504 v->frame++;
1505 v->x_pos = x;
1506 v->y_pos = y;
1507 v->UpdatePosition();
1508 RoadZPosAffectSpeed(v, v->UpdateInclination(true, false));
1509 return true;
1510 }
1511 }
1512
1513 rs->SetEntranceBusy(false);
1515
1516 v->last_station_visited = st->index;
1517
1518 if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) {
1519 RoadVehArrivesAt(v, st);
1520 v->BeginLoading();
1521 return false;
1522 }
1523 } else {
1524 /* Vehicle is ready to leave a bay in a road stop */
1525 if (rs->IsEntranceBusy()) {
1526 /* Road stop entrance is busy, so wait as there is nowhere else to go */
1527 v->cur_speed = 0;
1528 return false;
1529 }
1530 if (v->current_order.IsType(OT_LEAVESTATION)) v->current_order.Free();
1531 }
1532
1533 if (IsBayRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
1534
1535 StartRoadVehSound(v);
1537 }
1538
1539 /* Check tile position conditions - i.e. stop position in depot,
1540 * entry onto bridge or into tunnel */
1541 uint32_t r = VehicleEnterTile(v, v->tile, x, y);
1542 if (HasBit(r, VETS_CANNOT_ENTER)) {
1543 v->cur_speed = 0;
1544 return false;
1545 }
1546
1547 if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
1548 v->current_order.Free();
1549 }
1550
1551 /* Move to next frame unless vehicle arrived at a stop position
1552 * in a depot or entered a tunnel/bridge */
1553 if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
1554 v->x_pos = x;
1555 v->y_pos = y;
1556 v->UpdatePosition();
1557 RoadZPosAffectSpeed(v, v->UpdateInclination(false, true));
1558 return true;
1559}
1560
1561static bool RoadVehController(RoadVehicle *v)
1562{
1563 /* decrease counters */
1564 v->current_order_time++;
1565 if (v->reverse_ctr != 0) v->reverse_ctr--;
1566
1567 /* handle crashed */
1568 if (v->vehstatus & VS_CRASHED || RoadVehCheckTrainCrash(v)) {
1569 return RoadVehIsCrashed(v);
1570 }
1571
1572 /* road vehicle has broken down? */
1573 if (v->HandleBreakdown()) return true;
1574 if (v->vehstatus & VS_STOPPED) {
1575 v->SetLastSpeed();
1576 return true;
1577 }
1578
1579 ProcessOrders(v);
1580 v->HandleLoading();
1581
1582 if (v->current_order.IsType(OT_LOADING)) return true;
1583
1584 if (v->IsInDepot()) {
1585 /* Check if we should wait here for unbunching. */
1586 if (v->IsWaitingForUnbunching()) return true;
1587 if (RoadVehLeaveDepot(v, true)) return true;
1588 }
1589
1590 v->ShowVisualEffect();
1591
1592 /* Check how far the vehicle needs to proceed */
1593 int j = v->UpdateSpeed();
1594
1595 int adv_spd = v->GetAdvanceDistance();
1596 bool blocked = false;
1597 while (j >= adv_spd) {
1598 j -= adv_spd;
1599
1600 RoadVehicle *u = v;
1601 for (RoadVehicle *prev = nullptr; u != nullptr; prev = u, u = u->Next()) {
1602 if (!IndividualRoadVehicleController(u, prev)) {
1603 blocked = true;
1604 break;
1605 }
1606 }
1607 if (blocked) break;
1608
1609 /* Determine distance to next map position */
1610 adv_spd = v->GetAdvanceDistance();
1611
1612 /* Test for a collision, but only if another movement will occur. */
1613 if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
1614 }
1615
1616 v->SetLastSpeed();
1617
1618 for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
1619 if ((u->vehstatus & VS_HIDDEN) != 0) continue;
1620
1621 u->UpdateViewport(false, false);
1622 }
1623
1624 /* If movement is blocked, set 'progress' to its maximum, so the roadvehicle does
1625 * not accelerate again before it can actually move. I.e. make sure it tries to advance again
1626 * on next tick to discover whether it is still blocked. */
1627 if (v->progress == 0) v->progress = blocked ? adv_spd - 1 : j;
1628
1629 return true;
1630}
1631
1633{
1634 const Engine *e = this->GetEngine();
1635 if (e->u.road.running_cost_class == INVALID_PRICE) return 0;
1636
1637 uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->u.road.running_cost);
1638 if (cost_factor == 0) return 0;
1639
1640 return GetPrice(e->u.road.running_cost_class, cost_factor, e->GetGRF());
1641}
1642
1644{
1646
1647 this->tick_counter++;
1648
1649 if (this->IsFrontEngine()) {
1650 if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
1651 return RoadVehController(this);
1652 }
1653
1654 return true;
1655}
1656
1657void RoadVehicle::SetDestTile(TileIndex tile)
1658{
1659 if (tile == this->dest_tile) return;
1660 this->path.clear();
1661 this->dest_tile = tile;
1662}
1663
1664static void CheckIfRoadVehNeedsService(RoadVehicle *v)
1665{
1666 /* If we already got a slot at a stop, use that FIRST, and go to a depot later */
1667 if (Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
1668 if (v->IsChainInDepot()) {
1670 return;
1671 }
1672
1674
1675 FindDepotData rfdd = FindClosestRoadDepot(v, max_penalty);
1676 /* Only go to the depot if it is not too far out of our way. */
1677 if (rfdd.best_length == UINT_MAX || rfdd.best_length > max_penalty) {
1678 if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1679 /* If we were already heading for a depot but it has
1680 * suddenly moved farther away, we continue our normal
1681 * schedule? */
1684 }
1685 return;
1686 }
1687
1688 DepotID depot = GetDepotIndex(rfdd.tile);
1689
1690 if (v->current_order.IsType(OT_GOTO_DEPOT) &&
1692 !Chance16(1, 20)) {
1693 return;
1694 }
1695
1698 v->SetDestTile(rfdd.tile);
1700}
1701
1704{
1705 if (!this->IsFrontEngine()) return;
1706 AgeVehicle(this);
1707}
1708
1711{
1712 if (!this->IsFrontEngine()) return;
1713 EconomyAgeVehicle(this);
1714
1715 if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
1716 if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
1717
1718 CheckIfRoadVehNeedsService(this);
1719
1720 CheckOrders(this);
1721
1722 if (this->running_ticks == 0) return;
1723
1725
1726 this->profit_this_year -= cost.GetCost();
1727 this->running_ticks = 0;
1728
1730
1733}
1734
1736{
1737 if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
1738
1739 if (this->IsInDepot()) {
1740 /* We'll assume the road vehicle is facing outwards */
1741 return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
1742 }
1743
1744 if (IsBayRoadStopTile(this->tile)) {
1745 /* We'll assume the road vehicle is facing outwards */
1746 return DiagDirToDiagTrackdir(GetBayRoadStopDir(this->tile)); // Road vehicle in a station
1747 }
1748
1749 /* Drive through road stops / wormholes (tunnels) */
1751
1752 /* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
1753 * otherwise transform it into a valid track direction */
1754 return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
1755}
1756
1758{
1759 uint16_t weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnits(this->GetEngine()->DetermineCapacity(this));
1760
1761 /* Vehicle weight is not added for articulated parts. */
1762 if (!this->IsArticulatedPart()) {
1763 /* Road vehicle weight is in units of 1/4 t. */
1764 weight += GetVehicleProperty(this, PROP_ROADVEH_WEIGHT, RoadVehInfo(this->engine_type)->weight) / 4;
1765 }
1766
1767 return weight;
1768}
Base functions for all AIs.
void AddArticulatedParts(Vehicle *first)
Add the remaining articulated parts to the given vehicle.
void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
Checks whether the specs of freshly build articulated vehicles are consistent with the information sp...
Functions related to articulated vehicles.
Class for backupping variables and making sure they are restored later.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
constexpr T KillFirstBit(T value)
Clear the first bit in an integer.
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition bridge.h:67
BridgeType GetBridgeType(Tile t)
Determines the type of bridge on a tile.
Definition bridge_map.h:56
bool IsValidCargoType(CargoType t)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:105
bool IsCargoInClass(CargoType c, CargoClass cc)
Does cargo c have cargo class cc?
Definition cargotype.h:240
@ CC_PASSENGERS
Passengers.
Definition cargotype.h:51
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.
bool Succeeded() const
Did this command succeed?
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
constexpr bool Test(Tenum value) const
Test if the enum value is set.
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
RAII class for measuring multi-step elements of performance.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:112
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).
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_NO_WATER
don't allow building on water
@ DC_EXEC
execute the given command
Definition of stuff that is very close to a company, like the company struct itself.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
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.
Owner
Enum for all companies/owners.
Map related accessors for depots.
DepotID GetDepotIndex(Tile t)
Get the index of which depot is attached to the tile.
Definition depot_map.h:52
uint16_t DepotID
Type for the unique identifier of depots.
Definition depot_type.h:13
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 ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
bool IsDiagonalDirection(Direction dir)
Checks if a given Direction is diagonal.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a 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.
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.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition economy.cpp:966
@ EXPENSES_ROADVEH_RUN
Running costs road vehicles.
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
Functions related to effect vehicles.
@ EV_EXPLOSION_LARGE
Various explosions.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
uint16_t EngineID
Unique identification number of an engine.
Definition engine_type.h:23
@ ExclusivePreview
This vehicle is in the exclusive preview stage, either being used or being offered to a company.
Error reporting related functions.
fluid_settings_t * settings
FluidSynth settings handle.
Types for recording game performance data.
@ PFE_GL_ROADVEHS
Time spend processing road vehicles.
Base functions for all Games.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
@ AS_BRAKE
We want to stop.
@ GVF_SUPPRESS_IMPLICIT_ORDERS
Disable insertion and removal of automatic orders until the vehicle completes the real order.
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.
@ Random
Randomise borders.
TileIndex TileAddByDir(TileIndex tile, Direction dir)
Adds a Direction to a tile.
Definition map_func.h:599
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:570
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
Base for the NewGRF implementation.
@ CBID_VEHICLE_LENGTH
Vehicle length, returns the amount of 1/8's the vehicle is shorter for trains and RVs.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
@ PROP_ROADVEH_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_ROADVEH_WEIGHT
Weight in 1/4 t.
@ PROP_ROADVEH_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_ROADVEH_SHORTEN_FACTOR
Shorter vehicles.
@ PROP_ROADVEH_SPEED
Max. speed: 1 unit = 1/0.8 mph = 2 km-ish/h.
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
NewsType
Type of news.
Definition news_type.h:23
@ NT_ACCIDENT_OTHER
An accident or disaster has occurred.
Definition news_type.h:27
@ 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
@ NT_ACCIDENT
An accident or disaster has occurred.
Definition news_type.h:26
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
@ ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS
The vehicle will not stop at any stations it passes except the destination.
Definition order_type.h:74
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:217
Road related functions.
RoadBits AxisToRoadBits(Axis a)
Create the road-part which belongs to the given Axis.
Definition road_func.h:111
RoadBits DiagDirToRoadBits(DiagDirection d)
Create the road-part which belongs to the given DiagDirection.
Definition road_func.h:96
RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance)
Returns the RoadBits on an arbitrary tile Special behaviour:
Definition road_map.cpp:33
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:74
static debug_inline bool IsRoadDepot(Tile t)
Return whether a tile is a road depot.
Definition road_map.h:106
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition road_map.h:95
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:128
bool HasTileAnyRoadType(Tile t, RoadTypes rts)
Check if a tile has one of the specified road types.
Definition road_map.h:222
DisallowedRoadDirections GetDisallowedRoadDirections(Tile t)
Gets the disallowed directions.
Definition road_map.h:301
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition road_map.h:565
static debug_inline bool IsRoadDepotTile(Tile t)
Return whether a tile is a road depot tile.
Definition road_map.h:116
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition road_map.h:513
RoadBits
Enumeration for the road parts on a tile.
Definition road_type.h:52
@ ROAD_SW
South-west part.
Definition road_type.h:55
@ ROAD_NONE
No road-part is build.
Definition road_type.h:53
@ ROAD_NE
North-east part.
Definition road_type.h:57
@ ROAD_SE
South-east part.
Definition road_type.h:56
@ ROAD_Y
Full road along the y-axis (north-west + south-east)
Definition road_type.h:59
@ ROAD_NW
North-west part.
Definition road_type.h:54
@ ROAD_X
Full road along the x-axis (south-west + north-east)
Definition road_type.h:58
RoadType
The different roadtypes we support.
Definition road_type.h:25
@ DRD_NONE
None of the directions are disallowed.
Definition road_type.h:74
Base class for roadstops.
Road vehicle states.
@ RVSB_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition roadveh.h:51
@ RVS_ENTERED_STOP
Only set when a vehicle has entered the stop.
Definition roadveh.h:43
@ RVSB_IN_ROAD_STOP
The vehicle is in a road stop.
Definition roadveh.h:49
@ RVSB_ROAD_STOP_TRACKDIR_MASK
Only bits 0 and 3 are used to encode the trackdir for road stops.
Definition roadveh.h:57
@ RVS_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition roadveh.h:46
@ RVSB_TRACKDIR_MASK
The mask used to extract track dirs.
Definition roadveh.h:56
@ RVSB_DRIVE_SIDE
The vehicle is at the opposite side of the road.
Definition roadveh.h:54
@ RVSB_IN_DEPOT
The vehicle is in a depot.
Definition roadveh.h:38
@ RVSB_WORMHOLE
The vehicle is in a tunnel and/or bridge.
Definition roadveh.h:39
@ RVS_DRIVE_SIDE
Only used when retrieving move data.
Definition roadveh.h:44
static const uint RDE_TURNED
We just finished turning.
Definition roadveh.h:62
static const uint8_t RV_OVERTAKE_TIMEOUT
The number of ticks a vehicle has for overtaking.
Definition roadveh.h:79
static const uint RDE_NEXT_TILE
State information about the Road Vehicle controller.
Definition roadveh.h:61
static bool RoadVehIsCrashed(RoadVehicle *v)
Road vehicle chain has crashed.
static uint GetRoadVehLength(const RoadVehicle *v)
Get length of a road vehicle.
static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
A road vehicle arrives at a station.
static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
Check if overtaking is possible on a piece of track.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
Update the cache of a road vehicle.
static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadType rt, RoadBits r)
Can a tram track build without destruction on the given tile?
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a road vehicle sprite heading west (used for lists).
void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
Draw a road vehicle engine.
static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection enterdir)
Returns direction to for a road vehicle to take or INVALID_TRACKDIR if the direction is currently blo...
static void DeleteLastRoadVeh(RoadVehicle *v)
Delete last vehicle of a chain road vehicles.
CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a road vehicle.
static Vehicle * EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
Check routine whether a road and a train vehicle have collided.
CommandCost CmdTurnRoadVeh(DoCommandFlag flags, VehicleID veh_id)
Turn a roadvehicle around.
Command definitions related to road vehicles.
Data about how a road vehicle must drive on a tile.
const uint8_t _road_stop_stop_frame[]
Table of road stop stop frames, when to stop at a road stop.
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
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
Functions related to sound.
@ SND_19_DEPARTURE_OLD_RV_1
23 == 0x17 Station departure: truck and old bus (1) (non-toyland)
Definition sound_type.h:70
@ SND_12_EXPLOSION
16 == 0x10 Destruction, crashes, disasters, ...
Definition sound_type.h:63
@ SND_1A_DEPARTURE_OLD_RV_2
24 == 0x18 Station departure: truck and old bus (2) (random variation of SND_19_DEPARTURE_OLD_RV_1) (...
Definition sound_type.h:71
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.
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
bool IsDriveThroughStopTile(Tile t)
Is tile t a drive through road stop station or waypoint?
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
bool IsStationRoadStop(Tile t)
Is the station at t a road station?
DiagDirection GetBayRoadStopDir(Tile t)
Gets the direction the bay road stop entrance points towards.
RoadStopType GetRoadStopType(Tile t)
Get the road stop type of this tile.
Definition station_map.h:56
RoadStopType
Types of RoadStops.
@ Bus
A standard stop for buses.
@ Truck
A standard stop for trucks.
@ HVOT_TRUCK
Station has seen a truck.
@ HVOT_BUS
Station has seen a bus.
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:277
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.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Class to backup a specific variable and restore it later.
void Restore()
Restore the variable.
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 (.
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
TileIndex xy
Base tile of the station.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
VehicleType type
Type of vehicle.
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition bridge.h:48
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
Definition cargotype.h:140
SoundSettings sound
sound effect settings
Structure to return information about the closest depot location, and whether it could be found.
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the engine is tied to.
Definition engine.cpp:157
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition engine_base.h:49
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
EngineFlags flags
Flags of the engine.
Definition engine_base.h:56
uint8_t original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition engine_base.h:60
TimerGameCalendar::Date GetLifeLengthInDays() const
Returns the vehicle's (not model's!) life length in days.
Definition engine.cpp:443
CargoType GetDefaultCargoType() const
Determines the default cargo type of an engine.
uint16_t reliability
Current reliability of the engine.
Definition engine_base.h:48
Helper container to find a depot.
uint best_length
The distance towards the depot in penalty, or UINT_MAX if not found.
TileIndex tile
The tile of the depot.
PathfinderSettings pf
settings for all pathfinders
VehicleSettings vehicle
options for vehicles
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
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
uint16_t cached_total_length
Length of the whole vehicle (valid only for the first engine).
uint8_t cached_veh_length
Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can b...
uint16_t cached_max_track_speed
Maximum consist speed (in internal units) limited by track type (valid only for the first engine).
bool IsChainInDepot() const override
Check whether the whole vehicle chain is in the depot.
int UpdateInclination(bool new_tile, bool update_delta)
Checks if the vehicle is in a slope and sets the required flags in that case.
GroundVehicleCache gcache
Cache of often calculated values.
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
void SetFrontEngine()
Set front engine state.
uint Crash(bool flooded) override
Common code executed for crashed ground vehicles.
uint DoUpdateSpeed(uint accel, int min_speed, int max_speed)
Update the speed of the vehicle.
int GetAcceleration() const
Calculates the acceleration of the vehicle under its current conditions.
void SetLastSpeed()
Update the GUI variant of the current speed of the vehicle.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
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 MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoType cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition order_cmd.cpp:90
void MakeDummy()
Makes this order a Dummy order.
void Free()
'Free' the order
Definition order_cmd.cpp:63
bool ShouldStopAtStation(const Vehicle *v, StationID station) const
Check whether the given vehicle should stop at the given station based on this order and the non-stop...
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:140
YAPFSettings yapf
pathfinder settings for the yet another pathfinder
bool roadveh_queue
buggy road vehicle queueing
Coordinates of a point in 2D.
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.
A Stop for a Road Vehicle.
void SetEntranceBusy(bool busy)
Makes an entrance occupied or free.
void Leave(RoadVehicle *rv)
Leave the road stop.
Definition roadstop.cpp:214
bool IsEntranceBusy() const
Checks whether the entrance of the road stop is occupied by a vehicle.
static bool IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next)
Checks whether the 'next' tile is still part of the road same drive through stop 'rs' in the same dir...
Definition roadstop.cpp:303
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition roadstop.cpp:264
Information about a road vehicle.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
RoadType roadtype
Road type.
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
Buses, trucks and trams belong to this class.
Definition roadveh.h:98
uint Crash(bool flooded=false) override
Common code executed for crashed ground vehicles.
TileIndex GetOrderStationLocation(StationID station) override
Determine the location for the station where the vehicle goes to next.
void OnNewEconomyDay() override
Economy day handler.
uint8_t state
Definition roadveh.h:100
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a road vehicle image in the GUI.
Money GetRunningCost() const override
Gets the running cost of a vehicle.
bool IsPrimaryVehicle() const override
Whether this is the primary vehicle in the chain.
Definition roadveh.h:122
uint16_t GetMaxWeight() const override
Calculates the weight value that this vehicle will have when fully loaded with its current cargo.
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition roadveh.h:110
AccelStatus GetAccelerationStatus() const
Checks the current acceleration status of this vehicle.
Definition roadveh.h:223
void UpdateDeltaXY() override
Updates the x and y offsets and the size of the sprite used for this vehicle.
uint16_t crashed_ctr
Animation counter when the vehicle has crashed.
Definition roadveh.h:105
bool IsBus() const
Check whether a roadvehicle is a bus.
uint8_t overtaking_ctr
The length of the current overtake attempt.
Definition roadveh.h:104
void OnNewCalendarDay() override
Calandar day handler.
bool IsInDepot() const override
Check whether the vehicle is in the depot.
Definition roadveh.h:128
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override
Gets the sprite to show for the given direction.
RoadVehPathCache path
Cached path.
Definition roadveh.h:99
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
int GetCurrentMaxSpeed() const override
Calculates the maximum speed of the vehicle under its current conditions.
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:108
uint8_t overtaking
Set to RVSB_DRIVE_SIDE when overtaking, otherwise 0.
Definition roadveh.h:103
int UpdateSpeed()
This function looks at the vehicle and updates its speed (cur_speed and subspeed) variables.
bool Tick() override
Calls the tick handler of the vehicle.
ClosestDepot FindClosestDepot() override
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
void MarkDirty() override
Marks the vehicles to be redrawn and updates cached variables.
bool disaster
Play disaster and accident sounds.
static Station * Get(size_t index)
Gets station with given index.
static T * GetIfValid(size_t index)
Returns vehicle if the index is a valid index for this vehicle type.
T * Next() const
Get next vehicle in the chain.
T * Previous() const
Get previous vehicle in the chain.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * First() const
Get the first vehicle in the chain.
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
Station data structure.
uint16_t cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
uint8_t roadveh_acceleration_model
realistic acceleration for road vehicles
uint8_t road_side
the side of the road vehicles drive on
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.
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...
VehicleCargoList cargo
The cargo this vehicle is carrying.
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.
bool HasArticulatedPart() const
Check if an engine has an articulated part.
SpriteID colourmap
NOSAVE: cached colour mapping.
uint8_t breakdown_ctr
Counter for managing breakdown events.
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...
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
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
CargoType cargo_type
type of cargo this vehicle is carrying
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Vehicle * First() const
Get the first vehicle of this vehicle chain.
int8_t x_bb_offs
x offset of vehicle bounding box
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: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.
void InvalidateNewGRFCache()
Invalidates cached NewGRF variables.
uint8_t vehstatus
Status.
VehicleCache vcache
Cache of often used vehicle values.
int8_t y_bb_offs
y offset of vehicle bounding box
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
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition vehicle.cpp:2937
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.
virtual bool IsInDepot() const
Check whether the vehicle is in the depot.
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.
uint32_t maximum_go_to_depot_penalty
What is the maximum penalty that may be endured for going to a depot.
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
@ 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
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
static const uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
@ 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
Definition of the game-calendar-timer.
Definition of the game-economy-timer.
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition track_func.h:352
bool IsReversingRoadTrackdir(Trackdir dir)
Checks whether the trackdir means that we are reversing.
Definition track_func.h:673
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:555
bool IsStraightRoadTrackdir(Trackdir dir)
Checks whether the given trackdir is a straight road.
Definition track_func.h:684
Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition track_func.h:537
TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
Returns the red-signal-information of a TrackStatus.
Definition track_func.h:376
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_CROSS
X-Y-axis cross.
Definition track_type.h:43
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:67
@ TRACKDIR_RVREV_NE
(Road vehicle) reverse direction north-east
Definition track_type.h:75
@ TRACKDIR_LOWER_E
Lower track and direction to east.
Definition track_type.h:72
@ TRACKDIR_RIGHT_N
Right track and direction to north.
Definition track_type.h:82
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:86
@ TRACKDIR_UPPER_E
Upper track and direction to east.
Definition track_type.h:71
@ TRACKDIR_LEFT_S
Left track and direction to south.
Definition track_type.h:73
@ TRACKDIR_UPPER_W
Upper track and direction to west.
Definition track_type.h:79
@ TRACKDIR_RVREV_SE
(Road vehicle) reverse direction south-east
Definition track_type.h:76
@ TRACKDIR_LOWER_W
Lower track and direction to west.
Definition track_type.h:80
@ TRACKDIR_END
Used for iterations.
Definition track_type.h:85
@ TRACKDIR_RIGHT_S
Right track and direction to south.
Definition track_type.h:74
@ TRACKDIR_RVREV_NW
(Road vehicle) reverse direction north-west
Definition track_type.h:84
@ TRACKDIR_RVREV_SW
(Road vehicle) reverse direction south-west
Definition track_type.h:83
@ TRACKDIR_LEFT_N
Left track and direction to north.
Definition track_type.h:81
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:98
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:99
@ TRANSPORT_ROAD
Transport by road vehicle.
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1552
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle in on a specific location.
Definition vehicle.cpp:461
void VehicleLengthChanged(const Vehicle *u)
Logs a bug in GRF and shows a warning message if this is for the first time this happened.
Definition vehicle.cpp:346
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition vehicle.cpp:167
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition vehicle.cpp:445
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 FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition vehicle.cpp:505
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
@ 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.
@ VF_BUILT_AS_PROTOTYPE
Vehicle is a prototype (accepted as exclusive preview).
Functions related to vehicles.
EngineImageType
Visualisation contexts of vehicles and engines.
@ VEH_ROAD
Road vehicle type.
@ VEH_TRAIN
Train vehicle type.
uint32_t VehicleID
The type all our vehicle IDs have.
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3125
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:3217
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:3112
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3099
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Entry point for OpenTTD to YAPF.
Trackdir YapfRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirs, bool &path_found, RoadVehPathCache &path_cache)
Finds the best path for given road vehicle using YAPF.
FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_penalty)
Used when user sends road vehicle to the nearest depot or if road vehicle needs servicing using YAPF.
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition zoom_func.h:107
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition zoom_func.h:77