OpenTTD Source 20251126-master-g67ded4f980
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 <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "road.h"
12#include "road_internal.h"
13#include "viewport_func.h"
14#include "command_func.h"
15#include "company_func.h"
17#include "depot_base.h"
18#include "newgrf.h"
19#include "autoslope.h"
20#include "tunnelbridge_map.h"
21#include "strings_func.h"
22#include "vehicle_func.h"
23#include "sound_func.h"
24#include "tunnelbridge.h"
25#include "cheat_type.h"
26#include "effectvehicle_func.h"
27#include "effectvehicle_base.h"
28#include "elrail_func.h"
29#include "roadveh.h"
30#include "train.h"
31#include "town.h"
32#include "company_base.h"
33#include "core/random_func.hpp"
35#include "newgrf_debug.h"
36#include "newgrf_railtype.h"
37#include "newgrf_roadtype.h"
39#include "genworld.h"
40#include "company_gui.h"
41#include "road_func.h"
42#include "road_cmd.h"
43#include "landscape_cmd.h"
44#include "rail_cmd.h"
45
46#include "table/strings.h"
47#include "table/roadtypes.h"
48
49#include "safeguards.h"
50
52typedef std::vector<RoadVehicle *> RoadVehicleList;
53
54RoadTypeInfo _roadtypes[ROADTYPE_END];
55std::vector<RoadType> _sorted_roadtypes;
59
64{
65 static_assert(std::size(_original_roadtypes) <= std::size(_roadtypes));
66
67 auto insert = std::copy(std::begin(_original_roadtypes), std::end(_original_roadtypes), std::begin(_roadtypes));
68 std::fill(insert, std::end(_roadtypes), RoadTypeInfo{});
69
73}
74
75void ResolveRoadTypeGUISprites(RoadTypeInfo *rti)
76{
78 if (cursors_base != 0) {
79 rti->gui_sprites.build_y_road = cursors_base + 0;
80 rti->gui_sprites.build_x_road = cursors_base + 1;
81 rti->gui_sprites.auto_road = cursors_base + 2;
82 rti->gui_sprites.build_depot = cursors_base + 3;
83 rti->gui_sprites.build_tunnel = cursors_base + 4;
84 rti->gui_sprites.convert_road = cursors_base + 5;
85 rti->cursor.road_swne = cursors_base + 6;
86 rti->cursor.road_nwse = cursors_base + 7;
87 rti->cursor.autoroad = cursors_base + 8;
88 rti->cursor.depot = cursors_base + 9;
89 rti->cursor.tunnel = cursors_base + 10;
90 rti->cursor.convert_road = cursors_base + 11;
91 }
92}
93
100static bool CompareRoadTypes(const RoadType &first, const RoadType &second)
101{
102 if (RoadTypeIsRoad(first) == RoadTypeIsRoad(second)) {
104 }
105 return RoadTypeIsTram(first) < RoadTypeIsTram(second);
106}
107
112{
113 _sorted_roadtypes.clear();
114 for (RoadTypeInfo &rti : _roadtypes) {
115 RoadType rt = rti.Index();
116
117 ResolveRoadTypeGUISprites(&rti);
119
120 if (rti.label == 0) continue;
121 _sorted_roadtypes.push_back(rt);
122 }
123 std::sort(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), CompareRoadTypes);
124}
125
129RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
130{
131 auto it = std::ranges::find(_roadtypes, 0, &RoadTypeInfo::label);
132 if (it == std::end(_roadtypes)) return INVALID_ROADTYPE;
133
134 RoadTypeInfo &rti = *it;
135 RoadType rt = rti.Index();
136
137 /* Set up new road type based on default tram or road. */
139 rti.label = label;
140 rti.alternate_labels.clear();
141 rti.flags = {};
143
144 /* Make us compatible with ourself. */
145 rti.powered_roadtypes = rt;
146
147 /* We also introduce ourself. */
148 rti.introduces_roadtypes = rt;
149
150 /* Default sort order; order of allocation, but with some
151 * offsets so it's easier for NewGRF to pick a spot without
152 * changing the order of other (original) road types.
153 * The << is so you can place other roadtypes in between the
154 * other roadtypes, the 7 is to be able to place something
155 * before the first (default) road type. */
156 rti.sorting_order = rt << 2 | 7;
157
158 /* Set bitmap of road/tram types */
159 _roadtypes_road.Set(rt, rtt == RTT_ROAD);
160 _roadtypes_tram.Set(rt, rtt == RTT_TRAM);
161
162 return rt;
163}
164
170{
171 return !RoadVehicle::Iterate().empty();
172}
173
181{
182 if (rt == INVALID_ROADTYPE) return;
183
185 if (c == nullptr) return;
186
187 c->infrastructure.road[rt] += count;
189}
190
193 /* The inverse of the mixable RoadBits on a leveled slope */
194 {
195 ROAD_NONE, // SLOPE_FLAT
196 ROAD_NE | ROAD_SE, // SLOPE_W
197 ROAD_NE | ROAD_NW, // SLOPE_S
198
199 ROAD_NE, // SLOPE_SW
200 ROAD_NW | ROAD_SW, // SLOPE_E
201 ROAD_NONE, // SLOPE_EW
202
203 ROAD_NW, // SLOPE_SE
204 ROAD_NONE, // SLOPE_WSE
205 ROAD_SE | ROAD_SW, // SLOPE_N
206
207 ROAD_SE, // SLOPE_NW
208 ROAD_NONE, // SLOPE_NS
209 ROAD_NONE, // SLOPE_ENW
210
211 ROAD_SW, // SLOPE_NE
212 ROAD_NONE, // SLOPE_SEN
213 ROAD_NONE // SLOPE_NWS
214 },
215 /* The inverse of the allowed straight roads on a slope
216 * (with and without a foundation). */
217 {
218 ROAD_NONE, // SLOPE_FLAT
219 ROAD_NONE, // SLOPE_W Foundation
220 ROAD_NONE, // SLOPE_S Foundation
221
222 ROAD_Y, // SLOPE_SW
223 ROAD_NONE, // SLOPE_E Foundation
224 ROAD_ALL, // SLOPE_EW
225
226 ROAD_X, // SLOPE_SE
227 ROAD_ALL, // SLOPE_WSE
228 ROAD_NONE, // SLOPE_N Foundation
229
230 ROAD_X, // SLOPE_NW
231 ROAD_ALL, // SLOPE_NS
232 ROAD_ALL, // SLOPE_ENW
233
234 ROAD_Y, // SLOPE_NE
235 ROAD_ALL, // SLOPE_SEN
236 ROAD_ALL // SLOPE_NW
237 }
238};
239
240static Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
241
252CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlags flags, bool town_check)
253{
254 if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return CommandCost();
255
256 /* Water can always flood and towns can always remove "normal" road pieces.
257 * Towns are not be allowed to remove non "normal" road pieces, like tram
258 * tracks as that would result in trams that cannot turn. */
261
262 /* Only do the special processing if the road is owned
263 * by a town */
264 if (owner != OWNER_TOWN) {
265 if (owner == OWNER_NONE) return CommandCost();
266 CommandCost ret = CheckOwnership(owner);
267 return ret;
268 }
269
270 if (!town_check) return CommandCost();
271
273
274 Town *t = ClosestTownFromTile(tile, UINT_MAX);
275 if (t == nullptr) return CommandCost();
276
277 /* check if you're allowed to remove the street owned by a town
278 * removal allowance depends on difficulty setting */
280 if (ret.Failed()) return ret;
281
282 /* Get a bitmask of which neighbouring roads has a tile */
284 RoadBits present = GetAnyRoadBits(tile, rtt);
285 if ((present & ROAD_NE) && (GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt) & ROAD_SW)) n |= ROAD_NE;
286 if ((present & ROAD_SE) && (GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt) & ROAD_NW)) n |= ROAD_SE;
287 if ((present & ROAD_SW) && (GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt) & ROAD_NE)) n |= ROAD_SW;
288 if ((present & ROAD_NW) && (GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt) & ROAD_SE)) n |= ROAD_NW;
289
290 int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE;
291 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
292 * then allow it */
293 if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) {
294 /* you can remove all kind of roads with extra dynamite */
296 return CommandCostWithParam(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS, t->index);
297 }
298 rating_decrease = RATING_ROAD_DOWN_STEP_INNER;
299 }
300 ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM, flags);
301
302 return CommandCost();
303}
304
305
314static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check)
315{
316 assert(pieces != ROAD_NONE);
317
318 RoadType existing_rt = MayHaveRoad(tile) ? GetRoadType(tile, rtt) : INVALID_ROADTYPE;
319 /* The tile doesn't have the given road type */
320 if (existing_rt == INVALID_ROADTYPE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
321
322 switch (GetTileType(tile)) {
323 case MP_ROAD: {
325 if (ret.Failed()) return ret;
326 break;
327 }
328
329 case MP_STATION: {
330 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
331
333 if (ret.Failed()) return ret;
334 break;
335 }
336
337 case MP_TUNNELBRIDGE: {
340 if (ret.Failed()) return ret;
341 break;
342 }
343
344 default:
345 return CMD_ERROR;
346 }
347
348 CommandCost ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rtt), rtt, flags, town_check);
349 if (ret.Failed()) return ret;
350
351 if (!IsTileType(tile, MP_ROAD)) {
352 /* If it's the last roadtype, just clear the whole tile */
353 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
354
356 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
357 /* Removing any roadbit in the bridge axis removes the roadtype (that's the behaviour remove-long-roads needs) */
358 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);
359
360 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
361 /* Pay for *every* tile of the bridge or tunnel */
362 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
363 cost.AddCost(len * 2 * RoadClearCost(existing_rt));
364 if (flags.Test(DoCommandFlag::Execute)) {
365 /* A full diagonal road tile has two road bits. */
366 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
367
368 SetRoadType(other_end, rtt, INVALID_ROADTYPE);
369 SetRoadType(tile, rtt, INVALID_ROADTYPE);
370
371 /* If the owner of the bridge sells all its road, also move the ownership
372 * to the owner of the other roadtype, unless the bridge owner is a town. */
373 Owner other_owner = GetRoadOwner(tile, OtherRoadTramType(rtt));
374 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
375 SetTileOwner(tile, other_owner);
376 SetTileOwner(other_end, other_owner);
377 }
378
379 /* Mark tiles dirty that have been repaved */
380 if (IsBridge(tile)) {
381 MarkBridgeDirty(tile);
382 } else {
384 MarkTileDirtyByTile(other_end);
385 }
386 }
387 } else {
388 assert(IsDriveThroughStopTile(tile));
389 cost.AddCost(RoadClearCost(existing_rt) * 2);
390 if (flags.Test(DoCommandFlag::Execute)) {
391 /* A full diagonal road tile has two road bits. */
392 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
393 SetRoadType(tile, rtt, INVALID_ROADTYPE);
395 }
396 }
397 return cost;
398 }
399
400 switch (GetRoadTileType(tile)) {
402 Slope tileh = GetTileSlope(tile);
403
404 /* Steep slopes behave the same as slopes with one corner raised. */
405 if (IsSteepSlope(tileh)) {
407 }
408
409 RoadBits present = GetRoadBits(tile, rtt);
410 const RoadBits other = GetRoadBits(tile, OtherRoadTramType(rtt));
411 const Foundation f = GetRoadFoundation(tileh, present);
412
413 if (HasRoadWorks(tile) && _current_company != OWNER_WATER) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
414
415 /* Autocomplete to a straight road
416 * @li if the bits of the other roadtypes result in another foundation
417 * @li if build on slopes is disabled */
418 if ((IsStraightRoad(other) && (other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
420 pieces |= MirrorRoadBits(pieces);
421 }
422
423 /* limit the bits to delete to the existing bits. */
424 pieces &= present;
425 if (pieces == ROAD_NONE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
426
427 /* Now set present what it will be after the remove */
428 present ^= pieces;
429
430 /* Check for invalid RoadBit combinations on slopes */
431 if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
432 (present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == present) {
433 return CMD_ERROR;
434 }
435
436 if (flags.Test(DoCommandFlag::Execute)) {
437 if (HasRoadWorks(tile)) {
438 /* flooding tile with road works, don't forget to remove the effect vehicle too */
439 assert(_current_company == OWNER_WATER);
441 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
442 delete v;
443 }
444 }
445 }
446
447 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)CountBits(pieces));
448
449 if (present == ROAD_NONE) {
450 /* No other road type, just clear tile. */
451 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
452 /* Includes MarkTileDirtyByTile() */
453 DoClearSquare(tile);
454 } else {
455 if (rtt == RTT_ROAD && IsRoadOwner(tile, rtt, OWNER_TOWN)) {
456 /* Update nearest-town index */
457 const Town *town = CalcClosestTownFromTile(tile);
458 SetTownIndex(tile, town == nullptr ? TownID::Invalid() : town->index);
459 }
461 SetRoadBits(tile, ROAD_NONE, rtt);
462 SetRoadType(tile, rtt, INVALID_ROADTYPE);
464 }
465 } else {
466 /* When bits are removed, you *always* end up with something that
467 * is not a complete straight road tile. However, trams do not have
468 * onewayness, so they cannot remove it either. */
470 SetRoadBits(tile, present, rtt);
472 }
473 }
474
475 CommandCost cost(EXPENSES_CONSTRUCTION, CountBits(pieces) * RoadClearCost(existing_rt));
476 /* If we build a foundation we have to pay for it. */
477 if (f == FOUNDATION_NONE && GetRoadFoundation(tileh, present) != FOUNDATION_NONE) cost.AddCost(_price[PR_BUILD_FOUNDATION]);
478
479 return cost;
480 }
481
483 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
484 return CMD_ERROR;
485 }
486
487 if (flags.Test(DoCommandFlag::Execute)) {
489
490 /* A full diagonal road tile has two road bits. */
491 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
492
493 Track railtrack = GetCrossingRailTrack(tile);
494 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
495 TrackBits tracks = GetCrossingRailBits(tile);
496 bool reserved = HasCrossingReservation(tile);
497 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
498 if (reserved) SetTrackReservation(tile, tracks);
499
500 /* Update rail count for level crossings. The plain track should still be accounted
501 * for, so only subtract the difference to the level crossing cost. */
503 if (c != nullptr) {
506 }
507 } else {
508 SetRoadType(tile, rtt, INVALID_ROADTYPE);
509 }
511 YapfNotifyTrackLayoutChange(tile, railtrack);
512 }
513 return CommandCost(EXPENSES_CONSTRUCTION, RoadClearCost(existing_rt) * 2);
514 }
515
516 default:
518 return CMD_ERROR;
519 }
520}
521
522
534static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
535{
536 /* Remove already build pieces */
537 *pieces &= ~existing;
538
539 /* If we can't build anything stop here */
540 if (*pieces == ROAD_NONE) return CMD_ERROR;
541
542 /* All RoadBit combos are valid on flat land */
543 if (tileh == SLOPE_FLAT) return CommandCost();
544
545 /* Steep slopes behave the same as slopes with one corner raised. */
546 if (IsSteepSlope(tileh)) {
548 }
549
550 /* Save the merge of all bits of the current type */
551 RoadBits type_bits = existing | *pieces;
552
553 /* Roads on slopes */
554 if (_settings_game.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
555
556 /* If we add leveling we've got to pay for it */
557 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
558
559 return CommandCost();
560 }
561
562 /* Autocomplete uphill roads */
563 *pieces |= MirrorRoadBits(*pieces);
564 type_bits = existing | *pieces;
565
566 /* Uphill roads */
567 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
568 (_invalid_tileh_slopes_road[1][tileh] & (other | type_bits)) == ROAD_NONE) {
569
570 /* Slopes with foundation ? */
571 if (IsSlopeWithOneCornerRaised(tileh)) {
572
573 /* Prevent build on slopes if it isn't allowed */
575
576 /* If we add foundation we've got to pay for it */
577 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
578
579 return CommandCost();
580 }
581 } else {
582 if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
583 return CommandCost();
584 }
585 }
586 return CMD_ERROR;
587}
588
600{
601 CompanyID company = _current_company;
603
604 RoadBits existing = ROAD_NONE;
605 RoadBits other_bits = ROAD_NONE;
606
607 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
608 * if a non-company is building the road */
609 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;
610 if (company != OWNER_TOWN) {
611 const Town *town = CalcClosestTownFromTile(tile);
612 town_id = (town != nullptr) ? town->index : TownID::Invalid();
613
614 if (company == OWNER_DEITY) {
615 company = OWNER_TOWN;
616
617 /* If we are not within a town, we are not owned by the town */
618 if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) {
619 company = OWNER_NONE;
620 }
621 }
622 }
623
624 /* do not allow building 'zero' road bits, code wouldn't handle it */
625 if (pieces == ROAD_NONE || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR;
626 if (!ValParamRoadType(rt)) return CMD_ERROR;
627
628 Slope tileh = GetTileSlope(tile);
629 RoadTramType rtt = GetRoadTramType(rt);
630
631 bool need_to_clear = false;
632 switch (GetTileType(tile)) {
633 case MP_ROAD:
634 switch (GetRoadTileType(tile)) {
636 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
637
638 other_bits = GetRoadBits(tile, OtherRoadTramType(rtt));
639 if (!HasTileRoadType(tile, rtt)) break;
640
641 existing = GetRoadBits(tile, rtt);
642 bool crossing = !IsStraightRoad(existing | pieces);
643 if (rtt == RTT_ROAD && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
644 /* Junctions cannot be one-way */
645 return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
646 }
647 if ((existing & pieces) == pieces) {
648 /* We only want to set the (dis)allowed road directions */
649 if (toggle_drd != DRD_NONE && rtt == RTT_ROAD) {
650 Owner owner = GetRoadOwner(tile, rtt);
651 if (owner != OWNER_NONE) {
652 CommandCost ret = CheckOwnership(owner, tile);
653 if (ret.Failed()) return ret;
654 }
655
657 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
658
659 /* We allow removing disallowed directions to break up
660 * deadlocks, but adding them can break articulated
661 * vehicles. As such, only when less is disallowed,
662 * i.e. bits are removed, we skip the vehicle check. */
663 if (CountBits(dis_existing) <= CountBits(dis_new)) {
665 if (ret.Failed()) return ret;
666 }
667
668 /* Ignore half built tiles */
669 if (flags.Test(DoCommandFlag::Execute) && IsStraightRoad(existing)) {
670 SetDisallowedRoadDirections(tile, dis_new);
672 }
673 return CommandCost();
674 }
675 return CommandCost(STR_ERROR_ALREADY_BUILT);
676 }
677 /* Disallow breaking end-of-line of someone else
678 * so trams can still reverse on this tile. */
679 if (rtt == RTT_TRAM && HasExactlyOneBit(existing)) {
680 Owner owner = GetRoadOwner(tile, rtt);
681 if (Company::IsValidID(owner)) {
682 CommandCost ret = CheckOwnership(owner);
683 if (ret.Failed()) return ret;
684 }
685 }
686 break;
687 }
688
690 if (RoadNoLevelCrossing(rt)) {
691 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
692 }
693
694 other_bits = GetCrossingRoadBits(tile);
695 if (pieces & ComplementRoadBits(other_bits)) goto do_clear;
696 pieces = other_bits; // we need to pay for both roadbits
697
698 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
699 break;
700
702 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
703 goto do_clear;
704
705 default: NOT_REACHED();
706 }
707 break;
708
709 case MP_RAILWAY: {
710 if (IsSteepSlope(tileh)) {
711 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
712 }
713
714 /* Level crossings may only be built on these slopes */
715 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
716 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
717 }
718
721 if (ret.Failed()) return ret;
722 }
723
724 if (GetRailTileType(tile) != RailTileType::Normal) goto do_clear;
725
726 if (RoadNoLevelCrossing(rt)) {
727 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
728 }
729
731 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
732 }
733
734 Axis roaddir;
735 switch (GetTrackBits(tile)) {
736 case TRACK_BIT_X:
737 if (pieces & ROAD_X) goto do_clear;
738 roaddir = AXIS_Y;
739 break;
740
741 case TRACK_BIT_Y:
742 if (pieces & ROAD_Y) goto do_clear;
743 roaddir = AXIS_X;
744 break;
745
746 default: goto do_clear;
747 }
748
750 if (ret.Failed()) return ret;
751
752 if (flags.Test(DoCommandFlag::Execute)) {
753 Track railtrack = AxisToTrack(OtherAxis(roaddir));
754 YapfNotifyTrackLayoutChange(tile, railtrack);
755 /* Update company infrastructure counts. A level crossing has two road bits. */
756 UpdateCompanyRoadInfrastructure(rt, company, 2);
757
758 /* Update rail count for level crossings. The plain track is already
759 * counted, so only add the difference to the level crossing cost. */
761 if (c != nullptr) {
764 }
765
766 /* Always add road to the roadtypes (can't draw without it) */
767 bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
768 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id);
769 SetCrossingReservation(tile, reserved);
770 UpdateLevelCrossing(tile, false);
773 }
775 }
776
777 case MP_STATION: {
778 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
779 if (!IsDriveThroughStopTile(tile)) goto do_clear;
780
782 if (pieces & ~curbits) goto do_clear;
783 pieces = curbits; // we need to pay for both roadbits
784
785 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
786 break;
787 }
788
789 case MP_TUNNELBRIDGE: {
790 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) goto do_clear;
791 /* Only allow building the outer roadbit, so building long roads stops at existing bridges */
792 if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
793 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
794 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
796 if (ret.Failed()) return ret;
797 break;
798 }
799
800 default: {
801do_clear:;
802 need_to_clear = true;
803 break;
804 }
805 }
806
807 if (need_to_clear) {
809 if (ret.Failed()) return ret;
810 cost.AddCost(ret.GetCost());
811 }
812
813 if (other_bits != pieces) {
814 /* Check the foundation/slopes when adding road/tram bits */
815 CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
816 /* Return an error if we need to build a foundation (ret != 0) but the
817 * current setting is turned off */
818 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
819 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
820 }
821 cost.AddCost(ret.GetCost());
822 }
823
824 if (!need_to_clear) {
825 if (IsTileType(tile, MP_ROAD)) {
826 /* Don't put the pieces that already exist */
827 pieces &= ComplementRoadBits(existing);
828
829 /* Check if new road bits will have the same foundation as other existing road types */
830 if (IsNormalRoad(tile)) {
831 Slope slope = GetTileSlope(tile);
832 Foundation found_new = GetRoadFoundation(slope, pieces | existing);
833
834 RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt));
835 /* do not check if there are not road bits of given type */
836 if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) {
837 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
838 }
839 }
840 }
841
843 if (ret.Failed()) return ret;
844
845 if (IsNormalRoadTile(tile)) {
846 /* If the road types don't match, try to convert only if vehicles of
847 * the new road type are not powered on the present road type and vehicles of
848 * the present road type are powered on the new road type. */
849 RoadType existing_rt = GetRoadType(tile, rtt);
850 if (existing_rt != INVALID_ROADTYPE && existing_rt != rt) {
851 if (HasPowerOnRoad(rt, existing_rt)) {
852 rt = existing_rt;
853 } else if (HasPowerOnRoad(existing_rt, rt)) {
854 ret = Command<CMD_CONVERT_ROAD>::Do(flags, tile, tile, rt, false);
855 if (ret.Failed()) return ret;
856 cost.AddCost(ret.GetCost());
857 } else {
858 return CMD_ERROR;
859 }
860 }
861 }
862 }
863
864 uint num_pieces = (!need_to_clear && IsTileType(tile, MP_TUNNELBRIDGE)) ?
865 /* There are 2 pieces on *every* tile of the bridge or tunnel */
866 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) :
867 /* Count pieces */
868 CountBits(pieces);
869
870 cost.AddCost(num_pieces * RoadBuildCost(rt));
871
872 if (flags.Test(DoCommandFlag::Execute)) {
873 switch (GetTileType(tile)) {
874 case MP_ROAD: {
875 RoadTileType rttype = GetRoadTileType(tile);
876 if (existing == ROAD_NONE || rttype == RoadTileType::Crossing) {
877 SetRoadType(tile, rtt, rt);
878 SetRoadOwner(tile, rtt, company);
879 if (rtt == RTT_ROAD) SetTownIndex(tile, town_id);
880 }
881 if (rttype != RoadTileType::Crossing) SetRoadBits(tile, existing | pieces, rtt);
882 break;
883 }
884
885 case MP_TUNNELBRIDGE: {
886 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
887
888 SetRoadType(other_end, rtt, rt);
889 SetRoadType(tile, rtt, rt);
890 SetRoadOwner(other_end, rtt, company);
891 SetRoadOwner(tile, rtt, company);
892
893 /* Mark tiles dirty that have been repaved */
894 if (IsBridge(tile)) {
895 MarkBridgeDirty(tile);
896 } else {
897 MarkTileDirtyByTile(other_end);
899 }
900 break;
901 }
902
903 case MP_STATION: {
904 assert(IsDriveThroughStopTile(tile));
905 SetRoadType(tile, rtt, rt);
906 SetRoadOwner(tile, rtt, company);
907 break;
908 }
909
910 default:
911 MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company);
912 break;
913 }
914
915 /* Update company infrastructure count. */
917 UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), num_pieces);
918
919 if (rtt == RTT_ROAD && IsNormalRoadTile(tile)) {
920 existing |= pieces;
922 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
923 }
924
926 }
927 return cost;
928}
929
938{
939 tile += TileOffsByDiagDir(dir);
940 if (!IsValidTile(tile) || !MayHaveRoad(tile)) return false;
941
942 RoadTramType rtt = GetRoadTramType(rt);
943 RoadType existing = GetRoadType(tile, rtt);
944 if (existing == INVALID_ROADTYPE) return false;
945 if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false;
946
947 RoadBits bits = GetAnyRoadBits(tile, rtt, false);
948 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
949}
950
966CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
967{
968 if (start_tile >= Map::Size()) return CMD_ERROR;
969
970 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
971
972 /* Only drag in X or Y direction dictated by the direction variable */
973 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
974 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
975
976 DiagDirection dir = AxisToDiagDir(axis);
977
978 /* Swap direction, also the half-tile drag vars. */
979 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
980 dir = ReverseDiagDir(dir);
981 start_half = !start_half;
982 end_half = !end_half;
983 if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
984 }
985
986 /* On the X-axis, we have to swap the initial bits, so they
987 * will be interpreted correctly in the GTTS. Furthermore
988 * when you just 'click' on one tile to build them. */
989 if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
990
992 CommandCost last_error = CMD_ERROR;
993 TileIndex tile = start_tile;
994 bool had_bridge = false;
995 bool had_tunnel = false;
996 bool had_success = false;
997
998 /* Start tile is the first tile clicked by the user. */
999 for (;;) {
1000 RoadBits bits = AxisToRoadBits(axis);
1001
1002 /* Determine which road parts should be built. */
1003 if (!is_ai && start_tile != end_tile) {
1004 /* Only build the first and last roadbit if they can connect to something. */
1005 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1006 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1007 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1008 bits = DiagDirToRoadBits(dir);
1009 }
1010 } else {
1011 /* Road parts only have to be built at the start tile or at the end tile. */
1012 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1013 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1014 }
1015
1016 CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, TownID::Invalid());
1017 if (!is_ai && ret.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true;
1018 if (ret.Failed()) {
1019 last_error = std::move(ret);
1020 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1021 if (is_ai) return last_error;
1022 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1023 }
1024 } else {
1025 had_success = true;
1026 /* Only pay for the upgrade on one side of the bridges and tunnels */
1027 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1028 if (IsBridge(tile)) {
1029 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1030 cost.AddCost(ret.GetCost());
1031 }
1032 had_bridge = true;
1033 } else { // IsTunnel(tile)
1034 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1035 cost.AddCost(ret.GetCost());
1036 }
1037 had_tunnel = true;
1038 }
1039 } else {
1040 cost.AddCost(ret.GetCost());
1041 }
1042 }
1043
1044 if (tile == end_tile) break;
1045
1046 tile += TileOffsByDiagDir(dir);
1047 }
1048
1049 return had_success ? cost : last_error;
1050}
1051
1063std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
1064{
1066
1067 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
1068 if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 };
1069
1070 /* Only drag in X or Y direction dictated by the direction variable */
1071 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis
1072 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis
1073
1074 /* Swap start and ending tile, also the half-tile drag vars. */
1075 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
1076 std::swap(start_tile, end_tile);
1077 std::swap(start_half, end_half);
1078 }
1079
1080 Money money_available = GetAvailableMoneyForCommand();
1081 Money money_spent = 0;
1082 TileIndex tile = start_tile;
1083 CommandCost last_error = CMD_ERROR;
1084 bool had_success = false;
1085 /* Start tile is the small number. */
1086 for (;;) {
1087 RoadBits bits = AxisToRoadBits(axis);
1088
1089 if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
1090 if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
1091
1092 /* try to remove the halves. */
1093 if (bits != 0) {
1094 RoadTramType rtt = GetRoadTramType(rt);
1095 CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true);
1096 if (ret.Succeeded()) {
1097 if (flags.Test(DoCommandFlag::Execute)) {
1098 money_spent += ret.GetCost();
1099 if (money_spent > 0 && money_spent > money_available) {
1100 return { cost, std::get<0>(Command<CMD_REMOVE_LONG_ROAD>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), end_tile, start_tile, rt, axis, start_half, end_half)).GetCost() };
1101 }
1102 RemoveRoad(tile, flags, bits, rtt, false);
1103 }
1104 cost.AddCost(ret.GetCost());
1105 had_success = true;
1106 } else {
1107 /* Some errors are more equal than others. */
1108 switch (last_error.GetErrorMessage()) {
1109 case STR_ERROR_OWNED_BY:
1110 case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS:
1111 break;
1112 default:
1113 last_error = std::move(ret);
1114 }
1115 }
1116 }
1117
1118 if (tile == end_tile) break;
1119
1120 tile += TileOffsByAxis(axis);
1121 }
1122
1123 return { had_success ? cost : last_error, 0 };
1124}
1125
1138{
1139 if (!ValParamRoadType(rt) || !IsValidDiagDirection(dir)) return CMD_ERROR;
1140
1142
1143 Slope tileh = GetTileSlope(tile);
1144 if (tileh != SLOPE_FLAT) {
1146 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
1147 }
1148 cost.AddCost(_price[PR_BUILD_FOUNDATION]);
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<CMD_LANDSCAPE_CLEAR>::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 = new Depot(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
1190 cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
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
1218 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_ROAD]);
1219}
1220
1221static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlags flags)
1222{
1223 switch (GetRoadTileType(tile)) {
1224 case RoadTileType::Normal: {
1225 RoadBits b = GetAllRoadBits(tile);
1226
1227 /* Clear the road if only one piece is on the tile OR we are not using the DoCommandFlag::Auto flag */
1228 if ((HasExactlyOneBit(b) && GetRoadBits(tile, RTT_TRAM) == ROAD_NONE) || !flags.Test(DoCommandFlag::Auto)) {
1230 for (RoadTramType rtt : _roadtramtypes) {
1231 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1232
1233 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true);
1234 if (tmp_ret.Failed()) return tmp_ret;
1235 ret.AddCost(tmp_ret.GetCost());
1236 }
1237 return ret;
1238 }
1239 return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1240 }
1241
1244
1245 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1246
1247 /* Must iterate over the roadtypes in a reverse manner because
1248 * tram tracks must be removed before the road bits. */
1249 for (RoadTramType rtt : { RTT_TRAM, RTT_ROAD }) {
1250 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1251
1252 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rtt, true);
1253 if (tmp_ret.Failed()) return tmp_ret;
1254 ret.AddCost(tmp_ret.GetCost());
1255 }
1256
1257 if (flags.Test(DoCommandFlag::Execute)) {
1259 }
1260 return ret;
1261 }
1262
1263 default:
1265 if (flags.Test(DoCommandFlag::Auto)) {
1266 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1267 }
1268 return RemoveRoadDepot(tile, flags);
1269 }
1270}
1271
1272
1274 uint16_t image;
1275 uint8_t subcoord_x;
1276 uint8_t subcoord_y;
1277};
1278
1279#include "table/road_land.h"
1280
1289{
1290 /* Flat land and land without a road doesn't require a foundation */
1291 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1292
1293 /* Steep slopes behave the same as slopes with one corner raised. */
1294 if (IsSteepSlope(tileh)) {
1296 }
1297
1298 /* Leveled RoadBits on a slope */
1299 if ((_invalid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1300
1301 /* Straight roads without foundation on a slope */
1302 if (!IsSlopeWithOneCornerRaised(tileh) &&
1303 (_invalid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE)
1304 return FOUNDATION_NONE;
1305
1306 /* Roads on steep Slopes or on Slopes with one corner raised */
1308}
1309
1310const uint8_t _road_sloped_sprites[14] = {
1311 0, 0, 2, 0,
1312 0, 1, 0, 0,
1313 3, 0, 0, 0,
1314 0, 0
1315};
1316
1323static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
1324{
1325 if (slope != SLOPE_FLAT) {
1326 switch (slope) {
1327 case SLOPE_NE: return 11;
1328 case SLOPE_SE: return 12;
1329 case SLOPE_SW: return 13;
1330 case SLOPE_NW: return 14;
1331 default: NOT_REACHED();
1332 }
1333 } else {
1334 static const uint offsets[] = {
1335 0, 18, 17, 7,
1336 16, 0, 10, 5,
1337 15, 8, 1, 4,
1338 9, 3, 6, 2
1339 };
1340 return offsets[bits];
1341 }
1342}
1343
1353static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
1354{
1355 return (snow_or_desert &&
1356 !(_settings_game.game_creation.landscape == LandscapeType::Tropic && HasGrfMiscBit(GrfMiscBit::DesertPavedRoads) &&
1357 roadside != Roadside::Barren && roadside != Roadside::Grass && roadside != Roadside::GrassRoadWorks));
1358}
1359
1367{
1368 /* Don't draw the catenary under a low bridge */
1370 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1371
1372 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1373 }
1374
1375 if (CountBits(rb) > 2) {
1376 /* On junctions we check whether neighbouring tiles also have catenary, and possibly
1377 * do not draw catenary towards those neighbours, which do not have catenary. */
1378 RoadBits rb_new = ROAD_NONE;
1379 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
1380 if (rb & DiagDirToRoadBits(dir)) {
1381 TileIndex neighbour = TileAddByDiagDir(ti->tile, dir);
1382 if (MayHaveRoad(neighbour)) {
1383 RoadType rt_road = GetRoadTypeRoad(neighbour);
1384 RoadType rt_tram = GetRoadTypeTram(neighbour);
1385
1386 if ((rt_road != INVALID_ROADTYPE && HasRoadCatenary(rt_road)) ||
1387 (rt_tram != INVALID_ROADTYPE && HasRoadCatenary(rt_tram))) {
1388 rb_new |= DiagDirToRoadBits(dir);
1389 }
1390 }
1391 }
1392 }
1393 if (CountBits(rb_new) >= 2) rb = rb_new;
1394 }
1395
1396 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1399
1400 if (front != 0 || back != 0) {
1401 if (front != 0) front += GetRoadSpriteOffset(ti->tileh, rb);
1402 if (back != 0) back += GetRoadSpriteOffset(ti->tileh, rb);
1403 } else if (ti->tileh != SLOPE_FLAT) {
1404 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1405 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1406 } else {
1407 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb];
1408 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb];
1409 }
1410
1411 /* Catenary uses 1st company colour to help identify owner.
1412 * For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
1413 Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
1414 PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(COLOUR_GREY) : GetCompanyPalette(owner));
1415 uint8_t z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
1416 if (back != 0) {
1417 /* The "back" sprite contains the west, north and east pillars.
1418 * We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
1419 * 3/8 is chosen so that sprites can somewhat graphically extend into the tile. */
1420 static const int INF = 1000;
1421 static const SubSprite west = { -INF, -INF, -12, INF };
1422 static const SubSprite north = { -12, -INF, 12, INF };
1423 static const SubSprite east = { 12, -INF, INF, INF };
1424 int8_t west_z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
1425 int8_t north_z = GetSlopePixelZInCorner(ti->tileh, CORNER_N);
1426 int8_t east_z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
1427 AddSortableSpriteToDraw(back, pal, *ti, {{15, 0, west_z}, {1, 1, z_wires}, {-15, 0, static_cast<int8_t>(-west_z)}}, IsTransparencySet(TO_CATENARY), &west);
1428 AddSortableSpriteToDraw(back, pal, *ti, {{0, 0, north_z}, {1, 1, z_wires}, {0, 0, static_cast<int8_t>(-north_z)}}, IsTransparencySet(TO_CATENARY), &north);
1429 AddSortableSpriteToDraw(back, pal, *ti, {{0, 15, east_z}, {1, 1, z_wires}, {0, -15, static_cast<int8_t>(-east_z)}}, IsTransparencySet(TO_CATENARY), &east);
1430 }
1431 if (front != 0) {
1432 /* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
1433 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));
1434 }
1435}
1436
1442{
1443 RoadBits road = ROAD_NONE;
1444 RoadBits tram = ROAD_NONE;
1445
1446 if (IsTileType(ti->tile, MP_ROAD)) {
1447 if (IsNormalRoad(ti->tile)) {
1448 road = GetRoadBits(ti->tile, RTT_ROAD);
1449 tram = GetRoadBits(ti->tile, RTT_TRAM);
1450 } else if (IsLevelCrossing(ti->tile)) {
1451 tram = road = (GetCrossingRailAxis(ti->tile) == AXIS_Y ? ROAD_X : ROAD_Y);
1452 }
1453 } else if (IsTileType(ti->tile, MP_STATION)) {
1454 if (IsAnyRoadStop(ti->tile)) {
1455 if (IsDriveThroughStopTile(ti->tile)) {
1456 Axis axis = GetDriveThroughStopAxis(ti->tile);
1457 tram = road = (axis == AXIS_X ? ROAD_X : ROAD_Y);
1458 } else {
1459 tram = road = DiagDirToRoadBits(GetBayRoadStopDir(ti->tile));
1460 }
1461 }
1462 } else {
1463 /* No road here, no catenary to draw */
1464 return;
1465 }
1466
1467 RoadType rt = GetRoadTypeRoad(ti->tile);
1468 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1469 DrawRoadTypeCatenary(ti, rt, road);
1470 }
1471
1472 rt = GetRoadTypeTram(ti->tile);
1473 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1474 DrawRoadTypeCatenary(ti, rt, tram);
1475 }
1476}
1477
1487static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int8_t dx, int8_t dy, uint8_t h, bool transparent)
1488{
1489 int x = ti->x | dx;
1490 int y = ti->y | dy;
1491 int z = ti->z;
1492 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1493 AddSortableSpriteToDraw(img, PAL_NONE, ti->x, ti->y, z, {{dx, dy, 0}, {2, 2, h}, {}}, transparent);
1494}
1495
1505void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
1506{
1507 if (draw_underlay) {
1508 /* Road underlay takes precedence over tram */
1509 if (road_rti != nullptr) {
1510 if (road_rti->UsesOverlay()) {
1511 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_GROUND);
1512 DrawGroundSprite(ground + road_offset, pal);
1513 }
1514 } else {
1515 if (tram_rti->UsesOverlay()) {
1516 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_GROUND);
1517 DrawGroundSprite(ground + tram_offset, pal);
1518 } else {
1519 DrawGroundSprite(SPR_TRAMWAY_TRAM + tram_offset, pal);
1520 }
1521 }
1522 }
1523
1524 /* Draw road overlay */
1525 if (road_rti != nullptr) {
1526 if (road_rti->UsesOverlay()) {
1527 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_OVERLAY);
1528 if (ground != 0) DrawGroundSprite(ground + road_offset, pal);
1529 }
1530 }
1531
1532 /* Draw tram overlay */
1533 if (tram_rti != nullptr) {
1534 if (tram_rti->UsesOverlay()) {
1535 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_OVERLAY);
1536 if (ground != 0) DrawGroundSprite(ground + tram_offset, pal);
1537 } else if (road_rti != nullptr) {
1538 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + tram_offset, pal);
1539 }
1540 }
1541}
1542
1552static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
1553{
1554 /* Draw bare ground sprite if no road or road uses overlay system. */
1555 if (rti == nullptr || rti->UsesOverlay()) {
1556 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1557 return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
1558 }
1559
1560 switch (roadside) {
1561 case Roadside::Barren:
1562 *pal = PALETTE_TO_BARE_LAND;
1563 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1564
1565 case Roadside::Grass:
1567 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1568
1569 default:
1570 break; // Paved
1571 }
1572 }
1573
1574 /* Draw original road base sprite */
1575 SpriteID image = SPR_ROAD_Y + offset;
1576 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1577 image += 19;
1578 } else {
1579 switch (roadside) {
1580 case Roadside::Barren:
1581 *pal = PALETTE_TO_BARE_LAND;
1582 break;
1583
1584 case Roadside::Grass:
1586 break;
1587
1588 default:
1589 image -= 19;
1590 break; // Paved
1591 }
1592 }
1593
1594 return image;
1595}
1596
1607void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
1608{
1609 /* Determine sprite offsets */
1610 uint road_offset = GetRoadSpriteOffset(ti->tileh, road);
1611 uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
1612
1613 /* Draw baseset underlay */
1614 PaletteID pal = PAL_NONE;
1615 SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, snow_or_desert, &pal);
1616 DrawGroundSprite(image, pal);
1617
1618 DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
1619}
1620
1625static void DrawRoadBits(TileInfo *ti)
1626{
1627 RoadBits road = GetRoadBits(ti->tile, RTT_ROAD);
1628 RoadBits tram = GetRoadBits(ti->tile, RTT_TRAM);
1629
1630 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1631 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1632 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1633 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1634
1635 if (ti->tileh != SLOPE_FLAT) {
1636 DrawFoundation(ti, GetRoadFoundation(ti->tileh, road | tram));
1637 /* DrawFoundation() modifies ti. */
1638 }
1639
1640 DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnowOrDesert(ti->tile));
1641
1642 /* Draw one way */
1643 if (road_rti != nullptr) {
1645 if (drd != DRD_NONE) {
1646 SpriteID oneway = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ONEWAY);
1647
1648 if (oneway == 0) oneway = SPR_ONEWAY_BASE;
1649
1650 if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) {
1651 oneway += ONEWAY_SLOPE_N_OFFSET;
1652 } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) {
1653 oneway += ONEWAY_SLOPE_S_OFFSET;
1654 }
1655
1656 DrawGroundSpriteAt(oneway + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1657 }
1658 }
1659
1660 if (HasRoadWorks(ti->tile)) {
1661 /* Road works */
1662 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1663 return;
1664 }
1665
1666 /* Draw road, tram catenary */
1667 DrawRoadCatenary(ti);
1668
1669 /* Return if full detail is disabled, or we are zoomed fully out. */
1670 if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZoomLevel::Detail) return;
1671
1672 /* Do not draw details (street lights, trees) under low bridge */
1673 Roadside roadside = GetRoadside(ti->tile);
1674 if (IsBridgeAbove(ti->tile) && (roadside == Roadside::Trees || roadside == Roadside::StreetLights)) {
1675 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1676 int minz = GetTileMaxZ(ti->tile) + 2;
1677
1678 if (roadside == Roadside::Trees) minz++;
1679
1680 if (height < minz) return;
1681 }
1682
1683 /* If there are no road bits, return, as there is nothing left to do */
1684 if (HasAtMostOneBit(road)) return;
1685
1686 /* Do not draw details when invisible. */
1687 if (roadside == Roadside::Trees && IsInvisibilitySet(TO_TREES)) return;
1688 if (roadside == Roadside::StreetLights && IsInvisibilitySet(TO_HOUSES)) return;
1689
1690 /* Check whether details should be transparent. */
1691 bool is_transparent = false;
1692 if (roadside == Roadside::Trees && IsTransparencySet(TO_TREES)) {
1693 is_transparent = true;
1694 }
1696 is_transparent = true;
1697 }
1698
1699 /* Draw extra details. */
1700 for (const DrawRoadTileStruct *drts = _road_display_table[to_underlying(roadside)][road | tram]; drts->image != 0; drts++) {
1701 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
1702 }
1703}
1704
1706static void DrawTile_Road(TileInfo *ti)
1707{
1708 BridgePillarFlags blocked_pillars{};
1709 switch (GetRoadTileType(ti->tile)) {
1711 DrawRoadBits(ti);
1712
1713 if (IsBridgeAbove(ti->tile)) {
1714 RoadBits bits = GetAllRoadBits(ti->tile);
1715 if ((bits & ROAD_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
1716 if ((bits & ROAD_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
1717 if ((bits & ROAD_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
1718 if ((bits & ROAD_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
1719 }
1720 break;
1721
1724
1725 Axis axis = GetCrossingRailAxis(ti->tile);
1726
1727 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1728
1729 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1730 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1731 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1732 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1733
1734 PaletteID pal = PAL_NONE;
1735
1736 /* Draw base ground */
1737 if (rti->UsesOverlay()) {
1738 SpriteID image = SPR_ROAD_Y + axis;
1739
1740 Roadside roadside = GetRoadside(ti->tile);
1741 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1742 image += 19;
1743 } else {
1744 switch (roadside) {
1745 case Roadside::Barren:
1747 break;
1748
1749 case Roadside::Grass:
1750 break;
1751
1752 default:
1753 image -= 19;
1754 break; // Paved
1755 }
1756 }
1757
1758 DrawGroundSprite(image, pal);
1759 } else {
1760 SpriteID image = rti->base_sprites.crossing + axis;
1761 if (IsCrossingBarred(ti->tile)) image += 2;
1762
1763 Roadside roadside = GetRoadside(ti->tile);
1764 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1765 image += 8;
1766 } else {
1767 switch (roadside) {
1768 case Roadside::Barren:
1770 break;
1771
1772 case Roadside::Grass:
1773 break;
1774
1775 default:
1776 image += 4;
1777 break; // Paved
1778 }
1779 }
1780
1781 DrawGroundSprite(image, pal);
1782 }
1783
1784 DrawRoadOverlays(ti, pal, road_rti, tram_rti, axis, axis);
1785
1786 /* Draw rail/PBS overlay */
1787 bool draw_pbs = _game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile);
1788 if (rti->UsesOverlay()) {
1789 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1790 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1791 DrawGroundSprite(rail, pal);
1792
1793 const Axis road_axis = GetCrossingRoadAxis(ti->tile);
1794 const DiagDirection dir1 = AxisToDiagDir(road_axis);
1795 const DiagDirection dir2 = ReverseDiagDir(dir1);
1796 DiagDirections adjacent_diagdirs{};
1797 for (DiagDirection dir : { dir1, dir2 }) {
1798 const TileIndex t = TileAddByDiagDir(ti->tile, dir);
1799 if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
1800 adjacent_diagdirs.Set(dir);
1801 }
1802 }
1803
1804 switch (adjacent_diagdirs.base()) {
1805 case DiagDirections{}.base():
1806 DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1807 break;
1808
1810 DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE);
1811 break;
1812
1814 DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE);
1815 break;
1816
1818 DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE);
1819 break;
1820
1822 DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE);
1823 break;
1824
1825 default:
1826 /* Show no sprites */
1827 break;
1828 }
1829 } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) {
1830 /* Add another rail overlay, unless there is only the base road sprite. */
1831 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1833 DrawGroundSprite(rail, pal);
1834 }
1835
1836 /* Draw road, tram catenary */
1837 DrawRoadCatenary(ti);
1838
1839 /* Draw rail catenary */
1841 blocked_pillars = {BridgePillarFlag::EdgeSW, BridgePillarFlag::EdgeNE, BridgePillarFlag::EdgeNW, BridgePillarFlag::EdgeSE};
1842 break;
1843 }
1844
1845 default:
1846 case RoadTileType::Depot: {
1848
1850
1851 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1852 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1853 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt == INVALID_ROADTYPE ? tram_rt : road_rt);
1854
1855 int relocation = GetCustomRoadSprite(rti, ti->tile, ROTSG_DEPOT);
1856 bool default_gfx = relocation == 0;
1857 if (default_gfx) {
1858 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1859 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && road_rt == INVALID_ROADTYPE && !rti->UsesOverlay()) {
1860 /* Sprites with track only work for default tram */
1861 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1862 default_gfx = false;
1863 } else {
1864 /* Sprites without track are always better, if provided */
1865 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1866 }
1867 }
1868 } else {
1869 relocation -= SPR_ROAD_DEPOT;
1870 }
1871
1873 const DrawTileSprites *dts = &_road_depot[dir];
1874 DrawGroundSprite(dts->ground.sprite, PAL_NONE);
1875
1876 if (default_gfx) {
1878 if (rti->UsesOverlay()) {
1879 SpriteID ground = GetCustomRoadSprite(rti, ti->tile, ROTSG_OVERLAY);
1880 if (ground != 0) DrawGroundSprite(ground + offset, PAL_NONE);
1881 } else if (road_rt == INVALID_ROADTYPE) {
1882 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE);
1883 }
1884 }
1885
1886 DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, palette);
1887 /* Depots can't have bridges above so no blocked pillars. */
1888 break;
1889 }
1890 }
1891 DrawBridgeMiddle(ti, blocked_pillars);
1892}
1893
1901void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
1902{
1904
1905 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1906 int relocation = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_DEPOT);
1907 bool default_gfx = relocation == 0;
1908 if (default_gfx) {
1909 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1910 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && RoadTypeIsTram(rt) && !rti->UsesOverlay()) {
1911 /* Sprites with track only work for default tram */
1912 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1913 default_gfx = false;
1914 } else {
1915 /* Sprites without track are always better, if provided */
1916 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1917 }
1918 }
1919 } else {
1920 relocation -= SPR_ROAD_DEPOT;
1921 }
1922
1923 const DrawTileSprites *dts = &_road_depot[dir];
1924 DrawSprite(dts->ground.sprite, PAL_NONE, x, y);
1925
1926 if (default_gfx) {
1928 if (rti->UsesOverlay()) {
1930 if (ground != 0) DrawSprite(ground + offset, PAL_NONE, x, y);
1931 } else if (RoadTypeIsTram(rt)) {
1932 DrawSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE, x, y);
1933 }
1934 }
1935
1936 DrawRailTileSeqInGUI(x, y, dts, relocation, 0, palette);
1937}
1938
1945{
1946 assert(!invalidate || _generating_world);
1947
1948 for (const auto t : Map::Iterate()) {
1949 if (IsTileType(t, MP_ROAD) && !IsRoadDepot(t) && !HasTownOwnedRoad(t)) {
1950 TownID tid = TownID::Invalid();
1951 if (!invalidate) {
1952 const Town *town = CalcClosestTownFromTile(t);
1953 if (town != nullptr) tid = town->index;
1954 }
1955 SetTownIndex(t, tid);
1956 }
1957 }
1958}
1959
1960static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, bool)
1961{
1962
1963 if (IsNormalRoad(tile)) {
1964 auto [tileh, z] = GetTilePixelSlope(tile);
1965 if (tileh == SLOPE_FLAT) return z;
1966
1968 z += ApplyPixelFoundationToSlope(f, tileh);
1969 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1970 } else {
1971 return GetTileMaxPixelZ(tile);
1972 }
1973}
1974
1975static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
1976{
1977 if (IsNormalRoad(tile)) {
1978 return GetRoadFoundation(tileh, GetAllRoadBits(tile));
1979 } else {
1980 return FlatteningFoundation(tileh);
1981 }
1982}
1983
1984static const Roadside _town_road_types[][2] = {
1990};
1991
1992static_assert(lengthof(_town_road_types) == NUM_HOUSE_ZONES);
1993
1994static const Roadside _town_road_types_2[][2] = {
2000};
2001
2002static_assert(lengthof(_town_road_types_2) == NUM_HOUSE_ZONES);
2003
2004
2005static void TileLoop_Road(TileIndex tile)
2006{
2008 case LandscapeType::Arctic: {
2009 /* Roads on flat foundations use the snow level of the height they are elevated to. All others use the snow level of their minimum height. */
2010 int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileZ(tile);
2011 if (IsOnSnowOrDesert(tile) != (tile_z > GetSnowLine())) {
2012 ToggleSnowOrDesert(tile);
2013 MarkTileDirtyByTile(tile);
2014 }
2015 break;
2016 }
2017
2018 case LandscapeType::Tropic:
2019 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnSnowOrDesert(tile)) {
2020 ToggleSnowOrDesert(tile);
2021 MarkTileDirtyByTile(tile);
2022 }
2023 break;
2024
2025 default:
2026 break;
2027 }
2028
2029 if (IsRoadDepot(tile)) return;
2030
2031 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
2032 if (!HasRoadWorks(tile)) {
2033 HouseZone grp = HouseZone::TownEdge;
2034
2035 if (t != nullptr) {
2036 grp = GetTownRadiusGroup(t, tile);
2037
2038 /* Show an animation to indicate road work */
2039 if (t->road_build_months != 0 &&
2040 (DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) &&
2041 IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) {
2042 if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
2043 StartRoadWorks(tile);
2044
2045 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
2047 TileX(tile) * TILE_SIZE + 7,
2048 TileY(tile) * TILE_SIZE + 7,
2049 0,
2050 EV_BULLDOZER);
2051 MarkTileDirtyByTile(tile);
2052 return;
2053 }
2054 }
2055 }
2056
2057 {
2058 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2059 const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[to_underlying(grp)] : _town_road_types[to_underlying(grp)];
2060 Roadside cur_rs = GetRoadside(tile);
2061
2062 /* We have our desired type, do nothing */
2063 if (cur_rs == new_rs[0]) return;
2064
2065 /* We have the pre-type of the desired type, switch to the desired type */
2066 if (cur_rs == new_rs[1]) {
2067 cur_rs = new_rs[0];
2068 /* We have barren land, install the pre-type */
2069 } else if (cur_rs == Roadside::Barren) {
2070 cur_rs = new_rs[1];
2071 /* We're totally off limits, remove any installation and make barren land */
2072 } else {
2073 cur_rs = Roadside::Barren;
2074 }
2075 SetRoadside(tile, cur_rs);
2076 MarkTileDirtyByTile(tile);
2077 }
2078 } else if (IncreaseRoadWorksCounter(tile)) {
2079 TerminateRoadWorks(tile);
2080
2082 /* Generate a nicer town surface */
2083 const RoadBits old_rb = GetAnyRoadBits(tile, RTT_ROAD);
2084 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2085
2086 if (old_rb != new_rb) {
2088
2089 /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */
2090 if (new_rb == 0) {
2091 MarkTileDirtyByTile(tile);
2092 return;
2093 }
2094 }
2095 }
2096
2097 /* Possibly change road type */
2098 if (GetRoadOwner(tile, RTT_ROAD) == OWNER_TOWN) {
2100 if (rt != GetRoadTypeRoad(tile)) {
2101 SetRoadType(tile, RTT_ROAD, rt);
2102 }
2103 }
2104
2105 MarkTileDirtyByTile(tile);
2106 }
2107}
2108
2109static bool ClickTile_Road(TileIndex tile)
2110{
2111 if (!IsRoadDepot(tile)) return false;
2112
2114 return true;
2115}
2116
2117/* Converts RoadBits to TrackBits */
2118static const TrackBits _road_trackbits[16] = {
2119 TRACK_BIT_NONE, // ROAD_NONE
2120 TRACK_BIT_NONE, // ROAD_NW
2121 TRACK_BIT_NONE, // ROAD_SW
2122 TRACK_BIT_LEFT, // ROAD_W
2123 TRACK_BIT_NONE, // ROAD_SE
2124 TRACK_BIT_Y, // ROAD_Y
2125 TRACK_BIT_LOWER, // ROAD_S
2126 TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | ROAD_SW
2127 TRACK_BIT_NONE, // ROAD_NE
2128 TRACK_BIT_UPPER, // ROAD_N
2129 TRACK_BIT_X, // ROAD_X
2130 TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | ROAD_NW
2131 TRACK_BIT_RIGHT, // ROAD_E
2132 TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | ROAD_NE
2133 TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | ROAD_SE
2134 TRACK_BIT_ALL, // ROAD_ALL
2135};
2136
2137static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
2138{
2139 TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
2140 TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
2141 switch (mode) {
2142 case TRANSPORT_RAIL:
2143 if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
2144 break;
2145
2146 case TRANSPORT_ROAD: {
2147 RoadTramType rtt = (RoadTramType)sub_mode;
2148 if (!HasTileRoadType(tile, rtt)) break;
2149 switch (GetRoadTileType(tile)) {
2150 case RoadTileType::Normal: {
2151 const uint drd_to_multiplier[DRD_END] = { 0x101, 0x100, 0x1, 0x0 };
2152 RoadBits bits = GetRoadBits(tile, rtt);
2153
2154 /* no roadbit at this side of tile, return 0 */
2155 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break;
2156
2157 uint multiplier = drd_to_multiplier[(rtt == RTT_TRAM) ? DRD_NONE : GetDisallowedRoadDirections(tile)];
2158 if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier);
2159 break;
2160 }
2161
2163 Axis axis = GetCrossingRoadAxis(tile);
2164
2165 if (side != INVALID_DIAGDIR && axis != DiagDirToAxis(side)) break;
2166
2167 trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis));
2168 if (IsCrossingBarred(tile)) {
2169 red_signals = trackdirbits;
2170 if (TrainOnCrossing(tile)) break;
2171
2172 auto mask_red_signal_bits_if_crossing_barred = [&](TileIndex t, TrackdirBits mask) {
2173 if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
2174 };
2175 /* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
2176 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE);
2177 /* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
2178 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW);
2179 }
2180 break;
2181 }
2182
2183 default:
2184 case RoadTileType::Depot: {
2186
2187 if (side != INVALID_DIAGDIR && side != dir) break;
2188
2190 break;
2191 }
2192 }
2193 break;
2194 }
2195
2196 default: break;
2197 }
2198 return CombineTrackStatus(trackdirbits, red_signals);
2199}
2200
2201static const StringID _road_tile_strings[] = {
2202 STR_LAI_ROAD_DESCRIPTION_ROAD,
2203 STR_LAI_ROAD_DESCRIPTION_ROAD,
2204 STR_LAI_ROAD_DESCRIPTION_ROAD,
2205 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2206 STR_LAI_ROAD_DESCRIPTION_ROAD,
2207 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2208 STR_LAI_ROAD_DESCRIPTION_ROAD,
2209 STR_LAI_ROAD_DESCRIPTION_ROAD,
2210};
2211
2212static void GetTileDesc_Road(TileIndex tile, TileDesc &td)
2213{
2214 Owner rail_owner = INVALID_OWNER;
2215 Owner road_owner = INVALID_OWNER;
2216 Owner tram_owner = INVALID_OWNER;
2217
2218 RoadType road_rt = GetRoadTypeRoad(tile);
2219 RoadType tram_rt = GetRoadTypeTram(tile);
2220 if (road_rt != INVALID_ROADTYPE) {
2221 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
2222 td.roadtype = rti->strings.name;
2223 td.road_speed = rti->max_speed / 2;
2224 road_owner = GetRoadOwner(tile, RTT_ROAD);
2225 }
2226 if (tram_rt != INVALID_ROADTYPE) {
2227 const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
2228 td.tramtype = rti->strings.name;
2229 td.tram_speed = rti->max_speed / 2;
2230 tram_owner = GetRoadOwner(tile, RTT_TRAM);
2231 }
2232
2233 switch (GetRoadTileType(tile)) {
2235 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING;
2236 rail_owner = GetTileOwner(tile);
2237
2238 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2239 td.railtype = rti->strings.name;
2240 td.rail_speed = rti->max_speed;
2241
2242 break;
2243 }
2244
2246 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
2247 td.build_date = Depot::GetByTile(tile)->build_date;
2248 break;
2249
2250 default: {
2251 td.str = (road_rt != INVALID_ROADTYPE ? _road_tile_strings[to_underlying(GetRoadside(tile))] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
2252 break;
2253 }
2254 }
2255
2256 /* Now we have to discover, if the tile has only one owner or many:
2257 * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
2258 * - Compare the found owner with the other owners, and test if they differ.
2259 * Note: If road exists it will be the first_owner.
2260 */
2261 Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
2262 bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
2263
2264 if (mixed_owners) {
2265 /* Multiple owners */
2266 td.owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_RAIL_OWNER);
2267 td.owner[0] = rail_owner;
2268 td.owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_ROAD_OWNER);
2269 td.owner[1] = road_owner;
2270 td.owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_TRAM_OWNER);
2271 td.owner[2] = tram_owner;
2272 } else {
2273 /* One to rule them all */
2274 td.owner[0] = first_owner;
2275 }
2276}
2277
2285
2286static VehicleEnterTileStates VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
2287{
2288 switch (GetRoadTileType(tile)) {
2289 case RoadTileType::Depot: {
2290 if (v->type != VEH_ROAD) break;
2291
2293 if (rv->frame == RVC_DEPOT_STOP_FRAME &&
2295 rv->state = RVSB_IN_DEPOT;
2297 rv->direction = ReverseDir(rv->direction);
2298 if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
2299 rv->tile = tile;
2300
2303 }
2304 break;
2305 }
2306
2307 default: break;
2308 }
2309 return {};
2310}
2311
2312
2313static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2314{
2315 if (IsRoadDepot(tile)) {
2316 if (GetTileOwner(tile) == old_owner) {
2317 if (new_owner == INVALID_OWNER) {
2319 } else {
2320 /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2321 RoadType rt = GetRoadTypeRoad(tile);
2322 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
2323 Company::Get(old_owner)->infrastructure.road[rt] -= 2;
2324 Company::Get(new_owner)->infrastructure.road[rt] += 2;
2325
2326 SetTileOwner(tile, new_owner);
2327 for (RoadTramType rtt : _roadtramtypes) {
2328 if (GetRoadOwner(tile, rtt) == old_owner) {
2329 SetRoadOwner(tile, rtt, new_owner);
2330 }
2331 }
2332 }
2333 }
2334 return;
2335 }
2336
2337 for (RoadTramType rtt : _roadtramtypes) {
2338 /* Update all roadtypes, no matter if they are present */
2339 if (GetRoadOwner(tile, rtt) == old_owner) {
2340 RoadType rt = GetRoadType(tile, rtt);
2341 if (rt != INVALID_ROADTYPE) {
2342 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2343 uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt));
2344 Company::Get(old_owner)->infrastructure.road[rt] -= num_bits;
2345 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits;
2346 }
2347
2348 SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
2349 }
2350 }
2351
2352 if (IsLevelCrossing(tile)) {
2353 if (GetTileOwner(tile) == old_owner) {
2354 if (new_owner == INVALID_OWNER) {
2356 } else {
2357 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2358 Company::Get(old_owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
2359 Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
2360
2361 SetTileOwner(tile, new_owner);
2362 }
2363 }
2364 }
2365}
2366
2367static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
2368{
2370 switch (GetRoadTileType(tile)) {
2372 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2373 break;
2374
2376 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2377 break;
2378
2379 case RoadTileType::Normal: {
2380 RoadBits bits = GetAllRoadBits(tile);
2381 RoadBits bits_copy = bits;
2382 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2383 if (CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE).Succeeded()) {
2384 /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
2385 if (bits == bits_copy) {
2386 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2387
2388 /* Get the slope on top of the foundation */
2389 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), tileh_old);
2390 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), tileh_new);
2391
2392 /* The surface slope must not be changed */
2393 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2394 }
2395 }
2396 break;
2397 }
2398
2399 default: NOT_REACHED();
2400 }
2401 }
2402
2403 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
2404}
2405
2413{
2414 return (owner == OWNER_NONE || (owner == OWNER_TOWN && rtt == RTT_ROAD));
2415}
2416
2425static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
2426{
2427 /* Scenario editor, maybe? Don't touch the owners when converting roadtypes... */
2428 if (_current_company >= MAX_COMPANIES) return;
2429
2430 /* We can't get a company from invalid owners but we can get ownership of roads without an owner */
2431 if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
2432
2433 Company *c;
2434
2435 switch (owner.base()) {
2436 case OWNER_NONE.base():
2437 SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company);
2439 break;
2440
2441 default:
2442 c = Company::Get(owner);
2443 c->infrastructure.road[from_type] -= num_pieces;
2444 c->infrastructure.road[to_type] += num_pieces;
2446 break;
2447 }
2448}
2449
2460CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal)
2461{
2462 TileIndex area_end = tile;
2463
2464 if (!ValParamRoadType(to_type)) return CMD_ERROR;
2465 if (area_start >= Map::Size()) return CMD_ERROR;
2466
2467 RoadVehicleList affected_rvs;
2468 RoadTramType rtt = GetRoadTramType(to_type);
2469
2471 CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert.
2472 bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633)
2473
2474 std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal);
2475 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
2476 /* Is road present on tile? */
2477 if (!MayHaveRoad(tile)) continue;
2478
2479 /* Converting to the same subtype? */
2480 RoadType from_type = GetRoadType(tile, rtt);
2481 if (from_type == INVALID_ROADTYPE || from_type == to_type) continue;
2482
2483 /* Check if there is any infrastructure on tile */
2484 TileType tt = GetTileType(tile);
2485 switch (tt) {
2486 case MP_STATION:
2487 if (!IsAnyRoadStop(tile)) continue;
2488 break;
2489 case MP_ROAD:
2490 if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
2491 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD);
2492 continue;
2493 }
2494 break;
2495 case MP_TUNNELBRIDGE:
2496 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) continue;
2497 break;
2498 default: continue;
2499 }
2500
2501 /* Trying to convert other's road */
2502 Owner owner = GetRoadOwner(tile, rtt);
2503 if (!CanConvertUnownedRoadType(owner, rtt)) {
2504 CommandCost ret = CheckOwnership(owner, tile);
2505 if (ret.Failed()) {
2506 error = std::move(ret);
2507 continue;
2508 }
2509 }
2510
2511 /* Base the ability to replace town roads and bridges on the town's
2512 * acceptance of destructive actions. */
2513 if (owner == OWNER_TOWN) {
2516 if (ret.Failed()) {
2517 error = std::move(ret);
2518 continue;
2519 }
2520 }
2521
2522 /* Vehicle on the tile when not converting normal <-> powered
2523 * Tunnels and bridges have special check later */
2524 if (tt != MP_TUNNELBRIDGE) {
2525 if (!HasPowerOnRoad(from_type, to_type)) {
2527 if (ret.Failed()) {
2528 error = std::move(ret);
2529 continue;
2530 }
2531
2532 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2533 error.MakeError(STR_ERROR_OWNED_BY);
2534 if (IsLocalCompany()) {
2535 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2536 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2537 }
2538 continue;
2539 }
2540 }
2541
2542 uint num_pieces = CountBits(GetAnyRoadBits(tile, rtt));
2543 if (tt == MP_STATION && IsBayRoadStopTile(tile)) {
2544 num_pieces *= ROAD_STOP_TRACKBIT_FACTOR;
2545 } else if (tt == MP_ROAD && IsRoadDepot(tile)) {
2546 num_pieces *= ROAD_DEPOT_TRACKBIT_FACTOR;
2547 }
2548
2549 found_convertible_road = true;
2550 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2551
2552 if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
2553 /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */
2554 if (owner == _current_company) {
2555 ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
2556 }
2557
2558 /* Perform the conversion */
2559 SetRoadType(tile, rtt, to_type);
2560 MarkTileDirtyByTile(tile);
2561
2562 /* update power of train on this tile */
2563 for (Vehicle *v : VehiclesOnTile(tile)) {
2564 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2565 }
2566
2567 if (IsRoadDepotTile(tile)) {
2568 /* Update build vehicle window related to this depot */
2571 }
2572 }
2573 } else {
2574 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
2575
2576 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
2577 * it would cause assert because of different test and exec runs */
2578 if (endtile < tile) {
2579 if (diagonal) {
2580 if (DiagonalTileArea(area_start, area_end).Contains(endtile)) continue;
2581 } else {
2582 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
2583 }
2584 }
2585
2586 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
2587 if (!HasPowerOnRoad(from_type, to_type)) {
2588 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
2589 if (ret.Failed()) {
2590 error = std::move(ret);
2591 continue;
2592 }
2593
2594 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2595 error.MakeError(STR_ERROR_OWNED_BY);
2596 if (IsLocalCompany()) {
2597 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2598 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2599 }
2600 continue;
2601 }
2602 }
2603
2604 /* There are 2 pieces on *every* tile of the bridge or tunnel */
2605 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * 2;
2606 found_convertible_road = true;
2607 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2608
2609 if (flags.Test(DoCommandFlag::Execute)) {
2610 /* Update the company infrastructure counters. */
2611 if (owner == _current_company) {
2612 /* Each piece should be counted TUNNELBRIDGE_TRACKBIT_FACTOR times
2613 * for the infrastructure counters (cause of #8297). */
2614 ConvertRoadTypeOwner(tile, num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR, owner, from_type, to_type);
2615 SetTunnelBridgeOwner(tile, endtile, _current_company);
2616 }
2617
2618 /* Perform the conversion */
2619 SetRoadType(tile, rtt, to_type);
2620 SetRoadType(endtile, rtt, to_type);
2621
2622 for (Vehicle *v : VehiclesOnTile(tile)) {
2623 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2624 }
2625 for (Vehicle *v : VehiclesOnTile(endtile)) {
2626 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2627 }
2628
2629 if (IsBridge(tile)) {
2630 MarkBridgeDirty(tile);
2631 } else {
2632 MarkTileDirtyByTile(tile);
2633 MarkTileDirtyByTile(endtile);
2634 }
2635 }
2636 }
2637 }
2638
2639 if (flags.Test(DoCommandFlag::Execute)) {
2640 /* Roadtype changed, update roadvehicles as when entering different track */
2641 for (RoadVehicle *v : affected_rvs) {
2642 v->CargoChanged();
2643 }
2644 }
2645
2646 return found_convertible_road ? cost : error;
2647}
2648
2649static CommandCost CheckBuildAbove_Road(TileIndex tile, DoCommandFlags flags, Axis, int)
2650{
2651 if (!IsRoadDepot(tile)) return CommandCost();
2652 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
2653}
2654
2656extern const TileTypeProcs _tile_type_road_procs = {
2657 DrawTile_Road, // draw_tile_proc
2658 GetSlopePixelZ_Road, // get_slope_z_proc
2659 ClearTile_Road, // clear_tile_proc
2660 nullptr, // add_accepted_cargo_proc
2661 GetTileDesc_Road, // get_tile_desc_proc
2662 GetTileTrackStatus_Road, // get_tile_track_status_proc
2663 ClickTile_Road, // click_tile_proc
2664 nullptr, // animate_tile_proc
2665 TileLoop_Road, // tile_loop_proc
2666 ChangeTileOwner_Road, // change_tile_owner_proc
2667 nullptr, // add_produced_cargo_proc
2668 VehicleEnter_Road, // vehicle_enter_tile_proc
2669 GetFoundation_Road, // get_foundation_proc
2670 TerraformTile_Road, // terraform_tile_proc
2671 CheckBuildAbove_Road, // check_build_above_proc
2672};
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
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
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
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 & Reset()
Reset all bits.
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:116
SpriteID single_x
single piece of rail in X direction, without ground
Definition rail.h:126
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:221
SpriteID crossing
level crossing, rail in X direction
Definition rail.h:133
SpriteID single_y
single piece of rail in Y direction, without ground
Definition rail.h:127
StringID name
Name of this rail type.
Definition rail.h:166
struct RailTypeInfo::@22 strings
Strings associated with the rail type.
struct RailTypeInfo::@19 base_sprites
Struct containing the main sprites.
struct RoadTypeInfo::@25 strings
Strings associated with the rail type.
RoadTypeLabel label
Unique 32 bit road type identifier.
Definition road.h:122
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:97
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:152
RoadType Index() const
Get the RoadType for this RoadTypeInfo.
Definition road.cpp:30
CursorID autoroad
Cursor for autorail tool.
Definition road.h:71
TimerGameCalendar::Date introduction_date
Introduction date.
Definition road.h:141
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
Definition road.h:157
RoadTypeFlags flags
Bit mask of road type flags.
Definition road.h:102
FlatSet< RoadTypeLabel > alternate_labels
Road type labels this type provides in addition to the main label.
Definition road.h:127
CursorID depot
Cursor for building a depot.
Definition road.h:72
CursorID road_nwse
Cursor for building rail in Y direction.
Definition road.h:70
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:117
StringID name
Name of this rail type.
Definition road.h:78
SpriteID build_y_road
button for building single rail in Y direction
Definition road.h:61
CursorID tunnel
Cursor for building a tunnel.
Definition road.h:73
SpriteID auto_road
button for the autoroad construction
Definition road.h:62
SpriteID convert_road
button for converting road types
Definition road.h:65
CursorID road_swne
Cursor for building rail in X direction.
Definition road.h:69
SpriteID build_x_road
button for building single rail in X direction
Definition road.h:60
SpriteID build_depot
button for building depots
Definition road.h:63
struct RoadTypeInfo::@24 cursor
Cursors associated with the road type.
struct RoadTypeInfo::@23 gui_sprites
struct containing the sprites for the road GUI.
SpriteID build_tunnel
button for building a tunnel
Definition road.h:64
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:291
static constexpr TimerGame< struct Calendar >::Date INVALID_DATE
Representation of an 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:417
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)
Set the right DParams 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.
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.
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:550
header file for electrified rail specific functions
bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition elrail_func.h:30
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:17
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:1032
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
Definition house.h:55
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,...
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.).
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:175
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:158
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:482
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:623
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:567
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:437
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:427
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:582
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:416
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:74
Base for the NewGRF implementation.
bool HasGrfMiscBit(GrfMiscBit bit)
Check for grf miscellaneous bits.
Definition newgrf.h:210
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
Definition newgrf.h:184
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:49
bool RailNoLevelCrossings(RailType rt)
Test if a RailType disallows build of level crossings.
Definition rail.h:399
Command definitions for rail.
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
static debug_inline RailTileType GetRailTileType(Tile t)
Returns the RailTileType (normal with or without signals, waypoint or depot).
Definition rail_map.h:36
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition rail_map.h:136
@ Normal
Normal rail tile without signals.
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:164
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:231
@ Catenary
Bit number for adding catenary.
@ Hidden
Bit number for hidden from construction.
Money RoadClearCost(RoadType roadtype)
Returns the cost of clearing the specified roadtype.
Definition road.h:252
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:216
Money RoadConvertCost(RoadType from, RoadType to)
Calculates the cost of road conversion.
Definition road.h:270
@ ROTSG_ONEWAY
Optional: One-way indicator images.
Definition road.h:49
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition road.h:39
@ ROTSG_GROUND
Required: Main group of ground images.
Definition road.h:40
@ ROTSG_DEPOT
Optional: Depot images.
Definition road.h:46
@ ROTSG_CURSORS
Optional: Cursor and toolbar icon images.
Definition road.h:38
@ ROTSG_CATENARY_BACK
Optional: Catenary back.
Definition road.h:43
@ ROTSG_CATENARY_FRONT
Optional: Catenary front.
Definition road.h:42
bool RoadNoLevelCrossing(RoadType roadtype)
Test if road disallows level crossings.
Definition road.h:284
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:241
void ResetRoadTypes()
Reset all road type information to its default values.
Definition road_cmd.cpp:63
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
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:599
static const RoadBits _invalid_tileh_slopes_road[2][15]
Invalid RoadBits on slopes.
Definition road_cmd.cpp:192
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:937
static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
Should the road be drawn as a unpaved snow/desert road? By default, roads are always drawn as unpaved...
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:534
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:169
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 for rendering a road tile 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:180
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.
RoadTypes _roadtypes_hidden_mask
Bitset of hidden roadtypes.
Definition road_cmd.cpp:56
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:966
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 ...
std::vector< RoadType > _sorted_roadtypes
Sorted list of road types.
Definition road_cmd.cpp:55
CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal)
Convert one road subtype to another.
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:314
const TileTypeProcs _tile_type_road_procs
Tile callback functions for road tiles.
Definition landscape.cpp:53
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...
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
Allocate a new road type label.
Definition road_cmd.cpp:129
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:252
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:145
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:135
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:235
bool HasCrossingReservation(Tile t)
Get the reservation state of the rail crossing.
Definition road_map.h:364
bool HasTownOwnedRoad(Tile t)
Checks if given tile has town owned road.
Definition road_map.h:264
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:58
static debug_inline bool IsRoadDepot(Tile t)
Return whether a tile is a road depot.
Definition road_map.h:90
void SetRoadDepotExitDirection(Tile tile, DiagDirection dir)
Sets the exit direction of a road depot.
Definition road_map.h:666
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:503
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:112
bool IsValidDisallowedRoadDirections(DisallowedRoadDirections drt)
Checks if a DisallowedRoadDirections is valid.
Definition road_map.h:275
Axis GetCrossingRoadAxis(Tile t)
Get the road axis of a level crossing.
Definition road_map.h:309
TrackBits GetCrossingRailBits(Tile tile)
Get the rail track bits of a level crossing.
Definition road_map.h:352
void SetDisallowedRoadDirections(Tile t, DisallowedRoadDirections drd)
Sets the disallowed directions.
Definition road_map.h:296
Track GetCrossingRailTrack(Tile tile)
Get the rail track of a level crossing.
Definition road_map.h:342
void StartRoadWorks(Tile t)
Start road works on a tile.
Definition road_map.h:515
DisallowedRoadDirections GetDisallowedRoadDirections(Tile t)
Gets the disallowed directions.
Definition road_map.h:285
bool HasTileRoadType(Tile t, RoadTramType rtt)
Check if a tile has a road or a tram road type.
Definition road_map.h:195
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition road_map.h:550
static debug_inline bool IsRoadDepotTile(Tile t)
Return whether a tile is a road depot tile.
Definition road_map.h:100
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:620
Roadside GetRoadside(Tile tile)
Get the decorations of a road.
Definition road_map.h:473
RoadTileType
The different types of road tiles.
Definition road_map.h:22
@ Normal
Normal road.
@ Depot
Depot (one entrance)
@ Crossing
Level crossing.
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:646
void ToggleSnowOrDesert(Tile t)
Toggle the snow/desert state of a road tile.
Definition road_map.h:450
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:321
void TerminateRoadWorks(Tile t)
Terminate road works on a tile.
Definition road_map.h:536
RoadBits GetCrossingRoadBits(Tile tile)
Get the road bits of a level crossing.
Definition road_map.h:332
void SetRoadType(Tile t, RoadTramType rtt, RoadType rt)
Set the road type of a tile.
Definition road_map.h:589
Owner GetRoadOwner(Tile t, RoadTramType rtt)
Get the owner of a specific road type.
Definition road_map.h:218
static debug_inline RoadTileType GetRoadTileType(Tile t)
Get the type of the road tile.
Definition road_map.h:36
bool IsCrossingBarred(Tile t)
Check if the level crossing is barred.
Definition road_map.h:400
void SetRoadside(Tile tile, Roadside s)
Set the decorations of a road.
Definition road_map.h:483
bool IsRoadOwner(Tile t, RoadTramType rtt, Owner o)
Check if a specific road type is owned by an owner.
Definition road_map.h:252
void MakeRoadDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RoadType rt)
Make a road depot.
Definition road_map.h:680
void SetCrossingReservation(Tile t, bool b)
Set the reservation state of the rail crossing.
Definition road_map.h:377
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:457
@ Paved
Road with paved sidewalks.
@ Barren
Road on barren land.
@ GrassRoadWorks
Road on grass with road works.
@ StreetLights
Road with street lights on paved sidewalks.
@ Trees
Road with trees on paved sidewalks.
@ Grass
Road on grass.
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition road_map.h:69
bool IsOnSnowOrDesert(Tile t)
Check if a road tile has snow/desert.
Definition road_map.h:441
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition road_map.h:493
static debug_inline bool IsNormalRoad(Tile t)
Return whether a tile is a normal road.
Definition road_map.h:48
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:21
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:48
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:61
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:56
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:58
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:57
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:55
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
@ FOUNDATION_LEVELED
The tile is leveled up to a flat slope.
Definition slope_type.h:95
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:94
@ FOUNDATION_INCLINED_X
The tile has an along X-axis inclined foundation.
Definition slope_type.h:96
@ FOUNDATION_INCLINED_Y
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:97
static const uint32_t VALID_LEVEL_CROSSING_SLOPES
Constant bitset with safe slopes for building a level crossing.
Definition slope_type.h:86
Functions related to sound.
@ SND_21_ROAD_WORKS
31 == 0x1F Road reconstruction animation
Definition sound_type.h:78
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:105
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:188
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:95
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.
bool value
tells if the bool cheat is active or not
Definition cheat_type.h:18
Cheat magic_bulldozer
dynamite industries, objects
Definition cheat_type.h:27
SoundSettings sound
sound effect settings
GUISettings gui
settings related to the GUI
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.
bool build_on_slopes
allow building on slopes
bool extra_dynamite
extra dynamite
bool crossing_with_competitor
allow building of level crossings with competitor roads or rails
T x
X coordinate.
T y
Y coordinate.
T z
Z coordinate.
TimerGameCalendar::Date build_date
Date of construction.
Definition depot_base.h:26
Represents a diagonal tile area.
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:52
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:53
bool mod_road_rebuild
roadworks remove unnecessary RoadBits
uint8_t dist_local_authority
distance for town local authority, default 20
A special vehicle is one of the following:
TramReplacement tram
In which way tram depots were replaced.
Definition newgrf.h:192
bool show_track_reservation
highlight reserved tracks.
LandscapeType landscape
the landscape we're currently in
EconomySettings economy
settings to change the economy
ConstructionSettings construction
construction of things in-game
GameCreationSettings game_creation
settings used during the creation of a game (map)
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:375
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:290
Represents the covered area of e.g.
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Buses, trucks and trams belong to this class.
Definition roadveh.h:98
uint8_t state
Definition roadveh.h:100
bool ambient
Play ambient, industry and town sounds.
T * Next() const
Get next vehicle in the chain.
static Pool::IterateWrapper< T > Iterate(size_t from=0)
Returns an iterable ensemble of all valid vehicles of type T.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
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:36
uint16_t rail_speed
Speed limit of rail (bridges and track)
Definition tile_cmd.h:49
StringID str
Description of the tile.
Definition tile_cmd.h:37
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:41
std::array< Owner, 4 > owner
Name of the owner(s)
Definition tile_cmd.h:39
uint16_t tram_speed
Speed limit of tram (bridges and track)
Definition tile_cmd.h:53
StringID roadtype
Type of road on the tile.
Definition tile_cmd.h:50
StringID tramtype
Type of tram on the tile.
Definition tile_cmd.h:52
StringID railtype
Type of rail on the tile.
Definition tile_cmd.h:48
uint16_t road_speed
Speed limit of road (bridges and track)
Definition tile_cmd.h:51
std::array< StringID, 4 > owner_type
Type of each owner.
Definition tile_cmd.h:40
Tile information, used while rendering the tile.
Definition tile_cmd.h:30
Slope tileh
Slope of the tile.
Definition tile_cmd.h:31
TileIndex tile
Tile index.
Definition tile_cmd.h:32
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:152
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:148
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/...
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:136
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
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
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
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
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
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:47
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
@ MP_RAILWAY
A railway.
Definition tile_type.h:49
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.
@ RoadRemove
Removal of a road owned by the town.
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:965
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:284
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:388
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:524
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:527
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1520
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:551
@ 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:663
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:3294
@ 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,...