OpenTTD Source 20260721-master-g25ec12c62d
road_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 "road.h"
12#include "road_internal.h"
13#include "viewport_func.h"
14#include "command_func.h"
15#include "company_func.h"
17#include "depot_base.h"
18#include "newgrf.h"
19#include "autoslope.h"
20#include "tunnelbridge_map.h"
21#include "strings_func.h"
22#include "vehicle_func.h"
23#include "sound_func.h"
24#include "tunnelbridge.h"
25#include "cheat_type.h"
26#include "effectvehicle_func.h"
27#include "effectvehicle_base.h"
28#include "elrail_func.h"
29#include "roadveh.h"
30#include "train.h"
31#include "town.h"
32#include "company_base.h"
33#include "core/random_func.hpp"
35#include "newgrf_debug.h"
36#include "newgrf_railtype.h"
37#include "newgrf_roadtype.h"
39#include "genworld.h"
40#include "company_gui.h"
41#include "road_func.h"
42#include "road_cmd.h"
43#include "landscape_cmd.h"
44#include "rail_cmd.h"
45
46#include "table/strings.h"
47#include "table/roadtypes.h"
48
49#include "safeguards.h"
50
52typedef std::vector<RoadVehicle *> RoadVehicleList;
53
54RoadTypeInfo _roadtypes[ROADTYPE_END];
55std::vector<RoadType> _sorted_roadtypes;
59
64{
65 static_assert(std::size(_original_roadtypes) <= std::size(_roadtypes));
66
67 auto insert = std::copy(std::begin(_original_roadtypes), std::end(_original_roadtypes), std::begin(_roadtypes));
68 std::fill(insert, std::end(_roadtypes), RoadTypeInfo{});
69
73}
74
75void ResolveRoadTypeGUISprites(RoadTypeInfo *rti)
76{
78 if (cursors_base != 0) {
79 rti->gui_sprites.build_y_road = cursors_base + 0;
80 rti->gui_sprites.build_x_road = cursors_base + 1;
81 rti->gui_sprites.auto_road = cursors_base + 2;
82 rti->gui_sprites.build_depot = cursors_base + 3;
83 rti->gui_sprites.build_tunnel = cursors_base + 4;
84 rti->gui_sprites.convert_road = cursors_base + 5;
85 rti->cursor.road_swne = cursors_base + 6;
86 rti->cursor.road_nwse = cursors_base + 7;
87 rti->cursor.autoroad = cursors_base + 8;
88 rti->cursor.depot = cursors_base + 9;
89 rti->cursor.tunnel = cursors_base + 10;
90 rti->cursor.convert_road = cursors_base + 11;
91 }
92}
93
100static bool CompareRoadTypes(const RoadType &first, const RoadType &second)
101{
102 if (RoadTypeIsRoad(first) == RoadTypeIsRoad(second)) {
104 }
105 return RoadTypeIsTram(first) < RoadTypeIsTram(second);
106}
107
112{
113 _sorted_roadtypes.clear();
114 for (RoadTypeInfo &rti : _roadtypes) {
115 RoadType rt = rti.Index();
116
117 ResolveRoadTypeGUISprites(&rti);
119
120 if (rti.label.Empty()) continue;
121 _sorted_roadtypes.push_back(rt);
122 }
123 std::sort(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), CompareRoadTypes);
124}
125
132RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
133{
134 auto it = std::ranges::find(_roadtypes, RoadTypeLabel{}, &RoadTypeInfo::label);
135 if (it == std::end(_roadtypes)) return INVALID_ROADTYPE;
136
137 RoadTypeInfo &rti = *it;
138 RoadType rt = rti.Index();
139
140 /* Set up new road type based on default tram or road. */
142 rti.label = label;
143 rti.alternate_labels.clear();
144 rti.flags = {};
146
147 /* Make us compatible with ourself. */
148 rti.powered_roadtypes = rt;
149
150 /* We also introduce ourself. */
151 rti.introduces_roadtypes = rt;
152
153 /* Default sort order; order of allocation, but with some
154 * offsets so it's easier for NewGRF to pick a spot without
155 * changing the order of other (original) road types.
156 * The << is so you can place other roadtypes in between the
157 * other roadtypes, the 7 is to be able to place something
158 * before the first (default) road type. */
159 rti.sorting_order = rt << 2 | 7;
160
161 /* Set bitmap of road/tram types */
162 _roadtypes_road.Set(rt, rtt == RoadTramType::Road);
163 _roadtypes_tram.Set(rt, rtt == RoadTramType::Tram);
164
165 return rt;
166}
167
173{
174 return !RoadVehicle::Iterate().empty();
175}
176
183void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
184{
185 if (rt == INVALID_ROADTYPE) return;
186
188 if (c == nullptr) return;
189
190 c->infrastructure.road[rt] += count;
192}
193
195static const std::array<NonSteepSlopeIndexArray<RoadBits>, 2> _invalid_tileh_slopes_road = {{
196 /* The inverse of the mixable RoadBits on a leveled slope */
197 {{{
198 {}, // SLOPE_FLAT
199 {RoadBit::NE, RoadBit::SE}, // SLOPE_W
200 {RoadBit::NE, RoadBit::NW}, // SLOPE_S
201
202 RoadBit::NE, // SLOPE_SW
203 {RoadBit::NW, RoadBit::SW}, // SLOPE_E
204 {}, // SLOPE_EW
205
206 RoadBit::NW, // SLOPE_SE
207 {}, // SLOPE_WSE
208 {RoadBit::SE, RoadBit::SW}, // SLOPE_N
209
210 RoadBit::SE, // SLOPE_NW
211 {}, // SLOPE_NS
212 {}, // SLOPE_ENW
213
214 RoadBit::SW, // SLOPE_NE
215 {}, // SLOPE_SEN
216 {}, // SLOPE_NWS
217 }}},
218 /* The inverse of the allowed straight roads on a slope
219 * (with and without a foundation). */
220 {{{
221 {}, // SLOPE_FLAT
222 {}, // SLOPE_W (Foundation)
223 {}, // SLOPE_S (Foundation)
224
225 ROAD_Y, // SLOPE_SW
226 {}, // SLOPE_E (Foundation)
227 ROAD_ALL, // SLOPE_EW
228
229 ROAD_X, // SLOPE_SE
230 ROAD_ALL, // SLOPE_WSE
231 {}, // SLOPE_N (Foundation)
232
233 ROAD_X, // SLOPE_NW
234 ROAD_ALL, // SLOPE_NS
235 ROAD_ALL, // SLOPE_ENW
236
237 ROAD_Y, // SLOPE_NE
238 ROAD_ALL, // SLOPE_SEN
239 ROAD_ALL, // SLOPE_NW
240 }}}
241}};
242
243static Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
244
255CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlags flags, bool town_check)
256{
257 if (_game_mode == GameMode::Editor || remove.None()) return CommandCost();
258
259 /* Water can always flood and towns can always remove "normal" road pieces.
260 * Towns are not be allowed to remove non "normal" road pieces, like tram
261 * tracks as that would result in trams that cannot turn. */
264
265 /* Only do the special processing if the road is owned
266 * by a town */
267 if (owner != OWNER_TOWN) {
268 if (owner == OWNER_NONE) return CommandCost();
269 CommandCost ret = CheckOwnership(owner);
270 return ret;
271 }
272
273 if (!town_check) return CommandCost();
274
275 if (_cheats.magic_bulldozer.value) return CommandCost();
276
277 Town *t = ClosestTownFromTile(tile, UINT_MAX);
278 if (t == nullptr) return CommandCost();
279
280 /* check if you're allowed to remove the street owned by a town
281 * removal allowance depends on difficulty setting */
283 if (ret.Failed()) return ret;
284
285 /* Get a bitmask of which neighbouring roads has a tile */
286 RoadBits n{};
287 RoadBits present = GetAnyRoadBits(tile, rtt);
288 if (present.Test(RoadBit::NE) && GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt).Test(RoadBit::SW)) n.Set(RoadBit::NE);
289 if (present.Test(RoadBit::SE) && GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt).Test(RoadBit::NW)) n.Set(RoadBit::SE);
290 if (present.Test(RoadBit::SW) && GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt).Test(RoadBit::NE)) n.Set(RoadBit::SW);
291 if (present.Test(RoadBit::NW) && GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt).Test(RoadBit::SE)) n.Set(RoadBit::NW);
292
293 int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE;
294 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
295 * then allow it */
296 if (n.Count() > 1 && n.Any(remove)) {
297 /* you can remove all kind of roads with extra dynamite */
298 if (!_settings_game.construction.extra_dynamite) {
299 return CommandCostWithParam(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS, t->index);
300 }
301 rating_decrease = RATING_ROAD_DOWN_STEP_INNER;
302 }
303 ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM, flags);
304
305 return CommandCost();
306}
307
308
318static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check)
319{
320 assert(pieces.Any());
321
322 RoadType existing_rt = MayHaveRoad(tile) ? GetRoadType(tile, rtt) : INVALID_ROADTYPE;
323 /* The tile doesn't have the given road type */
324 if (existing_rt == INVALID_ROADTYPE) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
325
326 switch (GetTileType(tile)) {
327 case TileType::Road: {
329 if (ret.Failed()) return ret;
330 break;
331 }
332
333 case TileType::Station: {
334 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
335
337 if (ret.Failed()) return ret;
338 break;
339 }
340
344 if (ret.Failed()) return ret;
345 break;
346 }
347
348 default:
349 return CMD_ERROR;
350 }
351
352 CommandCost ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rtt), rtt, flags, town_check);
353 if (ret.Failed()) return ret;
354
355 if (!IsTileType(tile, TileType::Road)) {
356 /* If it's the last roadtype, just clear the whole tile */
357 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) return Command<Commands::LandscapeClear>::Do(flags, tile);
358
361 /* Removing any roadbit in the bridge axis removes the roadtype (that's the behaviour remove-long-roads needs) */
362 if (!AxisToRoadBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))).Any(pieces)) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
363
364 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
365 /* Pay for *every* tile of the bridge or tunnel */
366 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
367 cost.AddCost(len * 2 * RoadClearCost(existing_rt));
368 if (flags.Test(DoCommandFlag::Execute)) {
369 /* A full diagonal road tile has two road bits. */
370 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
371
372 SetRoadType(other_end, rtt, INVALID_ROADTYPE);
373 SetRoadType(tile, rtt, INVALID_ROADTYPE);
374
375 /* If the owner of the bridge sells all its road, also move the ownership
376 * to the owner of the other roadtype, unless the bridge owner is a town. */
377 Owner other_owner = GetRoadOwner(tile, OtherRoadTramType(rtt));
378 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
379 SetTileOwner(tile, other_owner);
380 SetTileOwner(other_end, other_owner);
381 }
382
383 /* Mark tiles dirty that have been repaved */
384 if (IsBridge(tile)) {
385 MarkBridgeDirty(tile);
386 } else {
388 MarkTileDirtyByTile(other_end);
389 }
390 }
391 } else {
392 assert(IsDriveThroughStopTile(tile));
393 cost.AddCost(RoadClearCost(existing_rt) * 2);
394 if (flags.Test(DoCommandFlag::Execute)) {
395 /* A full diagonal road tile has two road bits. */
396 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
397 SetRoadType(tile, rtt, INVALID_ROADTYPE);
399 }
400 }
401 return cost;
402 }
403
404 switch (GetRoadTileType(tile)) {
406 Slope tileh = GetTileSlope(tile);
407
408 /* Steep slopes behave the same as slopes with one corner raised. */
409 if (IsSteepSlope(tileh)) {
411 }
412
413 RoadBits present = GetRoadBits(tile, rtt);
414 const RoadBits other = GetRoadBits(tile, OtherRoadTramType(rtt));
415 const Foundation f = GetRoadFoundation(tileh, present);
416
417 if (HasRoadWorks(tile) && _current_company != OWNER_WATER) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
418
419 /* Autocomplete to a straight road
420 * @li if the bits of the other roadtypes result in another foundation
421 * @li if build on slopes is disabled */
422 if ((IsStraightRoad(other) && other.Any(_invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED])) ||
423 (tileh != SLOPE_FLAT && !_settings_game.construction.build_on_slopes)) {
424 pieces.Set(MirrorRoadBits(pieces));
425 }
426
427 /* limit the bits to delete to the existing bits. */
428 pieces &= present;
429 if (pieces.None()) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
430
431 /* Now set present what it will be after the remove */
432 present.Flip(pieces);
433
434 /* Check for invalid RoadBit combinations on slopes */
435 if (tileh != SLOPE_FLAT && present.Any() &&
436 _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED].All(present)) {
437 return CMD_ERROR;
438 }
439
440 if (flags.Test(DoCommandFlag::Execute)) {
441 if (HasRoadWorks(tile)) {
442 /* flooding tile with road works, don't forget to remove the effect vehicle too */
443 assert(_current_company == OWNER_WATER);
445 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
446 delete v;
447 }
448 }
449 }
450
451 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -static_cast<int>(pieces.Count()));
452
453 if (present.None()) {
454 /* No other road type, just clear tile. */
455 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
456 /* Includes MarkTileDirtyByTile() */
457 DoClearSquare(tile);
458 } else {
459 if (rtt == RoadTramType::Road && IsRoadOwner(tile, rtt, OWNER_TOWN)) {
460 /* Update nearest-town index */
461 const Town *town = CalcClosestTownFromTile(tile);
462 SetTownIndex(tile, town == nullptr ? TownID::Invalid() : town->index);
463 }
465 SetRoadBits(tile, {}, rtt);
466 SetRoadType(tile, rtt, INVALID_ROADTYPE);
468 }
469 } else {
470 /* When bits are removed, you *always* end up with something that
471 * is not a complete straight road tile. However, trams do not have
472 * onewayness, so they cannot remove it either. */
474 SetRoadBits(tile, present, rtt);
476 }
477 }
478
479 CommandCost cost(ExpensesType::Construction, pieces.Count() * RoadClearCost(existing_rt));
480 /* If we build a foundation we have to pay for it. */
482
483 return cost;
484 }
485
487 if (pieces.Any(ComplementRoadBits(GetCrossingRoadBits(tile)))) {
488 return CMD_ERROR;
489 }
490
491 if (flags.Test(DoCommandFlag::Execute)) {
493
494 /* A full diagonal road tile has two road bits. */
495 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
496
497 Track track = GetCrossingRailTrack(tile);
498 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
499 bool reserved = HasCrossingReservation(tile);
500 MakeRailNormal(tile, GetTileOwner(tile), track, GetRailType(tile));
501 if (reserved) SetTrackReservation(tile, track);
502
503 /* Update rail count for level crossings. The plain track should still be accounted
504 * for, so only subtract the difference to the level crossing cost. */
506 if (c != nullptr) {
509 }
510 } else {
511 SetRoadType(tile, rtt, INVALID_ROADTYPE);
512 }
514 YapfNotifyTrackLayoutChange(tile, track);
515 }
516 return CommandCost(ExpensesType::Construction, RoadClearCost(existing_rt) * 2);
517 }
518
519 default:
521 return CMD_ERROR;
522 }
523}
524
525
537static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
538{
539 /* Remove already build pieces */
540 pieces->Reset(existing);
541
542 /* If we can't build anything stop here */
543 if (pieces->None()) return CMD_ERROR;
544
545 /* All RoadBit combos are valid on flat land */
546 if (tileh == SLOPE_FLAT) return CommandCost();
547
548 /* Steep slopes behave the same as slopes with one corner raised. */
549 if (IsSteepSlope(tileh)) {
551 }
552
553 /* Save the merge of all bits of the current type */
554 RoadBits type_bits = existing | *pieces;
555
556 /* Roads on slopes */
557 if (_settings_game.construction.build_on_slopes && !_invalid_tileh_slopes_road[0][tileh].Any(other | type_bits)) {
558
559 /* If we add leveling we've got to pay for it */
560 if ((other | existing).None()) return CommandCost(ExpensesType::Construction, _price[Price::BuildFoundation]);
561
562 return CommandCost();
563 }
564
565 /* Autocomplete uphill roads */
566 pieces->Set(MirrorRoadBits(*pieces));
567 type_bits = existing | *pieces;
568
569 /* Uphill roads */
570 if (IsStraightRoad(type_bits) && (other == type_bits || other.None()) &&
571 !_invalid_tileh_slopes_road[1][tileh].Any(other | type_bits)) {
572
573 /* Slopes with foundation ? */
574 if (IsSlopeWithOneCornerRaised(tileh)) {
575
576 /* Prevent build on slopes if it isn't allowed */
577 if (_settings_game.construction.build_on_slopes) {
578
579 /* If we add foundation we've got to pay for it */
580 if ((other | existing).None()) return CommandCost(ExpensesType::Construction, _price[Price::BuildFoundation]);
581
582 return CommandCost();
583 }
584 } else {
586 return CommandCost();
587 }
588 }
589 return CMD_ERROR;
590}
591
603{
604 CompanyID company = _current_company;
606
607 RoadBits existing{};
608 RoadBits other_bits{};
609
610 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
611 * if a non-company is building the road */
612 if ((Company::IsValidID(company) && town_id != TownID::Invalid()) || (company == OWNER_TOWN && !Town::IsValidID(town_id)) || (company == OWNER_DEITY && town_id != TownID::Invalid())) return CMD_ERROR;
613 if (company != OWNER_TOWN) {
614 const Town *town = CalcClosestTownFromTile(tile);
615 town_id = (town != nullptr) ? town->index : TownID::Invalid();
616
617 if (company == OWNER_DEITY) {
618 company = OWNER_TOWN;
619
620 /* If we are not within a town, we are not owned by the town */
621 if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) {
622 company = OWNER_NONE;
623 }
624 }
625 }
626
627 /* do not allow building 'zero' road bits, code wouldn't handle it */
628 if (pieces.None() || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR;
629 if (!ValParamRoadType(rt)) return CMD_ERROR;
630
631 Slope tileh = GetTileSlope(tile);
632 RoadTramType rtt = GetRoadTramType(rt);
633
634 bool need_to_clear = false;
635 switch (GetTileType(tile)) {
636 case TileType::Road:
637 switch (GetRoadTileType(tile)) {
639 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
640
641 other_bits = GetRoadBits(tile, OtherRoadTramType(rtt));
642 if (!HasTileRoadType(tile, rtt)) break;
643
644 existing = GetRoadBits(tile, rtt);
645 bool crossing = !IsStraightRoad(existing | pieces);
646 if (rtt == RoadTramType::Road && (GetDisallowedRoadDirections(tile).Any() || toggle_drd.Any()) && crossing) {
647 /* Junctions cannot be one-way */
648 return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
649 }
650 if (existing.All(pieces)) {
651 /* We only want to set the (dis)allowed road directions */
652 if (toggle_drd.Any() && rtt == RoadTramType::Road) {
653 Owner owner = GetRoadOwner(tile, rtt);
654 if (owner != OWNER_NONE) {
655 CommandCost ret = CheckOwnership(owner, tile);
656 if (ret.Failed()) return ret;
657 }
658
661
662 /* We allow removing disallowed directions to break up
663 * deadlocks, but adding them can break articulated
664 * vehicles. As such, only when less is disallowed,
665 * i.e. bits are removed, we skip the vehicle check. */
666 if (dis_existing.Count() <= dis_new.Count()) {
668 if (ret.Failed()) return ret;
669 }
670
671 /* Ignore half built tiles */
672 if (flags.Test(DoCommandFlag::Execute) && IsStraightRoad(existing)) {
673 SetDisallowedRoadDirections(tile, dis_new);
675 }
676 return CommandCost();
677 }
678 return CommandCost(STR_ERROR_ALREADY_BUILT);
679 }
680 /* Disallow breaking end-of-line of someone else
681 * so trams can still reverse on this tile. */
682 if (rtt == RoadTramType::Tram && existing.Count() == 1) {
683 Owner owner = GetRoadOwner(tile, rtt);
684 if (Company::IsValidID(owner)) {
685 CommandCost ret = CheckOwnership(owner);
686 if (ret.Failed()) return ret;
687 }
688 }
689 break;
690 }
691
693 if (RoadNoLevelCrossing(rt)) {
694 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
695 }
696
697 other_bits = GetCrossingRoadBits(tile);
698 if (pieces.Any(ComplementRoadBits(other_bits))) goto do_clear;
699 pieces = other_bits; // we need to pay for both roadbits
700
701 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
702 break;
703
705 if (GetAnyRoadBits(tile, rtt).All(pieces)) return CommandCost(STR_ERROR_ALREADY_BUILT);
706 goto do_clear;
707
708 default: NOT_REACHED();
709 }
710 break;
711
712 case TileType::Railway: {
713 if (IsSteepSlope(tileh)) {
714 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
715 }
716
717 /* Level crossings may only be built on these slopes */
718 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
719 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
720 }
721
722 if (!_settings_game.construction.crossing_with_competitor && company != OWNER_TOWN && company != OWNER_DEITY) {
724 if (ret.Failed()) return ret;
725 }
726
727 if (GetRailTileType(tile) != RailTileType::Normal) goto do_clear;
728
729 if (RoadNoLevelCrossing(rt)) {
730 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
731 }
732
734 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
735 }
736
737 Axis roaddir;
738 switch (GetTrackBits(tile).base()) {
739 case TrackBits{Track::X}.base():
740 if (pieces.Any(ROAD_X)) goto do_clear;
741 roaddir = Axis::Y;
742 break;
743
744 case TrackBits{Track::Y}.base():
745 if (pieces.Any(ROAD_Y)) goto do_clear;
746 roaddir = Axis::X;
747 break;
748
749 default: goto do_clear;
750 }
751
753 if (ret.Failed()) return ret;
754
755 if (flags.Test(DoCommandFlag::Execute)) {
756 Track railtrack = AxisToTrack(OtherAxis(roaddir));
757 YapfNotifyTrackLayoutChange(tile, railtrack);
758 /* Update company infrastructure counts. A level crossing has two road bits. */
759 UpdateCompanyRoadInfrastructure(rt, company, 2);
760
761 /* Update rail count for level crossings. The plain track is already
762 * counted, so only add the difference to the level crossing cost. */
764 if (c != nullptr) {
767 }
768
769 /* Always add road to the roadtypes (can't draw without it) */
770 bool reserved = GetRailReservationTrackBits(tile).Test(railtrack);
771 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RoadTramType::Road ? rt : INVALID_ROADTYPE, (rtt == RoadTramType::Tram) ? rt : INVALID_ROADTYPE, town_id);
772 SetCrossingReservation(tile, reserved);
773 UpdateLevelCrossing(tile, false);
776 }
778 }
779
780 case TileType::Station: {
781 if (GetAnyRoadBits(tile, rtt).All(pieces)) return CommandCost(STR_ERROR_ALREADY_BUILT);
782 if (!IsDriveThroughStopTile(tile)) goto do_clear;
783
785 if (pieces.Any(ComplementRoadBits(curbits))) goto do_clear;
786 pieces = curbits; // we need to pay for both roadbits
787
788 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
789 break;
790 }
791
793 if (GetTunnelBridgeTransportType(tile) != TransportType::Road) goto do_clear;
794 /* Only allow building the outer roadbit, so building long roads stops at existing bridges */
795 if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
796 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
797 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
799 if (ret.Failed()) return ret;
800 break;
801 }
802
803 default: {
804do_clear:;
805 need_to_clear = true;
806 break;
807 }
808 }
809
810 if (need_to_clear) {
811 CommandCost ret = Command<Commands::LandscapeClear>::Do(flags, tile);
812 if (ret.Failed()) return ret;
813 cost.AddCost(ret.GetCost());
814 }
815
816 if (other_bits != pieces) {
817 /* Check the foundation/slopes when adding road/tram bits */
818 CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
819 /* Return an error if we need to build a foundation (ret != 0) but the
820 * current setting is turned off */
821 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
822 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
823 }
824 cost.AddCost(ret.GetCost());
825 }
826
827 if (!need_to_clear) {
828 if (IsTileType(tile, TileType::Road)) {
829 /* Don't put the pieces that already exist */
830 pieces.Reset(existing);
831
832 /* Check if new road bits will have the same foundation as other existing road types */
833 if (IsNormalRoad(tile)) {
834 Slope slope = GetTileSlope(tile);
835 Foundation found_new = GetRoadFoundation(slope, pieces | existing);
836
837 RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt));
838 /* do not check if there are not road bits of given type */
839 if (bits.Any() && GetRoadFoundation(slope, bits) != found_new) {
840 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
841 }
842 }
843 }
844
846 if (ret.Failed()) return ret;
847
848 if (IsNormalRoadTile(tile)) {
849 /* If the road types don't match, try to convert only if vehicles of
850 * the new road type are not powered on the present road type and vehicles of
851 * the present road type are powered on the new road type. */
852 RoadType existing_rt = GetRoadType(tile, rtt);
853 if (existing_rt != INVALID_ROADTYPE && existing_rt != rt) {
854 if (HasPowerOnRoad(rt, existing_rt)) {
855 rt = existing_rt;
856 } else if (HasPowerOnRoad(existing_rt, rt)) {
857 ret = Command<Commands::ConvertRoad>::Do(flags, tile, tile, rt, false);
858 if (ret.Failed()) return ret;
859 cost.AddCost(ret.GetCost());
860 } else {
861 return CMD_ERROR;
862 }
863 }
864 }
865 }
866
867 uint num_pieces = (!need_to_clear && IsTileType(tile, TileType::TunnelBridge)) ?
868 /* There are 2 pieces on *every* tile of the bridge or tunnel */
869 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) :
870 /* Count pieces */
871 pieces.Count();
872
873 cost.AddCost(num_pieces * RoadBuildCost(rt));
874
875 if (flags.Test(DoCommandFlag::Execute)) {
876 switch (GetTileType(tile)) {
877 case TileType::Road: {
878 RoadTileType rttype = GetRoadTileType(tile);
879 if (existing.None() || rttype == RoadTileType::Crossing) {
880 SetRoadType(tile, rtt, rt);
881 SetRoadOwner(tile, rtt, company);
882 if (rtt == RoadTramType::Road) SetTownIndex(tile, town_id);
883 }
884 if (rttype != RoadTileType::Crossing) SetRoadBits(tile, existing | pieces, rtt);
885 break;
886 }
887
889 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
890
891 SetRoadType(other_end, rtt, rt);
892 SetRoadType(tile, rtt, rt);
893 SetRoadOwner(other_end, rtt, company);
894 SetRoadOwner(tile, rtt, company);
895
896 /* Mark tiles dirty that have been repaved */
897 if (IsBridge(tile)) {
898 MarkBridgeDirty(tile);
899 } else {
900 MarkTileDirtyByTile(other_end);
902 }
903 break;
904 }
905
906 case TileType::Station: {
907 assert(IsDriveThroughStopTile(tile));
908 SetRoadType(tile, rtt, rt);
909 SetRoadOwner(tile, rtt, company);
910 break;
911 }
912
913 default:
914 MakeRoadNormal(tile, pieces, (rtt == RoadTramType::Road) ? rt : INVALID_ROADTYPE, (rtt == RoadTramType::Tram) ? rt : INVALID_ROADTYPE, town_id, company, company);
915 break;
916 }
917
918 /* Update company infrastructure count. */
920 UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), num_pieces);
921
922 if (rtt == RoadTramType::Road && IsNormalRoadTile(tile)) {
923 existing.Set(pieces);
925 GetDisallowedRoadDirections(tile).Flip(toggle_drd) : DisallowedRoadDirections{});
926 }
927
929 }
930 return cost;
931}
932
941{
942 tile += TileOffsByDiagDir(dir);
943 if (!IsValidTile(tile) || !MayHaveRoad(tile)) return false;
944
945 RoadTramType rtt = GetRoadTramType(rt);
946 RoadType existing = GetRoadType(tile, rtt);
947 if (existing == INVALID_ROADTYPE) return false;
948 if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false;
949
950 RoadBits bits = GetAnyRoadBits(tile, rtt, false);
951 return bits.Any(DiagDirToRoadBits(ReverseDiagDir(dir)));
952}
953
969CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
970{
971 if (start_tile >= Map::Size()) return CMD_ERROR;
972
973 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
974
975 /* Only drag in X or Y direction dictated by the direction variable */
976 if (axis == Axis::X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
977 if (axis == Axis::Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
978
979 DiagDirection dir = AxisToDiagDir(axis);
980
981 /* Swap direction, also the half-tile drag vars. */
982 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
983 dir = ReverseDiagDir(dir);
984 start_half = !start_half;
985 end_half = !end_half;
987 }
988
989 /* On the X-axis, we have to swap the initial bits, so they
990 * will be interpreted correctly in the GTTS. Furthermore
991 * when you just 'click' on one tile to build them. */
992 if ((drd == DisallowedRoadDirection::Northbound || drd == DisallowedRoadDirection::Southbound) && (axis == Axis::Y) == (start_tile == end_tile && start_half == end_half)) drd.Flip({DisallowedRoadDirection::Northbound, DisallowedRoadDirection::Southbound});
993
995 CommandCost last_error = CMD_ERROR;
996 TileIndex tile = start_tile;
997 bool had_bridge = false;
998 bool had_tunnel = false;
999 bool had_success = false;
1000
1001 /* Start tile is the first tile clicked by the user. */
1002 for (;;) {
1003 RoadBits bits = AxisToRoadBits(axis);
1004
1005 /* Determine which road parts should be built. */
1006 if (!is_ai && start_tile != end_tile) {
1007 /* Only build the first and last roadbit if they can connect to something. */
1008 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1009 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1010 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1011 bits = DiagDirToRoadBits(dir);
1012 }
1013 } else {
1014 /* Road parts only have to be built at the start tile or at the end tile. */
1015 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1016 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1017 }
1018
1019 CommandCost ret = Command<Commands::BuildRoad>::Do(flags, tile, bits, rt, drd, TownID::Invalid());
1020 if (!is_ai && ret.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true;
1021 if (ret.Failed()) {
1022 last_error = std::move(ret);
1023 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1024 if (is_ai) return last_error;
1025 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1026 }
1027 } else {
1028 had_success = true;
1029 /* Only pay for the upgrade on one side of the bridges and tunnels */
1031 if (IsBridge(tile)) {
1032 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1033 cost.AddCost(ret.GetCost());
1034 }
1035 had_bridge = true;
1036 } else { // IsTunnel(tile)
1037 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1038 cost.AddCost(ret.GetCost());
1039 }
1040 had_tunnel = true;
1041 }
1042 } else {
1043 cost.AddCost(ret.GetCost());
1044 }
1045 }
1046
1047 if (tile == end_tile) break;
1048
1049 tile += TileOffsByDiagDir(dir);
1050 }
1051
1052 return had_success ? cost : last_error;
1053}
1054
1066std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
1067{
1069
1070 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
1071 if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 };
1072
1073 /* Only drag in X or Y direction dictated by the direction variable */
1074 if (axis == Axis::X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis
1075 if (axis == Axis::Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis
1076
1077 /* Swap start and ending tile, also the half-tile drag vars. */
1078 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
1079 std::swap(start_tile, end_tile);
1080 std::swap(start_half, end_half);
1081 }
1082
1083 Money money_available = GetAvailableMoneyForCommand();
1084 Money money_spent = 0;
1085 TileIndex tile = start_tile;
1086 CommandCost last_error = CMD_ERROR;
1087 bool had_success = false;
1088 /* Start tile is the small number. */
1089 for (;;) {
1090 RoadBits bits = AxisToRoadBits(axis);
1091
1092 if (tile == end_tile && !end_half) bits &= RoadBits{RoadBit::NW, RoadBit::NE};
1093 if (tile == start_tile && start_half) bits &= RoadBits{RoadBit::SE, RoadBit::SW};
1094
1095 /* try to remove the halves. */
1096 if (bits.Any()) {
1097 RoadTramType rtt = GetRoadTramType(rt);
1098 CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true);
1099 if (ret.Succeeded()) {
1100 if (flags.Test(DoCommandFlag::Execute)) {
1101 money_spent += ret.GetCost();
1102 if (money_spent > 0 && money_spent > money_available) {
1103 return { cost, ExtractCommandCost(Command<Commands::RemoveRoadLong>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), end_tile, start_tile, rt, axis, start_half, end_half)).GetCost() };
1104 }
1105 RemoveRoad(tile, flags, bits, rtt, false);
1106 }
1107 cost.AddCost(ret.GetCost());
1108 had_success = true;
1109 } else {
1110 /* Some errors are more equal than others. */
1111 switch (last_error.GetErrorMessage()) {
1112 case STR_ERROR_OWNED_BY:
1113 case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS:
1114 break;
1115 default:
1116 last_error = std::move(ret);
1117 }
1118 }
1119 }
1120
1121 if (tile == end_tile) break;
1122
1123 tile += TileOffsByAxis(axis);
1124 }
1125
1126 return { had_success ? cost : last_error, 0 };
1127}
1128
1138{
1139 if (!ValParamRoadType(rt) || !IsValidDiagDirection(dir)) return CMD_ERROR;
1140
1142
1143 Slope tileh = GetTileSlope(tile);
1144 if (tileh != SLOPE_FLAT) {
1145 if (!_settings_game.construction.build_on_slopes) return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
1146 if (!CanBuildDepotByTileh(dir, tileh)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
1148 }
1149
1150 /* Allow the user to rotate the depot instead of having to destroy it and build it again */
1151 bool rotate_existing_depot = false;
1152 if (IsRoadDepotTile(tile) && (HasRoadTypeTram(tile) ? rt == GetRoadTypeTram(tile) : rt == GetRoadTypeRoad(tile)))
1153 {
1154 CommandCost ret = CheckTileOwnership(tile);
1155 if (ret.Failed()) return ret;
1156
1157 if (dir == GetRoadDepotDirection(tile)) return CommandCost();
1158
1159 ret = EnsureNoVehicleOnGround(tile);
1160 if (ret.Failed()) return ret;
1161
1162 rotate_existing_depot = true;
1163 }
1164
1165 if (!rotate_existing_depot) {
1166 cost.AddCost(Command<Commands::LandscapeClear>::Do(flags, tile));
1167 if (cost.Failed()) return cost;
1168
1169 if (IsBridgeAbove(tile)) {
1171 if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADVEH_DEPOT, height_diff * TILE_HEIGHT_STEP);
1172 }
1173
1174 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1175 }
1176
1177 if (flags.Test(DoCommandFlag::Execute)) {
1178 if (rotate_existing_depot) {
1179 SetRoadDepotExitDirection(tile, dir);
1180 } else {
1181 Depot *dep = Depot::Create(tile);
1182 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1183 MakeDefaultName(dep);
1184
1185 /* A road depot has two road bits. */
1187 }
1188
1189 MarkTileDirtyByTile(tile);
1190 }
1191
1193 return cost;
1194}
1195
1196static CommandCost RemoveRoadDepot(TileIndex tile, DoCommandFlags flags)
1197{
1199 CommandCost ret = CheckTileOwnership(tile);
1200 if (ret.Failed()) return ret;
1201 }
1202
1204 if (ret.Failed()) return ret;
1205
1206 if (flags.Test(DoCommandFlag::Execute)) {
1208 if (c != nullptr) {
1209 /* A road depot has two road bits. */
1210 RoadType rt = GetRoadTypeRoad(tile);
1211 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
1214 }
1215
1216 delete Depot::GetByTile(tile);
1217 DoClearSquare(tile);
1218 }
1219
1221}
1222
1225{
1226 switch (GetRoadTileType(tile)) {
1227 case RoadTileType::Normal: {
1228 RoadBits b = GetAllRoadBits(tile);
1229
1230 /* Clear the road if only one piece is on the tile OR we are not using the DoCommandFlag::Auto flag */
1231 if ((b.Count() == 1 && GetRoadBits(tile, RoadTramType::Tram).None()) || !flags.Test(DoCommandFlag::Auto)) {
1233 for (RoadTramType rtt : ROADTRAMTYPES_ALL) {
1234 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1235
1236 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true);
1237 if (tmp_ret.Failed()) return tmp_ret;
1238 ret.AddCost(tmp_ret.GetCost());
1239 }
1240 return ret;
1241 }
1242 return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1243 }
1244
1247
1248 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1249
1250 /* Must iterate over the roadtypes in a reverse manner because
1251 * tram tracks must be removed before the road bits. */
1253 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1254
1255 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rtt, true);
1256 if (tmp_ret.Failed()) return tmp_ret;
1257 ret.AddCost(tmp_ret.GetCost());
1258 }
1259
1260 if (flags.Test(DoCommandFlag::Execute)) {
1261 Command<Commands::LandscapeClear>::Do(flags, tile);
1262 }
1263 return ret;
1264 }
1265
1266 default:
1268 if (flags.Test(DoCommandFlag::Auto)) {
1269 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1270 }
1271 return RemoveRoadDepot(tile, flags);
1272 }
1273}
1274
1275
1277 uint16_t image;
1278 uint8_t subcoord_x;
1279 uint8_t subcoord_y;
1280};
1281
1282#include "table/road_land.h"
1283
1292{
1293 /* Flat land and land without a road doesn't require a foundation */
1294 if (tileh == SLOPE_FLAT || bits.None()) return Foundation::None;
1295
1296 /* Steep slopes behave the same as slopes with one corner raised. */
1297 if (IsSteepSlope(tileh)) {
1299 }
1300
1301 /* Leveled RoadBits on a slope */
1302 if (!_invalid_tileh_slopes_road[0][tileh].Any(bits)) return Foundation::Leveled;
1303
1304 /* Straight roads without foundation on a slope */
1305 if (!IsSlopeWithOneCornerRaised(tileh) &&
1306 !_invalid_tileh_slopes_road[1][tileh].Any(bits))
1307 return Foundation::None;
1308
1309 /* Roads on steep Slopes or on Slopes with one corner raised */
1311}
1312
1315 0xFF, // Dummy value to prevent `index - 1` while accesing.
1316 0, 0, 2, 0,
1317 0, 1, 0, 0,
1318 3, 0, 0, 0,
1319 0, 0
1320};
1321
1328static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
1329{
1330 if (slope != SLOPE_FLAT) {
1331 switch (slope) {
1332 case SLOPE_NE: return 11;
1333 case SLOPE_SE: return 12;
1334 case SLOPE_SW: return 13;
1335 case SLOPE_NW: return 14;
1336 default: NOT_REACHED();
1337 }
1338 } else {
1339 static const uint offsets[] = {
1340 0, 18, 17, 7,
1341 16, 0, 10, 5,
1342 15, 8, 1, 4,
1343 9, 3, 6, 2
1344 };
1345 return offsets[bits.base()];
1346 }
1347}
1348
1358static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
1359{
1360 return (snow_or_desert &&
1362 roadside != Roadside::Barren && roadside != Roadside::Grass && roadside != Roadside::GrassRoadWorks));
1363}
1364
1372{
1373 /* Don't draw the catenary under a low bridge */
1375 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1376
1377 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1378 }
1379
1380 if (rb.Count() > 2) {
1381 /* On junctions we check whether neighbouring tiles also have catenary, and possibly
1382 * do not draw catenary towards those neighbours, which do not have catenary. */
1383 RoadBits rb_new{};
1385 if (rb.Any(DiagDirToRoadBits(dir))) {
1386 TileIndex neighbour = TileAddByDiagDir(ti->tile, dir);
1387 if (MayHaveRoad(neighbour)) {
1388 RoadType rt_road = GetRoadTypeRoad(neighbour);
1389 RoadType rt_tram = GetRoadTypeTram(neighbour);
1390
1391 if ((rt_road != INVALID_ROADTYPE && HasRoadCatenary(rt_road)) ||
1392 (rt_tram != INVALID_ROADTYPE && HasRoadCatenary(rt_tram))) {
1393 rb_new.Set(DiagDirToRoadBits(dir));
1394 }
1395 }
1396 }
1397 }
1398 if (rb_new.Count() >= 2) rb = rb_new;
1399 }
1400
1401 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1404
1405 if (front != 0 || back != 0) {
1406 if (front != 0) front += GetRoadSpriteOffset(ti->tileh, rb);
1407 if (back != 0) back += GetRoadSpriteOffset(ti->tileh, rb);
1408 } else if (ti->tileh != SLOPE_FLAT) {
1411 } else {
1412 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb.base()];
1413 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb.base()];
1414 }
1415
1416 /* Catenary uses 1st company colour to help identify owner.
1417 * For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
1418 Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
1419 PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(Colours::Grey) : GetCompanyPalette(owner));
1420 uint8_t z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
1421 if (back != 0) {
1422 /* The "back" sprite contains the west, north and east pillars.
1423 * We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
1424 * 3/8 is chosen so that sprites can somewhat graphically extend into the tile. */
1425 static const int INF = 1000;
1426 static const SubSprite west = { -INF, -INF, -12, INF };
1427 static const SubSprite north = { -12, -INF, 12, INF };
1428 static const SubSprite east = { 12, -INF, INF, INF };
1429 int8_t west_z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
1430 int8_t north_z = GetSlopePixelZInCorner(ti->tileh, CORNER_N);
1431 int8_t east_z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
1432 AddSortableSpriteToDraw(back, pal, *ti, {{15, 0, west_z}, {1, 1, z_wires}, {-15, 0, static_cast<int8_t>(-west_z)}}, IsTransparencySet(TransparencyOption::Catenary), &west);
1433 AddSortableSpriteToDraw(back, pal, *ti, {{0, 0, north_z}, {1, 1, z_wires}, {0, 0, static_cast<int8_t>(-north_z)}}, IsTransparencySet(TransparencyOption::Catenary), &north);
1434 AddSortableSpriteToDraw(back, pal, *ti, {{0, 15, east_z}, {1, 1, z_wires}, {0, -15, static_cast<int8_t>(-east_z)}}, IsTransparencySet(TransparencyOption::Catenary), &east);
1435 }
1436 if (front != 0) {
1437 /* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
1438 AddSortableSpriteToDraw(front, pal, *ti, {{0, 0, static_cast<int8_t>(z_wires)}, {TILE_SIZE, TILE_SIZE, 1}, {0, 0, static_cast<int8_t>(-z_wires)}}, IsTransparencySet(TransparencyOption::Catenary));
1439 }
1440}
1441
1447{
1448 RoadBits road{};
1449 RoadBits tram{};
1450
1451 if (IsTileType(ti->tile, TileType::Road)) {
1452 if (IsNormalRoad(ti->tile)) {
1453 road = GetRoadBits(ti->tile, RoadTramType::Road);
1454 tram = GetRoadBits(ti->tile, RoadTramType::Tram);
1455 } else if (IsLevelCrossing(ti->tile)) {
1456 tram = road = GetCrossingRoadBits(ti->tile);
1457 }
1458 } else if (IsTileType(ti->tile, TileType::Station)) {
1459 if (IsAnyRoadStop(ti->tile)) {
1460 if (IsDriveThroughStopTile(ti->tile)) {
1461 Axis axis = GetDriveThroughStopAxis(ti->tile);
1462 tram = road = AxisToRoadBits(axis);
1463 } else {
1464 tram = road = DiagDirToRoadBits(GetBayRoadStopDir(ti->tile));
1465 }
1466 }
1467 } else {
1468 /* No road here, no catenary to draw */
1469 return;
1470 }
1471
1472 RoadType rt = GetRoadTypeRoad(ti->tile);
1473 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1474 DrawRoadTypeCatenary(ti, rt, road);
1475 }
1476
1477 rt = GetRoadTypeTram(ti->tile);
1478 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1479 DrawRoadTypeCatenary(ti, rt, tram);
1480 }
1481}
1482
1492static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int8_t dx, int8_t dy, uint8_t h, bool transparent)
1493{
1494 int x = ti->x | dx;
1495 int y = ti->y | dy;
1496 int z = ti->z;
1497 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1498 AddSortableSpriteToDraw(img, PAL_NONE, ti->x, ti->y, z, {{dx, dy, 0}, {2, 2, h}, {}}, transparent);
1499}
1500
1511void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
1512{
1513 if (draw_underlay) {
1514 /* Road underlay takes precedence over tram */
1515 if (road_rti != nullptr) {
1516 if (road_rti->UsesOverlay()) {
1518 DrawGroundSprite(ground + road_offset, pal);
1519 }
1520 } else {
1521 if (tram_rti->UsesOverlay()) {
1523 DrawGroundSprite(ground + tram_offset, pal);
1524 } else {
1525 DrawGroundSprite(SPR_TRAMWAY_TRAM + tram_offset, pal);
1526 }
1527 }
1528 }
1529
1530 /* Draw road overlay */
1531 if (road_rti != nullptr) {
1532 if (road_rti->UsesOverlay()) {
1534 if (ground != 0) DrawGroundSprite(ground + road_offset, pal);
1535 }
1536 }
1537
1538 /* Draw tram overlay */
1539 if (tram_rti != nullptr) {
1540 if (tram_rti->UsesOverlay()) {
1542 if (ground != 0) DrawGroundSprite(ground + tram_offset, pal);
1543 } else if (road_rti != nullptr) {
1544 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + tram_offset, pal);
1545 }
1546 }
1547}
1548
1559static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
1560{
1561 /* Draw bare ground sprite if no road or road uses overlay system. */
1562 if (rti == nullptr || rti->UsesOverlay()) {
1563 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1565 }
1566
1567 switch (roadside) {
1568 case Roadside::Barren:
1569 *pal = PALETTE_TO_BARE_LAND;
1571
1572 case Roadside::Grass:
1575
1576 default:
1577 break; // Paved
1578 }
1579 }
1580
1581 /* Draw original road base sprite */
1582 SpriteID image = SPR_ROAD_Y + offset;
1583 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1584 image += NUM_SLOPES;
1585 } else {
1586 switch (roadside) {
1587 case Roadside::Barren:
1588 *pal = PALETTE_TO_BARE_LAND;
1589 break;
1590
1591 case Roadside::Grass:
1593 break;
1594
1595 default:
1596 image -= NUM_SLOPES;
1597 break; // Paved
1598 }
1599 }
1600
1601 return image;
1602}
1603
1614void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
1615{
1616 /* Determine sprite offsets */
1617 uint road_offset = GetRoadSpriteOffset(ti->tileh, road);
1618 uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
1619
1620 /* Draw baseset underlay */
1621 PaletteID pal = PAL_NONE;
1622 SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road.None() ? tram_offset : road_offset, snow_or_desert, &pal);
1623 DrawGroundSprite(image, pal);
1624
1625 DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
1626}
1627
1632static void DrawRoadBits(TileInfo *ti)
1633{
1636
1637 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1638 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1639 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1640 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1641
1642 if (ti->tileh != SLOPE_FLAT) {
1643 DrawFoundation(ti, GetRoadFoundation(ti->tileh, road | tram));
1644 /* DrawFoundation() modifies ti. */
1645 }
1646
1647 DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnowOrDesert(ti->tile));
1648
1649 /* Draw one way */
1650 if (road_rti != nullptr) {
1652 if (drd.Any()) {
1654
1655 if (oneway == 0) oneway = SPR_ONEWAY_BASE;
1656
1657 if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) {
1658 oneway += ONEWAY_SLOPE_N_OFFSET;
1659 } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) {
1660 oneway += ONEWAY_SLOPE_S_OFFSET;
1661 }
1662
1663 DrawGroundSpriteAt(oneway + drd.base() - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1664 }
1665 }
1666
1667 if (HasRoadWorks(ti->tile)) {
1668 /* Road works */
1669 DrawGroundSprite((road | tram).Any(ROAD_X) ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1670 return;
1671 }
1672
1673 /* Draw road, tram catenary */
1674 DrawRoadCatenary(ti);
1675
1676 /* Return if full detail is disabled, or we are zoomed fully out. */
1677 if (!_display_opt.Test(DisplayOption::FullDetail) || _cur_dpi->zoom > ZoomLevel::Detail) return;
1678
1679 /* Do not draw details (street lights, trees) under low bridge */
1680 Roadside roadside = GetRoadside(ti->tile);
1681 if (IsBridgeAbove(ti->tile) && (roadside == Roadside::Trees || roadside == Roadside::StreetLights)) {
1682 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1683 int minz = GetTileMaxZ(ti->tile) + 2;
1684
1685 if (roadside == Roadside::Trees) minz++;
1686
1687 if (height < minz) return;
1688 }
1689
1690 /* If there are no road bits, return, as there is nothing left to do */
1691 if (road.Count() <= 1) return;
1692
1693 /* Do not draw details when invisible. */
1696
1697 /* Check whether details should be transparent. */
1698 bool is_transparent = false;
1700 is_transparent = true;
1701 }
1703 is_transparent = true;
1704 }
1705
1706 /* Draw extra details. */
1707 for (const DrawRoadTileStruct *drts = _road_display_table[to_underlying(roadside)][(road | tram).base()]; drts->image != 0; drts++) {
1708 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
1709 }
1710}
1711
1713static void DrawTile_Road(TileInfo *ti)
1714{
1715 BridgePillarFlags blocked_pillars{};
1716 switch (GetRoadTileType(ti->tile)) {
1718 DrawRoadBits(ti);
1719
1720 if (IsBridgeAbove(ti->tile)) {
1721 RoadBits bits = GetAllRoadBits(ti->tile);
1722 if (bits.Test(RoadBit::NE)) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
1723 if (bits.Test(RoadBit::SE)) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
1724 if (bits.Test(RoadBit::SW)) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
1725 if (bits.Test(RoadBit::NW)) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
1726 }
1727 break;
1728
1731
1732 Axis axis = GetCrossingRailAxis(ti->tile);
1733
1734 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1735
1736 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1737 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1738 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1739 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1740
1741 PaletteID pal = PAL_NONE;
1742
1743 /* Draw base ground */
1744 if (rti->UsesOverlay()) {
1745 SpriteID image = SPR_ROAD_Y + to_underlying(axis);
1746
1747 Roadside roadside = GetRoadside(ti->tile);
1748 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1749 image += NUM_SLOPES;
1750 } else {
1751 switch (roadside) {
1752 case Roadside::Barren:
1754 break;
1755
1756 case Roadside::Grass:
1757 break;
1758
1759 default:
1760 image -= NUM_SLOPES;
1761 break; // Paved
1762 }
1763 }
1764
1765 DrawGroundSprite(image, pal);
1766 } else {
1767 SpriteID image = rti->base_sprites.crossing + to_underlying(axis);
1768 if (IsCrossingBarred(ti->tile)) image += 2;
1769
1770 Roadside roadside = GetRoadside(ti->tile);
1771 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1772 image += 8;
1773 } else {
1774 switch (roadside) {
1775 case Roadside::Barren:
1777 break;
1778
1779 case Roadside::Grass:
1780 break;
1781
1782 default:
1783 image += 4;
1784 break; // Paved
1785 }
1786 }
1787
1788 DrawGroundSprite(image, pal);
1789 }
1790
1791 DrawRoadOverlays(ti, pal, road_rti, tram_rti, to_underlying(axis), to_underlying(axis));
1792
1793 /* Draw rail/PBS overlay */
1794 bool draw_pbs = _game_mode != GameMode::Menu && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile);
1795 if (rti->UsesOverlay()) {
1796 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1798 DrawGroundSprite(rail, pal);
1799
1800 Axis road_axis = GetCrossingRoadAxis(ti->tile);
1801 DiagDirections adjacent_diagdirs{};
1802 for (DiagDirection dir : AxisToDiagDirs(road_axis)) {
1803 const TileIndex t = TileAddByDiagDir(ti->tile, dir);
1804 if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
1805 adjacent_diagdirs.Set(dir);
1806 }
1807 }
1808
1809 switch (adjacent_diagdirs.base()) {
1810 case DiagDirections{}.base():
1811 DrawRailTileSeq(ti, &_crossing_layout, TransparencyOption::Catenary, rail, 0, PAL_NONE);
1812 break;
1813
1814 case DiagDirections{DiagDirection::NE}.base():
1815 DrawRailTileSeq(ti, &_crossing_layout_SW, TransparencyOption::Catenary, rail, 0, PAL_NONE);
1816 break;
1817
1818 case DiagDirections{DiagDirection::SE}.base():
1819 DrawRailTileSeq(ti, &_crossing_layout_NW, TransparencyOption::Catenary, rail, 0, PAL_NONE);
1820 break;
1821
1822 case DiagDirections{DiagDirection::SW}.base():
1823 DrawRailTileSeq(ti, &_crossing_layout_NE, TransparencyOption::Catenary, rail, 0, PAL_NONE);
1824 break;
1825
1826 case DiagDirections{DiagDirection::NW}.base():
1827 DrawRailTileSeq(ti, &_crossing_layout_SE, TransparencyOption::Catenary, rail, 0, PAL_NONE);
1828 break;
1829
1830 default:
1831 /* Show no sprites */
1832 break;
1833 }
1834 } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) {
1835 /* Add another rail overlay, unless there is only the base road sprite. */
1836 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1838 DrawGroundSprite(rail, pal);
1839 }
1840
1841 /* Draw road, tram catenary */
1842 DrawRoadCatenary(ti);
1843
1844 /* Draw rail catenary */
1847 break;
1848 }
1849
1850 default:
1851 case RoadTileType::Depot: {
1853
1855
1856 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1857 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1858 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt == INVALID_ROADTYPE ? tram_rt : road_rt);
1859
1860 int relocation = GetCustomRoadSprite(rti, ti->tile, RoadSpriteType::Depot);
1861 bool default_gfx = relocation == 0;
1862 if (default_gfx) {
1863 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1864 if (_loaded_newgrf_features.tram == TramDepotReplacement::WithTrack && road_rt == INVALID_ROADTYPE && !rti->UsesOverlay()) {
1865 /* Sprites with track only work for default tram */
1867 default_gfx = false;
1868 } else {
1869 /* Sprites without track are always better, if provided */
1871 }
1872 }
1873 } else {
1874 relocation -= SPR_ROAD_DEPOT;
1875 }
1876
1878 const DrawTileSprites *dts = &_road_depot[dir];
1879 DrawGroundSprite(dts->ground.sprite, PAL_NONE);
1880
1881 if (default_gfx) {
1883 if (rti->UsesOverlay()) {
1885 if (ground != 0) DrawGroundSprite(ground + offset, PAL_NONE);
1886 } else if (road_rt == INVALID_ROADTYPE) {
1887 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE);
1888 }
1889 }
1890
1891 DrawRailTileSeq(ti, dts, TransparencyOption::Buildings, relocation, 0, palette);
1892 blocked_pillars = BRIDGEPILLARFLAGS_ALL;
1893 break;
1894 }
1895 }
1896 DrawBridgeMiddle(ti, blocked_pillars);
1897}
1898
1906void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
1907{
1909
1910 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1912 bool default_gfx = relocation == 0;
1913 if (default_gfx) {
1914 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1915 if (_loaded_newgrf_features.tram == TramDepotReplacement::WithTrack && RoadTypeIsTram(rt) && !rti->UsesOverlay()) {
1916 /* Sprites with track only work for default tram */
1918 default_gfx = false;
1919 } else {
1920 /* Sprites without track are always better, if provided */
1922 }
1923 }
1924 } else {
1925 relocation -= SPR_ROAD_DEPOT;
1926 }
1927
1928 const DrawTileSprites *dts = &_road_depot[dir];
1929 DrawSprite(dts->ground.sprite, PAL_NONE, x, y);
1930
1931 if (default_gfx) {
1933 if (rti->UsesOverlay()) {
1935 if (ground != 0) DrawSprite(ground + offset, PAL_NONE, x, y);
1936 } else if (RoadTypeIsTram(rt)) {
1937 DrawSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE, x, y);
1938 }
1939 }
1940
1941 DrawRailTileSeqInGUI(x, y, dts, relocation, 0, palette);
1942}
1943
1950{
1951 assert(!invalidate || _generating_world);
1952
1953 for (const auto t : Map::Iterate()) {
1954 if (IsTileType(t, TileType::Road) && !IsRoadDepot(t) && !HasTownOwnedRoad(t)) {
1955 TownID tid = TownID::Invalid();
1956 if (!invalidate) {
1957 const Town *town = CalcClosestTownFromTile(t);
1958 if (town != nullptr) tid = town->index;
1959 }
1960 SetTownIndex(t, tid);
1961 }
1962 }
1963}
1964
1966static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, [[maybe_unused]] bool ground_vehicle)
1967{
1968
1969 if (IsNormalRoad(tile)) {
1970 auto [tileh, z] = GetTilePixelSlope(tile);
1971 if (tileh == SLOPE_FLAT) return z;
1972
1974 z += ApplyPixelFoundationToSlope(f, tileh);
1975 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1976 } else {
1977 return GetTileMaxPixelZ(tile);
1978 }
1979}
1980
1983{
1984 if (IsNormalRoad(tile)) {
1985 return GetRoadFoundation(tileh, GetAllRoadBits(tile));
1986 } else {
1987 return FlatteningFoundation(tileh);
1988 }
1989}
1990
1991static const Roadside _town_road_types[][2] = {
1997};
1998
1999static_assert(lengthof(_town_road_types) == NUM_HOUSE_ZONES);
2000
2001static const Roadside _town_road_types_2[][2] = {
2007};
2008
2009static_assert(lengthof(_town_road_types_2) == NUM_HOUSE_ZONES);
2010
2011
2013static void TileLoop_Road(TileIndex tile)
2014{
2015 switch (_settings_game.game_creation.landscape) {
2016 case LandscapeType::Arctic: {
2017 /* Roads use the snow level of their maximum height minus one, unless flat. */
2018 int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileMaxZ(tile) - 1;
2019 if (IsOnSnowOrDesert(tile) != (tile_z > GetSnowLine())) {
2020 ToggleSnowOrDesert(tile);
2021 MarkTileDirtyByTile(tile);
2022 }
2023 break;
2024 }
2025
2027 if (GetTropicZone(tile) == TropicZone::Desert && !IsOnSnowOrDesert(tile)) {
2028 ToggleSnowOrDesert(tile);
2029 MarkTileDirtyByTile(tile);
2030 }
2031 break;
2032
2033 default:
2034 break;
2035 }
2036
2037 if (IsRoadDepot(tile)) return;
2038
2039 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
2040 if (!HasRoadWorks(tile)) {
2042
2043 if (t != nullptr) {
2044 grp = GetTownRadiusGroup(t, tile);
2045
2046 /* Show an animation to indicate road work */
2047 if (t->road_build_months != 0 &&
2048 (DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) &&
2049 IsNormalRoad(tile) && GetAllRoadBits(tile).Count() > 1) {
2050 if (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
2051 StartRoadWorks(tile);
2052
2053 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
2055 TileX(tile) * TILE_SIZE + 7,
2056 TileY(tile) * TILE_SIZE + 7,
2057 0,
2058 EV_BULLDOZER);
2059 MarkTileDirtyByTile(tile);
2060 return;
2061 }
2062 }
2063 }
2064
2065 {
2066 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2067 const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[to_underlying(grp)] : _town_road_types[to_underlying(grp)];
2068 Roadside cur_rs = GetRoadside(tile);
2069
2070 /* We have our desired type, do nothing */
2071 if (cur_rs == new_rs[0]) return;
2072
2073 /* We have the pre-type of the desired type, switch to the desired type */
2074 if (cur_rs == new_rs[1]) {
2075 cur_rs = new_rs[0];
2076 /* We have barren land, install the pre-type */
2077 } else if (cur_rs == Roadside::Barren) {
2078 cur_rs = new_rs[1];
2079 /* We're totally off limits, remove any installation and make barren land */
2080 } else {
2081 cur_rs = Roadside::Barren;
2082 }
2083 SetRoadside(tile, cur_rs);
2084 MarkTileDirtyByTile(tile);
2085 }
2086 } else if (IncreaseRoadWorksCounter(tile)) {
2087 TerminateRoadWorks(tile);
2088
2089 if (_settings_game.economy.mod_road_rebuild) {
2090 /* Generate a nicer town surface */
2092 RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2093
2094 if (old_rb != new_rb) {
2096
2097 /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */
2098 if (new_rb.None()) {
2099 MarkTileDirtyByTile(tile);
2100 return;
2101 }
2102 }
2103 }
2104
2105 /* Possibly change road type */
2108 if (rt != GetRoadTypeRoad(tile)) {
2110 }
2111 }
2112
2113 MarkTileDirtyByTile(tile);
2114 }
2115}
2116
2118static bool ClickTile_Road(TileIndex tile)
2119{
2120 if (!IsRoadDepot(tile)) return false;
2121
2123 return true;
2124}
2125
2127static const TrackBits _road_trackbits[16] = {
2128 {}, // ROAD_NONE
2129 {}, // RoadBit::NW
2130 {}, // RoadBit::SW
2131 Track::Left, // ROAD_W
2132 {}, // RoadBit::SE
2133 Track::Y, // ROAD_Y
2134 Track::Lower, // ROAD_S
2135 {Track::Left, Track::Lower, Track::Y}, // ROAD_Y | RoadBit::SW
2136 {}, // RoadBit::NE
2137 Track::Upper, // ROAD_N
2138 Track::X, // ROAD_X
2139 {Track::Left, Track::Upper, Track::X}, // ROAD_X | RoadBit::NW
2140 Track::Right, // ROAD_E
2141 {Track::Right, Track::Upper, Track::Y}, // ROAD_Y | RoadBit::NE
2142 {Track::Right, Track::Lower, Track::X}, // ROAD_X | RoadBit::SE
2143 TRACK_BIT_ALL, // ROAD_ALL
2144};
2145
2148{
2149 TrackdirBits trackdirbits{};
2150 TrackdirBits red_signals{}; // crossing barred
2151 switch (mode) {
2153 if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailTrack(tile));
2154 break;
2155
2156 case TransportType::Road: {
2157 RoadTramType rtt = (RoadTramType)sub_mode;
2158 if (!HasTileRoadType(tile, rtt)) break;
2159 switch (GetRoadTileType(tile)) {
2160 case RoadTileType::Normal: {
2161 const uint drd_to_multiplier[] = { 0x101, 0x100, 0x1, 0x0 };
2162 RoadBits bits = GetRoadBits(tile, rtt);
2163
2164 /* no roadbit at this side of tile, return 0 */
2165 if (side != DiagDirection::Invalid && !DiagDirToRoadBits(side).Any(bits)) break;
2166
2167 uint multiplier = drd_to_multiplier[(rtt == RoadTramType::Tram) ? 0 : GetDisallowedRoadDirections(tile).base()];
2168 if (!HasRoadWorks(tile)) trackdirbits = static_cast<TrackdirBits>(_road_trackbits[bits.base()].base() * multiplier);
2169 break;
2170 }
2171
2173 Axis axis = GetCrossingRoadAxis(tile);
2174
2175 if (side != DiagDirection::Invalid && axis != DiagDirToAxis(side)) break;
2176
2177 trackdirbits = TrackBitsToTrackdirBits(AxisToTrack(axis));
2178 if (IsCrossingBarred(tile)) {
2179 red_signals = trackdirbits;
2180 if (TrainOnCrossing(tile)) break;
2181
2182 auto mask_red_signal_bits_if_crossing_barred = [&](TileIndex t, TrackdirBits mask) {
2183 if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
2184 };
2185 /* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
2186 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), {Trackdir::X_SW, Trackdir::Y_SE});
2187 /* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
2188 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), {Trackdir::X_NE, Trackdir::Y_NW});
2189 }
2190 break;
2191 }
2192
2193 default:
2194 case RoadTileType::Depot: {
2196
2197 if (side != DiagDirection::Invalid && side != dir) break;
2198
2199 trackdirbits = TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir));
2200 break;
2201 }
2202 }
2203 break;
2204 }
2205
2206 default: break;
2207 }
2208 return {trackdirbits, red_signals};
2209}
2210
2211static const StringID _road_tile_strings[] = {
2212 STR_LAI_ROAD_DESCRIPTION_ROAD,
2213 STR_LAI_ROAD_DESCRIPTION_ROAD,
2214 STR_LAI_ROAD_DESCRIPTION_ROAD,
2215 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2216 STR_LAI_ROAD_DESCRIPTION_ROAD,
2217 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2218 STR_LAI_ROAD_DESCRIPTION_ROAD,
2219 STR_LAI_ROAD_DESCRIPTION_ROAD,
2220};
2221
2224{
2225 Owner rail_owner = INVALID_OWNER;
2226 Owner road_owner = INVALID_OWNER;
2227 Owner tram_owner = INVALID_OWNER;
2228
2229 RoadType road_rt = GetRoadTypeRoad(tile);
2230 RoadType tram_rt = GetRoadTypeTram(tile);
2231 if (road_rt != INVALID_ROADTYPE) {
2232 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
2233 td.roadtype = rti->strings.name;
2234 td.road_speed = rti->max_speed / 2;
2235 road_owner = GetRoadOwner(tile, RoadTramType::Road);
2236 }
2237 if (tram_rt != INVALID_ROADTYPE) {
2238 const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
2239 td.tramtype = rti->strings.name;
2240 td.tram_speed = rti->max_speed / 2;
2241 tram_owner = GetRoadOwner(tile, RoadTramType::Tram);
2242 }
2243
2244 switch (GetRoadTileType(tile)) {
2246 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING;
2247 rail_owner = GetTileOwner(tile);
2248
2249 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2250 td.railtype = rti->strings.name;
2251 td.rail_speed = rti->max_speed;
2252
2253 break;
2254 }
2255
2257 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
2258 td.build_date = Depot::GetByTile(tile)->build_date;
2259 break;
2260
2261 default: {
2262 td.str = (road_rt != INVALID_ROADTYPE ? _road_tile_strings[to_underlying(GetRoadside(tile))] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
2263 break;
2264 }
2265 }
2266
2267 /* Now we have to discover, if the tile has only one owner or many:
2268 * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
2269 * - Compare the found owner with the other owners, and test if they differ.
2270 * Note: If road exists it will be the first_owner.
2271 */
2272 Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
2273 bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
2274
2275 if (mixed_owners) {
2276 /* Multiple owners */
2277 td.owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_RAIL_OWNER);
2278 td.owner[0] = rail_owner;
2279 td.owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_ROAD_OWNER);
2280 td.owner[1] = road_owner;
2281 td.owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_TRAM_OWNER);
2282 td.owner[2] = tram_owner;
2283 } else {
2284 /* One to rule them all */
2285 td.owner[0] = first_owner;
2286 }
2287}
2288
2296
2298static VehicleEnterTileStates VehicleEnterTile_Road(Vehicle *v, TileIndex tile, [[maybe_unused]] int x, [[maybe_unused]] int y)
2299{
2300 switch (GetRoadTileType(tile)) {
2301 case RoadTileType::Depot: {
2302 if (v->type != VehicleType::Road) break;
2303
2305 if (rv->frame == RVC_DEPOT_STOP_FRAME &&
2306 _roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == static_cast<Trackdir>(rv->state)) {
2307 rv->state = RVSB_IN_DEPOT;
2309 rv->direction = ReverseDir(rv->direction);
2310 if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
2311 rv->tile = tile;
2312
2313 InvalidateWindowData(WindowClass::VehicleDepot, rv->tile);
2315 }
2316 break;
2317 }
2318
2319 default: break;
2320 }
2321 return {};
2322}
2323
2324
2326static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2327{
2328 if (IsRoadDepot(tile)) {
2329 if (GetTileOwner(tile) == old_owner) {
2330 if (new_owner == INVALID_OWNER) {
2331 Command<Commands::LandscapeClear>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile);
2332 } else {
2333 /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2334 RoadType rt = GetRoadTypeRoad(tile);
2335 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
2336 Company::Get(old_owner)->infrastructure.road[rt] -= 2;
2337 Company::Get(new_owner)->infrastructure.road[rt] += 2;
2338
2339 SetTileOwner(tile, new_owner);
2340 for (RoadTramType rtt : ROADTRAMTYPES_ALL) {
2341 if (GetRoadOwner(tile, rtt) == old_owner) {
2342 SetRoadOwner(tile, rtt, new_owner);
2343 }
2344 }
2345 }
2346 }
2347 return;
2348 }
2349
2350 for (RoadTramType rtt : ROADTRAMTYPES_ALL) {
2351 /* Update all roadtypes, no matter if they are present */
2352 if (GetRoadOwner(tile, rtt) == old_owner) {
2353 RoadType rt = GetRoadType(tile, rtt);
2354 if (rt != INVALID_ROADTYPE) {
2355 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2356 uint num_bits = IsLevelCrossing(tile) ? 2 : GetRoadBits(tile, rtt).Count();
2357 Company::Get(old_owner)->infrastructure.road[rt] -= num_bits;
2358 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits;
2359 }
2360
2361 SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
2362 }
2363 }
2364
2365 if (IsLevelCrossing(tile)) {
2366 if (GetTileOwner(tile) == old_owner) {
2367 if (new_owner == INVALID_OWNER) {
2368 Command<Commands::RemoveRail>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile, GetCrossingRailTrack(tile));
2369 } else {
2370 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2371 Company::Get(old_owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
2372 Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
2373
2374 SetTileOwner(tile, new_owner);
2375 }
2376 }
2377 }
2378}
2379
2381static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
2382{
2383 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
2384 switch (GetRoadTileType(tile)) {
2386 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(ExpensesType::Construction, _price[Price::BuildFoundation]);
2387 break;
2388
2391 break;
2392
2393 case RoadTileType::Normal: {
2394 RoadBits bits = GetAllRoadBits(tile);
2395 RoadBits bits_copy = bits;
2396 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2397 if (CheckRoadSlope(tileh_new, &bits_copy, {}, {}).Succeeded()) {
2398 /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
2399 if (bits == bits_copy) {
2400 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2401
2402 /* Get the slope on top of the foundation */
2403 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), tileh_old);
2404 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), tileh_new);
2405
2406 /* The surface slope must not be changed */
2407 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(ExpensesType::Construction, _price[Price::BuildFoundation]);
2408 }
2409 }
2410 break;
2411 }
2412
2413 default: NOT_REACHED();
2414 }
2415 }
2416
2417 return Command<Commands::LandscapeClear>::Do(flags, tile);
2418}
2419
2426static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
2427{
2428 return (owner == OWNER_NONE || (owner == OWNER_TOWN && rtt == RoadTramType::Road));
2429}
2430
2439static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
2440{
2441 /* Scenario editor, maybe? Don't touch the owners when converting roadtypes... */
2442 if (_current_company >= MAX_COMPANIES) return;
2443
2444 /* We can't get a company from invalid owners but we can get ownership of roads without an owner */
2445 if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
2446
2447 Company *c;
2448
2449 switch (owner.base()) {
2450 case OWNER_NONE.base():
2451 SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company);
2453 break;
2454
2455 default:
2456 c = Company::Get(owner);
2457 c->infrastructure.road[from_type] -= num_pieces;
2458 c->infrastructure.road[to_type] += num_pieces;
2460 break;
2461 }
2462}
2463
2475CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal)
2476{
2477 TileIndex area_end = tile;
2478
2479 if (!ValParamRoadType(to_type)) return CMD_ERROR;
2480 if (area_start >= Map::Size()) return CMD_ERROR;
2481
2482 RoadVehicleList affected_rvs;
2483 RoadTramType rtt = GetRoadTramType(to_type);
2484
2486 CommandCost error = CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert.
2487 bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633)
2488
2489 std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal);
2490 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
2491 /* Is road present on tile? */
2492 if (!MayHaveRoad(tile)) continue;
2493
2494 /* Converting to the same subtype? */
2495 RoadType from_type = GetRoadType(tile, rtt);
2496 if (from_type == INVALID_ROADTYPE || from_type == to_type) continue;
2497
2498 /* Check if there is any infrastructure on tile */
2499 TileType tt = GetTileType(tile);
2500 switch (tt) {
2501 case TileType::Station:
2502 if (!IsAnyRoadStop(tile)) continue;
2503 break;
2504 case TileType::Road:
2505 if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
2506 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD);
2507 continue;
2508 }
2509 break;
2512 break;
2513 default: continue;
2514 }
2515
2516 /* Trying to convert other's road */
2517 Owner owner = GetRoadOwner(tile, rtt);
2518 if (!CanConvertUnownedRoadType(owner, rtt)) {
2519 CommandCost ret = CheckOwnership(owner, tile);
2520 if (ret.Failed()) {
2521 error = std::move(ret);
2522 continue;
2523 }
2524 }
2525
2526 /* Base the ability to replace town roads and bridges on the town's
2527 * acceptance of destructive actions. */
2528 if (owner == OWNER_TOWN) {
2529 Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
2531 if (ret.Failed()) {
2532 error = std::move(ret);
2533 continue;
2534 }
2535 }
2536
2537 /* Vehicle on the tile when not converting normal <-> powered
2538 * Tunnels and bridges have special check later */
2539 if (tt != TileType::TunnelBridge) {
2540 if (!HasPowerOnRoad(from_type, to_type)) {
2542 if (ret.Failed()) {
2543 error = std::move(ret);
2544 continue;
2545 }
2546
2547 if (rtt == RoadTramType::Road && owner == OWNER_TOWN) {
2548 error.MakeError(STR_ERROR_OWNED_BY);
2549 if (IsLocalCompany()) {
2550 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2551 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2552 }
2553 continue;
2554 }
2555 }
2556
2557 uint num_pieces = GetAnyRoadBits(tile, rtt).Count();
2558 if (tt == TileType::Station && IsBayRoadStopTile(tile)) {
2559 num_pieces *= ROAD_STOP_TRACKBIT_FACTOR;
2560 } else if (tt == TileType::Road && IsRoadDepot(tile)) {
2561 num_pieces *= ROAD_DEPOT_TRACKBIT_FACTOR;
2562 }
2563
2564 found_convertible_road = true;
2565 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2566
2567 if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
2568 /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */
2569 if (owner == _current_company) {
2570 ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
2571 }
2572
2573 /* Perform the conversion */
2574 SetRoadType(tile, rtt, to_type);
2575 MarkTileDirtyByTile(tile);
2576
2577 /* update power of train on this tile */
2578 for (Vehicle *v : VehiclesOnTile(tile)) {
2579 if (v->type == VehicleType::Road) include(affected_rvs, RoadVehicle::From(v)->First());
2580 }
2581
2582 if (IsRoadDepotTile(tile)) {
2583 /* Update build vehicle window related to this depot */
2584 InvalidateWindowData(WindowClass::VehicleDepot, tile);
2585 InvalidateWindowData(WindowClass::BuildVehicle, tile);
2586 }
2587 }
2588 } else {
2589 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
2590
2591 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
2592 * it would cause assert because of different test and exec runs */
2593 if (endtile < tile) {
2594 if (diagonal) {
2595 if (DiagonalTileArea(area_start, area_end).Contains(endtile)) continue;
2596 } else {
2597 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
2598 }
2599 }
2600
2601 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
2602 if (!HasPowerOnRoad(from_type, to_type)) {
2603 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
2604 if (ret.Failed()) {
2605 error = std::move(ret);
2606 continue;
2607 }
2608
2609 if (rtt == RoadTramType::Road && owner == OWNER_TOWN) {
2610 error.MakeError(STR_ERROR_OWNED_BY);
2611 if (IsLocalCompany()) {
2612 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2613 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2614 }
2615 continue;
2616 }
2617 }
2618
2619 /* There are 2 pieces on *every* tile of the bridge or tunnel */
2620 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * 2;
2621 found_convertible_road = true;
2622 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2623
2624 if (flags.Test(DoCommandFlag::Execute)) {
2625 /* Update the company infrastructure counters. */
2626 if (owner == _current_company) {
2627 /* Each piece should be counted TUNNELBRIDGE_TRACKBIT_FACTOR times
2628 * for the infrastructure counters (cause of #8297). */
2629 ConvertRoadTypeOwner(tile, num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR, owner, from_type, to_type);
2630 SetTunnelBridgeOwner(tile, endtile, _current_company);
2631 }
2632
2633 /* Perform the conversion */
2634 SetRoadType(tile, rtt, to_type);
2635 SetRoadType(endtile, rtt, to_type);
2636
2637 for (Vehicle *v : VehiclesOnTile(tile)) {
2638 if (v->type == VehicleType::Road) include(affected_rvs, RoadVehicle::From(v)->First());
2639 }
2640 for (Vehicle *v : VehiclesOnTile(endtile)) {
2641 if (v->type == VehicleType::Road) include(affected_rvs, RoadVehicle::From(v)->First());
2642 }
2643
2644 if (IsBridge(tile)) {
2645 MarkBridgeDirty(tile);
2646 } else {
2647 MarkTileDirtyByTile(tile);
2648 MarkTileDirtyByTile(endtile);
2649 }
2650 }
2651 }
2652 }
2653
2654 if (flags.Test(DoCommandFlag::Execute)) {
2655 /* Roadtype changed, update roadvehicles as when entering different track */
2656 for (RoadVehicle *v : affected_rvs) {
2657 v->CargoChanged();
2658 }
2659 }
2660
2661 return found_convertible_road ? cost : error;
2662}
2663
2665static CommandCost CheckBuildAbove_Road(TileIndex tile, [[maybe_unused]] DoCommandFlags flags, [[maybe_unused]] Axis axis, int height)
2666{
2667 if (!IsRoadDepot(tile)) return CommandCost();
2668
2669 int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - height;
2670 if (height_diff <= 0) return CommandCost();
2671 return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADVEH_DEPOT, height_diff * TILE_HEIGHT_STEP);
2672}
2673
2675extern const TileTypeProcs _tile_type_road_procs = {
2676 .draw_tile_proc = DrawTile_Road,
2677 .get_slope_pixel_z_proc = GetSlopePixelZ_Road,
2678 .clear_tile_proc = ClearTile_Road,
2679 .get_tile_desc_proc = GetTileDesc_Road,
2680 .get_tile_track_status_proc = GetTileTrackStatus_Road,
2681 .click_tile_proc = ClickTile_Road,
2682 .tile_loop_proc = TileLoop_Road,
2683 .change_tile_owner_proc = ChangeTileOwner_Road,
2684 .vehicle_enter_tile_proc = VehicleEnterTile_Road,
2685 .get_foundation_proc = GetFoundation_Road,
2686 .terraform_tile_proc = TerraformTile_Road,
2687 .check_build_above_proc = CheckBuildAbove_Road,
2688};
@ None
Tile is not animated.
Functions related to autoslope.
bool AutoslopeCheckForEntranceEdge(TileIndex tile, int z_new, Slope tileh_new, DiagDirection entrance)
Autoslope check for tiles with an entrance on an edge.
Definition autoslope.h:31
bool AutoslopeEnabled()
Tests if autoslope is enabled for _current_company.
Definition autoslope.h:65
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
void DrawBridgeMiddle(const TileInfo *ti, BridgePillarFlags blocked_pillars)
Draw the middle bits of a bridge.
TileIndex GetSouthernBridgeEnd(TileIndex t)
Finds the southern end of a bridge starting at a middle tile.
TileIndex GetNorthernBridgeEnd(TileIndex t)
Finds the northern end of a bridge starting at a middle tile.
int GetBridgeHeight(TileIndex t)
Get the height ('z') of a bridge.
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
bool IsBridge(Tile t)
Checks if this is a bridge, instead of a tunnel.
Definition bridge_map.h:24
EnumBitSet< BridgePillarFlag, uint8_t > BridgePillarFlags
Bitset of BridgePillarFlag elements.
Definition bridge_type.h:53
@ EdgeNE
Northeast edge is obstructed.
Definition bridge_type.h:46
@ EdgeSW
Southwest edge is obstructed.
Definition bridge_type.h:48
@ EdgeNW
Northwest edge is obstructed.
Definition bridge_type.h:49
@ EdgeSE
Southeast edge is obstructed.
Definition bridge_type.h:47
Cheats _cheats
All the cheats.
Definition cheat.cpp:16
Types related to cheating.
uint Count() const
Count the number of set bits.
constexpr bool All(const Timpl &other) const
Test if all of the values are set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit 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.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
void MakeError(StringID message)
Makes this CommandCost behave like an error command.
Money GetCost() const
The costs as made up to this moment.
void SetEncodedMessage(EncodedString &&message)
Set the encoded message string.
bool Failed() const
Did this command fail?
StringID GetErrorMessage() const
Returns the error message of a command.
Iterate a range of enum values.
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:117
SpriteID single_x
single piece of rail in X direction, without ground
Definition rail.h:127
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:222
struct RailTypeInfo::@157247141350136173143103254227157213063052244122 strings
Strings associated with the rail type.
SpriteID crossing
level crossing, rail in X direction
Definition rail.h:134
SpriteID single_y
single piece of rail in Y direction, without ground
Definition rail.h:128
StringID name
Name of this rail type.
Definition rail.h:167
struct RailTypeInfo::@332027037331076264023214171276243307073252216167 base_sprites
Struct containing the main sprites.
RoadTypeLabel label
Unique 32 bit road type identifier.
Definition road.h:123
struct RoadTypeInfo::@040007041145073342004320043002073006000034160103 gui_sprites
struct containing the sprites for the road GUI.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:98
struct RoadTypeInfo::@262365004142063215107272155332373126354130071373 cursor
Cursors associated with the road type.
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:153
RoadType Index() const
Get the RoadType for this RoadTypeInfo.
Definition road.cpp:30
CursorID autoroad
Cursor for autorail tool.
Definition road.h:72
TimerGameCalendar::Date introduction_date
Introduction date.
Definition road.h:142
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
Definition road.h:158
RoadTypeFlags flags
Bit mask of road type flags.
Definition road.h:103
FlatSet< RoadTypeLabel > alternate_labels
Road type labels this type provides in addition to the main label.
Definition road.h:128
CursorID depot
Cursor for building a depot.
Definition road.h:73
CursorID road_nwse
Cursor for building rail in Y direction.
Definition road.h:71
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:118
struct RoadTypeInfo::@070000167274302256150317022075324310363002361255 strings
Strings associated with the rail type.
StringID name
Name of this rail type.
Definition road.h:79
SpriteID build_y_road
button for building single rail in Y direction
Definition road.h:62
CursorID tunnel
Cursor for building a tunnel.
Definition road.h:74
SpriteID auto_road
button for the autoroad construction
Definition road.h:63
SpriteID convert_road
button for converting road types
Definition road.h:66
CursorID road_swne
Cursor for building rail in X direction.
Definition road.h:70
SpriteID build_x_road
button for building single rail in X direction
Definition road.h:61
SpriteID build_depot
button for building depots
Definition road.h:64
SpriteID build_tunnel
button for building a tunnel
Definition road.h:65
static std::unique_ptr< TileIterator > Create(TileIndex corner1, TileIndex corner2, bool diagonal)
Create either an OrthogonalTileIterator or DiagonalTileIterator given the diagonal parameter.
Definition tilearea.cpp:292
static constexpr TimerGame< struct Calendar >::Date INVALID_DATE
Iterate over all vehicles on a tile.
CommandCost CommandCostWithParam(StringID str, uint64_t value)
Return an error status, with string and parameter.
Definition command.cpp:416
Functions related to commands.
CommandCost & ExtractCommandCost(Tret &ret)
Extract the CommandCost from a command proc result.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Auto
don't allow building on structures
@ NoWater
don't allow building on water
@ Execute
execute the given command
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
Definition of stuff that is very close to a company, like the company struct itself.
std::array< StringParameter, 2 > GetParamsForOwnedBy(Owner owner, TileIndex tile)
Get the right StringParameters for STR_ERROR_OWNED_BY.
CommandCost CheckTileOwnership(TileIndex tile)
Check whether the current owner owns the stuff on the given tile.
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
Money GetAvailableMoneyForCommand()
This functions returns the money which can be used to execute a command.
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.
Functions related to companies.
bool IsLocalCompany()
Is the current company the local company?
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
static constexpr Owner OWNER_TOWN
A town owns the tile, or a town is expanding.
static constexpr Owner OWNER_NONE
The tile has no ownership.
static constexpr Owner INVALID_OWNER
An invalid owner.
static constexpr Owner OWNER_WATER
The tile/execution is done by "water".
Some simple functions to help with accessing containers.
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
Base for all depots (except hangars).
bool CanBuildDepotByTileh(DiagDirection direction, Slope tileh)
Find out if the slope of the tile is suitable to build a depot of given direction.
Definition depot_func.h:27
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
static constexpr uint8_t MINIMAL_DEPOT_BRIDGE_HEIGHT
Minimal height for a bridge above any depot tile.
Definition depot_type.h:21
bool IsValidAxis(Axis d)
Checks if an integer value is a valid Axis.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirections AxisToDiagDirs(Axis a)
Converts an Axis to DiagDirections.
Direction ReverseDir(Direction d)
Return the reverse of a direction.
bool IsValidDiagDirection(DiagDirection d)
Checks if an integer value is a valid DiagDirection.
DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
Axis OtherAxis(Axis a)
Select the other axis as provided.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
EnumIndexArray< T, DiagDirection, DiagDirection::End > DiagDirectionIndexArray
Array with DiagDirection as index.
Axis
Enumeration for the two axis X and Y.
@ X
The X axis.
@ Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ Invalid
Flag for an invalid DiagDirection.
@ SW
Southwest.
@ NW
Northwest.
@ End
Used for iterations.
@ NE
Northeast, upper right on your monitor.
@ SE
Southeast.
EnumBitSet< DiagDirection, uint8_t > DiagDirections
Bitset of DiagDirection elements.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:106
static const uint LEVELCROSSING_TRACKBIT_FACTOR
Multiplier for how many regular track bits a level crossing counts.
static const uint ROAD_STOP_TRACKBIT_FACTOR
Multiplier for how many regular track bits a bay stop counts.
static const uint ROAD_DEPOT_TRACKBIT_FACTOR
Multiplier for how many regular track bits a road depot counts.
@ Construction
Construction costs.
static const uint TUNNELBRIDGE_TRACKBIT_FACTOR
Multiplier for how many regular track bits a tunnel/bridge counts.
@ ClearDepotRoad
Price for destroying road vehicle depots.
@ BuildFoundation
Price for building foundation under other constructions e.g. roads, rails, depots,...
@ BuildDepotRoad
Price for building road vehicle depots.
EffectVehicle * CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular location.
Base class for all effect vehicles.
Functions related to effect vehicles.
@ EV_BULLDOZER
Bulldozer at roadworks.
void DrawRailCatenary(const TileInfo *ti)
Draws overhead wires and pylons for electric railways.
Definition elrail.cpp:553
Header file for electrified rail specific functions.
bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition elrail_func.h:32
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
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
Functions related to world/map generation.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1037
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
@ Grey
Grey.
Definition gfx_type.h:299
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
HouseZone
Concentric rings of zoning around the centre of a town.
Definition house.h:59
@ TownEdge
Edge of the town; roads without pavement.
Definition house.h:60
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
std::tuple< Slope, int > GetFoundationSlope(TileIndex tile)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation,...
const TileTypeProcs _tile_type_road_procs
TileTypeProcs definitions for TileType::Road tiles.
Definition landscape.cpp:54
uint ApplyFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
uint ApplyPixelFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.h:128
int GetSlopePixelZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition landscape.h:55
Command definitions related to landscape (slopes etc.).
@ Arctic
Landscape with snow levels.
@ Toyland
Landscape with funky industries and vehicles.
@ Tropic
Landscape with distinct rainforests and deserts,.
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
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:474
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:407
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:615
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:559
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
@ First
The first client ID.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:76
Base for the NewGRF implementation.
bool HasGrfMiscBit(GrfMiscBit bit)
Check for grf miscellaneous bits.
Definition newgrf.h:227
@ WithTrack
Electrified depot graphics with tram track were loaded.
Definition newgrf.h:200
@ DesertPavedRoads
Show pavement and lights in desert towns.
Definition newgrf.h:67
@ Any
Use first found.
Functions/types related to NewGRF debugging.
SpriteID GetCustomRailSprite(const RailTypeInfo *rti, TileIndex tile, RailSpriteType rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
NewGRF handling of rail types.
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadSpriteType rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
NewGRF handling of road types.
@ All
Match if all bits are triggered.
@ FullDetail
Also draw details of track and roads.
Definition openttd.h:50
@ Editor
In the scenario editor.
Definition openttd.h:21
@ Menu
In the main menu.
Definition openttd.h:19
@ Crossing
Level crossing overlay images.
Definition rail.h:50
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:303
bool RailNoLevelCrossings(RailType rt)
Test if a RailType disallows build of level crossings.
Definition rail.h:401
static const int INF
Big number compared to tilesprite size.
Command definitions for rail.
static RailTileType GetRailTileType(Tile t)
Returns the RailTileType (normal with or without signals, waypoint or depot).
Definition rail_map.h:36
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition rail_map.h:136
void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r)
Make the given tile a normal rail.
Definition rail_map.h:624
@ Normal
Normal rail tile without signals.
Definition rail_map.h:24
void SetTrackReservation(Tile t, TrackBits b)
Sets the reserved track bits of the tile.
Definition rail_map.h:209
TrackBits GetRailReservationTrackBits(Tile t)
Returns the reserved track bits of the tile.
Definition rail_map.h:194
Pseudo random number generator.
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.
RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
Clean up unnecessary RoadBits of a planned tile.
Definition road.cpp:59
bool ValParamRoadType(RoadType roadtype)
Validate functions for rail building.
Definition road.cpp:165
Road specific functions.
bool HasPowerOnRoad(RoadType enginetype, RoadType tiletype)
Checks if an engine of the given RoadType got power on a tile with a given RoadType.
Definition road.h:232
@ Catenary
Bit number for adding catenary.
Definition road.h:25
@ Hidden
Bit number for hidden from construction.
Definition road.h:28
RoadTypes _roadtypes_hidden_mask
Bitset of hidden roadtypes.
Definition road_cmd.cpp:56
Money RoadClearCost(RoadType roadtype)
Returns the cost of clearing the specified roadtype.
Definition road.h:253
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:217
Money RoadConvertCost(RoadType from, RoadType to)
Calculates the cost of road conversion.
Definition road.h:271
@ Ground
Required: Main group of ground images.
Definition road.h:41
@ CatenaryFront
Optional: Catenary front.
Definition road.h:43
@ Overlay
Optional: Images for overlaying track.
Definition road.h:40
@ UI
Optional: Cursor and toolbar icon images.
Definition road.h:39
@ CatenaryRear
Optional: Catenary back.
Definition road.h:44
@ Depot
Optional: Depot images.
Definition road.h:47
@ Oneway
Optional: One-way indicator images.
Definition road.h:50
std::vector< RoadType > _sorted_roadtypes
Sorted list of road types.
Definition road_cmd.cpp:55
bool RoadNoLevelCrossing(RoadType roadtype)
Test if road disallows level crossings.
Definition road.h:285
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:242
void ResetRoadTypes()
Reset all road type information to its default values.
Definition road_cmd.cpp:63
static VehicleEnterTileStates VehicleEnterTile_Road(Vehicle *v, TileIndex tile, int x, int y)
Tile callback function for a vehicle entering a tile.
std::vector< RoadVehicle * > RoadVehicleList
Helper type for lists/vectors of road vehicles.
Definition road_cmd.cpp:52
void InitRoadTypes()
Resolve sprites of custom road types.
Definition road_cmd.cpp:111
static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
Tile callback function signature of the terraforming callback.
CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, RoadType rt, DisallowedRoadDirections toggle_drd, TownID town_id)
Build a piece of road.
Definition road_cmd.cpp:602
static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
Tile callback function signature for getting the foundation of a tile.
static Foundation GetRoadFoundation(Slope tileh, RoadBits bits)
Get the foundationtype of a RoadBits Slope combination.
static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir)
Checks whether a road or tram connection can be found when building a new road or tram.
Definition road_cmd.cpp:940
static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
Should the road be drawn as a unpaved snow/desert road?
static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
Calculate the costs for roads on slopes Aside modify the RoadBits to fit on the slopes.
Definition road_cmd.cpp:537
void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
Draw road ground sprites.
bool RoadVehiclesAreBuilt()
Verify whether a road vehicle is available.
Definition road_cmd.cpp:172
void DrawRoadCatenary(const TileInfo *ti)
Draws the catenary for the given tile.
void UpdateNearestTownForRoadTiles(bool invalidate)
Updates cached nearest town for all road tiles.
static void DrawTile_Road(TileInfo *ti)
Tile callback function signature for drawing a tile and its contents to the screen.
CommandCost CmdBuildRoadDepot(DoCommandFlags flags, TileIndex tile, RoadType rt, DiagDirection dir)
Build a road depot.
void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb)
Draws the catenary for the RoadType of the given tile.
void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
Draw the road depot sprite.
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
Update road infrastructure counts for a company.
Definition road_cmd.cpp:183
static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
Get ground sprite to draw for a road tile.
static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, bool ground_vehicle)
Tile callback function signature for obtaining the world Z coordinate of a given point of a tile.
static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
Tile callback function signature for changing the owner of a tile.
static bool ClickTile_Road(TileIndex tile)
Tile callback function signature for clicking a tile.
CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
Build a long piece of road.
Definition road_cmd.cpp:969
static const TrackBits _road_trackbits[16]
Converts RoadBits to TrackBits.
static constexpr NonSteepSlopeIndexArray< uint8_t > _road_sloped_sprites
Lookup table to convert tile's slope into corresponding road sprite offset.
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int8_t dx, int8_t dy, uint8_t h, bool transparent)
Draws details on/around the road.
RoadTypes _roadtypes_road
Bitset of road roadtypes.
Definition road_cmd.cpp:57
std::tuple< CommandCost, Money > CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
Remove a long piece of road.
static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
Checks the tile and returns whether the current player is allowed to convert the roadtype to another ...
static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlags flags)
Tile callback function signature for clearing a tile.
CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal)
Convert one road subtype to another.
static void GetTileDesc_Road(TileIndex tile, TileDesc &td)
Tile callback function signature for obtaining a tile description.
static void DrawRoadBits(TileInfo *ti)
Draw ground sprite and road pieces.
static const std::array< NonSteepSlopeIndexArray< RoadBits >, 2 > _invalid_tileh_slopes_road
Invalid RoadBits on slopes.
Definition road_cmd.cpp:195
static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check)
Delete a piece of road.
Definition road_cmd.cpp:318
static constexpr DiagDirectionIndexArray< Trackdir > _roadveh_enter_depot_dir
Given the direction the road depot is pointing, this is the direction the vehicle should be travellin...
static void TileLoop_Road(TileIndex tile)
Tile callback function signature for running periodic tile updates.
static CommandCost CheckBuildAbove_Road(TileIndex tile, DoCommandFlags flags, Axis axis, int height)
Tile callback function signature to test if a bridge can be built above a tile.
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
Allocate a new road type label.
Definition road_cmd.cpp:132
RoadTypes _roadtypes_tram
Bitset of tram roadtypes.
Definition road_cmd.cpp:58
static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
Get the sprite offset within a spritegroup.
CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlags flags, bool town_check)
Is it allowed to remove the given road bits from the given tile?
Definition road_cmd.cpp:255
static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
Convert the ownership of the RoadType of the tile if applicable.
static bool CompareRoadTypes(const RoadType &first, const RoadType &second)
Compare roadtypes based on their sorting order.
Definition road_cmd.cpp:100
void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
Draw road underlay and overlay sprites.
static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
Tile callback function signature for getting the possible tracks that can be taken on a given tile by...
Road related functions.
Functions related to roads.
RoadBits AxisToRoadBits(Axis a)
Create the road-part which belongs to the given Axis.
Definition road_func.h:93
bool IsValidRoadBits(RoadBits r)
Whether the given roadtype is valid.
Definition road_func.h:23
bool HasRoadCatenaryDrawn(RoadType roadtype)
Test if we should draw road catenary.
Definition road_func.h:129
void UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(TileIndex tile, Axis road_axis)
Update adjacent level crossing tiles in this multi-track crossing, due to removal of a level crossing...
bool HasRoadCatenary(RoadType roadtype)
Test if a road type has catenary.
Definition road_func.h:118
bool IsStraightRoad(RoadBits r)
Check if we've got a straight road.
Definition road_func.h:63
RoadBits MirrorRoadBits(RoadBits r)
Calculate the mirrored RoadBits.
Definition road_func.h:51
void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis)
Find adjacent level crossing tiles in this multi-track crossing and mark them dirty.
RoadBits DiagDirToRoadBits(DiagDirection d)
Create the road-part which belongs to the given DiagDirection.
Definition road_func.h:78
void UpdateLevelCrossing(TileIndex tile, bool sound=true, bool force_bar=false)
Update a level crossing to barred or open (crossing may include multiple adjacent tiles).
RoadBits ComplementRoadBits(RoadBits r)
Calculate the complement of a RoadBits value.
Definition road_func.h:37
Functions used internally by the roads.
Sprite constructs for road depots.
static const DiagDirectionIndexArray< DrawTileSpriteSpan > _road_depot
Sprite layout for a road depot for each direction.
Definition road_land.h:31
bool MayHaveRoad(Tile t)
Test whether a tile can have road/tram types.
Definition road_map.cpp:21
RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance)
Returns the RoadBits on an arbitrary tile Special behaviour:
Definition road_map.cpp:54
void SetRoadOwner(Tile t, RoadTramType rtt, Owner o)
Set the owner of a specific road type.
Definition road_map.h:261
bool HasCrossingReservation(Tile t)
Get the reservation state of the rail crossing.
Definition road_map.h:379
static RoadTileType GetRoadTileType(Tile t)
Get the type of the road tile.
Definition road_map.h:36
bool HasTownOwnedRoad(Tile t)
Checks if given tile has town owned road.
Definition road_map.h:290
RoadType GetRoadTypeRoad(Tile t)
Get the road type for RoadTramType being RoadTramType::Road.
Definition road_map.h:152
void SetRoadDepotExitDirection(Tile tile, DiagDirection dir)
Sets the exit direction of a road depot.
Definition road_map.h:681
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition road_map.h:79
bool IncreaseRoadWorksCounter(Tile t)
Increase the progress counter of road works.
Definition road_map.h:518
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:112
static bool IsRoadDepotTile(Tile t)
Return whether a tile is a road depot tile.
Definition road_map.h:100
bool IsValidDisallowedRoadDirections(DisallowedRoadDirections drt)
Checks if a DisallowedRoadDirections is valid.
Definition road_map.h:301
Axis GetCrossingRoadAxis(Tile t)
Get the road axis of a level crossing.
Definition road_map.h:335
void SetDisallowedRoadDirections(Tile t, DisallowedRoadDirections drd)
Sets the disallowed directions.
Definition road_map.h:322
Track GetCrossingRailTrack(Tile tile)
Get the rail track of a level crossing.
Definition road_map.h:368
bool HasRoadTypeTram(Tile t)
Check if a tile has a road type when RoadTramType is RoadTramType::Tram.
Definition road_map.h:210
void StartRoadWorks(Tile t)
Start road works on a tile.
Definition road_map.h:530
DisallowedRoadDirections GetDisallowedRoadDirections(Tile t)
Gets the disallowed directions.
Definition road_map.h:311
bool HasTileRoadType(Tile t, RoadTramType rtt)
Check if a tile has a road or a tram road type.
Definition road_map.h:221
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition road_map.h:565
static bool IsRoadDepot(Tile t)
Return whether a tile is a road depot.
Definition road_map.h:90
RoadType GetRoadTypeTram(Tile t)
Get the road type for RoadTramType being RoadTramType::Tram.
Definition road_map.h:163
void MakeRoadNormal(Tile t, RoadBits bits, RoadType road_rt, RoadType tram_rt, TownID town, Owner road, Owner tram)
Make a normal road tile.
Definition road_map.h:635
Roadside GetRoadside(Tile tile)
Get the decorations of a road.
Definition road_map.h:488
RoadTileType
The different types of road tiles.
Definition road_map.h:22
@ Normal
Normal road.
Definition road_map.h:23
@ Depot
Depot (one entrance).
Definition road_map.h:25
@ Crossing
Level crossing.
Definition road_map.h:24
void MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadType road_rt, RoadType tram_rt, TownID town)
Make a level crossing.
Definition road_map.h:661
void ToggleSnowOrDesert(Tile t)
Toggle the snow/desert state of a road tile.
Definition road_map.h:465
RoadBits GetAllRoadBits(Tile tile)
Get all set RoadBits on the given tile.
Definition road_map.h:125
Axis GetCrossingRailAxis(Tile t)
Get the rail axis of a level crossing.
Definition road_map.h:347
RoadType GetRoadType(Tile t, RoadTramType rtt)
Get the road type for the given RoadTramType.
Definition road_map.h:175
static bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:58
void TerminateRoadWorks(Tile t)
Terminate road works on a tile.
Definition road_map.h:551
RoadBits GetCrossingRoadBits(Tile tile)
Get the road bits of a level crossing.
Definition road_map.h:358
void SetRoadType(Tile t, RoadTramType rtt, RoadType rt)
Set the road type of a tile.
Definition road_map.h:604
Owner GetRoadOwner(Tile t, RoadTramType rtt)
Get the owner of a specific road type.
Definition road_map.h:244
bool IsCrossingBarred(Tile t)
Check if the level crossing is barred.
Definition road_map.h:415
void SetRoadside(Tile tile, Roadside s)
Set the decorations of a road.
Definition road_map.h:498
bool IsRoadOwner(Tile t, RoadTramType rtt, Owner o)
Check if a specific road type is owned by an owner.
Definition road_map.h:278
void MakeRoadDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RoadType rt)
Make a road depot.
Definition road_map.h:695
void SetCrossingReservation(Tile t, bool b)
Set the reservation state of the rail crossing.
Definition road_map.h:392
void SetRoadBits(Tile t, RoadBits r, RoadTramType rtt)
Set the present road bits for a specific road type.
Definition road_map.h:137
Roadside
The possible road side decorations.
Definition road_map.h:472
@ Paved
Road with paved sidewalks.
Definition road_map.h:475
@ Barren
Road on barren land.
Definition road_map.h:473
@ GrassRoadWorks
Road on grass with road works.
Definition road_map.h:479
@ StreetLights
Road with street lights on paved sidewalks.
Definition road_map.h:476
@ Trees
Road with trees on paved sidewalks.
Definition road_map.h:478
@ Grass
Road on grass.
Definition road_map.h:474
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition road_map.h:69
static bool IsNormalRoad(Tile t)
Return whether a tile is a normal road.
Definition road_map.h:48
bool IsOnSnowOrDesert(Tile t)
Check if a road tile has snow/desert.
Definition road_map.h:456
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition road_map.h:508
EnumBitSet< RoadType, uint64_t > RoadTypes
Bitset of RoadType elements.
Definition road_type.h:33
static constexpr RoadBits ROAD_X
Full road along the x-axis (south-west + north-east).
Definition road_type.h:67
@ Northbound
All northbound traffic is disallowed.
Definition road_type.h:80
@ Southbound
All southbound traffic is disallowed.
Definition road_type.h:79
EnumBitSet< RoadBit, uint8_t > RoadBits
Bitset of RoadBit elements.
Definition road_type.h:65
@ SW
South-west part.
Definition road_type.h:59
@ NW
North-west part.
Definition road_type.h:58
@ NE
North-east part.
Definition road_type.h:61
@ SE
South-east part.
Definition road_type.h:60
EnumBitSet< DisallowedRoadDirection, uint8_t > DisallowedRoadDirections
Bitset of DisallowedRoadDirection elements.
Definition road_type.h:85
static constexpr RoadBits ROAD_ALL
Full 4-way crossing.
Definition road_type.h:75
static constexpr RoadBits ROAD_Y
Full road along the y-axis (north-west + south-east).
Definition road_type.h:68
static constexpr RoadTramTypes ROADTRAMTYPES_ALL
All possible RoadTramTypes.
Definition road_type.h:49
RoadType
The different roadtypes we support.
Definition road_type.h:24
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:29
@ ROADTYPE_TRAM
Trams.
Definition road_type.h:27
@ ROADTYPE_ROAD
Basic road type.
Definition road_type.h:26
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:28
RoadTramType
The different types of road type.
Definition road_type.h:38
@ Tram
Tram type.
Definition road_type.h:40
@ Road
Road type.
Definition road_type.h:39
All the roadtype-specific information is stored here.
static const RoadTypeInfo _original_roadtypes[]
Global Roadtype definition.
Definition roadtypes.h:18
Road vehicle states.
@ RVSB_IN_DEPOT
The vehicle is in a depot.
Definition roadveh.h:38
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
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
static constexpr int GetSlopeMaxZ(Slope s)
Returns the height of the highest corner of a slope relative to TileZ (= minimal height).
Definition slope_func.h:170
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:98
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:423
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:136
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition slope_func.h:377
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:109
Slope
Enumeration for the slope-type.
Definition slope_type.h:53
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:66
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:61
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:54
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:63
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:62
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:60
static constexpr uint8_t NUM_SLOPES
The total number of possible slope types.
Definition slope_type.h:86
Foundation
Enumeration for Foundations.
Definition slope_type.h:119
@ Leveled
The tile is leveled up to a flat slope.
Definition slope_type.h:121
@ None
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:120
@ InclinedY
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:123
@ InclinedX
The tile has an along X-axis inclined foundation.
Definition slope_type.h:122
static const uint32_t VALID_LEVEL_CROSSING_SLOPES
Constant bitset with safe slopes for building a level crossing.
Definition slope_type.h:112
EnumClassIndexContainer< std::array< T, SLOPE_ELEVATED >, Slope > NonSteepSlopeIndexArray
Array with non steep Slope as index.
Definition slope_type.h:104
Functions related to sound.
@ SND_21_ROAD_WORKS
31 == 0x1F Road reconstruction animation
Definition sound_type.h:79
void DrawRailTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence in GUI with railroad specifics.
Definition sprite.h:122
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:221
void DrawRailTileSeq(const struct TileInfo *ti, const DrawTileSprites *dts, TransparencyOption to, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence on tile with railroad specifics.
Definition sprite.h:108
static const SpriteID SPR_TRAMWAY_TRAM
Definition sprites.h:304
static const SpriteID SPR_TRAMWAY_DEPOT_WITH_TRACK
Definition sprites.h:312
static const SpriteID SPR_TRAMWAY_BACK_WIRES_SLOPED
Definition sprites.h:315
static const uint16_t ONEWAY_SLOPE_N_OFFSET
Definition sprites.h:326
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1793
static const SpriteID SPR_TRAMWAY_DEPOT_NO_TRACK
Definition sprites.h:319
static const SpriteID SPR_ROAD_DEPOT
Definition sprites.h:665
static const SpriteID SPR_FLAT_SNOW_DESERT_TILE
Definition sprites.h:688
static const SpriteID SPR_TRAMWAY_OVERLAY
Definition sprites.h:303
static const SpriteID SPR_TRAMWAY_BASE
Definition sprites.h:302
static const SpriteID SPR_ROAD_Y
Definition sprites.h:660
static const uint16_t ONEWAY_SLOPE_S_OFFSET
Definition sprites.h:327
static const SpriteID SPR_FLAT_GRASS_TILE
Definition sprites.h:676
static const PaletteID PALETTE_TO_BARE_LAND
sets colour to bare land stuff for rail, road and crossings
Definition sprites.h:1781
static const SpriteID SPR_TRAMWAY_FRONT_WIRES_SLOPED
Definition sprites.h:316
static const SpriteID SPR_ONEWAY_BASE
Definition sprites.h:325
@ Count
by amount of cargo
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?
bool IsAnyRoadStop(Tile t)
Is the station at t a road station?
Axis GetDriveThroughStopAxis(Tile t)
Gets the axis of the drive through stop.
DiagDirection GetBayRoadStopDir(Tile t)
Gets the direction the bay road stop entrance points towards.
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 GetEncodedStringWithArgs(StringID str, std::span< const StringParameter > params)
Encode a string with its parameters into an encoded string.
Definition strings.cpp:102
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
constexpr bool Empty() const
Check whether the label is empty.
VehicleType type
Type of vehicle.
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
std::array< uint32_t, RAILTYPE_END > rail
Count of company owned track bits for each rail type.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
T x
X coordinate.
T y
Y coordinate.
T z
Z coordinate.
Represents a diagonal tile area.
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:55
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:56
A special vehicle is one of the following:
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:366
static uint Size()
Get the size of the map.
Definition map_func.h:280
Represents the covered area of e.g.
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
static Pool::IterateWrapper< Vehicle > Iterate(size_t from=0)
static T * Create(Targs &&... args)
static Company * Get(auto index)
static bool CanAllocateItem(size_t n=1)
static Company * GetIfValid(auto index)
Buses, trucks and trams belong to this class.
Definition roadveh.h:105
uint8_t state
Definition roadveh.h:107
T * Next() const
Get next vehicle in the chain.
static RoadVehicle * From(Vehicle *v)
T * First() const
Get the first vehicle in the chain.
Used to only draw a part of the sprite.
Definition gfx_type.h:278
Tile description for the 'land area information' tool.
Definition tile_cmd.h:40
uint16_t rail_speed
Speed limit of rail (bridges and track).
Definition tile_cmd.h:53
StringID str
Description of the tile.
Definition tile_cmd.h:41
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:45
std::array< Owner, 4 > owner
Name of the owner(s).
Definition tile_cmd.h:43
uint16_t tram_speed
Speed limit of tram (bridges and track).
Definition tile_cmd.h:57
StringID roadtype
Type of road on the tile.
Definition tile_cmd.h:54
StringID tramtype
Type of tram on the tile.
Definition tile_cmd.h:56
StringID railtype
Type of rail on the tile.
Definition tile_cmd.h:52
uint16_t road_speed
Speed limit of road (bridges and track).
Definition tile_cmd.h:55
std::array< StringID, 4 > owner_type
Type of each owner.
Definition tile_cmd.h:44
Tile information, used while rendering the tile.
Definition tile_cmd.h:34
Slope tileh
Slope of the tile.
Definition tile_cmd.h:35
TileIndex tile
Tile index.
Definition tile_cmd.h:36
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:214
std::array< uint32_t, NUM_HOUSE_ZONES > squared_town_zone_radius
UpdateTownRadius updates this given the house count.
Definition town.h:57
Town data structure.
Definition town.h:64
TileIndex xy
town center tile
Definition town.h:65
TownCache cache
Container for all cacheable data.
Definition town.h:67
uint8_t road_build_months
fund road reconstruction in action?
Definition town.h:197
Track status of a tile.
Definition track_type.h:105
Vehicle data structure.
Direction direction
facing
VehStates vehstatus
Status.
TileIndex tile
Current tile index.
@ EnteredWormhole
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition tile_cmd.h:26
EnumBitSet< VehicleEnterTileState, uint8_t > VehicleEnterTileStates
Bitset of VehicleEnterTileState elements.
Definition tile_cmd.h:31
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.cpp:55
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:135
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
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
void SetTileOwner(Tile tile, Owner owner)
Sets the owner of a tile.
Definition tile_map.h:198
int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition tile_map.h:312
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition tile_map.h:289
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
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
@ Desert
Tile is desert.
Definition tile_type.h:83
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
TileType
The different types of tiles.
Definition tile_type.h:48
@ TunnelBridge
Tunnel entry/exit and bridge heads.
Definition tile_type.h:58
@ Station
A tile of a station or airport.
Definition tile_type.h:54
@ Railway
A tile with railway.
Definition tile_type.h:50
@ Road
A tile with road and/or tram tracks.
Definition tile_type.h:51
Definition of the game-calendar-timer.
Base of the town class.
void ChangeTownRating(Town *t, int add, int max, DoCommandFlags flags)
Changes town rating of the current company.
@ TunnelBridgeRemove
Removal of a tunnel or bridge owned by the town.
Definition town.h:276
@ RoadRemove
Removal of a road owned by the town.
Definition town.h:275
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
RoadType GetTownRoadType()
Get the road type that towns should build at this current moment.
Definition town_cmd.cpp:935
Town * CalcClosestTownFromTile(TileIndex tile, uint threshold=UINT_MAX)
Return the town closest to the given tile within threshold.
CommandCost CheckforTownRating(DoCommandFlags flags, Town *t, TownRatingCheckType type)
Does the town authority allow the (destructive) action of the current company?
HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile)
Returns the bit corresponding to the town zone of the specified tile.
void MakeDefaultName(T *obj)
Set the default name for a depot/waypoint.
Definition town.h:334
void SetTownIndex(Tile t, TownID index)
Set the town index for a road or house tile.
Definition town_map.h:35
static constexpr int RATING_ROAD_DOWN_STEP_EDGE
removing a roadpiece at the edge
Definition town_type.h:66
static constexpr int RATING_ROAD_DOWN_STEP_INNER
removing a roadpiece in the middle
Definition town_type.h:65
static constexpr int RATING_ROAD_MINIMUM
minimum rating after removing town owned road
Definition town_type.h:67
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:292
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
Track DiagDirToDiagTrack(DiagDirection diagdir)
Maps a DiagDirection to the associated diagonal Track.
Definition track_func.h:419
EnumBitSet< Trackdir, uint16_t > TrackdirBits
Bitset of Trackdir elements.
Definition track_type.h:93
EnumBitSet< Track, uint8_t > TrackBits
Bitset of Track elements.
Definition track_type.h:43
static constexpr TrackBits TRACK_BIT_ALL
All possible tracks.
Definition track_type.h:52
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
@ X_SW
X-axis and direction to south-west.
Definition track_type.h:72
@ Y_SE
Y-axis and direction to south-east.
Definition track_type.h:65
@ Y_NW
Y-axis and direction to north-west.
Definition track_type.h:73
Track
These are used to specify a single track.
Definition track_type.h:19
@ X
Track along the x-axis (north-east to south-west).
Definition track_type.h:21
@ Upper
Track in the upper corner of the tile (north).
Definition track_type.h:23
@ Y
Track along the y-axis (north-west to south-east).
Definition track_type.h:22
@ Right
Track in the right corner of the tile (east).
Definition track_type.h:26
@ Left
Track in the left corner of the tile (west).
Definition track_type.h:25
@ Lower
Track in the lower corner of the tile (south).
Definition track_type.h:24
Base for the train class.
bool TrainOnCrossing(TileIndex tile)
Check if a level crossing tile has a train on it.
bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren't in the game menu (there's never transpar...
bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren't in the game menu (there's never transpar...
DisplayOptions _display_opt
What do we want to draw/do?
@ Houses
town buildings
@ Buildings
company buildings - depots, stations, HQ, ...
TransportType
Available types of transport.
@ Rail
Transport by train.
@ Road
Transport by road vehicle.
Header file for things common for tunnels and bridges.
void SetTunnelBridgeOwner(TileIndex begin, TileIndex end, Owner owner)
Sets the ownership of the bridge/tunnel ramps.
void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
Mark bridge tiles dirty.
uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
Calculates the length of a tunnel or a bridge (without end tiles).
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition vehicle.cpp:557
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1562
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:581
@ Hidden
Vehicle is not visible.
Functions related to vehicles.
@ Road
Road vehicle type.
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:664
void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32_t x, int32_t y, int z, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite at a specific world-coordinate relative to the current tile.
Definition viewport.cpp:556
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition viewport.cpp:579
Functions related to (drawing on) viewports.
static const int TILE_HEIGHT_STEP
One Z unit tile height difference is displayed as 50m.
static constexpr int BB_HEIGHT_UNDER_BRIDGE
Some values for constructing bounding boxes (BB).
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:3315
Entry point for OpenTTD to YAPF's cache.
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.
@ Detail
All zoom levels below or equal to this will result in details on the screen, like road-work,...
Definition zoom_type.h:44