OpenTTD Source 20260311-master-g511d3794ce
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;
57RoadTypes _roadtypes_road;
58RoadTypes _roadtypes_tram;
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 == 0) 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, 0, &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 == RTT_ROAD);
163 _roadtypes_tram.Set(rt, rtt == RTT_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
196 /* The inverse of the mixable RoadBits on a leveled slope */
197 {
198 ROAD_NONE, // SLOPE_FLAT
199 ROAD_NE | ROAD_SE, // SLOPE_W
200 ROAD_NE | ROAD_NW, // SLOPE_S
201
202 ROAD_NE, // SLOPE_SW
203 ROAD_NW | ROAD_SW, // SLOPE_E
204 ROAD_NONE, // SLOPE_EW
205
206 ROAD_NW, // SLOPE_SE
207 ROAD_NONE, // SLOPE_WSE
208 ROAD_SE | ROAD_SW, // SLOPE_N
209
210 ROAD_SE, // SLOPE_NW
211 ROAD_NONE, // SLOPE_NS
212 ROAD_NONE, // SLOPE_ENW
213
214 ROAD_SW, // SLOPE_NE
215 ROAD_NONE, // SLOPE_SEN
216 ROAD_NONE // SLOPE_NWS
217 },
218 /* The inverse of the allowed straight roads on a slope
219 * (with and without a foundation). */
220 {
221 ROAD_NONE, // SLOPE_FLAT
222 ROAD_NONE, // SLOPE_W Foundation
223 ROAD_NONE, // SLOPE_S Foundation
224
225 ROAD_Y, // SLOPE_SW
226 ROAD_NONE, // SLOPE_E Foundation
227 ROAD_ALL, // SLOPE_EW
228
229 ROAD_X, // SLOPE_SE
230 ROAD_ALL, // SLOPE_WSE
231 ROAD_NONE, // 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 == GM_EDITOR || remove == ROAD_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 */
287 RoadBits present = GetAnyRoadBits(tile, rtt);
288 if ((present & ROAD_NE) && (GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt) & ROAD_SW)) n |= ROAD_NE;
289 if ((present & ROAD_SE) && (GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt) & ROAD_NW)) n |= ROAD_SE;
290 if ((present & ROAD_SW) && (GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt) & ROAD_NE)) n |= ROAD_SW;
291 if ((present & ROAD_NW) && (GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt) & ROAD_SE)) n |= ROAD_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 (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) {
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 != ROAD_NONE);
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 == RTT_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))) & pieces) == ROAD_NONE) return CommandCost((rtt == RTT_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 & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
423 (tileh != SLOPE_FLAT && !_settings_game.construction.build_on_slopes)) {
424 pieces |= MirrorRoadBits(pieces);
425 }
426
427 /* limit the bits to delete to the existing bits. */
428 pieces &= present;
429 if (pieces == ROAD_NONE) return CommandCost((rtt == RTT_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 ^= pieces;
433
434 /* Check for invalid RoadBit combinations on slopes */
435 if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
436 (present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == 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), -(int)CountBits(pieces));
452
453 if (present == ROAD_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 == RTT_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, ROAD_NONE, 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(EXPENSES_CONSTRUCTION, CountBits(pieces) * RoadClearCost(existing_rt));
480 /* If we build a foundation we have to pay for it. */
482
483 return cost;
484 }
485
487 if (pieces & 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 railtrack = GetCrossingRailTrack(tile);
498 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
499 TrackBits tracks = GetCrossingRailBits(tile);
500 bool reserved = HasCrossingReservation(tile);
501 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
502 if (reserved) SetTrackReservation(tile, tracks);
503
504 /* Update rail count for level crossings. The plain track should still be accounted
505 * for, so only subtract the difference to the level crossing cost. */
507 if (c != nullptr) {
510 }
511 } else {
512 SetRoadType(tile, rtt, INVALID_ROADTYPE);
513 }
515 YapfNotifyTrackLayoutChange(tile, railtrack);
516 }
517 return CommandCost(EXPENSES_CONSTRUCTION, RoadClearCost(existing_rt) * 2);
518 }
519
520 default:
522 return CMD_ERROR;
523 }
524}
525
526
538static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
539{
540 /* Remove already build pieces */
541 *pieces &= ~existing;
542
543 /* If we can't build anything stop here */
544 if (*pieces == ROAD_NONE) return CMD_ERROR;
545
546 /* All RoadBit combos are valid on flat land */
547 if (tileh == SLOPE_FLAT) return CommandCost();
548
549 /* Steep slopes behave the same as slopes with one corner raised. */
550 if (IsSteepSlope(tileh)) {
552 }
553
554 /* Save the merge of all bits of the current type */
555 RoadBits type_bits = existing | *pieces;
556
557 /* Roads on slopes */
558 if (_settings_game.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
559
560 /* If we add leveling we've got to pay for it */
561 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]);
562
563 return CommandCost();
564 }
565
566 /* Autocomplete uphill roads */
567 *pieces |= MirrorRoadBits(*pieces);
568 type_bits = existing | *pieces;
569
570 /* Uphill roads */
571 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
572 (_invalid_tileh_slopes_road[1][tileh] & (other | type_bits)) == ROAD_NONE) {
573
574 /* Slopes with foundation ? */
575 if (IsSlopeWithOneCornerRaised(tileh)) {
576
577 /* Prevent build on slopes if it isn't allowed */
578 if (_settings_game.construction.build_on_slopes) {
579
580 /* If we add foundation we've got to pay for it */
581 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]);
582
583 return CommandCost();
584 }
585 } else {
587 return CommandCost();
588 }
589 }
590 return CMD_ERROR;
591}
592
603CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, RoadType rt, DisallowedRoadDirections toggle_drd, TownID town_id)
604{
605 CompanyID company = _current_company;
607
608 RoadBits existing = ROAD_NONE;
609 RoadBits other_bits = ROAD_NONE;
610
611 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
612 * if a non-company is building the road */
613 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;
614 if (company != OWNER_TOWN) {
615 const Town *town = CalcClosestTownFromTile(tile);
616 town_id = (town != nullptr) ? town->index : TownID::Invalid();
617
618 if (company == OWNER_DEITY) {
619 company = OWNER_TOWN;
620
621 /* If we are not within a town, we are not owned by the town */
622 if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) {
623 company = OWNER_NONE;
624 }
625 }
626 }
627
628 /* do not allow building 'zero' road bits, code wouldn't handle it */
629 if (pieces == ROAD_NONE || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR;
630 if (!ValParamRoadType(rt)) return CMD_ERROR;
631
632 Slope tileh = GetTileSlope(tile);
633 RoadTramType rtt = GetRoadTramType(rt);
634
635 bool need_to_clear = false;
636 switch (GetTileType(tile)) {
637 case TileType::Road:
638 switch (GetRoadTileType(tile)) {
640 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
641
642 other_bits = GetRoadBits(tile, OtherRoadTramType(rtt));
643 if (!HasTileRoadType(tile, rtt)) break;
644
645 existing = GetRoadBits(tile, rtt);
646 bool crossing = !IsStraightRoad(existing | pieces);
647 if (rtt == RTT_ROAD && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
648 /* Junctions cannot be one-way */
649 return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
650 }
651 if ((existing & pieces) == pieces) {
652 /* We only want to set the (dis)allowed road directions */
653 if (toggle_drd != DRD_NONE && rtt == RTT_ROAD) {
654 Owner owner = GetRoadOwner(tile, rtt);
655 if (owner != OWNER_NONE) {
656 CommandCost ret = CheckOwnership(owner, tile);
657 if (ret.Failed()) return ret;
658 }
659
661 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
662
663 /* We allow removing disallowed directions to break up
664 * deadlocks, but adding them can break articulated
665 * vehicles. As such, only when less is disallowed,
666 * i.e. bits are removed, we skip the vehicle check. */
667 if (CountBits(dis_existing) <= CountBits(dis_new)) {
669 if (ret.Failed()) return ret;
670 }
671
672 /* Ignore half built tiles */
673 if (flags.Test(DoCommandFlag::Execute) && IsStraightRoad(existing)) {
674 SetDisallowedRoadDirections(tile, dis_new);
676 }
677 return CommandCost();
678 }
679 return CommandCost(STR_ERROR_ALREADY_BUILT);
680 }
681 /* Disallow breaking end-of-line of someone else
682 * so trams can still reverse on this tile. */
683 if (rtt == RTT_TRAM && HasExactlyOneBit(existing)) {
684 Owner owner = GetRoadOwner(tile, rtt);
685 if (Company::IsValidID(owner)) {
686 CommandCost ret = CheckOwnership(owner);
687 if (ret.Failed()) return ret;
688 }
689 }
690 break;
691 }
692
694 if (RoadNoLevelCrossing(rt)) {
695 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
696 }
697
698 other_bits = GetCrossingRoadBits(tile);
699 if (pieces & ComplementRoadBits(other_bits)) goto do_clear;
700 pieces = other_bits; // we need to pay for both roadbits
701
702 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
703 break;
704
706 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
707 goto do_clear;
708
709 default: NOT_REACHED();
710 }
711 break;
712
713 case TileType::Railway: {
714 if (IsSteepSlope(tileh)) {
715 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
716 }
717
718 /* Level crossings may only be built on these slopes */
719 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
720 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
721 }
722
723 if (!_settings_game.construction.crossing_with_competitor && company != OWNER_TOWN && company != OWNER_DEITY) {
725 if (ret.Failed()) return ret;
726 }
727
728 if (GetRailTileType(tile) != RailTileType::Normal) goto do_clear;
729
730 if (RoadNoLevelCrossing(rt)) {
731 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
732 }
733
735 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
736 }
737
738 Axis roaddir;
739 switch (GetTrackBits(tile)) {
740 case TRACK_BIT_X:
741 if (pieces & ROAD_X) goto do_clear;
742 roaddir = AXIS_Y;
743 break;
744
745 case TRACK_BIT_Y:
746 if (pieces & ROAD_Y) goto do_clear;
747 roaddir = AXIS_X;
748 break;
749
750 default: goto do_clear;
751 }
752
754 if (ret.Failed()) return ret;
755
756 if (flags.Test(DoCommandFlag::Execute)) {
757 Track railtrack = AxisToTrack(OtherAxis(roaddir));
758 YapfNotifyTrackLayoutChange(tile, railtrack);
759 /* Update company infrastructure counts. A level crossing has two road bits. */
760 UpdateCompanyRoadInfrastructure(rt, company, 2);
761
762 /* Update rail count for level crossings. The plain track is already
763 * counted, so only add the difference to the level crossing cost. */
765 if (c != nullptr) {
768 }
769
770 /* Always add road to the roadtypes (can't draw without it) */
771 bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
772 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id);
773 SetCrossingReservation(tile, reserved);
774 UpdateLevelCrossing(tile, false);
777 }
779 }
780
781 case TileType::Station: {
782 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
783 if (!IsDriveThroughStopTile(tile)) goto do_clear;
784
786 if (pieces & ~curbits) goto do_clear;
787 pieces = curbits; // we need to pay for both roadbits
788
789 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
790 break;
791 }
792
794 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) goto do_clear;
795 /* Only allow building the outer roadbit, so building long roads stops at existing bridges */
796 if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
797 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
798 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
800 if (ret.Failed()) return ret;
801 break;
802 }
803
804 default: {
805do_clear:;
806 need_to_clear = true;
807 break;
808 }
809 }
810
811 if (need_to_clear) {
812 CommandCost ret = Command<Commands::LandscapeClear>::Do(flags, tile);
813 if (ret.Failed()) return ret;
814 cost.AddCost(ret.GetCost());
815 }
816
817 if (other_bits != pieces) {
818 /* Check the foundation/slopes when adding road/tram bits */
819 CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
820 /* Return an error if we need to build a foundation (ret != 0) but the
821 * current setting is turned off */
822 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
823 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
824 }
825 cost.AddCost(ret.GetCost());
826 }
827
828 if (!need_to_clear) {
829 if (IsTileType(tile, TileType::Road)) {
830 /* Don't put the pieces that already exist */
831 pieces &= ComplementRoadBits(existing);
832
833 /* Check if new road bits will have the same foundation as other existing road types */
834 if (IsNormalRoad(tile)) {
835 Slope slope = GetTileSlope(tile);
836 Foundation found_new = GetRoadFoundation(slope, pieces | existing);
837
838 RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt));
839 /* do not check if there are not road bits of given type */
840 if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) {
841 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
842 }
843 }
844 }
845
847 if (ret.Failed()) return ret;
848
849 if (IsNormalRoadTile(tile)) {
850 /* If the road types don't match, try to convert only if vehicles of
851 * the new road type are not powered on the present road type and vehicles of
852 * the present road type are powered on the new road type. */
853 RoadType existing_rt = GetRoadType(tile, rtt);
854 if (existing_rt != INVALID_ROADTYPE && existing_rt != rt) {
855 if (HasPowerOnRoad(rt, existing_rt)) {
856 rt = existing_rt;
857 } else if (HasPowerOnRoad(existing_rt, rt)) {
858 ret = Command<Commands::ConvertRoad>::Do(flags, tile, tile, rt, false);
859 if (ret.Failed()) return ret;
860 cost.AddCost(ret.GetCost());
861 } else {
862 return CMD_ERROR;
863 }
864 }
865 }
866 }
867
868 uint num_pieces = (!need_to_clear && IsTileType(tile, TileType::TunnelBridge)) ?
869 /* There are 2 pieces on *every* tile of the bridge or tunnel */
870 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) :
871 /* Count pieces */
872 CountBits(pieces);
873
874 cost.AddCost(num_pieces * RoadBuildCost(rt));
875
876 if (flags.Test(DoCommandFlag::Execute)) {
877 switch (GetTileType(tile)) {
878 case TileType::Road: {
879 RoadTileType rttype = GetRoadTileType(tile);
880 if (existing == ROAD_NONE || rttype == RoadTileType::Crossing) {
881 SetRoadType(tile, rtt, rt);
882 SetRoadOwner(tile, rtt, company);
883 if (rtt == RTT_ROAD) SetTownIndex(tile, town_id);
884 }
885 if (rttype != RoadTileType::Crossing) SetRoadBits(tile, existing | pieces, rtt);
886 break;
887 }
888
890 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
891
892 SetRoadType(other_end, rtt, rt);
893 SetRoadType(tile, rtt, rt);
894 SetRoadOwner(other_end, rtt, company);
895 SetRoadOwner(tile, rtt, company);
896
897 /* Mark tiles dirty that have been repaved */
898 if (IsBridge(tile)) {
899 MarkBridgeDirty(tile);
900 } else {
901 MarkTileDirtyByTile(other_end);
903 }
904 break;
905 }
906
907 case TileType::Station: {
908 assert(IsDriveThroughStopTile(tile));
909 SetRoadType(tile, rtt, rt);
910 SetRoadOwner(tile, rtt, company);
911 break;
912 }
913
914 default:
915 MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company);
916 break;
917 }
918
919 /* Update company infrastructure count. */
921 UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), num_pieces);
922
923 if (rtt == RTT_ROAD && IsNormalRoadTile(tile)) {
924 existing |= pieces;
926 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
927 }
928
930 }
931 return cost;
932}
933
942{
943 tile += TileOffsByDiagDir(dir);
944 if (!IsValidTile(tile) || !MayHaveRoad(tile)) return false;
945
946 RoadTramType rtt = GetRoadTramType(rt);
947 RoadType existing = GetRoadType(tile, rtt);
948 if (existing == INVALID_ROADTYPE) return false;
949 if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false;
950
951 RoadBits bits = GetAnyRoadBits(tile, rtt, false);
952 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
953}
954
970CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
971{
972 if (start_tile >= Map::Size()) return CMD_ERROR;
973
974 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
975
976 /* Only drag in X or Y direction dictated by the direction variable */
977 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
978 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
979
980 DiagDirection dir = AxisToDiagDir(axis);
981
982 /* Swap direction, also the half-tile drag vars. */
983 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
984 dir = ReverseDiagDir(dir);
985 start_half = !start_half;
986 end_half = !end_half;
987 if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
988 }
989
990 /* On the X-axis, we have to swap the initial bits, so they
991 * will be interpreted correctly in the GTTS. Furthermore
992 * when you just 'click' on one tile to build them. */
993 if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
994
996 CommandCost last_error = CMD_ERROR;
997 TileIndex tile = start_tile;
998 bool had_bridge = false;
999 bool had_tunnel = false;
1000 bool had_success = false;
1001
1002 /* Start tile is the first tile clicked by the user. */
1003 for (;;) {
1004 RoadBits bits = AxisToRoadBits(axis);
1005
1006 /* Determine which road parts should be built. */
1007 if (!is_ai && start_tile != end_tile) {
1008 /* Only build the first and last roadbit if they can connect to something. */
1009 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1010 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1011 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1012 bits = DiagDirToRoadBits(dir);
1013 }
1014 } else {
1015 /* Road parts only have to be built at the start tile or at the end tile. */
1016 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1017 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1018 }
1019
1020 CommandCost ret = Command<Commands::BuildRoad>::Do(flags, tile, bits, rt, drd, TownID::Invalid());
1021 if (!is_ai && ret.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true;
1022 if (ret.Failed()) {
1023 last_error = std::move(ret);
1024 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1025 if (is_ai) return last_error;
1026 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1027 }
1028 } else {
1029 had_success = true;
1030 /* Only pay for the upgrade on one side of the bridges and tunnels */
1032 if (IsBridge(tile)) {
1033 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1034 cost.AddCost(ret.GetCost());
1035 }
1036 had_bridge = true;
1037 } else { // IsTunnel(tile)
1038 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1039 cost.AddCost(ret.GetCost());
1040 }
1041 had_tunnel = true;
1042 }
1043 } else {
1044 cost.AddCost(ret.GetCost());
1045 }
1046 }
1047
1048 if (tile == end_tile) break;
1049
1050 tile += TileOffsByDiagDir(dir);
1051 }
1052
1053 return had_success ? cost : last_error;
1054}
1055
1067std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
1068{
1070
1071 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
1072 if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 };
1073
1074 /* Only drag in X or Y direction dictated by the direction variable */
1075 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis
1076 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis
1077
1078 /* Swap start and ending tile, also the half-tile drag vars. */
1079 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
1080 std::swap(start_tile, end_tile);
1081 std::swap(start_half, end_half);
1082 }
1083
1084 Money money_available = GetAvailableMoneyForCommand();
1085 Money money_spent = 0;
1086 TileIndex tile = start_tile;
1087 CommandCost last_error = CMD_ERROR;
1088 bool had_success = false;
1089 /* Start tile is the small number. */
1090 for (;;) {
1091 RoadBits bits = AxisToRoadBits(axis);
1092
1093 if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
1094 if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
1095
1096 /* try to remove the halves. */
1097 if (bits != 0) {
1098 RoadTramType rtt = GetRoadTramType(rt);
1099 CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true);
1100 if (ret.Succeeded()) {
1101 if (flags.Test(DoCommandFlag::Execute)) {
1102 money_spent += ret.GetCost();
1103 if (money_spent > 0 && money_spent > money_available) {
1104 return { cost, std::get<0>(Command<Commands::RemoveRoadLong>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), end_tile, start_tile, rt, axis, start_half, end_half)).GetCost() };
1105 }
1106 RemoveRoad(tile, flags, bits, rtt, false);
1107 }
1108 cost.AddCost(ret.GetCost());
1109 had_success = true;
1110 } else {
1111 /* Some errors are more equal than others. */
1112 switch (last_error.GetErrorMessage()) {
1113 case STR_ERROR_OWNED_BY:
1114 case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS:
1115 break;
1116 default:
1117 last_error = std::move(ret);
1118 }
1119 }
1120 }
1121
1122 if (tile == end_tile) break;
1123
1124 tile += TileOffsByAxis(axis);
1125 }
1126
1127 return { had_success ? cost : last_error, 0 };
1128}
1129
1139{
1140 if (!ValParamRoadType(rt) || !IsValidDiagDirection(dir)) return CMD_ERROR;
1141
1143
1144 Slope tileh = GetTileSlope(tile);
1145 if (tileh != SLOPE_FLAT) {
1146 if (!_settings_game.construction.build_on_slopes) return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
1147 if (!CanBuildDepotByTileh(dir, tileh)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
1149 }
1150
1151 /* Allow the user to rotate the depot instead of having to destroy it and build it again */
1152 bool rotate_existing_depot = false;
1153 if (IsRoadDepotTile(tile) && (HasRoadTypeTram(tile) ? rt == GetRoadTypeTram(tile) : rt == GetRoadTypeRoad(tile)))
1154 {
1155 CommandCost ret = CheckTileOwnership(tile);
1156 if (ret.Failed()) return ret;
1157
1158 if (dir == GetRoadDepotDirection(tile)) return CommandCost();
1159
1160 ret = EnsureNoVehicleOnGround(tile);
1161 if (ret.Failed()) return ret;
1162
1163 rotate_existing_depot = true;
1164 }
1165
1166 if (!rotate_existing_depot) {
1167 cost.AddCost(Command<Commands::LandscapeClear>::Do(flags, tile));
1168 if (cost.Failed()) return cost;
1169
1170 if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1171
1172 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1173 }
1174
1175 if (flags.Test(DoCommandFlag::Execute)) {
1176 if (rotate_existing_depot) {
1177 SetRoadDepotExitDirection(tile, dir);
1178 } else {
1179 Depot *dep = Depot::Create(tile);
1180 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1181 MakeDefaultName(dep);
1182
1183 /* A road depot has two road bits. */
1185 }
1186
1187 MarkTileDirtyByTile(tile);
1188 }
1189
1191 return cost;
1192}
1193
1194static CommandCost RemoveRoadDepot(TileIndex tile, DoCommandFlags flags)
1195{
1197 CommandCost ret = CheckTileOwnership(tile);
1198 if (ret.Failed()) return ret;
1199 }
1200
1202 if (ret.Failed()) return ret;
1203
1204 if (flags.Test(DoCommandFlag::Execute)) {
1206 if (c != nullptr) {
1207 /* A road depot has two road bits. */
1208 RoadType rt = GetRoadTypeRoad(tile);
1209 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
1212 }
1213
1214 delete Depot::GetByTile(tile);
1215 DoClearSquare(tile);
1216 }
1217
1219}
1220
1222static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlags flags)
1223{
1224 switch (GetRoadTileType(tile)) {
1225 case RoadTileType::Normal: {
1226 RoadBits b = GetAllRoadBits(tile);
1227
1228 /* Clear the road if only one piece is on the tile OR we are not using the DoCommandFlag::Auto flag */
1229 if ((HasExactlyOneBit(b) && GetRoadBits(tile, RTT_TRAM) == ROAD_NONE) || !flags.Test(DoCommandFlag::Auto)) {
1231 for (RoadTramType rtt : _roadtramtypes) {
1232 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1233
1234 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true);
1235 if (tmp_ret.Failed()) return tmp_ret;
1236 ret.AddCost(tmp_ret.GetCost());
1237 }
1238 return ret;
1239 }
1240 return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1241 }
1242
1245
1246 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1247
1248 /* Must iterate over the roadtypes in a reverse manner because
1249 * tram tracks must be removed before the road bits. */
1250 for (RoadTramType rtt : { RTT_TRAM, RTT_ROAD }) {
1251 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1252
1253 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rtt, true);
1254 if (tmp_ret.Failed()) return tmp_ret;
1255 ret.AddCost(tmp_ret.GetCost());
1256 }
1257
1258 if (flags.Test(DoCommandFlag::Execute)) {
1259 Command<Commands::LandscapeClear>::Do(flags, tile);
1260 }
1261 return ret;
1262 }
1263
1264 default:
1266 if (flags.Test(DoCommandFlag::Auto)) {
1267 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1268 }
1269 return RemoveRoadDepot(tile, flags);
1270 }
1271}
1272
1273
1275 uint16_t image;
1276 uint8_t subcoord_x;
1277 uint8_t subcoord_y;
1278};
1279
1280#include "table/road_land.h"
1281
1290{
1291 /* Flat land and land without a road doesn't require a foundation */
1292 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1293
1294 /* Steep slopes behave the same as slopes with one corner raised. */
1295 if (IsSteepSlope(tileh)) {
1297 }
1298
1299 /* Leveled RoadBits on a slope */
1300 if ((_invalid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1301
1302 /* Straight roads without foundation on a slope */
1303 if (!IsSlopeWithOneCornerRaised(tileh) &&
1304 (_invalid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE)
1305 return FOUNDATION_NONE;
1306
1307 /* Roads on steep Slopes or on Slopes with one corner raised */
1309}
1310
1311const uint8_t _road_sloped_sprites[14] = {
1312 0, 0, 2, 0,
1313 0, 1, 0, 0,
1314 3, 0, 0, 0,
1315 0, 0
1316};
1317
1324static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
1325{
1326 if (slope != SLOPE_FLAT) {
1327 switch (slope) {
1328 case SLOPE_NE: return 11;
1329 case SLOPE_SE: return 12;
1330 case SLOPE_SW: return 13;
1331 case SLOPE_NW: return 14;
1332 default: NOT_REACHED();
1333 }
1334 } else {
1335 static const uint offsets[] = {
1336 0, 18, 17, 7,
1337 16, 0, 10, 5,
1338 15, 8, 1, 4,
1339 9, 3, 6, 2
1340 };
1341 return offsets[bits];
1342 }
1343}
1344
1354static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
1355{
1356 return (snow_or_desert &&
1358 roadside != Roadside::Barren && roadside != Roadside::Grass && roadside != Roadside::GrassRoadWorks));
1359}
1360
1368{
1369 /* Don't draw the catenary under a low bridge */
1371 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1372
1373 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1374 }
1375
1376 if (CountBits(rb) > 2) {
1377 /* On junctions we check whether neighbouring tiles also have catenary, and possibly
1378 * do not draw catenary towards those neighbours, which do not have catenary. */
1379 RoadBits rb_new = ROAD_NONE;
1380 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
1381 if (rb & DiagDirToRoadBits(dir)) {
1382 TileIndex neighbour = TileAddByDiagDir(ti->tile, dir);
1383 if (MayHaveRoad(neighbour)) {
1384 RoadType rt_road = GetRoadTypeRoad(neighbour);
1385 RoadType rt_tram = GetRoadTypeTram(neighbour);
1386
1387 if ((rt_road != INVALID_ROADTYPE && HasRoadCatenary(rt_road)) ||
1388 (rt_tram != INVALID_ROADTYPE && HasRoadCatenary(rt_tram))) {
1389 rb_new |= DiagDirToRoadBits(dir);
1390 }
1391 }
1392 }
1393 }
1394 if (CountBits(rb_new) >= 2) rb = rb_new;
1395 }
1396
1397 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1400
1401 if (front != 0 || back != 0) {
1402 if (front != 0) front += GetRoadSpriteOffset(ti->tileh, rb);
1403 if (back != 0) back += GetRoadSpriteOffset(ti->tileh, rb);
1404 } else if (ti->tileh != SLOPE_FLAT) {
1405 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1406 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1407 } else {
1408 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb];
1409 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb];
1410 }
1411
1412 /* Catenary uses 1st company colour to help identify owner.
1413 * For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
1414 Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
1415 PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(COLOUR_GREY) : GetCompanyPalette(owner));
1416 uint8_t z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
1417 if (back != 0) {
1418 /* The "back" sprite contains the west, north and east pillars.
1419 * We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
1420 * 3/8 is chosen so that sprites can somewhat graphically extend into the tile. */
1421 static const int INF = 1000;
1422 static const SubSprite west = { -INF, -INF, -12, INF };
1423 static const SubSprite north = { -12, -INF, 12, INF };
1424 static const SubSprite east = { 12, -INF, INF, INF };
1425 int8_t west_z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
1426 int8_t north_z = GetSlopePixelZInCorner(ti->tileh, CORNER_N);
1427 int8_t east_z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
1428 AddSortableSpriteToDraw(back, pal, *ti, {{15, 0, west_z}, {1, 1, z_wires}, {-15, 0, static_cast<int8_t>(-west_z)}}, IsTransparencySet(TO_CATENARY), &west);
1429 AddSortableSpriteToDraw(back, pal, *ti, {{0, 0, north_z}, {1, 1, z_wires}, {0, 0, static_cast<int8_t>(-north_z)}}, IsTransparencySet(TO_CATENARY), &north);
1430 AddSortableSpriteToDraw(back, pal, *ti, {{0, 15, east_z}, {1, 1, z_wires}, {0, -15, static_cast<int8_t>(-east_z)}}, IsTransparencySet(TO_CATENARY), &east);
1431 }
1432 if (front != 0) {
1433 /* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
1434 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(TO_CATENARY));
1435 }
1436}
1437
1443{
1444 RoadBits road = ROAD_NONE;
1445 RoadBits tram = ROAD_NONE;
1446
1447 if (IsTileType(ti->tile, TileType::Road)) {
1448 if (IsNormalRoad(ti->tile)) {
1449 road = GetRoadBits(ti->tile, RTT_ROAD);
1450 tram = GetRoadBits(ti->tile, RTT_TRAM);
1451 } else if (IsLevelCrossing(ti->tile)) {
1452 tram = road = (GetCrossingRailAxis(ti->tile) == AXIS_Y ? ROAD_X : ROAD_Y);
1453 }
1454 } else if (IsTileType(ti->tile, TileType::Station)) {
1455 if (IsAnyRoadStop(ti->tile)) {
1456 if (IsDriveThroughStopTile(ti->tile)) {
1457 Axis axis = GetDriveThroughStopAxis(ti->tile);
1458 tram = road = (axis == AXIS_X ? ROAD_X : ROAD_Y);
1459 } else {
1460 tram = road = DiagDirToRoadBits(GetBayRoadStopDir(ti->tile));
1461 }
1462 }
1463 } else {
1464 /* No road here, no catenary to draw */
1465 return;
1466 }
1467
1468 RoadType rt = GetRoadTypeRoad(ti->tile);
1469 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1470 DrawRoadTypeCatenary(ti, rt, road);
1471 }
1472
1473 rt = GetRoadTypeTram(ti->tile);
1474 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1475 DrawRoadTypeCatenary(ti, rt, tram);
1476 }
1477}
1478
1488static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int8_t dx, int8_t dy, uint8_t h, bool transparent)
1489{
1490 int x = ti->x | dx;
1491 int y = ti->y | dy;
1492 int z = ti->z;
1493 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1494 AddSortableSpriteToDraw(img, PAL_NONE, ti->x, ti->y, z, {{dx, dy, 0}, {2, 2, h}, {}}, transparent);
1495}
1496
1507void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
1508{
1509 if (draw_underlay) {
1510 /* Road underlay takes precedence over tram */
1511 if (road_rti != nullptr) {
1512 if (road_rti->UsesOverlay()) {
1513 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_GROUND);
1514 DrawGroundSprite(ground + road_offset, pal);
1515 }
1516 } else {
1517 if (tram_rti->UsesOverlay()) {
1518 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_GROUND);
1519 DrawGroundSprite(ground + tram_offset, pal);
1520 } else {
1521 DrawGroundSprite(SPR_TRAMWAY_TRAM + tram_offset, pal);
1522 }
1523 }
1524 }
1525
1526 /* Draw road overlay */
1527 if (road_rti != nullptr) {
1528 if (road_rti->UsesOverlay()) {
1529 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_OVERLAY);
1530 if (ground != 0) DrawGroundSprite(ground + road_offset, pal);
1531 }
1532 }
1533
1534 /* Draw tram overlay */
1535 if (tram_rti != nullptr) {
1536 if (tram_rti->UsesOverlay()) {
1537 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_OVERLAY);
1538 if (ground != 0) DrawGroundSprite(ground + tram_offset, pal);
1539 } else if (road_rti != nullptr) {
1540 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + tram_offset, pal);
1541 }
1542 }
1543}
1544
1555static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
1556{
1557 /* Draw bare ground sprite if no road or road uses overlay system. */
1558 if (rti == nullptr || rti->UsesOverlay()) {
1559 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1560 return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
1561 }
1562
1563 switch (roadside) {
1564 case Roadside::Barren:
1565 *pal = PALETTE_TO_BARE_LAND;
1566 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1567
1568 case Roadside::Grass:
1570 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1571
1572 default:
1573 break; // Paved
1574 }
1575 }
1576
1577 /* Draw original road base sprite */
1578 SpriteID image = SPR_ROAD_Y + offset;
1579 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1580 image += 19;
1581 } else {
1582 switch (roadside) {
1583 case Roadside::Barren:
1584 *pal = PALETTE_TO_BARE_LAND;
1585 break;
1586
1587 case Roadside::Grass:
1589 break;
1590
1591 default:
1592 image -= 19;
1593 break; // Paved
1594 }
1595 }
1596
1597 return image;
1598}
1599
1610void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
1611{
1612 /* Determine sprite offsets */
1613 uint road_offset = GetRoadSpriteOffset(ti->tileh, road);
1614 uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
1615
1616 /* Draw baseset underlay */
1617 PaletteID pal = PAL_NONE;
1618 SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, snow_or_desert, &pal);
1619 DrawGroundSprite(image, pal);
1620
1621 DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
1622}
1623
1628static void DrawRoadBits(TileInfo *ti)
1629{
1630 RoadBits road = GetRoadBits(ti->tile, RTT_ROAD);
1631 RoadBits tram = GetRoadBits(ti->tile, RTT_TRAM);
1632
1633 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1634 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1635 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1636 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1637
1638 if (ti->tileh != SLOPE_FLAT) {
1639 DrawFoundation(ti, GetRoadFoundation(ti->tileh, road | tram));
1640 /* DrawFoundation() modifies ti. */
1641 }
1642
1643 DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnowOrDesert(ti->tile));
1644
1645 /* Draw one way */
1646 if (road_rti != nullptr) {
1648 if (drd != DRD_NONE) {
1649 SpriteID oneway = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ONEWAY);
1650
1651 if (oneway == 0) oneway = SPR_ONEWAY_BASE;
1652
1653 if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) {
1654 oneway += ONEWAY_SLOPE_N_OFFSET;
1655 } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) {
1656 oneway += ONEWAY_SLOPE_S_OFFSET;
1657 }
1658
1659 DrawGroundSpriteAt(oneway + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1660 }
1661 }
1662
1663 if (HasRoadWorks(ti->tile)) {
1664 /* Road works */
1665 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1666 return;
1667 }
1668
1669 /* Draw road, tram catenary */
1670 DrawRoadCatenary(ti);
1671
1672 /* Return if full detail is disabled, or we are zoomed fully out. */
1673 if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZoomLevel::Detail) return;
1674
1675 /* Do not draw details (street lights, trees) under low bridge */
1676 Roadside roadside = GetRoadside(ti->tile);
1677 if (IsBridgeAbove(ti->tile) && (roadside == Roadside::Trees || roadside == Roadside::StreetLights)) {
1678 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1679 int minz = GetTileMaxZ(ti->tile) + 2;
1680
1681 if (roadside == Roadside::Trees) minz++;
1682
1683 if (height < minz) return;
1684 }
1685
1686 /* If there are no road bits, return, as there is nothing left to do */
1687 if (HasAtMostOneBit(road)) return;
1688
1689 /* Do not draw details when invisible. */
1690 if (roadside == Roadside::Trees && IsInvisibilitySet(TO_TREES)) return;
1691 if (roadside == Roadside::StreetLights && IsInvisibilitySet(TO_HOUSES)) return;
1692
1693 /* Check whether details should be transparent. */
1694 bool is_transparent = false;
1695 if (roadside == Roadside::Trees && IsTransparencySet(TO_TREES)) {
1696 is_transparent = true;
1697 }
1699 is_transparent = true;
1700 }
1701
1702 /* Draw extra details. */
1703 for (const DrawRoadTileStruct *drts = _road_display_table[to_underlying(roadside)][road | tram]; drts->image != 0; drts++) {
1704 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
1705 }
1706}
1707
1709static void DrawTile_Road(TileInfo *ti)
1710{
1711 BridgePillarFlags blocked_pillars{};
1712 switch (GetRoadTileType(ti->tile)) {
1714 DrawRoadBits(ti);
1715
1716 if (IsBridgeAbove(ti->tile)) {
1717 RoadBits bits = GetAllRoadBits(ti->tile);
1718 if ((bits & ROAD_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
1719 if ((bits & ROAD_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
1720 if ((bits & ROAD_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
1721 if ((bits & ROAD_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
1722 }
1723 break;
1724
1727
1728 Axis axis = GetCrossingRailAxis(ti->tile);
1729
1730 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1731
1732 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1733 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1734 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1735 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1736
1737 PaletteID pal = PAL_NONE;
1738
1739 /* Draw base ground */
1740 if (rti->UsesOverlay()) {
1741 SpriteID image = SPR_ROAD_Y + axis;
1742
1743 Roadside roadside = GetRoadside(ti->tile);
1744 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1745 image += 19;
1746 } else {
1747 switch (roadside) {
1748 case Roadside::Barren:
1750 break;
1751
1752 case Roadside::Grass:
1753 break;
1754
1755 default:
1756 image -= 19;
1757 break; // Paved
1758 }
1759 }
1760
1761 DrawGroundSprite(image, pal);
1762 } else {
1763 SpriteID image = rti->base_sprites.crossing + axis;
1764 if (IsCrossingBarred(ti->tile)) image += 2;
1765
1766 Roadside roadside = GetRoadside(ti->tile);
1767 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1768 image += 8;
1769 } else {
1770 switch (roadside) {
1771 case Roadside::Barren:
1773 break;
1774
1775 case Roadside::Grass:
1776 break;
1777
1778 default:
1779 image += 4;
1780 break; // Paved
1781 }
1782 }
1783
1784 DrawGroundSprite(image, pal);
1785 }
1786
1787 DrawRoadOverlays(ti, pal, road_rti, tram_rti, axis, axis);
1788
1789 /* Draw rail/PBS overlay */
1790 bool draw_pbs = _game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile);
1791 if (rti->UsesOverlay()) {
1792 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1793 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1794 DrawGroundSprite(rail, pal);
1795
1796 const Axis road_axis = GetCrossingRoadAxis(ti->tile);
1797 const DiagDirection dir1 = AxisToDiagDir(road_axis);
1798 const DiagDirection dir2 = ReverseDiagDir(dir1);
1799 DiagDirections adjacent_diagdirs{};
1800 for (DiagDirection dir : { dir1, dir2 }) {
1801 const TileIndex t = TileAddByDiagDir(ti->tile, dir);
1802 if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
1803 adjacent_diagdirs.Set(dir);
1804 }
1805 }
1806
1807 switch (adjacent_diagdirs.base()) {
1808 case DiagDirections{}.base():
1809 DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1810 break;
1811
1812 case DiagDirections{DIAGDIR_NE}.base():
1813 DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE);
1814 break;
1815
1816 case DiagDirections{DIAGDIR_SE}.base():
1817 DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE);
1818 break;
1819
1820 case DiagDirections{DIAGDIR_SW}.base():
1821 DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE);
1822 break;
1823
1824 case DiagDirections{DIAGDIR_NW}.base():
1825 DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE);
1826 break;
1827
1828 default:
1829 /* Show no sprites */
1830 break;
1831 }
1832 } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) {
1833 /* Add another rail overlay, unless there is only the base road sprite. */
1834 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1836 DrawGroundSprite(rail, pal);
1837 }
1838
1839 /* Draw road, tram catenary */
1840 DrawRoadCatenary(ti);
1841
1842 /* Draw rail catenary */
1845 break;
1846 }
1847
1848 default:
1849 case RoadTileType::Depot: {
1851
1853
1854 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1855 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1856 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt == INVALID_ROADTYPE ? tram_rt : road_rt);
1857
1858 int relocation = GetCustomRoadSprite(rti, ti->tile, ROTSG_DEPOT);
1859 bool default_gfx = relocation == 0;
1860 if (default_gfx) {
1861 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1862 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && road_rt == INVALID_ROADTYPE && !rti->UsesOverlay()) {
1863 /* Sprites with track only work for default tram */
1864 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1865 default_gfx = false;
1866 } else {
1867 /* Sprites without track are always better, if provided */
1868 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1869 }
1870 }
1871 } else {
1872 relocation -= SPR_ROAD_DEPOT;
1873 }
1874
1876 const DrawTileSprites *dts = &_road_depot[dir];
1877 DrawGroundSprite(dts->ground.sprite, PAL_NONE);
1878
1879 if (default_gfx) {
1881 if (rti->UsesOverlay()) {
1882 SpriteID ground = GetCustomRoadSprite(rti, ti->tile, ROTSG_OVERLAY);
1883 if (ground != 0) DrawGroundSprite(ground + offset, PAL_NONE);
1884 } else if (road_rt == INVALID_ROADTYPE) {
1885 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE);
1886 }
1887 }
1888
1889 DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, palette);
1890 /* Depots can't have bridges above so no blocked pillars. */
1891 break;
1892 }
1893 }
1894 DrawBridgeMiddle(ti, blocked_pillars);
1895}
1896
1904void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
1905{
1907
1908 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1909 int relocation = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_DEPOT);
1910 bool default_gfx = relocation == 0;
1911 if (default_gfx) {
1912 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1913 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && RoadTypeIsTram(rt) && !rti->UsesOverlay()) {
1914 /* Sprites with track only work for default tram */
1915 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1916 default_gfx = false;
1917 } else {
1918 /* Sprites without track are always better, if provided */
1919 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1920 }
1921 }
1922 } else {
1923 relocation -= SPR_ROAD_DEPOT;
1924 }
1925
1926 const DrawTileSprites *dts = &_road_depot[dir];
1927 DrawSprite(dts->ground.sprite, PAL_NONE, x, y);
1928
1929 if (default_gfx) {
1931 if (rti->UsesOverlay()) {
1933 if (ground != 0) DrawSprite(ground + offset, PAL_NONE, x, y);
1934 } else if (RoadTypeIsTram(rt)) {
1935 DrawSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE, x, y);
1936 }
1937 }
1938
1939 DrawRailTileSeqInGUI(x, y, dts, relocation, 0, palette);
1940}
1941
1948{
1949 assert(!invalidate || _generating_world);
1950
1951 for (const auto t : Map::Iterate()) {
1952 if (IsTileType(t, TileType::Road) && !IsRoadDepot(t) && !HasTownOwnedRoad(t)) {
1953 TownID tid = TownID::Invalid();
1954 if (!invalidate) {
1955 const Town *town = CalcClosestTownFromTile(t);
1956 if (town != nullptr) tid = town->index;
1957 }
1958 SetTownIndex(t, tid);
1959 }
1960 }
1961}
1962
1964static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, [[maybe_unused]] bool ground_vehicle)
1965{
1966
1967 if (IsNormalRoad(tile)) {
1968 auto [tileh, z] = GetTilePixelSlope(tile);
1969 if (tileh == SLOPE_FLAT) return z;
1970
1972 z += ApplyPixelFoundationToSlope(f, tileh);
1973 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1974 } else {
1975 return GetTileMaxPixelZ(tile);
1976 }
1977}
1978
1981{
1982 if (IsNormalRoad(tile)) {
1983 return GetRoadFoundation(tileh, GetAllRoadBits(tile));
1984 } else {
1985 return FlatteningFoundation(tileh);
1986 }
1987}
1988
1989static const Roadside _town_road_types[][2] = {
1995};
1996
1997static_assert(lengthof(_town_road_types) == NUM_HOUSE_ZONES);
1998
1999static const Roadside _town_road_types_2[][2] = {
2005};
2006
2007static_assert(lengthof(_town_road_types_2) == NUM_HOUSE_ZONES);
2008
2009
2011static void TileLoop_Road(TileIndex tile)
2012{
2013 switch (_settings_game.game_creation.landscape) {
2014 case LandscapeType::Arctic: {
2015 /* Roads use the snow level of their maximum height minus one, unless flat. */
2016 int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileMaxZ(tile) - 1;
2017 if (IsOnSnowOrDesert(tile) != (tile_z > GetSnowLine())) {
2018 ToggleSnowOrDesert(tile);
2019 MarkTileDirtyByTile(tile);
2020 }
2021 break;
2022 }
2023
2025 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnSnowOrDesert(tile)) {
2026 ToggleSnowOrDesert(tile);
2027 MarkTileDirtyByTile(tile);
2028 }
2029 break;
2030
2031 default:
2032 break;
2033 }
2034
2035 if (IsRoadDepot(tile)) return;
2036
2037 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
2038 if (!HasRoadWorks(tile)) {
2040
2041 if (t != nullptr) {
2042 grp = GetTownRadiusGroup(t, tile);
2043
2044 /* Show an animation to indicate road work */
2045 if (t->road_build_months != 0 &&
2046 (DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) &&
2047 IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) {
2048 if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
2049 StartRoadWorks(tile);
2050
2051 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
2053 TileX(tile) * TILE_SIZE + 7,
2054 TileY(tile) * TILE_SIZE + 7,
2055 0,
2056 EV_BULLDOZER);
2057 MarkTileDirtyByTile(tile);
2058 return;
2059 }
2060 }
2061 }
2062
2063 {
2064 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2065 const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[to_underlying(grp)] : _town_road_types[to_underlying(grp)];
2066 Roadside cur_rs = GetRoadside(tile);
2067
2068 /* We have our desired type, do nothing */
2069 if (cur_rs == new_rs[0]) return;
2070
2071 /* We have the pre-type of the desired type, switch to the desired type */
2072 if (cur_rs == new_rs[1]) {
2073 cur_rs = new_rs[0];
2074 /* We have barren land, install the pre-type */
2075 } else if (cur_rs == Roadside::Barren) {
2076 cur_rs = new_rs[1];
2077 /* We're totally off limits, remove any installation and make barren land */
2078 } else {
2079 cur_rs = Roadside::Barren;
2080 }
2081 SetRoadside(tile, cur_rs);
2082 MarkTileDirtyByTile(tile);
2083 }
2084 } else if (IncreaseRoadWorksCounter(tile)) {
2085 TerminateRoadWorks(tile);
2086
2087 if (_settings_game.economy.mod_road_rebuild) {
2088 /* Generate a nicer town surface */
2089 const RoadBits old_rb = GetAnyRoadBits(tile, RTT_ROAD);
2090 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2091
2092 if (old_rb != new_rb) {
2094
2095 /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */
2096 if (new_rb == 0) {
2097 MarkTileDirtyByTile(tile);
2098 return;
2099 }
2100 }
2101 }
2102
2103 /* Possibly change road type */
2104 if (GetRoadOwner(tile, RTT_ROAD) == OWNER_TOWN) {
2106 if (rt != GetRoadTypeRoad(tile)) {
2107 SetRoadType(tile, RTT_ROAD, rt);
2108 }
2109 }
2110
2111 MarkTileDirtyByTile(tile);
2112 }
2113}
2114
2116static bool ClickTile_Road(TileIndex tile)
2117{
2118 if (!IsRoadDepot(tile)) return false;
2119
2121 return true;
2122}
2123
2125static const TrackBits _road_trackbits[16] = {
2126 TRACK_BIT_NONE, // ROAD_NONE
2127 TRACK_BIT_NONE, // ROAD_NW
2128 TRACK_BIT_NONE, // ROAD_SW
2129 TRACK_BIT_LEFT, // ROAD_W
2130 TRACK_BIT_NONE, // ROAD_SE
2131 TRACK_BIT_Y, // ROAD_Y
2132 TRACK_BIT_LOWER, // ROAD_S
2133 TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | ROAD_SW
2134 TRACK_BIT_NONE, // ROAD_NE
2135 TRACK_BIT_UPPER, // ROAD_N
2136 TRACK_BIT_X, // ROAD_X
2137 TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | ROAD_NW
2138 TRACK_BIT_RIGHT, // ROAD_E
2139 TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | ROAD_NE
2140 TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | ROAD_SE
2141 TRACK_BIT_ALL, // ROAD_ALL
2142};
2143
2145static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
2146{
2147 TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
2148 TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
2149 switch (mode) {
2150 case TRANSPORT_RAIL:
2151 if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
2152 break;
2153
2154 case TRANSPORT_ROAD: {
2155 RoadTramType rtt = (RoadTramType)sub_mode;
2156 if (!HasTileRoadType(tile, rtt)) break;
2157 switch (GetRoadTileType(tile)) {
2158 case RoadTileType::Normal: {
2159 const uint drd_to_multiplier[DRD_END] = { 0x101, 0x100, 0x1, 0x0 };
2160 RoadBits bits = GetRoadBits(tile, rtt);
2161
2162 /* no roadbit at this side of tile, return 0 */
2163 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break;
2164
2165 uint multiplier = drd_to_multiplier[(rtt == RTT_TRAM) ? DRD_NONE : GetDisallowedRoadDirections(tile)];
2166 if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier);
2167 break;
2168 }
2169
2171 Axis axis = GetCrossingRoadAxis(tile);
2172
2173 if (side != INVALID_DIAGDIR && axis != DiagDirToAxis(side)) break;
2174
2175 trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis));
2176 if (IsCrossingBarred(tile)) {
2177 red_signals = trackdirbits;
2178 if (TrainOnCrossing(tile)) break;
2179
2180 auto mask_red_signal_bits_if_crossing_barred = [&](TileIndex t, TrackdirBits mask) {
2181 if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
2182 };
2183 /* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
2184 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE);
2185 /* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
2186 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW);
2187 }
2188 break;
2189 }
2190
2191 default:
2192 case RoadTileType::Depot: {
2194
2195 if (side != INVALID_DIAGDIR && side != dir) break;
2196
2198 break;
2199 }
2200 }
2201 break;
2202 }
2203
2204 default: break;
2205 }
2206 return CombineTrackStatus(trackdirbits, red_signals);
2207}
2208
2209static const StringID _road_tile_strings[] = {
2210 STR_LAI_ROAD_DESCRIPTION_ROAD,
2211 STR_LAI_ROAD_DESCRIPTION_ROAD,
2212 STR_LAI_ROAD_DESCRIPTION_ROAD,
2213 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2214 STR_LAI_ROAD_DESCRIPTION_ROAD,
2215 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2216 STR_LAI_ROAD_DESCRIPTION_ROAD,
2217 STR_LAI_ROAD_DESCRIPTION_ROAD,
2218};
2219
2222{
2223 Owner rail_owner = INVALID_OWNER;
2224 Owner road_owner = INVALID_OWNER;
2225 Owner tram_owner = INVALID_OWNER;
2226
2227 RoadType road_rt = GetRoadTypeRoad(tile);
2228 RoadType tram_rt = GetRoadTypeTram(tile);
2229 if (road_rt != INVALID_ROADTYPE) {
2230 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
2231 td.roadtype = rti->strings.name;
2232 td.road_speed = rti->max_speed / 2;
2233 road_owner = GetRoadOwner(tile, RTT_ROAD);
2234 }
2235 if (tram_rt != INVALID_ROADTYPE) {
2236 const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
2237 td.tramtype = rti->strings.name;
2238 td.tram_speed = rti->max_speed / 2;
2239 tram_owner = GetRoadOwner(tile, RTT_TRAM);
2240 }
2241
2242 switch (GetRoadTileType(tile)) {
2244 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING;
2245 rail_owner = GetTileOwner(tile);
2246
2247 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2248 td.railtype = rti->strings.name;
2249 td.rail_speed = rti->max_speed;
2250
2251 break;
2252 }
2253
2255 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
2256 td.build_date = Depot::GetByTile(tile)->build_date;
2257 break;
2258
2259 default: {
2260 td.str = (road_rt != INVALID_ROADTYPE ? _road_tile_strings[to_underlying(GetRoadside(tile))] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
2261 break;
2262 }
2263 }
2264
2265 /* Now we have to discover, if the tile has only one owner or many:
2266 * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
2267 * - Compare the found owner with the other owners, and test if they differ.
2268 * Note: If road exists it will be the first_owner.
2269 */
2270 Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
2271 bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
2272
2273 if (mixed_owners) {
2274 /* Multiple owners */
2275 td.owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_RAIL_OWNER);
2276 td.owner[0] = rail_owner;
2277 td.owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_ROAD_OWNER);
2278 td.owner[1] = road_owner;
2279 td.owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_TRAM_OWNER);
2280 td.owner[2] = tram_owner;
2281 } else {
2282 /* One to rule them all */
2283 td.owner[0] = first_owner;
2284 }
2285}
2286
2294
2296static VehicleEnterTileStates VehicleEnterTile_Road(Vehicle *v, TileIndex tile, [[maybe_unused]] int x, [[maybe_unused]] int y)
2297{
2298 switch (GetRoadTileType(tile)) {
2299 case RoadTileType::Depot: {
2300 if (v->type != VEH_ROAD) break;
2301
2303 if (rv->frame == RVC_DEPOT_STOP_FRAME &&
2305 rv->state = RVSB_IN_DEPOT;
2307 rv->direction = ReverseDir(rv->direction);
2308 if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
2309 rv->tile = tile;
2310
2313 }
2314 break;
2315 }
2316
2317 default: break;
2318 }
2319 return {};
2320}
2321
2322
2324static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2325{
2326 if (IsRoadDepot(tile)) {
2327 if (GetTileOwner(tile) == old_owner) {
2328 if (new_owner == INVALID_OWNER) {
2329 Command<Commands::LandscapeClear>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile);
2330 } else {
2331 /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2332 RoadType rt = GetRoadTypeRoad(tile);
2333 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
2334 Company::Get(old_owner)->infrastructure.road[rt] -= 2;
2335 Company::Get(new_owner)->infrastructure.road[rt] += 2;
2336
2337 SetTileOwner(tile, new_owner);
2338 for (RoadTramType rtt : _roadtramtypes) {
2339 if (GetRoadOwner(tile, rtt) == old_owner) {
2340 SetRoadOwner(tile, rtt, new_owner);
2341 }
2342 }
2343 }
2344 }
2345 return;
2346 }
2347
2348 for (RoadTramType rtt : _roadtramtypes) {
2349 /* Update all roadtypes, no matter if they are present */
2350 if (GetRoadOwner(tile, rtt) == old_owner) {
2351 RoadType rt = GetRoadType(tile, rtt);
2352 if (rt != INVALID_ROADTYPE) {
2353 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2354 uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt));
2355 Company::Get(old_owner)->infrastructure.road[rt] -= num_bits;
2356 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits;
2357 }
2358
2359 SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
2360 }
2361 }
2362
2363 if (IsLevelCrossing(tile)) {
2364 if (GetTileOwner(tile) == old_owner) {
2365 if (new_owner == INVALID_OWNER) {
2366 Command<Commands::RemoveRail>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile, GetCrossingRailTrack(tile));
2367 } else {
2368 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2369 Company::Get(old_owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
2370 Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
2371
2372 SetTileOwner(tile, new_owner);
2373 }
2374 }
2375 }
2376}
2377
2379static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
2380{
2381 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
2382 switch (GetRoadTileType(tile)) {
2384 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]);
2385 break;
2386
2389 break;
2390
2391 case RoadTileType::Normal: {
2392 RoadBits bits = GetAllRoadBits(tile);
2393 RoadBits bits_copy = bits;
2394 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2395 if (CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE).Succeeded()) {
2396 /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
2397 if (bits == bits_copy) {
2398 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2399
2400 /* Get the slope on top of the foundation */
2401 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), tileh_old);
2402 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), tileh_new);
2403
2404 /* The surface slope must not be changed */
2405 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]);
2406 }
2407 }
2408 break;
2409 }
2410
2411 default: NOT_REACHED();
2412 }
2413 }
2414
2415 return Command<Commands::LandscapeClear>::Do(flags, tile);
2416}
2417
2424static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
2425{
2426 return (owner == OWNER_NONE || (owner == OWNER_TOWN && rtt == RTT_ROAD));
2427}
2428
2437static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
2438{
2439 /* Scenario editor, maybe? Don't touch the owners when converting roadtypes... */
2440 if (_current_company >= MAX_COMPANIES) return;
2441
2442 /* We can't get a company from invalid owners but we can get ownership of roads without an owner */
2443 if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
2444
2445 Company *c;
2446
2447 switch (owner.base()) {
2448 case OWNER_NONE.base():
2449 SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company);
2451 break;
2452
2453 default:
2454 c = Company::Get(owner);
2455 c->infrastructure.road[from_type] -= num_pieces;
2456 c->infrastructure.road[to_type] += num_pieces;
2458 break;
2459 }
2460}
2461
2473CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal)
2474{
2475 TileIndex area_end = tile;
2476
2477 if (!ValParamRoadType(to_type)) return CMD_ERROR;
2478 if (area_start >= Map::Size()) return CMD_ERROR;
2479
2480 RoadVehicleList affected_rvs;
2481 RoadTramType rtt = GetRoadTramType(to_type);
2482
2484 CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert.
2485 bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633)
2486
2487 std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal);
2488 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
2489 /* Is road present on tile? */
2490 if (!MayHaveRoad(tile)) continue;
2491
2492 /* Converting to the same subtype? */
2493 RoadType from_type = GetRoadType(tile, rtt);
2494 if (from_type == INVALID_ROADTYPE || from_type == to_type) continue;
2495
2496 /* Check if there is any infrastructure on tile */
2497 TileType tt = GetTileType(tile);
2498 switch (tt) {
2499 case TileType::Station:
2500 if (!IsAnyRoadStop(tile)) continue;
2501 break;
2502 case TileType::Road:
2503 if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
2504 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD);
2505 continue;
2506 }
2507 break;
2509 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) continue;
2510 break;
2511 default: continue;
2512 }
2513
2514 /* Trying to convert other's road */
2515 Owner owner = GetRoadOwner(tile, rtt);
2516 if (!CanConvertUnownedRoadType(owner, rtt)) {
2517 CommandCost ret = CheckOwnership(owner, tile);
2518 if (ret.Failed()) {
2519 error = std::move(ret);
2520 continue;
2521 }
2522 }
2523
2524 /* Base the ability to replace town roads and bridges on the town's
2525 * acceptance of destructive actions. */
2526 if (owner == OWNER_TOWN) {
2527 Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
2529 if (ret.Failed()) {
2530 error = std::move(ret);
2531 continue;
2532 }
2533 }
2534
2535 /* Vehicle on the tile when not converting normal <-> powered
2536 * Tunnels and bridges have special check later */
2537 if (tt != TileType::TunnelBridge) {
2538 if (!HasPowerOnRoad(from_type, to_type)) {
2540 if (ret.Failed()) {
2541 error = std::move(ret);
2542 continue;
2543 }
2544
2545 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2546 error.MakeError(STR_ERROR_OWNED_BY);
2547 if (IsLocalCompany()) {
2548 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2549 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2550 }
2551 continue;
2552 }
2553 }
2554
2555 uint num_pieces = CountBits(GetAnyRoadBits(tile, rtt));
2556 if (tt == TileType::Station && IsBayRoadStopTile(tile)) {
2557 num_pieces *= ROAD_STOP_TRACKBIT_FACTOR;
2558 } else if (tt == TileType::Road && IsRoadDepot(tile)) {
2559 num_pieces *= ROAD_DEPOT_TRACKBIT_FACTOR;
2560 }
2561
2562 found_convertible_road = true;
2563 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2564
2565 if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
2566 /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */
2567 if (owner == _current_company) {
2568 ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
2569 }
2570
2571 /* Perform the conversion */
2572 SetRoadType(tile, rtt, to_type);
2573 MarkTileDirtyByTile(tile);
2574
2575 /* update power of train on this tile */
2576 for (Vehicle *v : VehiclesOnTile(tile)) {
2577 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2578 }
2579
2580 if (IsRoadDepotTile(tile)) {
2581 /* Update build vehicle window related to this depot */
2584 }
2585 }
2586 } else {
2587 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
2588
2589 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
2590 * it would cause assert because of different test and exec runs */
2591 if (endtile < tile) {
2592 if (diagonal) {
2593 if (DiagonalTileArea(area_start, area_end).Contains(endtile)) continue;
2594 } else {
2595 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
2596 }
2597 }
2598
2599 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
2600 if (!HasPowerOnRoad(from_type, to_type)) {
2601 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
2602 if (ret.Failed()) {
2603 error = std::move(ret);
2604 continue;
2605 }
2606
2607 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2608 error.MakeError(STR_ERROR_OWNED_BY);
2609 if (IsLocalCompany()) {
2610 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2611 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2612 }
2613 continue;
2614 }
2615 }
2616
2617 /* There are 2 pieces on *every* tile of the bridge or tunnel */
2618 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * 2;
2619 found_convertible_road = true;
2620 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2621
2622 if (flags.Test(DoCommandFlag::Execute)) {
2623 /* Update the company infrastructure counters. */
2624 if (owner == _current_company) {
2625 /* Each piece should be counted TUNNELBRIDGE_TRACKBIT_FACTOR times
2626 * for the infrastructure counters (cause of #8297). */
2627 ConvertRoadTypeOwner(tile, num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR, owner, from_type, to_type);
2628 SetTunnelBridgeOwner(tile, endtile, _current_company);
2629 }
2630
2631 /* Perform the conversion */
2632 SetRoadType(tile, rtt, to_type);
2633 SetRoadType(endtile, rtt, to_type);
2634
2635 for (Vehicle *v : VehiclesOnTile(tile)) {
2636 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2637 }
2638 for (Vehicle *v : VehiclesOnTile(endtile)) {
2639 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2640 }
2641
2642 if (IsBridge(tile)) {
2643 MarkBridgeDirty(tile);
2644 } else {
2645 MarkTileDirtyByTile(tile);
2646 MarkTileDirtyByTile(endtile);
2647 }
2648 }
2649 }
2650 }
2651
2652 if (flags.Test(DoCommandFlag::Execute)) {
2653 /* Roadtype changed, update roadvehicles as when entering different track */
2654 for (RoadVehicle *v : affected_rvs) {
2655 v->CargoChanged();
2656 }
2657 }
2658
2659 return found_convertible_road ? cost : error;
2660}
2661
2663static CommandCost CheckBuildAbove_Road(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] Axis axis, [[maybe_unused]] int height)
2664{
2665 if (!IsRoadDepot(tile)) return CommandCost();
2666 return Command<Commands::LandscapeClear>::Do(flags, tile);
2667}
2668
2670extern const TileTypeProcs _tile_type_road_procs = {
2671 .draw_tile_proc = DrawTile_Road,
2672 .get_slope_pixel_z_proc = GetSlopePixelZ_Road,
2673 .clear_tile_proc = ClearTile_Road,
2674 .get_tile_desc_proc = GetTileDesc_Road,
2675 .get_tile_track_status_proc = GetTileTrackStatus_Road,
2676 .click_tile_proc = ClickTile_Road,
2677 .tile_loop_proc = TileLoop_Road,
2678 .change_tile_owner_proc = ChangeTileOwner_Road,
2679 .vehicle_enter_tile_proc = VehicleEnterTile_Road,
2680 .get_foundation_proc = GetFoundation_Road,
2681 .terraform_tile_proc = TerraformTile_Road,
2682 .check_build_above_proc = CheckBuildAbove_Road,
2683};
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 HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
constexpr T KillFirstBit(T value)
Clear the first bit in an integer.
void DrawBridgeMiddle(const TileInfo *ti, BridgePillarFlags blocked_pillars)
Draw the middle bits of a bridge.
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
@ 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.
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 Timpl & Set()
Set all bits.
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.
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:115
SpriteID single_x
single piece of rail in X direction, without ground
Definition rail.h:125
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:220
struct RailTypeInfo::@157247141350136173143103254227157213063052244122 strings
Strings associated with the rail type.
SpriteID crossing
level crossing, rail in X direction
Definition rail.h:132
SpriteID single_y
single piece of rail in Y direction, without ground
Definition rail.h:126
StringID name
Name of this rail type.
Definition rail.h:165
struct RailTypeInfo::@332027037331076264023214171276243307073252216167 base_sprites
Struct containing the main sprites.
RoadTypeLabel label
Unique 32 bit road type identifier.
Definition road.h:121
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:96
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:151
RoadType Index() const
Get the RoadType for this RoadTypeInfo.
Definition road.cpp:30
CursorID autoroad
Cursor for autorail tool.
Definition road.h:70
TimerGameCalendar::Date introduction_date
Introduction date.
Definition road.h:140
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
Definition road.h:156
RoadTypeFlags flags
Bit mask of road type flags.
Definition road.h:101
FlatSet< RoadTypeLabel > alternate_labels
Road type labels this type provides in addition to the main label.
Definition road.h:126
CursorID depot
Cursor for building a depot.
Definition road.h:71
CursorID road_nwse
Cursor for building rail in Y direction.
Definition road.h:69
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:116
struct RoadTypeInfo::@070000167274302256150317022075324310363002361255 strings
Strings associated with the rail type.
StringID name
Name of this rail type.
Definition road.h:77
SpriteID build_y_road
button for building single rail in Y direction
Definition road.h:60
CursorID tunnel
Cursor for building a tunnel.
Definition road.h:72
SpriteID auto_road
button for the autoroad construction
Definition road.h:61
SpriteID convert_road
button for converting road types
Definition road.h:64
CursorID road_swne
Cursor for building rail in X direction.
Definition road.h:68
SpriteID build_x_road
button for building single rail in X direction
Definition road.h:59
SpriteID build_depot
button for building depots
Definition road.h:62
SpriteID build_tunnel
button for building a tunnel
Definition road.h:63
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.
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
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.
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.
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.
Axis
Allow incrementing of DiagDirDiff variables.
@ AXIS_X
The X axis.
@ AXIS_Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
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.
@ EXPENSES_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:559
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:1038
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
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:57
@ TownEdge
Edge of the town; roads without pavement.
Definition house.h:58
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
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:75
Base for the NewGRF implementation.
bool HasGrfMiscBit(GrfMiscBit bit)
Check for grf miscellaneous bits.
Definition newgrf.h:217
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
Definition newgrf.h:191
@ DesertPavedRoads
Show pavement and lights in desert towns.
Definition newgrf.h:61
Functions/types related to NewGRF debugging.
SpriteID GetCustomRailSprite(const RailTypeInfo *rti, TileIndex tile, RailTypeSpriteGroup 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, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
NewGRF handling of road types.
@ DO_FULL_DETAIL
Also draw details of track and roads.
Definition openttd.h:50
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:301
@ RTSG_CROSSING
Level crossing overlay images.
Definition rail.h:48
bool RailNoLevelCrossings(RailType rt)
Test if a RailType disallows build of level crossings.
Definition rail.h:399
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:614
@ 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:230
@ 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:251
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:215
Money RoadConvertCost(RoadType from, RoadType to)
Calculates the cost of road conversion.
Definition road.h:269
std::vector< RoadType > _sorted_roadtypes
Sorted list of road types.
Definition road_cmd.cpp:55
@ ROTSG_ONEWAY
Optional: One-way indicator images.
Definition road.h:48
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition road.h:38
@ ROTSG_GROUND
Required: Main group of ground images.
Definition road.h:39
@ ROTSG_DEPOT
Optional: Depot images.
Definition road.h:45
@ ROTSG_CURSORS
Optional: Cursor and toolbar icon images.
Definition road.h:37
@ ROTSG_CATENARY_BACK
Optional: Catenary back.
Definition road.h:42
@ ROTSG_CATENARY_FRONT
Optional: Catenary front.
Definition road.h:41
bool RoadNoLevelCrossing(RoadType roadtype)
Test if road disallows level crossings.
Definition road.h:283
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:240
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:603
static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
Tile callback function signature for getting the foundation of a tile.
static const RoadBits _invalid_tileh_slopes_road[2][15]
Invalid RoadBits on slopes.
Definition road_cmd.cpp:195
static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Tile callback function signature for getting the possible tracks that can be taken on a given tile by...
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:941
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:538
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:970
static const TrackBits _road_trackbits[16]
Converts RoadBits to TrackBits.
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 CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check)
Delete a piece of road.
Definition road_cmd.cpp:318
static void TileLoop_Road(TileIndex tile)
Tile callback function signature for running periodic tile updates.
static const uint8_t _roadveh_enter_depot_dir[4]
Given the direction the road depot is pointing, this is the direction the vehicle should be travellin...
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.
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:111
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:147
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:136
bool IsStraightRoad(RoadBits r)
Check if we've got a straight road.
Definition road_func.h:81
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:96
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.
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:390
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 RTT_ROAD.
Definition road_map.h:152
void SetRoadDepotExitDirection(Tile tile, DiagDirection dir)
Sets the exit direction of a road depot.
Definition road_map.h:692
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:529
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
TrackBits GetCrossingRailBits(Tile tile)
Get the rail track bits of a level crossing.
Definition road_map.h:378
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 RTT_TRAM.
Definition road_map.h:210
void StartRoadWorks(Tile t)
Start road works on a tile.
Definition road_map.h:541
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:576
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 RTT_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:646
Roadside GetRoadside(Tile tile)
Get the decorations of a road.
Definition road_map.h:499
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:672
void ToggleSnowOrDesert(Tile t)
Toggle the snow/desert state of a road tile.
Definition road_map.h:476
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:562
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:615
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:426
void SetRoadside(Tile tile, Roadside s)
Set the decorations of a road.
Definition road_map.h:509
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:706
void SetCrossingReservation(Tile t, bool b)
Set the reservation state of the rail crossing.
Definition road_map.h:403
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:483
@ Paved
Road with paved sidewalks.
Definition road_map.h:486
@ Barren
Road on barren land.
Definition road_map.h:484
@ GrassRoadWorks
Road on grass with road works.
Definition road_map.h:490
@ StreetLights
Road with street lights on paved sidewalks.
Definition road_map.h:487
@ Trees
Road with trees on paved sidewalks.
Definition road_map.h:489
@ Grass
Road on grass.
Definition road_map.h:485
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:467
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition road_map.h:519
RoadBits
Enumeration for the road parts on a tile.
Definition road_type.h:56
@ ROAD_SW
South-west part.
Definition road_type.h:59
@ ROAD_ALL
Full 4-way crossing.
Definition road_type.h:70
@ ROAD_NONE
No road-part is build.
Definition road_type.h:57
@ ROAD_NE
North-east part.
Definition road_type.h:61
@ ROAD_SE
South-east part.
Definition road_type.h:60
@ ROAD_Y
Full road along the y-axis (north-west + south-east).
Definition road_type.h:63
@ ROAD_NW
North-west part.
Definition road_type.h:58
@ ROAD_X
Full road along the x-axis (south-west + north-east).
Definition road_type.h:62
RoadTramType
The different types of road type.
Definition road_type.h:37
@ RTT_ROAD
Road road type.
Definition road_type.h:38
@ RTT_TRAM
Tram road type.
Definition road_type.h:39
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
@ ROADTYPE_TRAM
Trams.
Definition road_type.h:26
@ ROADTYPE_ROAD
Basic road type.
Definition road_type.h:25
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:27
DisallowedRoadDirections
Which directions are disallowed ?
Definition road_type.h:77
@ DRD_NORTHBOUND
All northbound traffic is disallowed.
Definition road_type.h:80
@ DRD_END
Sentinel.
Definition road_type.h:82
@ DRD_BOTH
All directions are disallowed.
Definition road_type.h:81
@ DRD_NONE
None of the directions are disallowed.
Definition road_type.h:78
@ DRD_SOUTHBOUND
All southbound traffic is disallowed.
Definition road_type.h:79
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:160
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:415
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:126
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:369
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:99
Slope
Enumeration for the slope-type.
Definition slope_type.h:47
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:60
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:55
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:48
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:57
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:56
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:54
Foundation
Enumeration for Foundations.
Definition slope_type.h:92
@ FOUNDATION_LEVELED
The tile is leveled up to a flat slope.
Definition slope_type.h:94
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:93
@ FOUNDATION_INCLINED_X
The tile has an along X-axis inclined foundation.
Definition slope_type.h:95
@ FOUNDATION_INCLINED_Y
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:96
static const uint32_t VALID_LEVEL_CROSSING_SLOPES
Constant bitset with safe slopes for building a level crossing.
Definition slope_type.h:85
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 PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1619
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
Definition sprites.h:274
static const PaletteID PALETTE_TO_BARE_LAND
sets colour to bare land stuff for rail, road and crossings
Definition sprites.h:1607
static const SpriteID SPR_ONEWAY_BASE
One way road sprites.
Definition sprites.h:295
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:271
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.
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 Company * Get(auto index)
static bool CanAllocateItem(size_t n=1)
static T * Create(Targs &&... args)
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:38
uint16_t rail_speed
Speed limit of rail (bridges and track).
Definition tile_cmd.h:51
StringID str
Description of the tile.
Definition tile_cmd.h:39
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:43
std::array< Owner, 4 > owner
Name of the owner(s).
Definition tile_cmd.h:41
uint16_t tram_speed
Speed limit of tram (bridges and track).
Definition tile_cmd.h:55
StringID roadtype
Type of road on the tile.
Definition tile_cmd.h:52
StringID tramtype
Type of tram on the tile.
Definition tile_cmd.h:54
StringID railtype
Type of rail on the tile.
Definition tile_cmd.h:50
uint16_t road_speed
Speed limit of road (bridges and track).
Definition tile_cmd.h:53
std::array< StringID, 4 > owner_type
Type of each owner.
Definition tile_cmd.h:42
Tile information, used while rendering the tile.
Definition tile_cmd.h:32
Slope tileh
Slope of the tile.
Definition tile_cmd.h:33
TileIndex tile
Tile index.
Definition tile_cmd.h:34
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:212
std::array< uint32_t, NUM_HOUSE_ZONES > squared_town_zone_radius
UpdateTownRadius updates this given the house count.
Definition town.h:56
Town data structure.
Definition town.h:63
TileIndex xy
town center tile
Definition town.h:64
TownCache cache
Container for all cacheable data.
Definition town.h:66
uint8_t road_build_months
fund road reconstruction in action?
Definition town.h:150
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:25
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
@ TROPICZONE_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:229
@ RoadRemove
Removal of a road owned by the town.
Definition town.h:228
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:937
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:287
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:67
static constexpr int RATING_ROAD_DOWN_STEP_INNER
removing a roadpiece in the middle
Definition town_type.h:66
static constexpr int RATING_ROAD_MINIMUM
minimum rating after removing town owned road
Definition town_type.h:68
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:319
TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition track_func.h:390
TrackBits AxisToTrackBits(Axis a)
Maps an Axis to the corresponding TrackBits value.
Definition track_func.h:88
TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track bits incidating with that diagdir.
Definition track_func.h:529
Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track AXIS_X -> TRACK_X AXIS_Y -> TRACK_Y Uses the fact that the...
Definition track_func.h:66
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
@ TRACK_BIT_UPPER
Upper track.
Definition track_type.h:39
@ TRACK_BIT_LEFT
Left track.
Definition track_type.h:41
@ TRACK_BIT_Y
Y-axis track.
Definition track_type.h:38
@ TRACK_BIT_NONE
No track.
Definition track_type.h:36
@ TRACK_BIT_X
X-axis track.
Definition track_type.h:37
@ TRACK_BIT_LOWER
Lower track.
Definition track_type.h:40
@ TRACK_BIT_ALL
All possible tracks.
Definition track_type.h:50
@ TRACK_BIT_RIGHT
Right track.
Definition track_type.h:42
@ TRACKDIR_X_NE
X-axis and direction to north-east.
Definition track_type.h:68
@ TRACKDIR_Y_SE
Y-axis and direction to south-east.
Definition track_type.h:69
@ TRACKDIR_X_SW
X-axis and direction to south-west.
Definition track_type.h:76
@ TRACKDIR_Y_NW
Y-axis and direction to north-west.
Definition track_type.h:77
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:97
@ TRACKDIR_BIT_Y_NW
Track y-axis, direction north-west.
Definition track_type.h:107
@ TRACKDIR_BIT_X_NE
Track x-axis, direction north-east.
Definition track_type.h:99
@ TRACKDIR_BIT_Y_SE
Track y-axis, direction south-east.
Definition track_type.h:100
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
@ TRACKDIR_BIT_X_SW
Track x-axis, direction south-west.
Definition track_type.h:106
Track
These are used to specify a single track.
Definition track_type.h:19
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...
uint8_t _display_opt
What do we want to draw/do?
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...
@ TO_BUILDINGS
company buildings - depots, stations, HQ, ...
@ TO_CATENARY
catenary
@ TO_TREES
trees
@ TO_HOUSES
town buildings
TransportType
Available types of transport.
@ TRANSPORT_RAIL
Transport by train.
@ TRANSPORT_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:556
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1564
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:580
@ Hidden
Vehicle is not visible.
Functions related to vehicles.
@ VEH_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:658
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 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:3321
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
@ WC_BUILD_VEHICLE
Build vehicle; Window numbers:
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