OpenTTD Source 20250529-master-g10c159a79f
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 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
114 RoadTypeInfo *rti = &_roadtypes[rt];
115 ResolveRoadTypeGUISprites(rti);
117 }
118
119 _sorted_roadtypes.clear();
120 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
121 if (_roadtypes[rt].label == 0) continue;
122 _sorted_roadtypes.push_back(rt);
123 }
124 std::sort(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), CompareRoadTypes);
125}
126
130RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
131{
132 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
133 RoadTypeInfo *rti = &_roadtypes[rt];
134
135 if (rti->label == 0) {
136 /* Set up new road type */
137 *rti = _original_roadtypes[(rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD];
138 rti->label = label;
139 rti->alternate_labels.clear();
140 rti->flags = {};
142
143 /* Make us compatible with ourself. */
144 rti->powered_roadtypes = rt;
145
146 /* We also introduce ourself. */
147 rti->introduces_roadtypes = rt;
148
149 /* Default sort order; order of allocation, but with some
150 * offsets so it's easier for NewGRF to pick a spot without
151 * changing the order of other (original) road types.
152 * The << is so you can place other roadtypes in between the
153 * other roadtypes, the 7 is to be able to place something
154 * before the first (default) road type. */
155 rti->sorting_order = rt << 2 | 7;
156
157 /* Set bitmap of road/tram types */
158 if (rtt == RTT_TRAM) {
160 } else {
162 }
163
164 return rt;
165 }
166 }
167
168 return INVALID_ROADTYPE;
169}
170
176{
177 return !RoadVehicle::Iterate().empty();
178}
179
187{
188 if (rt == INVALID_ROADTYPE) return;
189
191 if (c == nullptr) return;
192
193 c->infrastructure.road[rt] += count;
195}
196
199 /* The inverse of the mixable RoadBits on a leveled slope */
200 {
201 ROAD_NONE, // SLOPE_FLAT
202 ROAD_NE | ROAD_SE, // SLOPE_W
203 ROAD_NE | ROAD_NW, // SLOPE_S
204
205 ROAD_NE, // SLOPE_SW
206 ROAD_NW | ROAD_SW, // SLOPE_E
207 ROAD_NONE, // SLOPE_EW
208
209 ROAD_NW, // SLOPE_SE
210 ROAD_NONE, // SLOPE_WSE
211 ROAD_SE | ROAD_SW, // SLOPE_N
212
213 ROAD_SE, // SLOPE_NW
214 ROAD_NONE, // SLOPE_NS
215 ROAD_NONE, // SLOPE_ENW
216
217 ROAD_SW, // SLOPE_NE
218 ROAD_NONE, // SLOPE_SEN
219 ROAD_NONE // SLOPE_NWS
220 },
221 /* The inverse of the allowed straight roads on a slope
222 * (with and without a foundation). */
223 {
224 ROAD_NONE, // SLOPE_FLAT
225 ROAD_NONE, // SLOPE_W Foundation
226 ROAD_NONE, // SLOPE_S Foundation
227
228 ROAD_Y, // SLOPE_SW
229 ROAD_NONE, // SLOPE_E Foundation
230 ROAD_ALL, // SLOPE_EW
231
232 ROAD_X, // SLOPE_SE
233 ROAD_ALL, // SLOPE_WSE
234 ROAD_NONE, // SLOPE_N Foundation
235
236 ROAD_X, // SLOPE_NW
237 ROAD_ALL, // SLOPE_NS
238 ROAD_ALL, // SLOPE_ENW
239
240 ROAD_Y, // SLOPE_NE
241 ROAD_ALL, // SLOPE_SEN
242 ROAD_ALL // SLOPE_NW
243 }
244};
245
246static Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
247
258CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlags flags, bool town_check)
259{
260 if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return CommandCost();
261
262 /* Water can always flood and towns can always remove "normal" road pieces.
263 * Towns are not be allowed to remove non "normal" road pieces, like tram
264 * tracks as that would result in trams that cannot turn. */
266 (rtt == RTT_ROAD && !Company::IsValidID(_current_company))) return CommandCost();
267
268 /* Only do the special processing if the road is owned
269 * by a town */
270 if (owner != OWNER_TOWN) {
271 if (owner == OWNER_NONE) return CommandCost();
272 CommandCost ret = CheckOwnership(owner);
273 return ret;
274 }
275
276 if (!town_check) return CommandCost();
277
279
280 Town *t = ClosestTownFromTile(tile, UINT_MAX);
281 if (t == nullptr) return CommandCost();
282
283 /* check if you're allowed to remove the street owned by a town
284 * removal allowance depends on difficulty setting */
286 if (ret.Failed()) return ret;
287
288 /* Get a bitmask of which neighbouring roads has a tile */
290 RoadBits present = GetAnyRoadBits(tile, rtt);
291 if ((present & ROAD_NE) && (GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt) & ROAD_SW)) n |= ROAD_NE;
292 if ((present & ROAD_SE) && (GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt) & ROAD_NW)) n |= ROAD_SE;
293 if ((present & ROAD_SW) && (GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt) & ROAD_NE)) n |= ROAD_SW;
294 if ((present & ROAD_NW) && (GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt) & ROAD_SE)) n |= ROAD_NW;
295
296 int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE;
297 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
298 * then allow it */
299 if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) {
300 /* you can remove all kind of roads with extra dynamite */
302 return CommandCostWithParam(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS, t->index);
303 }
304 rating_decrease = RATING_ROAD_DOWN_STEP_INNER;
305 }
306 ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM, flags);
307
308 return CommandCost();
309}
310
311
320static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check)
321{
322 assert(pieces != ROAD_NONE);
323
324 RoadType existing_rt = MayHaveRoad(tile) ? GetRoadType(tile, rtt) : INVALID_ROADTYPE;
325 /* The tile doesn't have the given road type */
326 if (existing_rt == INVALID_ROADTYPE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
327
328 switch (GetTileType(tile)) {
329 case MP_ROAD: {
331 if (ret.Failed()) return ret;
332 break;
333 }
334
335 case MP_STATION: {
336 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
337
339 if (ret.Failed()) return ret;
340 break;
341 }
342
343 case MP_TUNNELBRIDGE: {
346 if (ret.Failed()) return ret;
347 break;
348 }
349
350 default:
351 return CMD_ERROR;
352 }
353
354 CommandCost ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rtt), rtt, flags, town_check);
355 if (ret.Failed()) return ret;
356
357 if (!IsTileType(tile, MP_ROAD)) {
358 /* If it's the last roadtype, just clear the whole tile */
359 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
360
362 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
363 /* Removing any roadbit in the bridge axis removes the roadtype (that's the behaviour remove-long-roads needs) */
364 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);
365
366 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
367 /* Pay for *every* tile of the bridge or tunnel */
368 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
369 cost.AddCost(len * 2 * RoadClearCost(existing_rt));
370 if (flags.Test(DoCommandFlag::Execute)) {
371 /* A full diagonal road tile has two road bits. */
372 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
373
374 SetRoadType(other_end, rtt, INVALID_ROADTYPE);
375 SetRoadType(tile, rtt, INVALID_ROADTYPE);
376
377 /* If the owner of the bridge sells all its road, also move the ownership
378 * to the owner of the other roadtype, unless the bridge owner is a town. */
379 Owner other_owner = GetRoadOwner(tile, OtherRoadTramType(rtt));
380 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
381 SetTileOwner(tile, other_owner);
382 SetTileOwner(other_end, other_owner);
383 }
384
385 /* Mark tiles dirty that have been repaved */
386 if (IsBridge(tile)) {
387 MarkBridgeDirty(tile);
388 } else {
390 MarkTileDirtyByTile(other_end);
391 }
392 }
393 } else {
394 assert(IsDriveThroughStopTile(tile));
395 cost.AddCost(RoadClearCost(existing_rt) * 2);
396 if (flags.Test(DoCommandFlag::Execute)) {
397 /* A full diagonal road tile has two road bits. */
398 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
399 SetRoadType(tile, rtt, INVALID_ROADTYPE);
401 }
402 }
403 return cost;
404 }
405
406 switch (GetRoadTileType(tile)) {
407 case ROAD_TILE_NORMAL: {
408 Slope tileh = GetTileSlope(tile);
409
410 /* Steep slopes behave the same as slopes with one corner raised. */
411 if (IsSteepSlope(tileh)) {
413 }
414
415 RoadBits present = GetRoadBits(tile, rtt);
416 const RoadBits other = GetRoadBits(tile, OtherRoadTramType(rtt));
417 const Foundation f = GetRoadFoundation(tileh, present);
418
419 if (HasRoadWorks(tile) && _current_company != OWNER_WATER) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
420
421 /* Autocomplete to a straight road
422 * @li if the bits of the other roadtypes result in another foundation
423 * @li if build on slopes is disabled */
424 if ((IsStraightRoad(other) && (other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
426 pieces |= MirrorRoadBits(pieces);
427 }
428
429 /* limit the bits to delete to the existing bits. */
430 pieces &= present;
431 if (pieces == ROAD_NONE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
432
433 /* Now set present what it will be after the remove */
434 present ^= pieces;
435
436 /* Check for invalid RoadBit combinations on slopes */
437 if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
438 (present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == present) {
439 return CMD_ERROR;
440 }
441
442 if (flags.Test(DoCommandFlag::Execute)) {
443 if (HasRoadWorks(tile)) {
444 /* flooding tile with road works, don't forget to remove the effect vehicle too */
445 assert(_current_company == OWNER_WATER);
447 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
448 delete v;
449 }
450 }
451 }
452
453 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)CountBits(pieces));
454
455 if (present == ROAD_NONE) {
456 /* No other road type, just clear tile. */
457 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
458 /* Includes MarkTileDirtyByTile() */
459 DoClearSquare(tile);
460 } else {
461 if (rtt == RTT_ROAD && IsRoadOwner(tile, rtt, OWNER_TOWN)) {
462 /* Update nearest-town index */
463 const Town *town = CalcClosestTownFromTile(tile);
464 SetTownIndex(tile, town == nullptr ? TownID::Invalid() : town->index);
465 }
466 if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE);
467 SetRoadBits(tile, ROAD_NONE, rtt);
468 SetRoadType(tile, rtt, INVALID_ROADTYPE);
470 }
471 } else {
472 /* When bits are removed, you *always* end up with something that
473 * is not a complete straight road tile. However, trams do not have
474 * onewayness, so they cannot remove it either. */
475 if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE);
476 SetRoadBits(tile, present, rtt);
478 }
479 }
480
481 CommandCost cost(EXPENSES_CONSTRUCTION, CountBits(pieces) * RoadClearCost(existing_rt));
482 /* If we build a foundation we have to pay for it. */
483 if (f == FOUNDATION_NONE && GetRoadFoundation(tileh, present) != FOUNDATION_NONE) cost.AddCost(_price[PR_BUILD_FOUNDATION]);
484
485 return cost;
486 }
487
488 case ROAD_TILE_CROSSING: {
489 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
490 return CMD_ERROR;
491 }
492
493 if (flags.Test(DoCommandFlag::Execute)) {
495
496 /* A full diagonal road tile has two road bits. */
497 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
498
499 Track railtrack = GetCrossingRailTrack(tile);
500 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
501 TrackBits tracks = GetCrossingRailBits(tile);
502 bool reserved = HasCrossingReservation(tile);
503 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
504 if (reserved) SetTrackReservation(tile, tracks);
505
506 /* Update rail count for level crossings. The plain track should still be accounted
507 * for, so only subtract the difference to the level crossing cost. */
509 if (c != nullptr) {
512 }
513 } else {
514 SetRoadType(tile, rtt, INVALID_ROADTYPE);
515 }
517 YapfNotifyTrackLayoutChange(tile, railtrack);
518 }
519 return CommandCost(EXPENSES_CONSTRUCTION, RoadClearCost(existing_rt) * 2);
520 }
521
522 default:
523 case ROAD_TILE_DEPOT:
524 return CMD_ERROR;
525 }
526}
527
528
540static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
541{
542 /* Remove already build pieces */
543 *pieces &= ~existing;
544
545 /* If we can't build anything stop here */
546 if (*pieces == ROAD_NONE) return CMD_ERROR;
547
548 /* All RoadBit combos are valid on flat land */
549 if (tileh == SLOPE_FLAT) return CommandCost();
550
551 /* Steep slopes behave the same as slopes with one corner raised. */
552 if (IsSteepSlope(tileh)) {
554 }
555
556 /* Save the merge of all bits of the current type */
557 RoadBits type_bits = existing | *pieces;
558
559 /* Roads on slopes */
560 if (_settings_game.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
561
562 /* If we add leveling we've got to pay for it */
563 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
564
565 return CommandCost();
566 }
567
568 /* Autocomplete uphill roads */
569 *pieces |= MirrorRoadBits(*pieces);
570 type_bits = existing | *pieces;
571
572 /* Uphill roads */
573 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
574 (_invalid_tileh_slopes_road[1][tileh] & (other | type_bits)) == ROAD_NONE) {
575
576 /* Slopes with foundation ? */
577 if (IsSlopeWithOneCornerRaised(tileh)) {
578
579 /* Prevent build on slopes if it isn't allowed */
581
582 /* If we add foundation we've got to pay for it */
583 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
584
585 return CommandCost();
586 }
587 } else {
588 if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
589 return CommandCost();
590 }
591 }
592 return CMD_ERROR;
593}
594
606{
607 CompanyID company = _current_company;
609
610 RoadBits existing = ROAD_NONE;
611 RoadBits other_bits = ROAD_NONE;
612
613 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
614 * if a non-company is building the road */
615 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;
616 if (company != OWNER_TOWN) {
617 const Town *town = CalcClosestTownFromTile(tile);
618 town_id = (town != nullptr) ? town->index : TownID::Invalid();
619
620 if (company == OWNER_DEITY) {
621 company = OWNER_TOWN;
622
623 /* If we are not within a town, we are not owned by the town */
624 if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) {
625 company = OWNER_NONE;
626 }
627 }
628 }
629
630 /* do not allow building 'zero' road bits, code wouldn't handle it */
631 if (pieces == ROAD_NONE || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR;
632 if (!ValParamRoadType(rt)) return CMD_ERROR;
633
634 Slope tileh = GetTileSlope(tile);
635 RoadTramType rtt = GetRoadTramType(rt);
636
637 bool need_to_clear = false;
638 switch (GetTileType(tile)) {
639 case MP_ROAD:
640 switch (GetRoadTileType(tile)) {
641 case ROAD_TILE_NORMAL: {
642 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
643
644 other_bits = GetRoadBits(tile, OtherRoadTramType(rtt));
645 if (!HasTileRoadType(tile, rtt)) break;
646
647 existing = GetRoadBits(tile, rtt);
648 bool crossing = !IsStraightRoad(existing | pieces);
649 if (rtt == RTT_ROAD && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
650 /* Junctions cannot be one-way */
651 return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
652 }
653 if ((existing & pieces) == pieces) {
654 /* We only want to set the (dis)allowed road directions */
655 if (toggle_drd != DRD_NONE && rtt == RTT_ROAD) {
656 Owner owner = GetRoadOwner(tile, rtt);
657 if (owner != OWNER_NONE) {
658 CommandCost ret = CheckOwnership(owner, tile);
659 if (ret.Failed()) return ret;
660 }
661
663 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
664
665 /* We allow removing disallowed directions to break up
666 * deadlocks, but adding them can break articulated
667 * vehicles. As such, only when less is disallowed,
668 * i.e. bits are removed, we skip the vehicle check. */
669 if (CountBits(dis_existing) <= CountBits(dis_new)) {
671 if (ret.Failed()) return ret;
672 }
673
674 /* Ignore half built tiles */
675 if (flags.Test(DoCommandFlag::Execute) && IsStraightRoad(existing)) {
676 SetDisallowedRoadDirections(tile, dis_new);
678 }
679 return CommandCost();
680 }
681 return CommandCost(STR_ERROR_ALREADY_BUILT);
682 }
683 /* Disallow breaking end-of-line of someone else
684 * so trams can still reverse on this tile. */
685 if (rtt == RTT_TRAM && HasExactlyOneBit(existing)) {
686 Owner owner = GetRoadOwner(tile, rtt);
687 if (Company::IsValidID(owner)) {
688 CommandCost ret = CheckOwnership(owner);
689 if (ret.Failed()) return ret;
690 }
691 }
692 break;
693 }
694
696 if (RoadNoLevelCrossing(rt)) {
697 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
698 }
699
700 other_bits = GetCrossingRoadBits(tile);
701 if (pieces & ComplementRoadBits(other_bits)) goto do_clear;
702 pieces = other_bits; // we need to pay for both roadbits
703
704 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
705 break;
706
707 case ROAD_TILE_DEPOT:
708 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
709 goto do_clear;
710
711 default: NOT_REACHED();
712 }
713 break;
714
715 case MP_RAILWAY: {
716 if (IsSteepSlope(tileh)) {
717 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
718 }
719
720 /* Level crossings may only be built on these slopes */
721 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
722 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
723 }
724
727 if (ret.Failed()) return ret;
728 }
729
730 if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
731
732 if (RoadNoLevelCrossing(rt)) {
733 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
734 }
735
737 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
738 }
739
740 Axis roaddir;
741 switch (GetTrackBits(tile)) {
742 case TRACK_BIT_X:
743 if (pieces & ROAD_X) goto do_clear;
744 roaddir = AXIS_Y;
745 break;
746
747 case TRACK_BIT_Y:
748 if (pieces & ROAD_Y) goto do_clear;
749 roaddir = AXIS_X;
750 break;
751
752 default: goto do_clear;
753 }
754
756 if (ret.Failed()) return ret;
757
758 if (flags.Test(DoCommandFlag::Execute)) {
759 Track railtrack = AxisToTrack(OtherAxis(roaddir));
760 YapfNotifyTrackLayoutChange(tile, railtrack);
761 /* Update company infrastructure counts. A level crossing has two road bits. */
762 UpdateCompanyRoadInfrastructure(rt, company, 2);
763
764 /* Update rail count for level crossings. The plain track is already
765 * counted, so only add the difference to the level crossing cost. */
767 if (c != nullptr) {
770 }
771
772 /* Always add road to the roadtypes (can't draw without it) */
773 bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
774 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id);
775 SetCrossingReservation(tile, reserved);
776 UpdateLevelCrossing(tile, false);
779 }
781 }
782
783 case MP_STATION: {
784 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
785 if (!IsDriveThroughStopTile(tile)) goto do_clear;
786
788 if (pieces & ~curbits) goto do_clear;
789 pieces = curbits; // we need to pay for both roadbits
790
791 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
792 break;
793 }
794
795 case MP_TUNNELBRIDGE: {
796 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) goto do_clear;
797 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
798 if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
799 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
800 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
802 if (ret.Failed()) return ret;
803 break;
804 }
805
806 default: {
807do_clear:;
808 need_to_clear = true;
809 break;
810 }
811 }
812
813 if (need_to_clear) {
815 if (ret.Failed()) return ret;
816 cost.AddCost(ret.GetCost());
817 }
818
819 if (other_bits != pieces) {
820 /* Check the foundation/slopes when adding road/tram bits */
821 CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
822 /* Return an error if we need to build a foundation (ret != 0) but the
823 * current setting is turned off */
824 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
825 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
826 }
827 cost.AddCost(ret.GetCost());
828 }
829
830 if (!need_to_clear) {
831 if (IsTileType(tile, MP_ROAD)) {
832 /* Don't put the pieces that already exist */
833 pieces &= ComplementRoadBits(existing);
834
835 /* Check if new road bits will have the same foundation as other existing road types */
836 if (IsNormalRoad(tile)) {
837 Slope slope = GetTileSlope(tile);
838 Foundation found_new = GetRoadFoundation(slope, pieces | existing);
839
840 RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt));
841 /* do not check if there are not road bits of given type */
842 if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) {
843 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
844 }
845 }
846 }
847
849 if (ret.Failed()) return ret;
850
851 if (IsNormalRoadTile(tile)) {
852 /* If the road types don't match, try to convert only if vehicles of
853 * the new road type are not powered on the present road type and vehicles of
854 * the present road type are powered on the new road type. */
855 RoadType existing_rt = GetRoadType(tile, rtt);
856 if (existing_rt != INVALID_ROADTYPE && existing_rt != rt) {
857 if (HasPowerOnRoad(rt, existing_rt)) {
858 rt = existing_rt;
859 } else if (HasPowerOnRoad(existing_rt, rt)) {
860 ret = Command<CMD_CONVERT_ROAD>::Do(flags, tile, tile, rt, false);
861 if (ret.Failed()) return ret;
862 cost.AddCost(ret.GetCost());
863 } else {
864 return CMD_ERROR;
865 }
866 }
867 }
868 }
869
870 uint num_pieces = (!need_to_clear && IsTileType(tile, MP_TUNNELBRIDGE)) ?
871 /* There are 2 pieces on *every* tile of the bridge or tunnel */
872 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) :
873 /* Count pieces */
874 CountBits(pieces);
875
876 cost.AddCost(num_pieces * RoadBuildCost(rt));
877
878 if (flags.Test(DoCommandFlag::Execute)) {
879 switch (GetTileType(tile)) {
880 case MP_ROAD: {
881 RoadTileType rttype = GetRoadTileType(tile);
882 if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) {
883 SetRoadType(tile, rtt, rt);
884 SetRoadOwner(tile, rtt, company);
885 if (rtt == RTT_ROAD) SetTownIndex(tile, town_id);
886 }
887 if (rttype != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rtt);
888 break;
889 }
890
891 case MP_TUNNELBRIDGE: {
892 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
893
894 SetRoadType(other_end, rtt, rt);
895 SetRoadType(tile, rtt, rt);
896 SetRoadOwner(other_end, rtt, company);
897 SetRoadOwner(tile, rtt, company);
898
899 /* Mark tiles dirty that have been repaved */
900 if (IsBridge(tile)) {
901 MarkBridgeDirty(tile);
902 } else {
903 MarkTileDirtyByTile(other_end);
905 }
906 break;
907 }
908
909 case MP_STATION: {
910 assert(IsDriveThroughStopTile(tile));
911 SetRoadType(tile, rtt, rt);
912 SetRoadOwner(tile, rtt, company);
913 break;
914 }
915
916 default:
917 MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company);
918 break;
919 }
920
921 /* Update company infrastructure count. */
923 UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), num_pieces);
924
925 if (rtt == RTT_ROAD && IsNormalRoadTile(tile)) {
926 existing |= pieces;
928 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
929 }
930
932 }
933 return cost;
934}
935
944{
945 tile += TileOffsByDiagDir(dir);
946 if (!IsValidTile(tile) || !MayHaveRoad(tile)) return false;
947
948 RoadTramType rtt = GetRoadTramType(rt);
949 RoadType existing = GetRoadType(tile, rtt);
950 if (existing == INVALID_ROADTYPE) return false;
951 if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false;
952
953 RoadBits bits = GetAnyRoadBits(tile, rtt, false);
954 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
955}
956
972CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
973{
974 if (start_tile >= Map::Size()) return CMD_ERROR;
975
976 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
977
978 /* Only drag in X or Y direction dictated by the direction variable */
979 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
980 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
981
982 DiagDirection dir = AxisToDiagDir(axis);
983
984 /* Swap direction, also the half-tile drag vars. */
985 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
986 dir = ReverseDiagDir(dir);
987 start_half = !start_half;
988 end_half = !end_half;
989 if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
990 }
991
992 /* On the X-axis, we have to swap the initial bits, so they
993 * will be interpreted correctly in the GTTS. Furthermore
994 * when you just 'click' on one tile to build them. */
995 if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
996
998 CommandCost last_error = CMD_ERROR;
999 TileIndex tile = start_tile;
1000 bool had_bridge = false;
1001 bool had_tunnel = false;
1002 bool had_success = false;
1003
1004 /* Start tile is the first tile clicked by the user. */
1005 for (;;) {
1006 RoadBits bits = AxisToRoadBits(axis);
1007
1008 /* Determine which road parts should be built. */
1009 if (!is_ai && start_tile != end_tile) {
1010 /* Only build the first and last roadbit if they can connect to something. */
1011 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1012 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1013 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1014 bits = DiagDirToRoadBits(dir);
1015 }
1016 } else {
1017 /* Road parts only have to be built at the start tile or at the end tile. */
1018 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1019 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1020 }
1021
1022 CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, TownID::Invalid());
1023 if (!is_ai && ret.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true;
1024 if (ret.Failed()) {
1025 last_error = std::move(ret);
1026 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1027 if (is_ai) return last_error;
1028 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1029 }
1030 } else {
1031 had_success = true;
1032 /* Only pay for the upgrade on one side of the bridges and tunnels */
1033 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1034 if (IsBridge(tile)) {
1035 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1036 cost.AddCost(ret.GetCost());
1037 }
1038 had_bridge = true;
1039 } else { // IsTunnel(tile)
1040 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1041 cost.AddCost(ret.GetCost());
1042 }
1043 had_tunnel = true;
1044 }
1045 } else {
1046 cost.AddCost(ret.GetCost());
1047 }
1048 }
1049
1050 if (tile == end_tile) break;
1051
1052 tile += TileOffsByDiagDir(dir);
1053 }
1054
1055 return had_success ? cost : last_error;
1056}
1057
1069std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
1070{
1072
1073 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
1074 if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 };
1075
1076 /* Only drag in X or Y direction dictated by the direction variable */
1077 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis
1078 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis
1079
1080 /* Swap start and ending tile, also the half-tile drag vars. */
1081 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
1082 std::swap(start_tile, end_tile);
1083 std::swap(start_half, end_half);
1084 }
1085
1086 Money money_available = GetAvailableMoneyForCommand();
1087 Money money_spent = 0;
1088 TileIndex tile = start_tile;
1089 CommandCost last_error = CMD_ERROR;
1090 bool had_success = false;
1091 /* Start tile is the small number. */
1092 for (;;) {
1093 RoadBits bits = AxisToRoadBits(axis);
1094
1095 if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
1096 if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
1097
1098 /* try to remove the halves. */
1099 if (bits != 0) {
1100 RoadTramType rtt = GetRoadTramType(rt);
1101 CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true);
1102 if (ret.Succeeded()) {
1103 if (flags.Test(DoCommandFlag::Execute)) {
1104 money_spent += ret.GetCost();
1105 if (money_spent > 0 && money_spent > money_available) {
1106 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() };
1107 }
1108 RemoveRoad(tile, flags, bits, rtt, false);
1109 }
1110 cost.AddCost(ret.GetCost());
1111 had_success = true;
1112 } else {
1113 /* Some errors are more equal than others. */
1114 switch (last_error.GetErrorMessage()) {
1115 case STR_ERROR_OWNED_BY:
1116 case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS:
1117 break;
1118 default:
1119 last_error = std::move(ret);
1120 }
1121 }
1122 }
1123
1124 if (tile == end_tile) break;
1125
1126 tile += TileOffsByAxis(axis);
1127 }
1128
1129 return { had_success ? cost : last_error, 0 };
1130}
1131
1144{
1145 if (!ValParamRoadType(rt) || !IsValidDiagDirection(dir)) return CMD_ERROR;
1146
1148
1149 Slope tileh = GetTileSlope(tile);
1150 if (tileh != SLOPE_FLAT) {
1152 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
1153 }
1154 cost.AddCost(_price[PR_BUILD_FOUNDATION]);
1155 }
1156
1157 /* Allow the user to rotate the depot instead of having to destroy it and build it again */
1158 bool rotate_existing_depot = false;
1159 if (IsRoadDepotTile(tile) && (HasRoadTypeTram(tile) ? rt == GetRoadTypeTram(tile) : rt == GetRoadTypeRoad(tile)))
1160 {
1161 CommandCost ret = CheckTileOwnership(tile);
1162 if (ret.Failed()) return ret;
1163
1164 if (dir == GetRoadDepotDirection(tile)) return CommandCost();
1165
1166 ret = EnsureNoVehicleOnGround(tile);
1167 if (ret.Failed()) return ret;
1168
1169 rotate_existing_depot = true;
1170 }
1171
1172 if (!rotate_existing_depot) {
1173 cost.AddCost(Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile));
1174 if (cost.Failed()) return cost;
1175
1176 if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1177
1178 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1179 }
1180
1181 if (flags.Test(DoCommandFlag::Execute)) {
1182 if (rotate_existing_depot) {
1183 SetRoadDepotExitDirection(tile, dir);
1184 } else {
1185 Depot *dep = new Depot(tile);
1186 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1187 MakeDefaultName(dep);
1188
1189 /* A road depot has two road bits. */
1191 }
1192
1193 MarkTileDirtyByTile(tile);
1194 }
1195
1196 cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
1197 return cost;
1198}
1199
1200static CommandCost RemoveRoadDepot(TileIndex tile, DoCommandFlags flags)
1201{
1203 CommandCost ret = CheckTileOwnership(tile);
1204 if (ret.Failed()) return ret;
1205 }
1206
1208 if (ret.Failed()) return ret;
1209
1210 if (flags.Test(DoCommandFlag::Execute)) {
1212 if (c != nullptr) {
1213 /* A road depot has two road bits. */
1214 RoadType rt = GetRoadTypeRoad(tile);
1215 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
1218 }
1219
1220 delete Depot::GetByTile(tile);
1221 DoClearSquare(tile);
1222 }
1223
1224 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_ROAD]);
1225}
1226
1227static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlags flags)
1228{
1229 switch (GetRoadTileType(tile)) {
1230 case ROAD_TILE_NORMAL: {
1231 RoadBits b = GetAllRoadBits(tile);
1232
1233 /* Clear the road if only one piece is on the tile OR we are not using the DoCommandFlag::Auto flag */
1234 if ((HasExactlyOneBit(b) && GetRoadBits(tile, RTT_TRAM) == ROAD_NONE) || !flags.Test(DoCommandFlag::Auto)) {
1236 for (RoadTramType rtt : _roadtramtypes) {
1237 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1238
1239 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true);
1240 if (tmp_ret.Failed()) return tmp_ret;
1241 ret.AddCost(tmp_ret.GetCost());
1242 }
1243 return ret;
1244 }
1245 return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1246 }
1247
1248 case ROAD_TILE_CROSSING: {
1250
1251 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1252
1253 /* Must iterate over the roadtypes in a reverse manner because
1254 * tram tracks must be removed before the road bits. */
1255 for (RoadTramType rtt : { RTT_TRAM, RTT_ROAD }) {
1256 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1257
1258 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rtt, true);
1259 if (tmp_ret.Failed()) return tmp_ret;
1260 ret.AddCost(tmp_ret.GetCost());
1261 }
1262
1263 if (flags.Test(DoCommandFlag::Execute)) {
1265 }
1266 return ret;
1267 }
1268
1269 default:
1270 case ROAD_TILE_DEPOT:
1271 if (flags.Test(DoCommandFlag::Auto)) {
1272 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1273 }
1274 return RemoveRoadDepot(tile, flags);
1275 }
1276}
1277
1278
1280 uint16_t image;
1281 uint8_t subcoord_x;
1282 uint8_t subcoord_y;
1283};
1284
1285#include "table/road_land.h"
1286
1295{
1296 /* Flat land and land without a road doesn't require a foundation */
1297 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1298
1299 /* Steep slopes behave the same as slopes with one corner raised. */
1300 if (IsSteepSlope(tileh)) {
1302 }
1303
1304 /* Leveled RoadBits on a slope */
1305 if ((_invalid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1306
1307 /* Straight roads without foundation on a slope */
1308 if (!IsSlopeWithOneCornerRaised(tileh) &&
1309 (_invalid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE)
1310 return FOUNDATION_NONE;
1311
1312 /* Roads on steep Slopes or on Slopes with one corner raised */
1314}
1315
1316const uint8_t _road_sloped_sprites[14] = {
1317 0, 0, 2, 0,
1318 0, 1, 0, 0,
1319 3, 0, 0, 0,
1320 0, 0
1321};
1322
1329static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
1330{
1331 if (slope != SLOPE_FLAT) {
1332 switch (slope) {
1333 case SLOPE_NE: return 11;
1334 case SLOPE_SE: return 12;
1335 case SLOPE_SW: return 13;
1336 case SLOPE_NW: return 14;
1337 default: NOT_REACHED();
1338 }
1339 } else {
1340 static const uint offsets[] = {
1341 0, 18, 17, 7,
1342 16, 0, 10, 5,
1343 15, 8, 1, 4,
1344 9, 3, 6, 2
1345 };
1346 return offsets[bits];
1347 }
1348}
1349
1359static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
1360{
1361 return (snow_or_desert &&
1362 !(_settings_game.game_creation.landscape == LandscapeType::Tropic && HasGrfMiscBit(GrfMiscBit::DesertPavedRoads) &&
1363 roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS));
1364}
1365
1373{
1374 /* Don't draw the catenary under a low bridge */
1376 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1377
1378 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1379 }
1380
1381 if (CountBits(rb) > 2) {
1382 /* On junctions we check whether neighbouring tiles also have catenary, and possibly
1383 * do not draw catenary towards those neighbours, which do not have catenary. */
1384 RoadBits rb_new = ROAD_NONE;
1385 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
1386 if (rb & DiagDirToRoadBits(dir)) {
1387 TileIndex neighbour = TileAddByDiagDir(ti->tile, dir);
1388 if (MayHaveRoad(neighbour)) {
1389 RoadType rt_road = GetRoadTypeRoad(neighbour);
1390 RoadType rt_tram = GetRoadTypeTram(neighbour);
1391
1392 if ((rt_road != INVALID_ROADTYPE && HasRoadCatenary(rt_road)) ||
1393 (rt_tram != INVALID_ROADTYPE && HasRoadCatenary(rt_tram))) {
1394 rb_new |= DiagDirToRoadBits(dir);
1395 }
1396 }
1397 }
1398 }
1399 if (CountBits(rb_new) >= 2) rb = rb_new;
1400 }
1401
1402 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1405
1406 if (front != 0 || back != 0) {
1407 if (front != 0) front += GetRoadSpriteOffset(ti->tileh, rb);
1408 if (back != 0) back += GetRoadSpriteOffset(ti->tileh, rb);
1409 } else if (ti->tileh != SLOPE_FLAT) {
1410 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1411 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1412 } else {
1413 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb];
1414 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb];
1415 }
1416
1417 /* Catenary uses 1st company colour to help identify owner.
1418 * For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
1419 Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
1420 PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(COLOUR_GREY) : GetCompanyPalette(owner));
1421 int z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
1422 if (back != 0) {
1423 /* The "back" sprite contains the west, north and east pillars.
1424 * We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
1425 * 3/8 is chosen so that sprites can somewhat graphically extend into the tile. */
1426 static const int INF = 1000;
1427 static const SubSprite west = { -INF, -INF, -12, INF };
1428 static const SubSprite north = { -12, -INF, 12, INF };
1429 static const SubSprite east = { 12, -INF, INF, INF };
1430 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 16, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 15, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_W), &west);
1431 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_N), &north);
1432 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 16, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 15, GetSlopePixelZInCorner(ti->tileh, CORNER_E), &east);
1433 }
1434 if (front != 0) {
1435 /* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
1436 AddSortableSpriteToDraw(front, pal, ti->x, ti->y, 16, 16, z_wires + 1, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, z_wires);
1437 }
1438}
1439
1445{
1446 RoadBits road = ROAD_NONE;
1447 RoadBits tram = ROAD_NONE;
1448
1449 if (IsTileType(ti->tile, MP_ROAD)) {
1450 if (IsNormalRoad(ti->tile)) {
1451 road = GetRoadBits(ti->tile, RTT_ROAD);
1452 tram = GetRoadBits(ti->tile, RTT_TRAM);
1453 } else if (IsLevelCrossing(ti->tile)) {
1454 tram = road = (GetCrossingRailAxis(ti->tile) == AXIS_Y ? ROAD_X : ROAD_Y);
1455 }
1456 } else if (IsTileType(ti->tile, MP_STATION)) {
1457 if (IsAnyRoadStop(ti->tile)) {
1458 if (IsDriveThroughStopTile(ti->tile)) {
1459 Axis axis = GetDriveThroughStopAxis(ti->tile);
1460 tram = road = (axis == AXIS_X ? ROAD_X : ROAD_Y);
1461 } else {
1462 tram = road = DiagDirToRoadBits(GetBayRoadStopDir(ti->tile));
1463 }
1464 }
1465 } else {
1466 /* No road here, no catenary to draw */
1467 return;
1468 }
1469
1470 RoadType rt = GetRoadTypeRoad(ti->tile);
1471 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1472 DrawRoadTypeCatenary(ti, rt, road);
1473 }
1474
1475 rt = GetRoadTypeTram(ti->tile);
1476 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1477 DrawRoadTypeCatenary(ti, rt, tram);
1478 }
1479}
1480
1490static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
1491{
1492 int x = ti->x | dx;
1493 int y = ti->y | dy;
1494 int z = ti->z;
1495 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1496 AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z, transparent);
1497}
1498
1508void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
1509{
1510 if (draw_underlay) {
1511 /* Road underlay takes precedence over tram */
1512 if (road_rti != nullptr) {
1513 if (road_rti->UsesOverlay()) {
1514 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_GROUND);
1515 DrawGroundSprite(ground + road_offset, pal);
1516 }
1517 } else {
1518 if (tram_rti->UsesOverlay()) {
1519 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_GROUND);
1520 DrawGroundSprite(ground + tram_offset, pal);
1521 } else {
1522 DrawGroundSprite(SPR_TRAMWAY_TRAM + tram_offset, pal);
1523 }
1524 }
1525 }
1526
1527 /* Draw road overlay */
1528 if (road_rti != nullptr) {
1529 if (road_rti->UsesOverlay()) {
1530 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_OVERLAY);
1531 if (ground != 0) DrawGroundSprite(ground + road_offset, pal);
1532 }
1533 }
1534
1535 /* Draw tram overlay */
1536 if (tram_rti != nullptr) {
1537 if (tram_rti->UsesOverlay()) {
1538 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_OVERLAY);
1539 if (ground != 0) DrawGroundSprite(ground + tram_offset, pal);
1540 } else if (road_rti != nullptr) {
1541 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + tram_offset, pal);
1542 }
1543 }
1544}
1545
1555static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
1556{
1557 /* Draw bare ground sprite if no road or road uses overlay system. */
1558 if (rti == nullptr || rti->UsesOverlay()) {
1559 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1560 return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
1561 }
1562
1563 switch (roadside) {
1565 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1566 case ROADSIDE_GRASS:
1567 case ROADSIDE_GRASS_ROAD_WORKS: return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1568 default: break; // Paved
1569 }
1570 }
1571
1572 /* Draw original road base sprite */
1573 SpriteID image = SPR_ROAD_Y + offset;
1574 if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
1575 image += 19;
1576 } else {
1577 switch (roadside) {
1578 case ROADSIDE_BARREN: *pal = PALETTE_TO_BARE_LAND; break;
1579 case ROADSIDE_GRASS: break;
1580 case ROADSIDE_GRASS_ROAD_WORKS: break;
1581 default: image -= 19; break; // Paved
1582 }
1583 }
1584
1585 return image;
1586}
1587
1598void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
1599{
1600 /* Determine sprite offsets */
1601 uint road_offset = GetRoadSpriteOffset(ti->tileh, road);
1602 uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
1603
1604 /* Draw baseset underlay */
1605 PaletteID pal = PAL_NONE;
1606 SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, snow_or_desert, &pal);
1607 DrawGroundSprite(image, pal);
1608
1609 DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
1610}
1611
1616static void DrawRoadBits(TileInfo *ti)
1617{
1618 RoadBits road = GetRoadBits(ti->tile, RTT_ROAD);
1619 RoadBits tram = GetRoadBits(ti->tile, RTT_TRAM);
1620
1621 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1622 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1623 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1624 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1625
1626 if (ti->tileh != SLOPE_FLAT) {
1627 DrawFoundation(ti, GetRoadFoundation(ti->tileh, road | tram));
1628 /* DrawFoundation() modifies ti. */
1629 }
1630
1631 DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnowOrDesert(ti->tile));
1632
1633 /* Draw one way */
1634 if (road_rti != nullptr) {
1636 if (drd != DRD_NONE) {
1637 SpriteID oneway = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ONEWAY);
1638
1639 if (oneway == 0) oneway = SPR_ONEWAY_BASE;
1640
1641 if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) {
1642 oneway += ONEWAY_SLOPE_N_OFFSET;
1643 } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) {
1644 oneway += ONEWAY_SLOPE_S_OFFSET;
1645 }
1646
1647 DrawGroundSpriteAt(oneway + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1648 }
1649 }
1650
1651 if (HasRoadWorks(ti->tile)) {
1652 /* Road works */
1653 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1654 return;
1655 }
1656
1657 /* Draw road, tram catenary */
1658 DrawRoadCatenary(ti);
1659
1660 /* Return if full detail is disabled, or we are zoomed fully out. */
1661 if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZoomLevel::Detail) return;
1662
1663 /* Do not draw details (street lights, trees) under low bridge */
1664 Roadside roadside = GetRoadside(ti->tile);
1665 if (IsBridgeAbove(ti->tile) && (roadside == ROADSIDE_TREES || roadside == ROADSIDE_STREET_LIGHTS)) {
1666 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1667 int minz = GetTileMaxZ(ti->tile) + 2;
1668
1669 if (roadside == ROADSIDE_TREES) minz++;
1670
1671 if (height < minz) return;
1672 }
1673
1674 /* If there are no road bits, return, as there is nothing left to do */
1675 if (HasAtMostOneBit(road)) return;
1676
1677 /* Do not draw details when invisible. */
1678 if (roadside == ROADSIDE_TREES && IsInvisibilitySet(TO_TREES)) return;
1679 if (roadside == ROADSIDE_STREET_LIGHTS && IsInvisibilitySet(TO_HOUSES)) return;
1680
1681 /* Check whether details should be transparent. */
1682 bool is_transparent = false;
1683 if (roadside == ROADSIDE_TREES && IsTransparencySet(TO_TREES)) {
1684 is_transparent = true;
1685 }
1687 is_transparent = true;
1688 }
1689
1690 /* Draw extra details. */
1691 for (const DrawRoadTileStruct *drts = _road_display_table[roadside][road | tram]; drts->image != 0; drts++) {
1692 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
1693 }
1694}
1695
1697static void DrawTile_Road(TileInfo *ti)
1698{
1699 switch (GetRoadTileType(ti->tile)) {
1700 case ROAD_TILE_NORMAL:
1701 DrawRoadBits(ti);
1702 break;
1703
1704 case ROAD_TILE_CROSSING: {
1706
1707 Axis axis = GetCrossingRailAxis(ti->tile);
1708
1709 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1710
1711 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1712 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1713 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1714 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1715
1716 PaletteID pal = PAL_NONE;
1717
1718 /* Draw base ground */
1719 if (rti->UsesOverlay()) {
1720 SpriteID image = SPR_ROAD_Y + axis;
1721
1722 Roadside roadside = GetRoadside(ti->tile);
1723 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1724 image += 19;
1725 } else {
1726 switch (roadside) {
1727 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
1728 case ROADSIDE_GRASS: break;
1729 default: image -= 19; break; // Paved
1730 }
1731 }
1732
1733 DrawGroundSprite(image, pal);
1734 } else {
1735 SpriteID image = rti->base_sprites.crossing + axis;
1736 if (IsCrossingBarred(ti->tile)) image += 2;
1737
1738 Roadside roadside = GetRoadside(ti->tile);
1739 if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
1740 image += 8;
1741 } else {
1742 switch (roadside) {
1743 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
1744 case ROADSIDE_GRASS: break;
1745 default: image += 4; break; // Paved
1746 }
1747 }
1748
1749 DrawGroundSprite(image, pal);
1750 }
1751
1752 DrawRoadOverlays(ti, pal, road_rti, tram_rti, axis, axis);
1753
1754 /* Draw rail/PBS overlay */
1755 bool draw_pbs = _game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile);
1756 if (rti->UsesOverlay()) {
1757 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1758 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1759 DrawGroundSprite(rail, pal);
1760
1761 const Axis road_axis = GetCrossingRoadAxis(ti->tile);
1762 const DiagDirection dir1 = AxisToDiagDir(road_axis);
1763 const DiagDirection dir2 = ReverseDiagDir(dir1);
1764 DiagDirections adjacent_diagdirs{};
1765 for (DiagDirection dir : { dir1, dir2 }) {
1766 const TileIndex t = TileAddByDiagDir(ti->tile, dir);
1767 if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
1768 adjacent_diagdirs.Set(dir);
1769 }
1770 }
1771
1772 switch (adjacent_diagdirs.base()) {
1773 case DiagDirections{}.base():
1774 DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1775 break;
1776
1778 DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE);
1779 break;
1780
1782 DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE);
1783 break;
1784
1786 DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE);
1787 break;
1788
1790 DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE);
1791 break;
1792
1793 default:
1794 /* Show no sprites */
1795 break;
1796 }
1797 } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) {
1798 /* Add another rail overlay, unless there is only the base road sprite. */
1799 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1801 DrawGroundSprite(rail, pal);
1802 }
1803
1804 /* Draw road, tram catenary */
1805 DrawRoadCatenary(ti);
1806
1807 /* Draw rail catenary */
1809
1810 break;
1811 }
1812
1813 default:
1814 case ROAD_TILE_DEPOT: {
1816
1818
1819 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1820 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1821 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt == INVALID_ROADTYPE ? tram_rt : road_rt);
1822
1823 int relocation = GetCustomRoadSprite(rti, ti->tile, ROTSG_DEPOT);
1824 bool default_gfx = relocation == 0;
1825 if (default_gfx) {
1826 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1827 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && road_rt == INVALID_ROADTYPE && !rti->UsesOverlay()) {
1828 /* Sprites with track only work for default tram */
1829 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1830 default_gfx = false;
1831 } else {
1832 /* Sprites without track are always better, if provided */
1833 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1834 }
1835 }
1836 } else {
1837 relocation -= SPR_ROAD_DEPOT;
1838 }
1839
1841 const DrawTileSprites *dts = &_road_depot[dir];
1842 DrawGroundSprite(dts->ground.sprite, PAL_NONE);
1843
1844 if (default_gfx) {
1846 if (rti->UsesOverlay()) {
1847 SpriteID ground = GetCustomRoadSprite(rti, ti->tile, ROTSG_OVERLAY);
1848 if (ground != 0) DrawGroundSprite(ground + offset, PAL_NONE);
1849 } else if (road_rt == INVALID_ROADTYPE) {
1850 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE);
1851 }
1852 }
1853
1854 DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, palette);
1855 break;
1856 }
1857 }
1858 DrawBridgeMiddle(ti);
1859}
1860
1868void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
1869{
1871
1872 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1873 int relocation = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_DEPOT);
1874 bool default_gfx = relocation == 0;
1875 if (default_gfx) {
1876 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1877 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && RoadTypeIsTram(rt) && !rti->UsesOverlay()) {
1878 /* Sprites with track only work for default tram */
1879 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1880 default_gfx = false;
1881 } else {
1882 /* Sprites without track are always better, if provided */
1883 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1884 }
1885 }
1886 } else {
1887 relocation -= SPR_ROAD_DEPOT;
1888 }
1889
1890 const DrawTileSprites *dts = &_road_depot[dir];
1891 DrawSprite(dts->ground.sprite, PAL_NONE, x, y);
1892
1893 if (default_gfx) {
1895 if (rti->UsesOverlay()) {
1897 if (ground != 0) DrawSprite(ground + offset, PAL_NONE, x, y);
1898 } else if (RoadTypeIsTram(rt)) {
1899 DrawSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE, x, y);
1900 }
1901 }
1902
1903 DrawRailTileSeqInGUI(x, y, dts, relocation, 0, palette);
1904}
1905
1912{
1913 assert(!invalidate || _generating_world);
1914
1915 for (const auto t : Map::Iterate()) {
1916 if (IsTileType(t, MP_ROAD) && !IsRoadDepot(t) && !HasTownOwnedRoad(t)) {
1917 TownID tid = TownID::Invalid();
1918 if (!invalidate) {
1919 const Town *town = CalcClosestTownFromTile(t);
1920 if (town != nullptr) tid = town->index;
1921 }
1922 SetTownIndex(t, tid);
1923 }
1924 }
1925}
1926
1927static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, bool)
1928{
1929
1930 if (IsNormalRoad(tile)) {
1931 auto [tileh, z] = GetTilePixelSlope(tile);
1932 if (tileh == SLOPE_FLAT) return z;
1933
1935 z += ApplyPixelFoundationToSlope(f, tileh);
1936 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1937 } else {
1938 return GetTileMaxPixelZ(tile);
1939 }
1940}
1941
1942static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
1943{
1944 if (IsNormalRoad(tile)) {
1945 return GetRoadFoundation(tileh, GetAllRoadBits(tile));
1946 } else {
1947 return FlatteningFoundation(tileh);
1948 }
1949}
1950
1951static const Roadside _town_road_types[][2] = {
1957};
1958
1959static_assert(lengthof(_town_road_types) == NUM_HOUSE_ZONES);
1960
1961static const Roadside _town_road_types_2[][2] = {
1967};
1968
1969static_assert(lengthof(_town_road_types_2) == NUM_HOUSE_ZONES);
1970
1971
1972static void TileLoop_Road(TileIndex tile)
1973{
1975 case LandscapeType::Arctic: {
1976 /* 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. */
1977 int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileZ(tile);
1978 if (IsOnSnowOrDesert(tile) != (tile_z > GetSnowLine())) {
1979 ToggleSnowOrDesert(tile);
1980 MarkTileDirtyByTile(tile);
1981 }
1982 break;
1983 }
1984
1985 case LandscapeType::Tropic:
1986 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnSnowOrDesert(tile)) {
1987 ToggleSnowOrDesert(tile);
1988 MarkTileDirtyByTile(tile);
1989 }
1990 break;
1991
1992 default:
1993 break;
1994 }
1995
1996 if (IsRoadDepot(tile)) return;
1997
1998 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
1999 if (!HasRoadWorks(tile)) {
2000 HouseZone grp = HouseZone::TownEdge;
2001
2002 if (t != nullptr) {
2003 grp = GetTownRadiusGroup(t, tile);
2004
2005 /* Show an animation to indicate road work */
2006 if (t->road_build_months != 0 &&
2007 (DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) &&
2008 IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) {
2009 if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
2010 StartRoadWorks(tile);
2011
2012 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
2014 TileX(tile) * TILE_SIZE + 7,
2015 TileY(tile) * TILE_SIZE + 7,
2016 0,
2017 EV_BULLDOZER);
2018 MarkTileDirtyByTile(tile);
2019 return;
2020 }
2021 }
2022 }
2023
2024 {
2025 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2026 const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[to_underlying(grp)] : _town_road_types[to_underlying(grp)];
2027 Roadside cur_rs = GetRoadside(tile);
2028
2029 /* We have our desired type, do nothing */
2030 if (cur_rs == new_rs[0]) return;
2031
2032 /* We have the pre-type of the desired type, switch to the desired type */
2033 if (cur_rs == new_rs[1]) {
2034 cur_rs = new_rs[0];
2035 /* We have barren land, install the pre-type */
2036 } else if (cur_rs == ROADSIDE_BARREN) {
2037 cur_rs = new_rs[1];
2038 /* We're totally off limits, remove any installation and make barren land */
2039 } else {
2040 cur_rs = ROADSIDE_BARREN;
2041 }
2042 SetRoadside(tile, cur_rs);
2043 MarkTileDirtyByTile(tile);
2044 }
2045 } else if (IncreaseRoadWorksCounter(tile)) {
2046 TerminateRoadWorks(tile);
2047
2049 /* Generate a nicer town surface */
2050 const RoadBits old_rb = GetAnyRoadBits(tile, RTT_ROAD);
2051 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2052
2053 if (old_rb != new_rb) {
2054 RemoveRoad(tile, {DoCommandFlag::Execute, DoCommandFlag::Auto, DoCommandFlag::NoWater}, (old_rb ^ new_rb), RTT_ROAD, true);
2055
2056 /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */
2057 if (new_rb == 0) {
2058 MarkTileDirtyByTile(tile);
2059 return;
2060 }
2061 }
2062 }
2063
2064 /* Possibly change road type */
2065 if (GetRoadOwner(tile, RTT_ROAD) == OWNER_TOWN) {
2067 if (rt != GetRoadTypeRoad(tile)) {
2068 SetRoadType(tile, RTT_ROAD, rt);
2069 }
2070 }
2071
2072 MarkTileDirtyByTile(tile);
2073 }
2074}
2075
2076static bool ClickTile_Road(TileIndex tile)
2077{
2078 if (!IsRoadDepot(tile)) return false;
2079
2081 return true;
2082}
2083
2084/* Converts RoadBits to TrackBits */
2085static const TrackBits _road_trackbits[16] = {
2086 TRACK_BIT_NONE, // ROAD_NONE
2087 TRACK_BIT_NONE, // ROAD_NW
2088 TRACK_BIT_NONE, // ROAD_SW
2089 TRACK_BIT_LEFT, // ROAD_W
2090 TRACK_BIT_NONE, // ROAD_SE
2091 TRACK_BIT_Y, // ROAD_Y
2092 TRACK_BIT_LOWER, // ROAD_S
2093 TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | ROAD_SW
2094 TRACK_BIT_NONE, // ROAD_NE
2095 TRACK_BIT_UPPER, // ROAD_N
2096 TRACK_BIT_X, // ROAD_X
2097 TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | ROAD_NW
2098 TRACK_BIT_RIGHT, // ROAD_E
2099 TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | ROAD_NE
2100 TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | ROAD_SE
2101 TRACK_BIT_ALL, // ROAD_ALL
2102};
2103
2104static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
2105{
2106 TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
2107 TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
2108 switch (mode) {
2109 case TRANSPORT_RAIL:
2110 if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
2111 break;
2112
2113 case TRANSPORT_ROAD: {
2114 RoadTramType rtt = (RoadTramType)sub_mode;
2115 if (!HasTileRoadType(tile, rtt)) break;
2116 switch (GetRoadTileType(tile)) {
2117 case ROAD_TILE_NORMAL: {
2118 const uint drd_to_multiplier[DRD_END] = { 0x101, 0x100, 0x1, 0x0 };
2119 RoadBits bits = GetRoadBits(tile, rtt);
2120
2121 /* no roadbit at this side of tile, return 0 */
2122 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break;
2123
2124 uint multiplier = drd_to_multiplier[(rtt == RTT_TRAM) ? DRD_NONE : GetDisallowedRoadDirections(tile)];
2125 if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier);
2126 break;
2127 }
2128
2129 case ROAD_TILE_CROSSING: {
2130 Axis axis = GetCrossingRoadAxis(tile);
2131
2132 if (side != INVALID_DIAGDIR && axis != DiagDirToAxis(side)) break;
2133
2134 trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis));
2135 if (IsCrossingBarred(tile)) {
2136 red_signals = trackdirbits;
2137 if (TrainOnCrossing(tile)) break;
2138
2139 auto mask_red_signal_bits_if_crossing_barred = [&](TileIndex t, TrackdirBits mask) {
2140 if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
2141 };
2142 /* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
2143 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE);
2144 /* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
2145 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW);
2146 }
2147 break;
2148 }
2149
2150 default:
2151 case ROAD_TILE_DEPOT: {
2153
2154 if (side != INVALID_DIAGDIR && side != dir) break;
2155
2157 break;
2158 }
2159 }
2160 break;
2161 }
2162
2163 default: break;
2164 }
2165 return CombineTrackStatus(trackdirbits, red_signals);
2166}
2167
2168static const StringID _road_tile_strings[] = {
2169 STR_LAI_ROAD_DESCRIPTION_ROAD,
2170 STR_LAI_ROAD_DESCRIPTION_ROAD,
2171 STR_LAI_ROAD_DESCRIPTION_ROAD,
2172 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2173 STR_LAI_ROAD_DESCRIPTION_ROAD,
2174 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2175 STR_LAI_ROAD_DESCRIPTION_ROAD,
2176 STR_LAI_ROAD_DESCRIPTION_ROAD,
2177};
2178
2179static void GetTileDesc_Road(TileIndex tile, TileDesc &td)
2180{
2181 Owner rail_owner = INVALID_OWNER;
2182 Owner road_owner = INVALID_OWNER;
2183 Owner tram_owner = INVALID_OWNER;
2184
2185 RoadType road_rt = GetRoadTypeRoad(tile);
2186 RoadType tram_rt = GetRoadTypeTram(tile);
2187 if (road_rt != INVALID_ROADTYPE) {
2188 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
2189 td.roadtype = rti->strings.name;
2190 td.road_speed = rti->max_speed / 2;
2191 road_owner = GetRoadOwner(tile, RTT_ROAD);
2192 }
2193 if (tram_rt != INVALID_ROADTYPE) {
2194 const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
2195 td.tramtype = rti->strings.name;
2196 td.tram_speed = rti->max_speed / 2;
2197 tram_owner = GetRoadOwner(tile, RTT_TRAM);
2198 }
2199
2200 switch (GetRoadTileType(tile)) {
2201 case ROAD_TILE_CROSSING: {
2202 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING;
2203 rail_owner = GetTileOwner(tile);
2204
2205 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2206 td.railtype = rti->strings.name;
2207 td.rail_speed = rti->max_speed;
2208
2209 break;
2210 }
2211
2212 case ROAD_TILE_DEPOT:
2213 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
2214 td.build_date = Depot::GetByTile(tile)->build_date;
2215 break;
2216
2217 default: {
2218 td.str = (road_rt != INVALID_ROADTYPE ? _road_tile_strings[GetRoadside(tile)] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
2219 break;
2220 }
2221 }
2222
2223 /* Now we have to discover, if the tile has only one owner or many:
2224 * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
2225 * - Compare the found owner with the other owners, and test if they differ.
2226 * Note: If road exists it will be the first_owner.
2227 */
2228 Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
2229 bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
2230
2231 if (mixed_owners) {
2232 /* Multiple owners */
2233 td.owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_RAIL_OWNER);
2234 td.owner[0] = rail_owner;
2235 td.owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_ROAD_OWNER);
2236 td.owner[1] = road_owner;
2237 td.owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_TRAM_OWNER);
2238 td.owner[2] = tram_owner;
2239 } else {
2240 /* One to rule them all */
2241 td.owner[0] = first_owner;
2242 }
2243}
2244
2252
2253static VehicleEnterTileStates VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
2254{
2255 switch (GetRoadTileType(tile)) {
2256 case ROAD_TILE_DEPOT: {
2257 if (v->type != VEH_ROAD) break;
2258
2260 if (rv->frame == RVC_DEPOT_STOP_FRAME &&
2262 rv->state = RVSB_IN_DEPOT;
2264 rv->direction = ReverseDir(rv->direction);
2265 if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
2266 rv->tile = tile;
2267
2270 }
2271 break;
2272 }
2273
2274 default: break;
2275 }
2276 return {};
2277}
2278
2279
2280static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2281{
2282 if (IsRoadDepot(tile)) {
2283 if (GetTileOwner(tile) == old_owner) {
2284 if (new_owner == INVALID_OWNER) {
2286 } else {
2287 /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2288 RoadType rt = GetRoadTypeRoad(tile);
2289 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
2290 Company::Get(old_owner)->infrastructure.road[rt] -= 2;
2291 Company::Get(new_owner)->infrastructure.road[rt] += 2;
2292
2293 SetTileOwner(tile, new_owner);
2294 for (RoadTramType rtt : _roadtramtypes) {
2295 if (GetRoadOwner(tile, rtt) == old_owner) {
2296 SetRoadOwner(tile, rtt, new_owner);
2297 }
2298 }
2299 }
2300 }
2301 return;
2302 }
2303
2304 for (RoadTramType rtt : _roadtramtypes) {
2305 /* Update all roadtypes, no matter if they are present */
2306 if (GetRoadOwner(tile, rtt) == old_owner) {
2307 RoadType rt = GetRoadType(tile, rtt);
2308 if (rt != INVALID_ROADTYPE) {
2309 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2310 uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt));
2311 Company::Get(old_owner)->infrastructure.road[rt] -= num_bits;
2312 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits;
2313 }
2314
2315 SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
2316 }
2317 }
2318
2319 if (IsLevelCrossing(tile)) {
2320 if (GetTileOwner(tile) == old_owner) {
2321 if (new_owner == INVALID_OWNER) {
2323 } else {
2324 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2325 Company::Get(old_owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
2326 Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
2327
2328 SetTileOwner(tile, new_owner);
2329 }
2330 }
2331 }
2332}
2333
2334static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
2335{
2337 switch (GetRoadTileType(tile)) {
2338 case ROAD_TILE_CROSSING:
2339 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]);
2340 break;
2341
2342 case ROAD_TILE_DEPOT:
2343 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2344 break;
2345
2346 case ROAD_TILE_NORMAL: {
2347 RoadBits bits = GetAllRoadBits(tile);
2348 RoadBits bits_copy = bits;
2349 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2350 if (CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE).Succeeded()) {
2351 /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
2352 if (bits == bits_copy) {
2353 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2354
2355 /* Get the slope on top of the foundation */
2356 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), tileh_old);
2357 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), tileh_new);
2358
2359 /* The surface slope must not be changed */
2360 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2361 }
2362 }
2363 break;
2364 }
2365
2366 default: NOT_REACHED();
2367 }
2368 }
2369
2370 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
2371}
2372
2379static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
2380{
2381 return (owner == OWNER_NONE || (owner == OWNER_TOWN && rtt == RTT_ROAD));
2382}
2383
2392static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
2393{
2394 /* Scenario editor, maybe? Don't touch the owners when converting roadtypes... */
2395 if (_current_company >= MAX_COMPANIES) return;
2396
2397 /* We can't get a company from invalid owners but we can get ownership of roads without an owner */
2398 if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
2399
2400 Company *c;
2401
2402 switch (owner.base()) {
2403 case OWNER_NONE.base():
2404 SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company);
2406 break;
2407
2408 default:
2409 c = Company::Get(owner);
2410 c->infrastructure.road[from_type] -= num_pieces;
2411 c->infrastructure.road[to_type] += num_pieces;
2413 break;
2414 }
2415}
2416
2427CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal)
2428{
2429 TileIndex area_end = tile;
2430
2431 if (!ValParamRoadType(to_type)) return CMD_ERROR;
2432 if (area_start >= Map::Size()) return CMD_ERROR;
2433
2434 RoadVehicleList affected_rvs;
2435 RoadTramType rtt = GetRoadTramType(to_type);
2436
2438 CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert.
2439 bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633)
2440
2441 std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal);
2442 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
2443 /* Is road present on tile? */
2444 if (!MayHaveRoad(tile)) continue;
2445
2446 /* Converting to the same subtype? */
2447 RoadType from_type = GetRoadType(tile, rtt);
2448 if (from_type == INVALID_ROADTYPE || from_type == to_type) continue;
2449
2450 /* Check if there is any infrastructure on tile */
2451 TileType tt = GetTileType(tile);
2452 switch (tt) {
2453 case MP_STATION:
2454 if (!IsAnyRoadStop(tile)) continue;
2455 break;
2456 case MP_ROAD:
2457 if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
2458 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD);
2459 continue;
2460 }
2461 break;
2462 case MP_TUNNELBRIDGE:
2463 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) continue;
2464 break;
2465 default: continue;
2466 }
2467
2468 /* Trying to convert other's road */
2469 Owner owner = GetRoadOwner(tile, rtt);
2470 if (!CanConvertUnownedRoadType(owner, rtt)) {
2471 CommandCost ret = CheckOwnership(owner, tile);
2472 if (ret.Failed()) {
2473 error = std::move(ret);
2474 continue;
2475 }
2476 }
2477
2478 /* Base the ability to replace town roads and bridges on the town's
2479 * acceptance of destructive actions. */
2480 if (owner == OWNER_TOWN) {
2483 if (ret.Failed()) {
2484 error = std::move(ret);
2485 continue;
2486 }
2487 }
2488
2489 /* Vehicle on the tile when not converting normal <-> powered
2490 * Tunnels and bridges have special check later */
2491 if (tt != MP_TUNNELBRIDGE) {
2492 if (!HasPowerOnRoad(from_type, to_type)) {
2494 if (ret.Failed()) {
2495 error = std::move(ret);
2496 continue;
2497 }
2498
2499 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2500 error.MakeError(STR_ERROR_OWNED_BY);
2501 if (IsLocalCompany()) {
2502 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2503 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2504 }
2505 continue;
2506 }
2507 }
2508
2509 uint num_pieces = CountBits(GetAnyRoadBits(tile, rtt));
2510 if (tt == MP_STATION && IsBayRoadStopTile(tile)) {
2511 num_pieces *= ROAD_STOP_TRACKBIT_FACTOR;
2512 } else if (tt == MP_ROAD && IsRoadDepot(tile)) {
2513 num_pieces *= ROAD_DEPOT_TRACKBIT_FACTOR;
2514 }
2515
2516 found_convertible_road = true;
2517 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2518
2519 if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
2520 /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */
2521 if (owner == _current_company) {
2522 ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
2523 }
2524
2525 /* Perform the conversion */
2526 SetRoadType(tile, rtt, to_type);
2527 MarkTileDirtyByTile(tile);
2528
2529 /* update power of train on this tile */
2530 for (Vehicle *v : VehiclesOnTile(tile)) {
2531 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2532 }
2533
2534 if (IsRoadDepotTile(tile)) {
2535 /* Update build vehicle window related to this depot */
2538 }
2539 }
2540 } else {
2541 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
2542
2543 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
2544 * it would cause assert because of different test and exec runs */
2545 if (endtile < tile) {
2546 if (diagonal) {
2547 if (DiagonalTileArea(area_start, area_end).Contains(endtile)) continue;
2548 } else {
2549 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
2550 }
2551 }
2552
2553 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
2554 if (!HasPowerOnRoad(from_type, to_type)) {
2555 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
2556 if (ret.Failed()) {
2557 error = std::move(ret);
2558 continue;
2559 }
2560
2561 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2562 error.MakeError(STR_ERROR_OWNED_BY);
2563 if (IsLocalCompany()) {
2564 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2565 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2566 }
2567 continue;
2568 }
2569 }
2570
2571 /* There are 2 pieces on *every* tile of the bridge or tunnel */
2572 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * 2;
2573 found_convertible_road = true;
2574 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2575
2576 if (flags.Test(DoCommandFlag::Execute)) {
2577 /* Update the company infrastructure counters. */
2578 if (owner == _current_company) {
2579 /* Each piece should be counted TUNNELBRIDGE_TRACKBIT_FACTOR times
2580 * for the infrastructure counters (cause of #8297). */
2581 ConvertRoadTypeOwner(tile, num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR, owner, from_type, to_type);
2582 SetTunnelBridgeOwner(tile, endtile, _current_company);
2583 }
2584
2585 /* Perform the conversion */
2586 SetRoadType(tile, rtt, to_type);
2587 SetRoadType(endtile, rtt, to_type);
2588
2589 for (Vehicle *v : VehiclesOnTile(tile)) {
2590 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2591 }
2592 for (Vehicle *v : VehiclesOnTile(endtile)) {
2593 if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
2594 }
2595
2596 if (IsBridge(tile)) {
2597 MarkBridgeDirty(tile);
2598 } else {
2599 MarkTileDirtyByTile(tile);
2600 MarkTileDirtyByTile(endtile);
2601 }
2602 }
2603 }
2604 }
2605
2606 if (flags.Test(DoCommandFlag::Execute)) {
2607 /* Roadtype changed, update roadvehicles as when entering different track */
2608 for (RoadVehicle *v : affected_rvs) {
2609 v->CargoChanged();
2610 }
2611 }
2612
2613 return found_convertible_road ? cost : error;
2614}
2615
2616
2618extern const TileTypeProcs _tile_type_road_procs = {
2619 DrawTile_Road, // draw_tile_proc
2620 GetSlopePixelZ_Road, // get_slope_z_proc
2621 ClearTile_Road, // clear_tile_proc
2622 nullptr, // add_accepted_cargo_proc
2623 GetTileDesc_Road, // get_tile_desc_proc
2624 GetTileTrackStatus_Road, // get_tile_track_status_proc
2625 ClickTile_Road, // click_tile_proc
2626 nullptr, // animate_tile_proc
2627 TileLoop_Road, // tile_loop_proc
2628 ChangeTileOwner_Road, // change_tile_owner_proc
2629 nullptr, // add_produced_cargo_proc
2630 VehicleEnter_Road, // vehicle_enter_tile_proc
2631 GetFoundation_Road, // get_foundation_proc
2632 TerraformTile_Road, // terraform_tile_proc
2633};
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)
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:118
SpriteID single_x
single piece of rail in X direction, without ground
Definition rail.h:128
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:222
struct RailTypeInfo::@20 base_sprites
Struct containing the main sprites.
SpriteID crossing
level crossing, rail in X direction
Definition rail.h:135
SpriteID single_y
single piece of rail in Y direction, without ground
Definition rail.h:129
StringID name
Name of this rail type.
Definition rail.h:167
struct RailTypeInfo::@23 strings
Strings associated with the rail type.
RoadTypeLabel label
Unique 32 bit road type identifier.
Definition road.h:138
RoadTypeLabelList alternate_labels
Road type labels this type provides in addition to the main label.
Definition road.h:143
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:113
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:168
CursorID autoroad
Cursor for autorail tool.
Definition road.h:87
TimerGameCalendar::Date introduction_date
Introduction date.
Definition road.h:157
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
Definition road.h:173
RoadTypeFlags flags
Bit mask of road type flags.
Definition road.h:118
CursorID depot
Cursor for building a depot.
Definition road.h:88
CursorID road_nwse
Cursor for building rail in Y direction.
Definition road.h:86
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:133
struct RoadTypeInfo::@24 gui_sprites
struct containing the sprites for the road GUI.
StringID name
Name of this rail type.
Definition road.h:94
struct RoadTypeInfo::@25 cursor
Cursors associated with the road type.
SpriteID build_y_road
button for building single rail in Y direction
Definition road.h:77
CursorID tunnel
Cursor for building a tunnel.
Definition road.h:89
SpriteID auto_road
button for the autoroad construction
Definition road.h:78
SpriteID convert_road
button for converting road types
Definition road.h:81
CursorID road_swne
Cursor for building rail in X direction.
Definition road.h:85
SpriteID build_x_road
button for building single rail in X direction
Definition road.h:76
struct RoadTypeInfo::@26 strings
Strings associated with the rail type.
SpriteID build_depot
button for building depots
Definition road.h:79
SpriteID build_tunnel
button for building a tunnel
Definition road.h:80
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.
@ Execute
execute the given command
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
@ NoWater
don't allow building on water
@ Auto
don't allow building on structures
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:567
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:1024
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:126
int GetSlopePixelZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition landscape.h:53
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:159
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:142
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:469
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:610
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:554
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:424
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:414
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:569
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:403
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:73
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:300
@ RTSG_CROSSING
Level crossing overlay images.
Definition rail.h:48
bool RailNoLevelCrossings(RailType rt)
Test if a RailType disallows build of level crossings.
Definition rail.h:351
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
@ RAIL_TILE_NORMAL
Normal rail tile without signals.
Definition rail_map.h:24
void SetTrackReservation(Tile t, TrackBits b)
Sets the reserved track bits of the tile.
Definition rail_map.h:209
TrackBits GetRailReservationTrackBits(Tile t)
Returns the reserved track bits of the tile.
Definition rail_map.h:194
Pseudo random number generator.
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
Clean up unnecessary RoadBits of a planned tile.
Definition road.cpp:47
bool ValParamRoadType(RoadType roadtype)
Validate functions for rail building.
Definition road.cpp:152
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:258
@ 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:279
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:230
Money RoadConvertCost(RoadType from, RoadType to)
Calculates the cost of road conversion.
Definition road.h:297
@ ROTSG_ONEWAY
Optional: One-way indicator images.
Definition road.h:62
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition road.h:52
@ ROTSG_GROUND
Required: Main group of ground images.
Definition road.h:53
@ ROTSG_DEPOT
Optional: Depot images.
Definition road.h:59
@ ROTSG_CURSORS
Optional: Cursor and toolbar icon images.
Definition road.h:51
@ ROTSG_CATENARY_BACK
Optional: Catenary back.
Definition road.h:56
@ ROTSG_CATENARY_FRONT
Optional: Catenary front.
Definition road.h:55
bool RoadNoLevelCrossing(RoadType roadtype)
Test if road disallows level crossings.
Definition road.h:311
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:268
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:605
static const RoadBits _invalid_tileh_slopes_road[2][15]
Invalid RoadBits on slopes.
Definition road_cmd.cpp:198
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:943
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:540
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:175
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:186
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:972
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:320
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
Draws details on/around the road.
const TileTypeProcs _tile_type_road_procs
Tile callback functions for road tiles.
Definition landscape.cpp:51
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:130
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:258
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:660
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:545
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:615
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
@ ROAD_TILE_NORMAL
Normal road.
Definition road_map.h:23
@ ROAD_TILE_DEPOT
Depot (one entrance)
Definition road_map.h:25
@ ROAD_TILE_CROSSING
Level crossing.
Definition road_map.h:24
void MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadType road_rt, RoadType tram_rt, TownID town)
Make a level crossing.
Definition road_map.h:640
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:531
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:584
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:674
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
@ ROADSIDE_GRASS_ROAD_WORKS
Road on grass with road works.
Definition road_map.h:464
@ ROADSIDE_PAVED
Road with paved sidewalks.
Definition road_map.h:460
@ ROADSIDE_STREET_LIGHTS
Road with street lights on paved sidewalks.
Definition road_map.h:461
@ ROADSIDE_BARREN
Road on barren land.
Definition road_map.h:458
@ ROADSIDE_GRASS
Road on grass.
Definition road_map.h:459
@ ROADSIDE_TREES
Road with trees on paved sidewalks.
Definition road_map.h:463
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:40
@ ROAD_SW
South-west part.
Definition road_type.h:43
@ ROAD_ALL
Full 4-way crossing.
Definition road_type.h:54
@ ROAD_NONE
No road-part is build.
Definition road_type.h:41
@ ROAD_NE
North-east part.
Definition road_type.h:45
@ ROAD_SE
South-east part.
Definition road_type.h:44
@ ROAD_Y
Full road along the y-axis (north-west + south-east)
Definition road_type.h:47
@ ROAD_NW
North-west part.
Definition road_type.h:42
@ ROAD_X
Full road along the x-axis (south-west + north-east)
Definition road_type.h:46
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
@ ROADTYPE_BEGIN
Used for iterations.
Definition road_type.h:24
DisallowedRoadDirections
Which directions are disallowed ?
Definition road_type.h:61
@ DRD_NORTHBOUND
All northbound traffic is disallowed.
Definition road_type.h:64
@ DRD_END
Sentinel.
Definition road_type.h:66
@ DRD_BOTH
All directions are disallowed.
Definition road_type.h:65
@ DRD_NONE
None of the directions are disallowed.
Definition road_type.h:62
@ DRD_SOUTHBOUND
All southbound traffic is disallowed.
Definition road_type.h:63
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:101
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:184
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:91
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1611
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:1599
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:103
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
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:43
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:44
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:362
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:287
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:273
Tile description for the 'land area information' tool.
Definition tile_cmd.h:38
uint16_t rail_speed
Speed limit of rail (bridges and track)
Definition tile_cmd.h:51
StringID str
Description of the tile.
Definition tile_cmd.h:39
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:43
std::array< Owner, 4 > owner
Name of the owner(s)
Definition tile_cmd.h:41
uint16_t tram_speed
Speed limit of tram (bridges and track)
Definition tile_cmd.h:55
StringID roadtype
Type of road on the tile.
Definition tile_cmd.h:52
StringID tramtype
Type of tram on the tile.
Definition tile_cmd.h:54
StringID railtype
Type of rail on the tile.
Definition tile_cmd.h:50
uint16_t road_speed
Speed limit of road (bridges and track)
Definition tile_cmd.h:53
std::array< StringID, 4 > owner_type
Type of each owner.
Definition tile_cmd.h:42
Tile information, used while rendering the tile.
Definition tile_cmd.h:29
int z
Height.
Definition tile_cmd.h:34
int x
X position of the tile in unit coordinates.
Definition tile_cmd.h:30
Slope tileh
Slope of the tile.
Definition tile_cmd.h:32
TileIndex tile
Tile index.
Definition tile_cmd.h:33
int y
Y position of the tile in unit coordinates.
Definition tile_cmd.h:31
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:144
std::array< uint32_t, NUM_HOUSE_ZONES > squared_town_zone_radius
UpdateTownRadius updates this given the house count.
Definition town.h:45
Town data structure.
Definition town.h:52
TileIndex xy
town center tile
Definition town.h:53
TownCache cache
Container for all cacheable data.
Definition town.h:55
uint8_t road_build_months
fund road reconstruction in action?
Definition town.h:97
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
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
static const uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
@ 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
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.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
@ ROAD_REMOVE
Removal of a road owned by the town.
Definition town.h:174
@ TUNNELBRIDGE_REMOVE
Removal of a tunnel or bridge owned by the towb.
Definition town.h:175
RoadType GetTownRoadType()
Get the road type that towns should build at this current moment.
Definition town_cmd.cpp:953
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:247
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:1521
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 w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, 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 const uint 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:3265
@ 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,...