OpenTTD Source 20250312-master-gcdcc6b491d
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;
56RoadTypes _roadtypes_hidden_mask;
57
63
68{
69 static_assert(lengthof(_original_roadtypes) <= lengthof(_roadtypes));
70
71 auto insert = std::copy(std::begin(_original_roadtypes), std::end(_original_roadtypes), std::begin(_roadtypes));
72 std::fill(insert, std::end(_roadtypes), RoadTypeInfo{});
73
74 _roadtypes_hidden_mask = ROADTYPES_NONE;
76}
77
78void ResolveRoadTypeGUISprites(RoadTypeInfo *rti)
79{
81 if (cursors_base != 0) {
82 rti->gui_sprites.build_y_road = cursors_base + 0;
83 rti->gui_sprites.build_x_road = cursors_base + 1;
84 rti->gui_sprites.auto_road = cursors_base + 2;
85 rti->gui_sprites.build_depot = cursors_base + 3;
86 rti->gui_sprites.build_tunnel = cursors_base + 4;
87 rti->gui_sprites.convert_road = cursors_base + 5;
88 rti->cursor.road_swne = cursors_base + 6;
89 rti->cursor.road_nwse = cursors_base + 7;
90 rti->cursor.autoroad = cursors_base + 8;
91 rti->cursor.depot = cursors_base + 9;
92 rti->cursor.tunnel = cursors_base + 10;
93 rti->cursor.convert_road = cursors_base + 11;
94 }
95}
96
103static bool CompareRoadTypes(const RoadType &first, const RoadType &second)
104{
105 if (RoadTypeIsRoad(first) == RoadTypeIsRoad(second)) {
107 }
108 return RoadTypeIsTram(first) < RoadTypeIsTram(second);
109}
110
115{
116 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
117 RoadTypeInfo *rti = &_roadtypes[rt];
118 ResolveRoadTypeGUISprites(rti);
119 if (rti->flags.Test(RoadTypeFlag::Hidden)) SetBit(_roadtypes_hidden_mask, rt);
120 }
121
122 _sorted_roadtypes.clear();
123 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
124 if (_roadtypes[rt].label != 0 && !HasBit(_roadtypes_hidden_mask, rt)) {
125 _sorted_roadtypes.push_back(rt);
126 }
127 }
128 std::sort(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), CompareRoadTypes);
129}
130
134RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
135{
136 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
137 RoadTypeInfo *rti = &_roadtypes[rt];
138
139 if (rti->label == 0) {
140 /* Set up new road type */
141 *rti = _original_roadtypes[(rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD];
142 rti->label = label;
143 rti->alternate_labels.clear();
144 rti->flags = {};
146
147 /* Make us compatible with ourself. */
148 rti->powered_roadtypes = (RoadTypes)(1ULL << rt);
149
150 /* We also introduce ourself. */
151 rti->introduces_roadtypes = (RoadTypes)(1ULL << rt);
152
153 /* Default sort order; order of allocation, but with some
154 * offsets so it's easier for NewGRF to pick a spot without
155 * changing the order of other (original) road types.
156 * The << is so you can place other roadtypes in between the
157 * other roadtypes, the 7 is to be able to place something
158 * before the first (default) road type. */
159 rti->sorting_order = rt << 2 | 7;
160
161 /* Set bitmap of road/tram types */
162 if (rtt == RTT_TRAM) {
164 } else {
166 }
167
168 return rt;
169 }
170 }
171
172 return INVALID_ROADTYPE;
173}
174
180{
181 return !RoadVehicle::Iterate().empty();
182}
183
191{
192 if (rt == INVALID_ROADTYPE) return;
193
195 if (c == nullptr) return;
196
197 c->infrastructure.road[rt] += count;
199}
200
203 /* The inverse of the mixable RoadBits on a leveled slope */
204 {
205 ROAD_NONE, // SLOPE_FLAT
206 ROAD_NE | ROAD_SE, // SLOPE_W
207 ROAD_NE | ROAD_NW, // SLOPE_S
208
209 ROAD_NE, // SLOPE_SW
210 ROAD_NW | ROAD_SW, // SLOPE_E
211 ROAD_NONE, // SLOPE_EW
212
213 ROAD_NW, // SLOPE_SE
214 ROAD_NONE, // SLOPE_WSE
215 ROAD_SE | ROAD_SW, // SLOPE_N
216
217 ROAD_SE, // SLOPE_NW
218 ROAD_NONE, // SLOPE_NS
219 ROAD_NONE, // SLOPE_ENW
220
221 ROAD_SW, // SLOPE_NE
222 ROAD_NONE, // SLOPE_SEN
223 ROAD_NONE // SLOPE_NWS
224 },
225 /* The inverse of the allowed straight roads on a slope
226 * (with and without a foundation). */
227 {
228 ROAD_NONE, // SLOPE_FLAT
229 ROAD_NONE, // SLOPE_W Foundation
230 ROAD_NONE, // SLOPE_S Foundation
231
232 ROAD_Y, // SLOPE_SW
233 ROAD_NONE, // SLOPE_E Foundation
234 ROAD_ALL, // SLOPE_EW
235
236 ROAD_X, // SLOPE_SE
237 ROAD_ALL, // SLOPE_WSE
238 ROAD_NONE, // SLOPE_N Foundation
239
240 ROAD_X, // SLOPE_NW
241 ROAD_ALL, // SLOPE_NS
242 ROAD_ALL, // SLOPE_ENW
243
244 ROAD_Y, // SLOPE_NE
245 ROAD_ALL, // SLOPE_SEN
246 ROAD_ALL // SLOPE_NW
247 }
248};
249
250static Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
251
262CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlags flags, bool town_check)
263{
264 if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return CommandCost();
265
266 /* Water can always flood and towns can always remove "normal" road pieces.
267 * Towns are not be allowed to remove non "normal" road pieces, like tram
268 * tracks as that would result in trams that cannot turn. */
270 (rtt == RTT_ROAD && !Company::IsValidID(_current_company))) return CommandCost();
271
272 /* Only do the special processing if the road is owned
273 * by a town */
274 if (owner != OWNER_TOWN) {
275 if (owner == OWNER_NONE) return CommandCost();
276 CommandCost ret = CheckOwnership(owner);
277 return ret;
278 }
279
280 if (!town_check) return CommandCost();
281
283
284 Town *t = ClosestTownFromTile(tile, UINT_MAX);
285 if (t == nullptr) return CommandCost();
286
287 /* check if you're allowed to remove the street owned by a town
288 * removal allowance depends on difficulty setting */
290 if (ret.Failed()) return ret;
291
292 /* Get a bitmask of which neighbouring roads has a tile */
294 RoadBits present = GetAnyRoadBits(tile, rtt);
295 if ((present & ROAD_NE) && (GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt) & ROAD_SW)) n |= ROAD_NE;
296 if ((present & ROAD_SE) && (GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt) & ROAD_NW)) n |= ROAD_SE;
297 if ((present & ROAD_SW) && (GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt) & ROAD_NE)) n |= ROAD_SW;
298 if ((present & ROAD_NW) && (GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt) & ROAD_SE)) n |= ROAD_NW;
299
300 int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE;
301 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
302 * then allow it */
303 if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) {
304 /* you can remove all kind of roads with extra dynamite */
306 return CommandCostWithParam(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS, t->index);
307 }
308 rating_decrease = RATING_ROAD_DOWN_STEP_INNER;
309 }
310 ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM, flags);
311
312 return CommandCost();
313}
314
315
324static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check)
325{
326 assert(pieces != ROAD_NONE);
327
328 RoadType existing_rt = MayHaveRoad(tile) ? GetRoadType(tile, rtt) : INVALID_ROADTYPE;
329 /* The tile doesn't have the given road type */
330 if (existing_rt == INVALID_ROADTYPE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
331
332 switch (GetTileType(tile)) {
333 case MP_ROAD: {
335 if (ret.Failed()) return ret;
336 break;
337 }
338
339 case MP_STATION: {
340 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
341
343 if (ret.Failed()) return ret;
344 break;
345 }
346
347 case MP_TUNNELBRIDGE: {
350 if (ret.Failed()) return ret;
351 break;
352 }
353
354 default:
355 return CMD_ERROR;
356 }
357
358 CommandCost ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rtt), rtt, flags, town_check);
359 if (ret.Failed()) return ret;
360
361 if (!IsTileType(tile, MP_ROAD)) {
362 /* If it's the last roadtype, just clear the whole tile */
363 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
364
366 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
367 /* Removing any roadbit in the bridge axis removes the roadtype (that's the behaviour remove-long-roads needs) */
368 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);
369
370 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
371 /* Pay for *every* tile of the bridge or tunnel */
372 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
373 cost.AddCost(len * 2 * RoadClearCost(existing_rt));
374 if (flags.Test(DoCommandFlag::Execute)) {
375 /* A full diagonal road tile has two road bits. */
376 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
377
378 SetRoadType(other_end, rtt, INVALID_ROADTYPE);
379 SetRoadType(tile, rtt, INVALID_ROADTYPE);
380
381 /* If the owner of the bridge sells all its road, also move the ownership
382 * to the owner of the other roadtype, unless the bridge owner is a town. */
383 Owner other_owner = GetRoadOwner(tile, OtherRoadTramType(rtt));
384 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
385 SetTileOwner(tile, other_owner);
386 SetTileOwner(other_end, other_owner);
387 }
388
389 /* Mark tiles dirty that have been repaved */
390 if (IsBridge(tile)) {
391 MarkBridgeDirty(tile);
392 } else {
394 MarkTileDirtyByTile(other_end);
395 }
396 }
397 } else {
398 assert(IsDriveThroughStopTile(tile));
399 cost.AddCost(RoadClearCost(existing_rt) * 2);
400 if (flags.Test(DoCommandFlag::Execute)) {
401 /* A full diagonal road tile has two road bits. */
402 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
403 SetRoadType(tile, rtt, INVALID_ROADTYPE);
405 }
406 }
407 return cost;
408 }
409
410 switch (GetRoadTileType(tile)) {
411 case ROAD_TILE_NORMAL: {
412 Slope tileh = GetTileSlope(tile);
413
414 /* Steep slopes behave the same as slopes with one corner raised. */
415 if (IsSteepSlope(tileh)) {
417 }
418
419 RoadBits present = GetRoadBits(tile, rtt);
420 const RoadBits other = GetRoadBits(tile, OtherRoadTramType(rtt));
421 const Foundation f = GetRoadFoundation(tileh, present);
422
423 if (HasRoadWorks(tile) && _current_company != OWNER_WATER) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
424
425 /* Autocomplete to a straight road
426 * @li if the bits of the other roadtypes result in another foundation
427 * @li if build on slopes is disabled */
428 if ((IsStraightRoad(other) && (other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
430 pieces |= MirrorRoadBits(pieces);
431 }
432
433 /* limit the bits to delete to the existing bits. */
434 pieces &= present;
435 if (pieces == ROAD_NONE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
436
437 /* Now set present what it will be after the remove */
438 present ^= pieces;
439
440 /* Check for invalid RoadBit combinations on slopes */
441 if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
442 (present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == present) {
443 return CMD_ERROR;
444 }
445
446 if (flags.Test(DoCommandFlag::Execute)) {
447 if (HasRoadWorks(tile)) {
448 /* flooding tile with road works, don't forget to remove the effect vehicle too */
449 assert(_current_company == OWNER_WATER);
451 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
452 delete v;
453 }
454 }
455 }
456
457 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)CountBits(pieces));
458
459 if (present == ROAD_NONE) {
460 /* No other road type, just clear tile. */
461 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
462 /* Includes MarkTileDirtyByTile() */
463 DoClearSquare(tile);
464 } else {
465 if (rtt == RTT_ROAD && IsRoadOwner(tile, rtt, OWNER_TOWN)) {
466 /* Update nearest-town index */
467 const Town *town = CalcClosestTownFromTile(tile);
468 SetTownIndex(tile, town == nullptr ? TownID::Invalid() : town->index);
469 }
470 if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE);
471 SetRoadBits(tile, ROAD_NONE, rtt);
472 SetRoadType(tile, rtt, INVALID_ROADTYPE);
474 }
475 } else {
476 /* When bits are removed, you *always* end up with something that
477 * is not a complete straight road tile. However, trams do not have
478 * onewayness, so they cannot remove it either. */
479 if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE);
480 SetRoadBits(tile, present, rtt);
482 }
483 }
484
485 CommandCost cost(EXPENSES_CONSTRUCTION, CountBits(pieces) * RoadClearCost(existing_rt));
486 /* If we build a foundation we have to pay for it. */
487 if (f == FOUNDATION_NONE && GetRoadFoundation(tileh, present) != FOUNDATION_NONE) cost.AddCost(_price[PR_BUILD_FOUNDATION]);
488
489 return cost;
490 }
491
492 case ROAD_TILE_CROSSING: {
493 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
494 return CMD_ERROR;
495 }
496
497 if (flags.Test(DoCommandFlag::Execute)) {
499
500 /* A full diagonal road tile has two road bits. */
501 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
502
503 Track railtrack = GetCrossingRailTrack(tile);
504 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
505 TrackBits tracks = GetCrossingRailBits(tile);
506 bool reserved = HasCrossingReservation(tile);
507 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
508 if (reserved) SetTrackReservation(tile, tracks);
509
510 /* Update rail count for level crossings. The plain track should still be accounted
511 * for, so only subtract the difference to the level crossing cost. */
513 if (c != nullptr) {
516 }
517 } else {
518 SetRoadType(tile, rtt, INVALID_ROADTYPE);
519 }
521 YapfNotifyTrackLayoutChange(tile, railtrack);
522 }
523 return CommandCost(EXPENSES_CONSTRUCTION, RoadClearCost(existing_rt) * 2);
524 }
525
526 default:
527 case ROAD_TILE_DEPOT:
528 return CMD_ERROR;
529 }
530}
531
532
544static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
545{
546 /* Remove already build pieces */
547 CLRBITS(*pieces, existing);
548
549 /* If we can't build anything stop here */
550 if (*pieces == ROAD_NONE) return CMD_ERROR;
551
552 /* All RoadBit combos are valid on flat land */
553 if (tileh == SLOPE_FLAT) return CommandCost();
554
555 /* Steep slopes behave the same as slopes with one corner raised. */
556 if (IsSteepSlope(tileh)) {
558 }
559
560 /* Save the merge of all bits of the current type */
561 RoadBits type_bits = existing | *pieces;
562
563 /* Roads on slopes */
564 if (_settings_game.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
565
566 /* If we add leveling we've got to pay for it */
567 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
568
569 return CommandCost();
570 }
571
572 /* Autocomplete uphill roads */
573 *pieces |= MirrorRoadBits(*pieces);
574 type_bits = existing | *pieces;
575
576 /* Uphill roads */
577 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
578 (_invalid_tileh_slopes_road[1][tileh] & (other | type_bits)) == ROAD_NONE) {
579
580 /* Slopes with foundation ? */
581 if (IsSlopeWithOneCornerRaised(tileh)) {
582
583 /* Prevent build on slopes if it isn't allowed */
585
586 /* If we add foundation we've got to pay for it */
587 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
588
589 return CommandCost();
590 }
591 } else {
592 if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
593 return CommandCost();
594 }
595 }
596 return CMD_ERROR;
597}
598
610{
611 CompanyID company = _current_company;
613
614 RoadBits existing = ROAD_NONE;
615 RoadBits other_bits = ROAD_NONE;
616
617 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
618 * if a non-company is building the road */
619 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;
620 if (company != OWNER_TOWN) {
621 const Town *town = CalcClosestTownFromTile(tile);
622 town_id = (town != nullptr) ? town->index : TownID::Invalid();
623
624 if (company == OWNER_DEITY) {
625 company = OWNER_TOWN;
626
627 /* If we are not within a town, we are not owned by the town */
628 if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
629 company = OWNER_NONE;
630 }
631 }
632 }
633
634 /* do not allow building 'zero' road bits, code wouldn't handle it */
635 if (pieces == ROAD_NONE || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR;
636 if (!ValParamRoadType(rt)) return CMD_ERROR;
637
638 Slope tileh = GetTileSlope(tile);
639 RoadTramType rtt = GetRoadTramType(rt);
640
641 bool need_to_clear = false;
642 switch (GetTileType(tile)) {
643 case MP_ROAD:
644 switch (GetRoadTileType(tile)) {
645 case ROAD_TILE_NORMAL: {
646 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
647
648 other_bits = GetRoadBits(tile, OtherRoadTramType(rtt));
649 if (!HasTileRoadType(tile, rtt)) break;
650
651 existing = GetRoadBits(tile, rtt);
652 bool crossing = !IsStraightRoad(existing | pieces);
653 if (rtt == RTT_ROAD && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
654 /* Junctions cannot be one-way */
655 return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
656 }
657 if ((existing & pieces) == pieces) {
658 /* We only want to set the (dis)allowed road directions */
659 if (toggle_drd != DRD_NONE && rtt == RTT_ROAD) {
660 if (crossing) return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
661
662 Owner owner = GetRoadOwner(tile, rtt);
663 if (owner != OWNER_NONE) {
664 CommandCost ret = CheckOwnership(owner, tile);
665 if (ret.Failed()) return ret;
666 }
667
669 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
670
671 /* We allow removing disallowed directions to break up
672 * deadlocks, but adding them can break articulated
673 * vehicles. As such, only when less is disallowed,
674 * i.e. bits are removed, we skip the vehicle check. */
675 if (CountBits(dis_existing) <= CountBits(dis_new)) {
677 if (ret.Failed()) return ret;
678 }
679
680 /* Ignore half built tiles */
681 if (flags.Test(DoCommandFlag::Execute) && IsStraightRoad(existing)) {
682 SetDisallowedRoadDirections(tile, dis_new);
684 }
685 return CommandCost();
686 }
687 return CommandCost(STR_ERROR_ALREADY_BUILT);
688 }
689 /* Disallow breaking end-of-line of someone else
690 * so trams can still reverse on this tile. */
691 if (rtt == RTT_TRAM && HasExactlyOneBit(existing)) {
692 Owner owner = GetRoadOwner(tile, rtt);
693 if (Company::IsValidID(owner)) {
694 CommandCost ret = CheckOwnership(owner);
695 if (ret.Failed()) return ret;
696 }
697 }
698 break;
699 }
700
702 if (RoadNoLevelCrossing(rt)) {
703 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
704 }
705
706 other_bits = GetCrossingRoadBits(tile);
707 if (pieces & ComplementRoadBits(other_bits)) goto do_clear;
708 pieces = other_bits; // we need to pay for both roadbits
709
710 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
711 break;
712
713 case ROAD_TILE_DEPOT:
714 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
715 goto do_clear;
716
717 default: NOT_REACHED();
718 }
719 break;
720
721 case MP_RAILWAY: {
722 if (IsSteepSlope(tileh)) {
723 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
724 }
725
726 /* Level crossings may only be built on these slopes */
727 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
728 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
729 }
730
733 if (ret.Failed()) return ret;
734 }
735
736 if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
737
738 if (RoadNoLevelCrossing(rt)) {
739 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
740 }
741
743 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
744 }
745
746 Axis roaddir;
747 switch (GetTrackBits(tile)) {
748 case TRACK_BIT_X:
749 if (pieces & ROAD_X) goto do_clear;
750 roaddir = AXIS_Y;
751 break;
752
753 case TRACK_BIT_Y:
754 if (pieces & ROAD_Y) goto do_clear;
755 roaddir = AXIS_X;
756 break;
757
758 default: goto do_clear;
759 }
760
762 if (ret.Failed()) return ret;
763
764 if (flags.Test(DoCommandFlag::Execute)) {
765 Track railtrack = AxisToTrack(OtherAxis(roaddir));
766 YapfNotifyTrackLayoutChange(tile, railtrack);
767 /* Update company infrastructure counts. A level crossing has two road bits. */
768 UpdateCompanyRoadInfrastructure(rt, company, 2);
769
770 /* Update rail count for level crossings. The plain track is already
771 * counted, so only add the difference to the level crossing cost. */
773 if (c != nullptr) {
776 }
777
778 /* Always add road to the roadtypes (can't draw without it) */
779 bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
780 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id);
781 SetCrossingReservation(tile, reserved);
782 UpdateLevelCrossing(tile, false);
785 }
787 }
788
789 case MP_STATION: {
790 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
791 if (!IsDriveThroughStopTile(tile)) goto do_clear;
792
794 if (pieces & ~curbits) goto do_clear;
795 pieces = curbits; // we need to pay for both roadbits
796
797 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
798 break;
799 }
800
801 case MP_TUNNELBRIDGE: {
802 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) goto do_clear;
803 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
804 if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
805 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
806 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
808 if (ret.Failed()) return ret;
809 break;
810 }
811
812 default: {
813do_clear:;
814 need_to_clear = true;
815 break;
816 }
817 }
818
819 if (need_to_clear) {
821 if (ret.Failed()) return ret;
822 cost.AddCost(ret);
823 }
824
825 if (other_bits != pieces) {
826 /* Check the foundation/slopes when adding road/tram bits */
827 CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
828 /* Return an error if we need to build a foundation (ret != 0) but the
829 * current setting is turned off */
830 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
831 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
832 }
833 cost.AddCost(ret);
834 }
835
836 if (!need_to_clear) {
837 if (IsTileType(tile, MP_ROAD)) {
838 /* Don't put the pieces that already exist */
839 pieces &= ComplementRoadBits(existing);
840
841 /* Check if new road bits will have the same foundation as other existing road types */
842 if (IsNormalRoad(tile)) {
843 Slope slope = GetTileSlope(tile);
844 Foundation found_new = GetRoadFoundation(slope, pieces | existing);
845
846 RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt));
847 /* do not check if there are not road bits of given type */
848 if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) {
849 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
850 }
851 }
852 }
853
855 if (ret.Failed()) return ret;
856
857 if (IsNormalRoadTile(tile)) {
858 /* If the road types don't match, try to convert only if vehicles of
859 * the new road type are not powered on the present road type and vehicles of
860 * the present road type are powered on the new road type. */
861 RoadType existing_rt = GetRoadType(tile, rtt);
862 if (existing_rt != INVALID_ROADTYPE && existing_rt != rt) {
863 if (HasPowerOnRoad(rt, existing_rt)) {
864 rt = existing_rt;
865 } else if (HasPowerOnRoad(existing_rt, rt)) {
866 ret = Command<CMD_CONVERT_ROAD>::Do(flags, tile, tile, rt);
867 if (ret.Failed()) return ret;
868 cost.AddCost(ret);
869 } else {
870 return CMD_ERROR;
871 }
872 }
873 }
874 }
875
876 uint num_pieces = (!need_to_clear && IsTileType(tile, MP_TUNNELBRIDGE)) ?
877 /* There are 2 pieces on *every* tile of the bridge or tunnel */
878 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) :
879 /* Count pieces */
880 CountBits(pieces);
881
882 cost.AddCost(num_pieces * RoadBuildCost(rt));
883
884 if (flags.Test(DoCommandFlag::Execute)) {
885 switch (GetTileType(tile)) {
886 case MP_ROAD: {
887 RoadTileType rttype = GetRoadTileType(tile);
888 if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) {
889 SetRoadType(tile, rtt, rt);
890 SetRoadOwner(tile, rtt, company);
891 if (rtt == RTT_ROAD) SetTownIndex(tile, town_id);
892 }
893 if (rttype != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rtt);
894 break;
895 }
896
897 case MP_TUNNELBRIDGE: {
898 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
899
900 SetRoadType(other_end, rtt, rt);
901 SetRoadType(tile, rtt, rt);
902 SetRoadOwner(other_end, rtt, company);
903 SetRoadOwner(tile, rtt, company);
904
905 /* Mark tiles dirty that have been repaved */
906 if (IsBridge(tile)) {
907 MarkBridgeDirty(tile);
908 } else {
909 MarkTileDirtyByTile(other_end);
911 }
912 break;
913 }
914
915 case MP_STATION: {
916 assert(IsDriveThroughStopTile(tile));
917 SetRoadType(tile, rtt, rt);
918 SetRoadOwner(tile, rtt, company);
919 break;
920 }
921
922 default:
923 MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company);
924 break;
925 }
926
927 /* Update company infrastructure count. */
929 UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), num_pieces);
930
931 if (rtt == RTT_ROAD && IsNormalRoadTile(tile)) {
932 existing |= pieces;
934 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
935 }
936
938 }
939 return cost;
940}
941
950{
951 tile += TileOffsByDiagDir(dir);
952 if (!IsValidTile(tile) || !MayHaveRoad(tile)) return false;
953
954 RoadTramType rtt = GetRoadTramType(rt);
955 RoadType existing = GetRoadType(tile, rtt);
956 if (existing == INVALID_ROADTYPE) return false;
957 if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false;
958
959 RoadBits bits = GetAnyRoadBits(tile, rtt, false);
960 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
961}
962
978CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
979{
980 if (start_tile >= Map::Size()) return CMD_ERROR;
981
982 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
983
984 /* Only drag in X or Y direction dictated by the direction variable */
985 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
986 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
987
988 DiagDirection dir = AxisToDiagDir(axis);
989
990 /* Swap direction, also the half-tile drag vars. */
991 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
992 dir = ReverseDiagDir(dir);
993 start_half = !start_half;
994 end_half = !end_half;
995 if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
996 }
997
998 /* On the X-axis, we have to swap the initial bits, so they
999 * will be interpreted correctly in the GTTS. Furthermore
1000 * when you just 'click' on one tile to build them. */
1001 if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
1002
1004 CommandCost last_error = CMD_ERROR;
1005 TileIndex tile = start_tile;
1006 bool had_bridge = false;
1007 bool had_tunnel = false;
1008 bool had_success = false;
1009
1010 /* Start tile is the first tile clicked by the user. */
1011 for (;;) {
1012 RoadBits bits = AxisToRoadBits(axis);
1013
1014 /* Determine which road parts should be built. */
1015 if (!is_ai && start_tile != end_tile) {
1016 /* Only build the first and last roadbit if they can connect to something. */
1017 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1018 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1019 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1020 bits = DiagDirToRoadBits(dir);
1021 }
1022 } else {
1023 /* Road parts only have to be built at the start tile or at the end tile. */
1024 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1025 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1026 }
1027
1028 CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, TownID::Invalid());
1029 if (ret.Failed()) {
1030 last_error = ret;
1031 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1032 if (is_ai) return last_error;
1033 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1034 }
1035 } else {
1036 had_success = true;
1037 /* Only pay for the upgrade on one side of the bridges and tunnels */
1038 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1039 if (IsBridge(tile)) {
1040 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1041 cost.AddCost(ret);
1042 }
1043 had_bridge = true;
1044 } else { // IsTunnel(tile)
1045 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1046 cost.AddCost(ret);
1047 }
1048 had_tunnel = true;
1049 }
1050 } else {
1051 cost.AddCost(ret);
1052 }
1053 }
1054
1055 if (tile == end_tile) break;
1056
1057 tile += TileOffsByDiagDir(dir);
1058 }
1059
1060 return had_success ? cost : last_error;
1061}
1062
1074std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
1075{
1077
1078 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
1079 if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 };
1080
1081 /* Only drag in X or Y direction dictated by the direction variable */
1082 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis
1083 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis
1084
1085 /* Swap start and ending tile, also the half-tile drag vars. */
1086 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
1087 std::swap(start_tile, end_tile);
1088 std::swap(start_half, end_half);
1089 }
1090
1091 Money money_available = GetAvailableMoneyForCommand();
1092 Money money_spent = 0;
1093 TileIndex tile = start_tile;
1094 CommandCost last_error = CMD_ERROR;
1095 bool had_success = false;
1096 /* Start tile is the small number. */
1097 for (;;) {
1098 RoadBits bits = AxisToRoadBits(axis);
1099
1100 if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
1101 if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
1102
1103 /* try to remove the halves. */
1104 if (bits != 0) {
1105 RoadTramType rtt = GetRoadTramType(rt);
1106 CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true);
1107 if (ret.Succeeded()) {
1108 if (flags.Test(DoCommandFlag::Execute)) {
1109 money_spent += ret.GetCost();
1110 if (money_spent > 0 && money_spent > money_available) {
1111 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() };
1112 }
1113 RemoveRoad(tile, flags, bits, rtt, false);
1114 }
1115 cost.AddCost(ret);
1116 had_success = true;
1117 } else {
1118 /* Some errors are more equal than others. */
1119 switch (last_error.GetErrorMessage()) {
1120 case STR_ERROR_OWNED_BY:
1121 case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS:
1122 break;
1123 default:
1124 last_error = ret;
1125 }
1126 }
1127 }
1128
1129 if (tile == end_tile) break;
1130
1131 tile += TileOffsByAxis(axis);
1132 }
1133
1134 return { had_success ? cost : last_error, 0 };
1135}
1136
1149{
1150 if (!ValParamRoadType(rt) || !IsValidDiagDirection(dir)) return CMD_ERROR;
1151
1153
1154 Slope tileh = GetTileSlope(tile);
1155 if (tileh != SLOPE_FLAT) {
1157 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
1158 }
1159 cost.AddCost(_price[PR_BUILD_FOUNDATION]);
1160 }
1161
1162 /* Allow the user to rotate the depot instead of having to destroy it and build it again */
1163 bool rotate_existing_depot = false;
1164 if (IsRoadDepotTile(tile) && (HasRoadTypeTram(tile) ? rt == GetRoadTypeTram(tile) : rt == GetRoadTypeRoad(tile)))
1165 {
1166 CommandCost ret = CheckTileOwnership(tile);
1167 if (ret.Failed()) return ret;
1168
1169 if (dir == GetRoadDepotDirection(tile)) return CommandCost();
1170
1171 ret = EnsureNoVehicleOnGround(tile);
1172 if (ret.Failed()) return ret;
1173
1174 rotate_existing_depot = true;
1175 }
1176
1177 if (!rotate_existing_depot) {
1178 cost.AddCost(Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile));
1179 if (cost.Failed()) return cost;
1180
1181 if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1182
1183 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1184 }
1185
1186 if (flags.Test(DoCommandFlag::Execute)) {
1187 if (rotate_existing_depot) {
1188 SetRoadDepotExitDirection(tile, dir);
1189 } else {
1190 Depot *dep = new Depot(tile);
1191 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1192 MakeDefaultName(dep);
1193
1194 /* A road depot has two road bits. */
1196 }
1197
1198 MarkTileDirtyByTile(tile);
1199 }
1200
1201 cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
1202 return cost;
1203}
1204
1205static CommandCost RemoveRoadDepot(TileIndex tile, DoCommandFlags flags)
1206{
1208 CommandCost ret = CheckTileOwnership(tile);
1209 if (ret.Failed()) return ret;
1210 }
1211
1213 if (ret.Failed()) return ret;
1214
1215 if (flags.Test(DoCommandFlag::Execute)) {
1217 if (c != nullptr) {
1218 /* A road depot has two road bits. */
1219 RoadType rt = GetRoadTypeRoad(tile);
1220 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
1223 }
1224
1225 delete Depot::GetByTile(tile);
1226 DoClearSquare(tile);
1227 }
1228
1229 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_ROAD]);
1230}
1231
1232static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlags flags)
1233{
1234 switch (GetRoadTileType(tile)) {
1235 case ROAD_TILE_NORMAL: {
1236 RoadBits b = GetAllRoadBits(tile);
1237
1238 /* Clear the road if only one piece is on the tile OR we are not using the DoCommandFlag::Auto flag */
1239 if ((HasExactlyOneBit(b) && GetRoadBits(tile, RTT_TRAM) == ROAD_NONE) || !flags.Test(DoCommandFlag::Auto)) {
1241 for (RoadTramType rtt : _roadtramtypes) {
1242 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1243
1244 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true);
1245 if (tmp_ret.Failed()) return tmp_ret;
1246 ret.AddCost(tmp_ret);
1247 }
1248 return ret;
1249 }
1250 return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1251 }
1252
1253 case ROAD_TILE_CROSSING: {
1255
1256 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1257
1258 /* Must iterate over the roadtypes in a reverse manner because
1259 * tram tracks must be removed before the road bits. */
1260 for (RoadTramType rtt : { RTT_TRAM, RTT_ROAD }) {
1261 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1262
1263 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rtt, true);
1264 if (tmp_ret.Failed()) return tmp_ret;
1265 ret.AddCost(tmp_ret);
1266 }
1267
1268 if (flags.Test(DoCommandFlag::Execute)) {
1270 }
1271 return ret;
1272 }
1273
1274 default:
1275 case ROAD_TILE_DEPOT:
1276 if (flags.Test(DoCommandFlag::Auto)) {
1277 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1278 }
1279 return RemoveRoadDepot(tile, flags);
1280 }
1281}
1282
1283
1285 uint16_t image;
1286 uint8_t subcoord_x;
1287 uint8_t subcoord_y;
1288};
1289
1290#include "table/road_land.h"
1291
1300{
1301 /* Flat land and land without a road doesn't require a foundation */
1302 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1303
1304 /* Steep slopes behave the same as slopes with one corner raised. */
1305 if (IsSteepSlope(tileh)) {
1307 }
1308
1309 /* Leveled RoadBits on a slope */
1310 if ((_invalid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1311
1312 /* Straight roads without foundation on a slope */
1313 if (!IsSlopeWithOneCornerRaised(tileh) &&
1314 (_invalid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE)
1315 return FOUNDATION_NONE;
1316
1317 /* Roads on steep Slopes or on Slopes with one corner raised */
1319}
1320
1321const uint8_t _road_sloped_sprites[14] = {
1322 0, 0, 2, 0,
1323 0, 1, 0, 0,
1324 3, 0, 0, 0,
1325 0, 0
1326};
1327
1334static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
1335{
1336 if (slope != SLOPE_FLAT) {
1337 switch (slope) {
1338 case SLOPE_NE: return 11;
1339 case SLOPE_SE: return 12;
1340 case SLOPE_SW: return 13;
1341 case SLOPE_NW: return 14;
1342 default: NOT_REACHED();
1343 }
1344 } else {
1345 static const uint offsets[] = {
1346 0, 18, 17, 7,
1347 16, 0, 10, 5,
1348 15, 8, 1, 4,
1349 9, 3, 6, 2
1350 };
1351 return offsets[bits];
1352 }
1353}
1354
1364static bool DrawRoadAsSnowDesert(bool snow_or_desert, Roadside roadside)
1365{
1366 return (snow_or_desert &&
1367 !(_settings_game.game_creation.landscape == LandscapeType::Tropic && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) &&
1368 roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS));
1369}
1370
1378{
1379 /* Don't draw the catenary under a low bridge */
1381 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1382
1383 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1384 }
1385
1386 if (CountBits(rb) > 2) {
1387 /* On junctions we check whether neighbouring tiles also have catenary, and possibly
1388 * do not draw catenary towards those neighbours, which do not have catenary. */
1389 RoadBits rb_new = ROAD_NONE;
1390 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
1391 if (rb & DiagDirToRoadBits(dir)) {
1392 TileIndex neighbour = TileAddByDiagDir(ti->tile, dir);
1393 if (MayHaveRoad(neighbour)) {
1394 RoadType rt_road = GetRoadTypeRoad(neighbour);
1395 RoadType rt_tram = GetRoadTypeTram(neighbour);
1396
1397 if ((rt_road != INVALID_ROADTYPE && HasRoadCatenary(rt_road)) ||
1398 (rt_tram != INVALID_ROADTYPE && HasRoadCatenary(rt_tram))) {
1399 rb_new |= DiagDirToRoadBits(dir);
1400 }
1401 }
1402 }
1403 }
1404 if (CountBits(rb_new) >= 2) rb = rb_new;
1405 }
1406
1407 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1410
1411 if (front != 0 || back != 0) {
1412 if (front != 0) front += GetRoadSpriteOffset(ti->tileh, rb);
1413 if (back != 0) back += GetRoadSpriteOffset(ti->tileh, rb);
1414 } else if (ti->tileh != SLOPE_FLAT) {
1415 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1416 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1417 } else {
1418 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb];
1419 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb];
1420 }
1421
1422 /* Catenary uses 1st company colour to help identify owner.
1423 * For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
1424 Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
1425 PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GENERAL_SPRITE_COLOUR(COLOUR_GREY) : COMPANY_SPRITE_COLOUR(owner));
1426 int z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
1427 if (back != 0) {
1428 /* The "back" sprite contains the west, north and east pillars.
1429 * We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
1430 * 3/8 is chosen so that sprites can somewhat graphically extend into the tile. */
1431 static const int INF = 1000;
1432 static const SubSprite west = { -INF, -INF, -12, INF };
1433 static const SubSprite north = { -12, -INF, 12, INF };
1434 static const SubSprite east = { 12, -INF, INF, INF };
1435 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 16, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 15, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_W), &west);
1436 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_N), &north);
1437 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 16, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 15, GetSlopePixelZInCorner(ti->tileh, CORNER_E), &east);
1438 }
1439 if (front != 0) {
1440 /* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
1441 AddSortableSpriteToDraw(front, pal, ti->x, ti->y, 16, 16, z_wires + 1, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, z_wires);
1442 }
1443}
1444
1450{
1451 RoadBits road = ROAD_NONE;
1452 RoadBits tram = ROAD_NONE;
1453
1454 if (IsTileType(ti->tile, MP_ROAD)) {
1455 if (IsNormalRoad(ti->tile)) {
1456 road = GetRoadBits(ti->tile, RTT_ROAD);
1457 tram = GetRoadBits(ti->tile, RTT_TRAM);
1458 } else if (IsLevelCrossing(ti->tile)) {
1459 tram = road = (GetCrossingRailAxis(ti->tile) == AXIS_Y ? ROAD_X : ROAD_Y);
1460 }
1461 } else if (IsTileType(ti->tile, MP_STATION)) {
1462 if (IsAnyRoadStop(ti->tile)) {
1463 if (IsDriveThroughStopTile(ti->tile)) {
1464 Axis axis = GetDriveThroughStopAxis(ti->tile);
1465 tram = road = (axis == AXIS_X ? ROAD_X : ROAD_Y);
1466 } else {
1467 tram = road = DiagDirToRoadBits(GetBayRoadStopDir(ti->tile));
1468 }
1469 }
1470 } else {
1471 // No road here, no catenary to draw
1472 return;
1473 }
1474
1475 RoadType rt = GetRoadTypeRoad(ti->tile);
1476 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1477 DrawRoadTypeCatenary(ti, rt, road);
1478 }
1479
1480 rt = GetRoadTypeTram(ti->tile);
1481 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1482 DrawRoadTypeCatenary(ti, rt, tram);
1483 }
1484}
1485
1495static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
1496{
1497 int x = ti->x | dx;
1498 int y = ti->y | dy;
1499 int z = ti->z;
1500 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1501 AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z, transparent);
1502}
1503
1513void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
1514{
1515 if (draw_underlay) {
1516 /* Road underlay takes precedence over tram */
1517 if (road_rti != nullptr) {
1518 if (road_rti->UsesOverlay()) {
1519 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_GROUND);
1520 DrawGroundSprite(ground + road_offset, pal);
1521 }
1522 } else {
1523 if (tram_rti->UsesOverlay()) {
1524 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_GROUND);
1525 DrawGroundSprite(ground + tram_offset, pal);
1526 } else {
1527 DrawGroundSprite(SPR_TRAMWAY_TRAM + tram_offset, pal);
1528 }
1529 }
1530 }
1531
1532 /* Draw road overlay */
1533 if (road_rti != nullptr) {
1534 if (road_rti->UsesOverlay()) {
1535 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_OVERLAY);
1536 if (ground != 0) DrawGroundSprite(ground + road_offset, pal);
1537 }
1538 }
1539
1540 /* Draw tram overlay */
1541 if (tram_rti != nullptr) {
1542 if (tram_rti->UsesOverlay()) {
1543 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_OVERLAY);
1544 if (ground != 0) DrawGroundSprite(ground + tram_offset, pal);
1545 } else if (road_rti != nullptr) {
1546 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + tram_offset, pal);
1547 }
1548 }
1549}
1550
1560static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
1561{
1562 /* Draw bare ground sprite if no road or road uses overlay system. */
1563 if (rti == nullptr || rti->UsesOverlay()) {
1564 if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
1565 return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
1566 }
1567
1568 switch (roadside) {
1570 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1571 case ROADSIDE_GRASS:
1572 case ROADSIDE_GRASS_ROAD_WORKS: return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1573 default: break; // Paved
1574 }
1575 }
1576
1577 /* Draw original road base sprite */
1578 SpriteID image = SPR_ROAD_Y + offset;
1579 if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
1580 image += 19;
1581 } else {
1582 switch (roadside) {
1583 case ROADSIDE_BARREN: *pal = PALETTE_TO_BARE_LAND; break;
1584 case ROADSIDE_GRASS: break;
1585 case ROADSIDE_GRASS_ROAD_WORKS: break;
1586 default: image -= 19; break; // Paved
1587 }
1588 }
1589
1590 return image;
1591}
1592
1603void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
1604{
1605 /* Determine sprite offsets */
1606 uint road_offset = GetRoadSpriteOffset(ti->tileh, road);
1607 uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
1608
1609 /* Draw baseset underlay */
1610 PaletteID pal = PAL_NONE;
1611 SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, snow_or_desert, &pal);
1612 DrawGroundSprite(image, pal);
1613
1614 DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
1615}
1616
1621static void DrawRoadBits(TileInfo *ti)
1622{
1623 RoadBits road = GetRoadBits(ti->tile, RTT_ROAD);
1624 RoadBits tram = GetRoadBits(ti->tile, RTT_TRAM);
1625
1626 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1627 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1628 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1629 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1630
1631 if (ti->tileh != SLOPE_FLAT) {
1632 DrawFoundation(ti, GetRoadFoundation(ti->tileh, road | tram));
1633 /* DrawFoundation() modifies ti. */
1634 }
1635
1636 DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnow(ti->tile));
1637
1638 /* Draw one way */
1639 if (road_rti != nullptr) {
1641 if (drd != DRD_NONE) {
1642 SpriteID oneway = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ONEWAY);
1643
1644 if (oneway == 0) oneway = SPR_ONEWAY_BASE;
1645
1646 if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) {
1647 oneway += ONEWAY_SLOPE_N_OFFSET;
1648 } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) {
1649 oneway += ONEWAY_SLOPE_S_OFFSET;
1650 }
1651
1652 DrawGroundSpriteAt(oneway + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1653 }
1654 }
1655
1656 if (HasRoadWorks(ti->tile)) {
1657 /* Road works */
1658 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1659 return;
1660 }
1661
1662 /* Draw road, tram catenary */
1663 DrawRoadCatenary(ti);
1664
1665 /* Return if full detail is disabled, or we are zoomed fully out. */
1666 if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
1667
1668 /* Do not draw details (street lights, trees) under low bridge */
1669 Roadside roadside = GetRoadside(ti->tile);
1670 if (IsBridgeAbove(ti->tile) && (roadside == ROADSIDE_TREES || roadside == ROADSIDE_STREET_LIGHTS)) {
1671 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1672 int minz = GetTileMaxZ(ti->tile) + 2;
1673
1674 if (roadside == ROADSIDE_TREES) minz++;
1675
1676 if (height < minz) return;
1677 }
1678
1679 /* If there are no road bits, return, as there is nothing left to do */
1680 if (HasAtMostOneBit(road)) return;
1681
1682 /* Do not draw details when invisible. */
1683 if (roadside == ROADSIDE_TREES && IsInvisibilitySet(TO_TREES)) return;
1684 if (roadside == ROADSIDE_STREET_LIGHTS && IsInvisibilitySet(TO_HOUSES)) return;
1685
1686 /* Check whether details should be transparent. */
1687 bool is_transparent = false;
1688 if (roadside == ROADSIDE_TREES && IsTransparencySet(TO_TREES)) {
1689 is_transparent = true;
1690 }
1692 is_transparent = true;
1693 }
1694
1695 /* Draw extra details. */
1696 for (const DrawRoadTileStruct *drts = _road_display_table[roadside][road | tram]; drts->image != 0; drts++) {
1697 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
1698 }
1699}
1700
1702static void DrawTile_Road(TileInfo *ti)
1703{
1704 switch (GetRoadTileType(ti->tile)) {
1705 case ROAD_TILE_NORMAL:
1706 DrawRoadBits(ti);
1707 break;
1708
1709 case ROAD_TILE_CROSSING: {
1711
1712 Axis axis = GetCrossingRailAxis(ti->tile);
1713
1714 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1715
1716 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1717 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1718 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1719 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1720
1721 PaletteID pal = PAL_NONE;
1722
1723 /* Draw base ground */
1724 if (rti->UsesOverlay()) {
1725 SpriteID image = SPR_ROAD_Y + axis;
1726
1727 Roadside roadside = GetRoadside(ti->tile);
1728 if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
1729 image += 19;
1730 } else {
1731 switch (roadside) {
1732 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
1733 case ROADSIDE_GRASS: break;
1734 default: image -= 19; break; // Paved
1735 }
1736 }
1737
1738 DrawGroundSprite(image, pal);
1739 } else {
1740 SpriteID image = rti->base_sprites.crossing + axis;
1741 if (IsCrossingBarred(ti->tile)) image += 2;
1742
1743 Roadside roadside = GetRoadside(ti->tile);
1744 if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
1745 image += 8;
1746 } else {
1747 switch (roadside) {
1748 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
1749 case ROADSIDE_GRASS: break;
1750 default: image += 4; break; // Paved
1751 }
1752 }
1753
1754 DrawGroundSprite(image, pal);
1755 }
1756
1757 DrawRoadOverlays(ti, pal, road_rti, tram_rti, axis, axis);
1758
1759 /* Draw rail/PBS overlay */
1760 bool draw_pbs = _game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile);
1761 if (rti->UsesOverlay()) {
1762 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1763 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1764 DrawGroundSprite(rail, pal);
1765
1766 const Axis road_axis = GetCrossingRoadAxis(ti->tile);
1767 const DiagDirection dir1 = AxisToDiagDir(road_axis);
1768 const DiagDirection dir2 = ReverseDiagDir(dir1);
1769 uint adjacent_diagdirs = 0;
1770 for (DiagDirection dir : { dir1, dir2 }) {
1771 const TileIndex t = TileAddByDiagDir(ti->tile, dir);
1772 if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
1773 SetBit(adjacent_diagdirs, dir);
1774 }
1775 }
1776
1777 switch (adjacent_diagdirs) {
1778 case 0:
1779 DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1780 break;
1781
1782 case (1 << DIAGDIR_NE):
1783 DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE);
1784 break;
1785
1786 case (1 << DIAGDIR_SE):
1787 DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE);
1788 break;
1789
1790 case (1 << DIAGDIR_SW):
1791 DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE);
1792 break;
1793
1794 case (1 << DIAGDIR_NW):
1795 DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE);
1796 break;
1797
1798 default:
1799 /* Show no sprites */
1800 break;
1801 }
1802 } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) {
1803 /* Add another rail overlay, unless there is only the base road sprite. */
1804 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1806 DrawGroundSprite(rail, pal);
1807 }
1808
1809 /* Draw road, tram catenary */
1810 DrawRoadCatenary(ti);
1811
1812 /* Draw rail catenary */
1814
1815 break;
1816 }
1817
1818 default:
1819 case ROAD_TILE_DEPOT: {
1821
1822 PaletteID palette = COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile));
1823
1824 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1825 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1826 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt == INVALID_ROADTYPE ? tram_rt : road_rt);
1827
1828 int relocation = GetCustomRoadSprite(rti, ti->tile, ROTSG_DEPOT);
1829 bool default_gfx = relocation == 0;
1830 if (default_gfx) {
1831 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1832 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && road_rt == INVALID_ROADTYPE && !rti->UsesOverlay()) {
1833 /* Sprites with track only work for default tram */
1834 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1835 default_gfx = false;
1836 } else {
1837 /* Sprites without track are always better, if provided */
1838 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1839 }
1840 }
1841 } else {
1842 relocation -= SPR_ROAD_DEPOT;
1843 }
1844
1846 const DrawTileSprites *dts = &_road_depot[dir];
1847 DrawGroundSprite(dts->ground.sprite, PAL_NONE);
1848
1849 if (default_gfx) {
1851 if (rti->UsesOverlay()) {
1852 SpriteID ground = GetCustomRoadSprite(rti, ti->tile, ROTSG_OVERLAY);
1853 if (ground != 0) DrawGroundSprite(ground + offset, PAL_NONE);
1854 } else if (road_rt == INVALID_ROADTYPE) {
1855 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE);
1856 }
1857 }
1858
1859 DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, palette);
1860 break;
1861 }
1862 }
1863 DrawBridgeMiddle(ti);
1864}
1865
1873void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
1874{
1875 PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
1876
1877 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1878 int relocation = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_DEPOT);
1879 bool default_gfx = relocation == 0;
1880 if (default_gfx) {
1881 if (rti->flags.Test(RoadTypeFlag::Catenary)) {
1882 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && RoadTypeIsTram(rt) && !rti->UsesOverlay()) {
1883 /* Sprites with track only work for default tram */
1884 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1885 default_gfx = false;
1886 } else {
1887 /* Sprites without track are always better, if provided */
1888 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1889 }
1890 }
1891 } else {
1892 relocation -= SPR_ROAD_DEPOT;
1893 }
1894
1895 const DrawTileSprites *dts = &_road_depot[dir];
1896 DrawSprite(dts->ground.sprite, PAL_NONE, x, y);
1897
1898 if (default_gfx) {
1900 if (rti->UsesOverlay()) {
1902 if (ground != 0) DrawSprite(ground + offset, PAL_NONE, x, y);
1903 } else if (RoadTypeIsTram(rt)) {
1904 DrawSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE, x, y);
1905 }
1906 }
1907
1908 DrawRailTileSeqInGUI(x, y, dts, relocation, 0, palette);
1909}
1910
1917{
1918 assert(!invalidate || _generating_world);
1919
1920 for (const auto t : Map::Iterate()) {
1921 if (IsTileType(t, MP_ROAD) && !IsRoadDepot(t) && !HasTownOwnedRoad(t)) {
1922 TownID tid = TownID::Invalid();
1923 if (!invalidate) {
1924 const Town *town = CalcClosestTownFromTile(t);
1925 if (town != nullptr) tid = town->index;
1926 }
1927 SetTownIndex(t, tid);
1928 }
1929 }
1930}
1931
1932static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, bool)
1933{
1934
1935 if (IsNormalRoad(tile)) {
1936 auto [tileh, z] = GetTilePixelSlope(tile);
1937 if (tileh == SLOPE_FLAT) return z;
1938
1940 z += ApplyPixelFoundationToSlope(f, tileh);
1941 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1942 } else {
1943 return GetTileMaxPixelZ(tile);
1944 }
1945}
1946
1947static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
1948{
1949 if (IsNormalRoad(tile)) {
1950 return GetRoadFoundation(tileh, GetAllRoadBits(tile));
1951 } else {
1952 return FlatteningFoundation(tileh);
1953 }
1954}
1955
1956static const Roadside _town_road_types[][2] = {
1962};
1963
1964static_assert(lengthof(_town_road_types) == HZB_END);
1965
1966static const Roadside _town_road_types_2[][2] = {
1972};
1973
1974static_assert(lengthof(_town_road_types_2) == HZB_END);
1975
1976
1977static void TileLoop_Road(TileIndex tile)
1978{
1980 case LandscapeType::Arctic: {
1981 /* 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. */
1982 int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileZ(tile);
1983 if (IsOnSnow(tile) != (tile_z > GetSnowLine())) {
1984 ToggleSnow(tile);
1985 MarkTileDirtyByTile(tile);
1986 }
1987 break;
1988 }
1989
1990 case LandscapeType::Tropic:
1991 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
1992 ToggleDesert(tile);
1993 MarkTileDirtyByTile(tile);
1994 }
1995 break;
1996
1997 default:
1998 break;
1999 }
2000
2001 if (IsRoadDepot(tile)) return;
2002
2003 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
2004 if (!HasRoadWorks(tile)) {
2005 HouseZonesBits grp = HZB_TOWN_EDGE;
2006
2007 if (t != nullptr) {
2008 grp = GetTownRadiusGroup(t, tile);
2009
2010 /* Show an animation to indicate road work */
2011 if (t->road_build_months != 0 &&
2012 (DistanceManhattan(t->xy, tile) < 8 || grp != HZB_TOWN_EDGE) &&
2013 IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) {
2014 if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
2015 StartRoadWorks(tile);
2016
2017 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
2019 TileX(tile) * TILE_SIZE + 7,
2020 TileY(tile) * TILE_SIZE + 7,
2021 0,
2022 EV_BULLDOZER);
2023 MarkTileDirtyByTile(tile);
2024 return;
2025 }
2026 }
2027 }
2028
2029 {
2030 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2031 const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[grp] : _town_road_types[grp];
2032 Roadside cur_rs = GetRoadside(tile);
2033
2034 /* We have our desired type, do nothing */
2035 if (cur_rs == new_rs[0]) return;
2036
2037 /* We have the pre-type of the desired type, switch to the desired type */
2038 if (cur_rs == new_rs[1]) {
2039 cur_rs = new_rs[0];
2040 /* We have barren land, install the pre-type */
2041 } else if (cur_rs == ROADSIDE_BARREN) {
2042 cur_rs = new_rs[1];
2043 /* We're totally off limits, remove any installation and make barren land */
2044 } else {
2045 cur_rs = ROADSIDE_BARREN;
2046 }
2047 SetRoadside(tile, cur_rs);
2048 MarkTileDirtyByTile(tile);
2049 }
2050 } else if (IncreaseRoadWorksCounter(tile)) {
2051 TerminateRoadWorks(tile);
2052
2054 /* Generate a nicer town surface */
2055 const RoadBits old_rb = GetAnyRoadBits(tile, RTT_ROAD);
2056 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2057
2058 if (old_rb != new_rb) {
2059 RemoveRoad(tile, {DoCommandFlag::Execute, DoCommandFlag::Auto, DoCommandFlag::NoWater}, (old_rb ^ new_rb), RTT_ROAD, true);
2060
2061 /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */
2062 if (new_rb == 0) {
2063 MarkTileDirtyByTile(tile);
2064 return;
2065 }
2066 }
2067 }
2068
2069 /* Possibly change road type */
2070 if (GetRoadOwner(tile, RTT_ROAD) == OWNER_TOWN) {
2072 if (rt != GetRoadTypeRoad(tile)) {
2073 SetRoadType(tile, RTT_ROAD, rt);
2074 }
2075 }
2076
2077 MarkTileDirtyByTile(tile);
2078 }
2079}
2080
2081static bool ClickTile_Road(TileIndex tile)
2082{
2083 if (!IsRoadDepot(tile)) return false;
2084
2086 return true;
2087}
2088
2089/* Converts RoadBits to TrackBits */
2090static const TrackBits _road_trackbits[16] = {
2091 TRACK_BIT_NONE, // ROAD_NONE
2092 TRACK_BIT_NONE, // ROAD_NW
2093 TRACK_BIT_NONE, // ROAD_SW
2094 TRACK_BIT_LEFT, // ROAD_W
2095 TRACK_BIT_NONE, // ROAD_SE
2096 TRACK_BIT_Y, // ROAD_Y
2097 TRACK_BIT_LOWER, // ROAD_S
2098 TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | ROAD_SW
2099 TRACK_BIT_NONE, // ROAD_NE
2100 TRACK_BIT_UPPER, // ROAD_N
2101 TRACK_BIT_X, // ROAD_X
2102 TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | ROAD_NW
2103 TRACK_BIT_RIGHT, // ROAD_E
2104 TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | ROAD_NE
2105 TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | ROAD_SE
2106 TRACK_BIT_ALL, // ROAD_ALL
2107};
2108
2109static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
2110{
2111 TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
2112 TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
2113 switch (mode) {
2114 case TRANSPORT_RAIL:
2115 if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
2116 break;
2117
2118 case TRANSPORT_ROAD: {
2119 RoadTramType rtt = (RoadTramType)sub_mode;
2120 if (!HasTileRoadType(tile, rtt)) break;
2121 switch (GetRoadTileType(tile)) {
2122 case ROAD_TILE_NORMAL: {
2123 const uint drd_to_multiplier[DRD_END] = { 0x101, 0x100, 0x1, 0x0 };
2124 RoadBits bits = GetRoadBits(tile, rtt);
2125
2126 /* no roadbit at this side of tile, return 0 */
2127 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break;
2128
2129 uint multiplier = drd_to_multiplier[(rtt == RTT_TRAM) ? DRD_NONE : GetDisallowedRoadDirections(tile)];
2130 if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier);
2131 break;
2132 }
2133
2134 case ROAD_TILE_CROSSING: {
2135 Axis axis = GetCrossingRoadAxis(tile);
2136
2137 if (side != INVALID_DIAGDIR && axis != DiagDirToAxis(side)) break;
2138
2139 trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis));
2140 if (IsCrossingBarred(tile)) {
2141 red_signals = trackdirbits;
2142 if (TrainOnCrossing(tile)) break;
2143
2144 auto mask_red_signal_bits_if_crossing_barred = [&](TileIndex t, TrackdirBits mask) {
2145 if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
2146 };
2147 /* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
2148 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE);
2149 /* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
2150 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW);
2151 }
2152 break;
2153 }
2154
2155 default:
2156 case ROAD_TILE_DEPOT: {
2158
2159 if (side != INVALID_DIAGDIR && side != dir) break;
2160
2162 break;
2163 }
2164 }
2165 break;
2166 }
2167
2168 default: break;
2169 }
2170 return CombineTrackStatus(trackdirbits, red_signals);
2171}
2172
2173static const StringID _road_tile_strings[] = {
2174 STR_LAI_ROAD_DESCRIPTION_ROAD,
2175 STR_LAI_ROAD_DESCRIPTION_ROAD,
2176 STR_LAI_ROAD_DESCRIPTION_ROAD,
2177 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2178 STR_LAI_ROAD_DESCRIPTION_ROAD,
2179 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2180 STR_LAI_ROAD_DESCRIPTION_ROAD,
2181 STR_LAI_ROAD_DESCRIPTION_ROAD,
2182};
2183
2184static void GetTileDesc_Road(TileIndex tile, TileDesc &td)
2185{
2186 Owner rail_owner = INVALID_OWNER;
2187 Owner road_owner = INVALID_OWNER;
2188 Owner tram_owner = INVALID_OWNER;
2189
2190 RoadType road_rt = GetRoadTypeRoad(tile);
2191 RoadType tram_rt = GetRoadTypeTram(tile);
2192 if (road_rt != INVALID_ROADTYPE) {
2193 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
2194 td.roadtype = rti->strings.name;
2195 td.road_speed = rti->max_speed / 2;
2196 road_owner = GetRoadOwner(tile, RTT_ROAD);
2197 }
2198 if (tram_rt != INVALID_ROADTYPE) {
2199 const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
2200 td.tramtype = rti->strings.name;
2201 td.tram_speed = rti->max_speed / 2;
2202 tram_owner = GetRoadOwner(tile, RTT_TRAM);
2203 }
2204
2205 switch (GetRoadTileType(tile)) {
2206 case ROAD_TILE_CROSSING: {
2207 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING;
2208 rail_owner = GetTileOwner(tile);
2209
2210 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2211 td.railtype = rti->strings.name;
2212 td.rail_speed = rti->max_speed;
2213
2214 break;
2215 }
2216
2217 case ROAD_TILE_DEPOT:
2218 td.str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
2219 td.build_date = Depot::GetByTile(tile)->build_date;
2220 break;
2221
2222 default: {
2223 td.str = (road_rt != INVALID_ROADTYPE ? _road_tile_strings[GetRoadside(tile)] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
2224 break;
2225 }
2226 }
2227
2228 /* Now we have to discover, if the tile has only one owner or many:
2229 * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
2230 * - Compare the found owner with the other owners, and test if they differ.
2231 * Note: If road exists it will be the first_owner.
2232 */
2233 Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
2234 bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
2235
2236 if (mixed_owners) {
2237 /* Multiple owners */
2238 td.owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_RAIL_OWNER);
2239 td.owner[0] = rail_owner;
2240 td.owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_ROAD_OWNER);
2241 td.owner[1] = road_owner;
2242 td.owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_TRAM_OWNER);
2243 td.owner[2] = tram_owner;
2244 } else {
2245 /* One to rule them all */
2246 td.owner[0] = first_owner;
2247 }
2248}
2249
2257
2258static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
2259{
2260 switch (GetRoadTileType(tile)) {
2261 case ROAD_TILE_DEPOT: {
2262 if (v->type != VEH_ROAD) break;
2263
2265 if (rv->frame == RVC_DEPOT_STOP_FRAME &&
2267 rv->state = RVSB_IN_DEPOT;
2269 rv->direction = ReverseDir(rv->direction);
2270 if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
2271 rv->tile = tile;
2272
2275 }
2276 break;
2277 }
2278
2279 default: break;
2280 }
2281 return VETSB_CONTINUE;
2282}
2283
2284
2285static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2286{
2287 if (IsRoadDepot(tile)) {
2288 if (GetTileOwner(tile) == old_owner) {
2289 if (new_owner == INVALID_OWNER) {
2291 } else {
2292 /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2293 RoadType rt = GetRoadTypeRoad(tile);
2294 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
2295 Company::Get(old_owner)->infrastructure.road[rt] -= 2;
2296 Company::Get(new_owner)->infrastructure.road[rt] += 2;
2297
2298 SetTileOwner(tile, new_owner);
2299 for (RoadTramType rtt : _roadtramtypes) {
2300 if (GetRoadOwner(tile, rtt) == old_owner) {
2301 SetRoadOwner(tile, rtt, new_owner);
2302 }
2303 }
2304 }
2305 }
2306 return;
2307 }
2308
2309 for (RoadTramType rtt : _roadtramtypes) {
2310 /* Update all roadtypes, no matter if they are present */
2311 if (GetRoadOwner(tile, rtt) == old_owner) {
2312 RoadType rt = GetRoadType(tile, rtt);
2313 if (rt != INVALID_ROADTYPE) {
2314 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2315 uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt));
2316 Company::Get(old_owner)->infrastructure.road[rt] -= num_bits;
2317 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits;
2318 }
2319
2320 SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
2321 }
2322 }
2323
2324 if (IsLevelCrossing(tile)) {
2325 if (GetTileOwner(tile) == old_owner) {
2326 if (new_owner == INVALID_OWNER) {
2328 } else {
2329 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2330 Company::Get(old_owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
2331 Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
2332
2333 SetTileOwner(tile, new_owner);
2334 }
2335 }
2336 }
2337}
2338
2339static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
2340{
2342 switch (GetRoadTileType(tile)) {
2343 case ROAD_TILE_CROSSING:
2344 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]);
2345 break;
2346
2347 case ROAD_TILE_DEPOT:
2348 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2349 break;
2350
2351 case ROAD_TILE_NORMAL: {
2352 RoadBits bits = GetAllRoadBits(tile);
2353 RoadBits bits_copy = bits;
2354 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2355 if (CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE).Succeeded()) {
2356 /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
2357 if (bits == bits_copy) {
2358 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2359
2360 /* Get the slope on top of the foundation */
2361 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), tileh_old);
2362 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), tileh_new);
2363
2364 /* The surface slope must not be changed */
2365 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2366 }
2367 }
2368 break;
2369 }
2370
2371 default: NOT_REACHED();
2372 }
2373 }
2374
2375 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
2376}
2377
2380{
2381 if (v->type != VEH_ROAD) return nullptr;
2382
2383 RoadVehicleList *affected_rvs = static_cast<RoadVehicleList*>(data);
2384 include(*affected_rvs, RoadVehicle::From(v)->First());
2385
2386 return nullptr;
2387}
2388
2395static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
2396{
2397 return (owner == OWNER_NONE || (owner == OWNER_TOWN && rtt == RTT_ROAD));
2398}
2399
2408static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
2409{
2410 // Scenario editor, maybe? Don't touch the owners when converting roadtypes...
2411 if (_current_company >= MAX_COMPANIES) return;
2412
2413 // We can't get a company from invalid owners but we can get ownership of roads without an owner
2414 if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
2415
2416 Company *c;
2417
2418 switch (owner.base()) {
2419 case OWNER_NONE.base():
2420 SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company);
2422 break;
2423
2424 default:
2425 c = Company::Get(owner);
2426 c->infrastructure.road[from_type] -= num_pieces;
2427 c->infrastructure.road[to_type] += num_pieces;
2429 break;
2430 }
2431}
2432
2444{
2445 TileIndex area_end = tile;
2446
2447 if (!ValParamRoadType(to_type)) return CMD_ERROR;
2448 if (area_start >= Map::Size()) return CMD_ERROR;
2449
2450 RoadVehicleList affected_rvs;
2451 RoadTramType rtt = GetRoadTramType(to_type);
2452
2454 CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert.
2455 bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633)
2456
2457 std::unique_ptr<TileIterator> iter = std::make_unique<OrthogonalTileIterator>(area_start, area_end);
2458 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
2459 /* Is road present on tile? */
2460 if (!MayHaveRoad(tile)) continue;
2461
2462 /* Converting to the same subtype? */
2463 RoadType from_type = GetRoadType(tile, rtt);
2464 if (from_type == INVALID_ROADTYPE || from_type == to_type) continue;
2465
2466 /* Check if there is any infrastructure on tile */
2467 TileType tt = GetTileType(tile);
2468 switch (tt) {
2469 case MP_STATION:
2470 if (!IsAnyRoadStop(tile)) continue;
2471 break;
2472 case MP_ROAD:
2473 if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
2474 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD);
2475 continue;
2476 }
2477 break;
2478 case MP_TUNNELBRIDGE:
2479 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) continue;
2480 break;
2481 default: continue;
2482 }
2483
2484 /* Trying to convert other's road */
2485 Owner owner = GetRoadOwner(tile, rtt);
2486 if (!CanConvertUnownedRoadType(owner, rtt)) {
2487 CommandCost ret = CheckOwnership(owner, tile);
2488 if (ret.Failed()) {
2489 error = ret;
2490 continue;
2491 }
2492 }
2493
2494 /* Base the ability to replace town roads and bridges on the town's
2495 * acceptance of destructive actions. */
2496 if (owner == OWNER_TOWN) {
2499 if (ret.Failed()) {
2500 error = ret;
2501 continue;
2502 }
2503 }
2504
2505 /* Vehicle on the tile when not converting normal <-> powered
2506 * Tunnels and bridges have special check later */
2507 if (tt != MP_TUNNELBRIDGE) {
2508 if (!HasPowerOnRoad(from_type, to_type)) {
2510 if (ret.Failed()) {
2511 error = ret;
2512 continue;
2513 }
2514
2515 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2516 error.MakeError(STR_ERROR_OWNED_BY);
2517 if (IsLocalCompany()) {
2518 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2519 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2520 }
2521 continue;
2522 }
2523 }
2524
2525 uint num_pieces = CountBits(GetAnyRoadBits(tile, rtt));
2526 if (tt == MP_STATION && IsBayRoadStopTile(tile)) {
2527 num_pieces *= ROAD_STOP_TRACKBIT_FACTOR;
2528 } else if (tt == MP_ROAD && IsRoadDepot(tile)) {
2529 num_pieces *= ROAD_DEPOT_TRACKBIT_FACTOR;
2530 }
2531
2532 found_convertible_road = true;
2533 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2534
2535 if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
2536 /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */
2537 if (owner == _current_company) {
2538 ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
2539 }
2540
2541 /* Perform the conversion */
2542 SetRoadType(tile, rtt, to_type);
2543 MarkTileDirtyByTile(tile);
2544
2545 /* update power of train on this tile */
2546 FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
2547
2548 if (IsRoadDepotTile(tile)) {
2549 /* Update build vehicle window related to this depot */
2552 }
2553 }
2554 } else {
2555 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
2556
2557 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
2558 * it would cause assert because of different test and exec runs */
2559 if (endtile < tile) {
2560 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
2561 }
2562
2563 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
2564 if (!HasPowerOnRoad(from_type, to_type)) {
2565 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
2566 if (ret.Failed()) {
2567 error = ret;
2568 continue;
2569 }
2570
2571 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2572 error.MakeError(STR_ERROR_OWNED_BY);
2573 if (IsLocalCompany()) {
2574 auto params = GetParamsForOwnedBy(OWNER_TOWN, tile);
2575 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
2576 }
2577 continue;
2578 }
2579 }
2580
2581 /* There are 2 pieces on *every* tile of the bridge or tunnel */
2582 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * 2;
2583 found_convertible_road = true;
2584 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2585
2586 if (flags.Test(DoCommandFlag::Execute)) {
2587 /* Update the company infrastructure counters. */
2588 if (owner == _current_company) {
2589 /* Each piece should be counted TUNNELBRIDGE_TRACKBIT_FACTOR times
2590 * for the infrastructure counters (cause of #8297). */
2591 ConvertRoadTypeOwner(tile, num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR, owner, from_type, to_type);
2592 SetTunnelBridgeOwner(tile, endtile, _current_company);
2593 }
2594
2595 /* Perform the conversion */
2596 SetRoadType(tile, rtt, to_type);
2597 SetRoadType(endtile, rtt, to_type);
2598
2599 FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
2600 FindVehicleOnPos(endtile, &affected_rvs, &UpdateRoadVehPowerProc);
2601
2602 if (IsBridge(tile)) {
2603 MarkBridgeDirty(tile);
2604 } else {
2605 MarkTileDirtyByTile(tile);
2606 MarkTileDirtyByTile(endtile);
2607 }
2608 }
2609 }
2610 }
2611
2612 if (flags.Test(DoCommandFlag::Execute)) {
2613 /* Roadtype changed, update roadvehicles as when entering different track */
2614 for (RoadVehicle *v : affected_rvs) {
2615 v->CargoChanged();
2616 }
2617 }
2618
2619 return found_convertible_road ? cost : error;
2620}
2621
2622
2624extern const TileTypeProcs _tile_type_road_procs = {
2625 DrawTile_Road, // draw_tile_proc
2626 GetSlopePixelZ_Road, // get_slope_z_proc
2627 ClearTile_Road, // clear_tile_proc
2628 nullptr, // add_accepted_cargo_proc
2629 GetTileDesc_Road, // get_tile_desc_proc
2630 GetTileTrackStatus_Road, // get_tile_track_status_proc
2631 ClickTile_Road, // click_tile_proc
2632 nullptr, // animate_tile_proc
2633 TileLoop_Road, // tile_loop_proc
2634 ChangeTileOwner_Road, // change_tile_owner_proc
2635 nullptr, // add_produced_cargo_proc
2636 VehicleEnter_Road, // vehicle_enter_tile_proc
2637 GetFoundation_Road, // get_foundation_proc
2638 TerraformTile_Road, // terraform_tile_proc
2639};
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.
#define CLRBITS(x, y)
Clears several bits in a variable.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
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.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
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 Timpl & Set()
Set all bits.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
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.
static 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.
Enum-as-bit-set wrapper.
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::@24 strings
Strings associated with the rail type.
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::@21 base_sprites
Struct containing the main sprites.
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
StringID name
Name of this rail type.
Definition road.h:94
struct RoadTypeInfo::@26 cursor
Cursors associated with the road type.
SpriteID build_y_road
button for building single rail in Y direction
Definition road.h:77
struct RoadTypeInfo::@27 strings
Strings associated with the rail type.
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
SpriteID build_depot
button for building depots
Definition road.h:79
SpriteID build_tunnel
button for building a tunnel
Definition road.h:80
struct RoadTypeInfo::@25 gui_sprites
struct containing the sprites for the road GUI.
static constexpr TimerGame< struct Calendar >::Date INVALID_DATE
Representation of an invalid date.
CommandCost CommandCostWithParam(StringID str, uint64_t value)
Return an error status, with string and parameter.
Definition command.cpp:418
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.
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:568
header file for electrified rail specific functions
bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition elrail_func.h:30
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:72
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:989
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.
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:87
Base for the NewGRF implementation.
bool HasGrfMiscBit(GrfMiscBit bit)
Check for grf miscellaneous bits.
Definition newgrf.h:193
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
Definition newgrf.h:177
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:338
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:153
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:235
@ 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:256
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:220
Money RoadConvertCost(RoadType from, RoadType to)
Calculates the cost of road conversion.
Definition road.h:274
@ 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:288
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:245
void ResetRoadTypes()
Reset all road type information to its default values.
Definition road_cmd.cpp:67
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:114
RoadTypes _roadtypes_type
Bitmap of road/tram types.
Definition road_cmd.cpp:62
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:609
static const RoadBits _invalid_tileh_slopes_road[2][15]
Invalid RoadBits on slopes.
Definition road_cmd.cpp:202
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:949
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:544
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:179
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.
CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type)
Convert one road subtype to another.
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
Update road infrastructure counts for a company.
Definition road_cmd.cpp:190
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.
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:978
std::tuple< CommandCost, Money > CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
Remove a long piece of road.
static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
Checks the tile and returns whether the current player is allowed to convert the roadtype to another ...
static 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:324
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
Draws details on/around the road.
static bool DrawRoadAsSnowDesert(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...
const TileTypeProcs _tile_type_road_procs
Tile callback functions for road tiles.
Definition landscape.cpp:50
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:134
static Vehicle * UpdateRoadVehPowerProc(Vehicle *v, void *data)
Update power of road vehicle under which is the roadtype being converted.
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:262
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:103
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.
RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance)
Returns the RoadBits on an arbitrary tile Special behaviour:
Definition road_map.cpp:33
void SetRoadOwner(Tile t, RoadTramType rtt, Owner o)
Set the owner of a specific road type.
Definition road_map.h:251
bool HasCrossingReservation(Tile t)
Get the reservation state of the rail crossing.
Definition road_map.h:380
bool HasTownOwnedRoad(Tile t)
Checks if given tile has town owned road.
Definition road_map.h:280
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:74
static debug_inline bool IsRoadDepot(Tile t)
Return whether a tile is a road depot.
Definition road_map.h:106
#define IsOnDesert
Check if a road tile has snow/desert.
Definition road_map.h:453
void SetRoadDepotExitDirection(Tile tile, DiagDirection dir)
Sets the exit direction of a road depot.
Definition road_map.h:680
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition road_map.h:95
bool IncreaseRoadWorksCounter(Tile t)
Increase the progress counter of road works.
Definition road_map.h:523
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:128
bool MayHaveRoad(Tile t)
Test whether a tile can have road/tram types.
Definition road_map.h:33
bool IsValidDisallowedRoadDirections(DisallowedRoadDirections drt)
Checks if a DisallowedRoadDirections is valid.
Definition road_map.h:291
Axis GetCrossingRoadAxis(Tile t)
Get the road axis of a level crossing.
Definition road_map.h:325
TrackBits GetCrossingRailBits(Tile tile)
Get the rail track bits of a level crossing.
Definition road_map.h:368
void SetDisallowedRoadDirections(Tile t, DisallowedRoadDirections drd)
Sets the disallowed directions.
Definition road_map.h:312
Track GetCrossingRailTrack(Tile tile)
Get the rail track of a level crossing.
Definition road_map.h:358
void StartRoadWorks(Tile t)
Start road works on a tile.
Definition road_map.h:535
DisallowedRoadDirections GetDisallowedRoadDirections(Tile t)
Gets the disallowed directions.
Definition road_map.h:301
bool HasTileRoadType(Tile t, RoadTramType rtt)
Check if a tile has a road or a tram road type.
Definition road_map.h:211
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition road_map.h:565
#define ToggleDesert
Toggle the snow/desert state of a road tile.
Definition road_map.h:465
static debug_inline bool IsRoadDepotTile(Tile t)
Return whether a tile is a road depot tile.
Definition road_map.h:116
void MakeRoadNormal(Tile t, RoadBits bits, RoadType road_rt, RoadType tram_rt, TownID town, Owner road, Owner tram)
Make a normal road tile.
Definition road_map.h:635
Roadside GetRoadside(Tile tile)
Get the decorations of a road.
Definition road_map.h:493
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:660
RoadBits GetAllRoadBits(Tile tile)
Get all set RoadBits on the given tile.
Definition road_map.h:141
void ToggleSnow(Tile t)
Toggle the snow/desert state of a road tile.
Definition road_map.h:470
bool IsOnSnow(Tile t)
Check if a road tile has snow/desert.
Definition road_map.h:459
Axis GetCrossingRailAxis(Tile t)
Get the rail axis of a level crossing.
Definition road_map.h:337
void TerminateRoadWorks(Tile t)
Terminate road works on a tile.
Definition road_map.h:551
RoadBits GetCrossingRoadBits(Tile tile)
Get the road bits of a level crossing.
Definition road_map.h:348
void SetRoadType(Tile t, RoadTramType rtt, RoadType rt)
Set the road type of a tile.
Definition road_map.h:604
Owner GetRoadOwner(Tile t, RoadTramType rtt)
Get the owner of a specific road type.
Definition road_map.h:234
static debug_inline RoadTileType GetRoadTileType(Tile t)
Get the type of the road tile.
Definition road_map.h:52
bool IsCrossingBarred(Tile t)
Check if the level crossing is barred.
Definition road_map.h:416
void SetRoadside(Tile tile, Roadside s)
Set the decorations of a road.
Definition road_map.h:503
bool IsRoadOwner(Tile t, RoadTramType rtt, Owner o)
Check if a specific road type is owned by an owner.
Definition road_map.h:268
void MakeRoadDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RoadType rt)
Make a road depot.
Definition road_map.h:694
void SetCrossingReservation(Tile t, bool b)
Set the reservation state of the rail crossing.
Definition road_map.h:393
void SetRoadBits(Tile t, RoadBits r, RoadTramType rtt)
Set the present road bits for a specific road type.
Definition road_map.h:153
Roadside
The possible road side decorations.
Definition road_map.h:477
@ ROADSIDE_GRASS_ROAD_WORKS
Road on grass with road works.
Definition road_map.h:484
@ ROADSIDE_PAVED
Road with paved sidewalks.
Definition road_map.h:480
@ ROADSIDE_STREET_LIGHTS
Road with street lights on paved sidewalks.
Definition road_map.h:481
@ ROADSIDE_BARREN
Road on barren land.
Definition road_map.h:478
@ ROADSIDE_GRASS
Road on grass.
Definition road_map.h:479
@ ROADSIDE_TREES
Road with trees on paved sidewalks.
Definition road_map.h:483
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition road_map.h:85
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition road_map.h:513
static debug_inline bool IsNormalRoad(Tile t)
Return whether a tile is a normal road.
Definition road_map.h:64
RoadBits
Enumeration for the road parts on a tile.
Definition road_type.h:52
@ ROAD_SW
South-west part.
Definition road_type.h:55
@ ROAD_ALL
Full 4-way crossing.
Definition road_type.h:66
@ ROAD_NONE
No road-part is build.
Definition road_type.h:53
@ ROAD_NE
North-east part.
Definition road_type.h:57
@ ROAD_SE
South-east part.
Definition road_type.h:56
@ ROAD_Y
Full road along the y-axis (north-west + south-east)
Definition road_type.h:59
@ ROAD_NW
North-west part.
Definition road_type.h:54
@ ROAD_X
Full road along the x-axis (south-west + north-east)
Definition road_type.h:58
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition road_type.h:38
@ ROADTYPES_TRAM
Trams.
Definition road_type.h:41
@ ROADTYPES_NONE
No roadtypes.
Definition road_type.h:39
RoadType
The different roadtypes we support.
Definition road_type.h:25
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:30
@ ROADTYPE_TRAM
Trams.
Definition road_type.h:28
@ ROADTYPE_ROAD
Basic road type.
Definition road_type.h:27
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:29
@ ROADTYPE_BEGIN
Used for iterations.
Definition road_type.h:26
DisallowedRoadDirections
Which directions are disallowed ?
Definition road_type.h:73
@ DRD_NORTHBOUND
All northbound traffic is disallowed.
Definition road_type.h:76
@ DRD_END
Sentinel.
Definition road_type.h:78
@ DRD_BOTH
All directions are disallowed.
Definition road_type.h:77
@ DRD_NONE
None of the directions are disallowed.
Definition road_type.h:74
@ DRD_SOUTHBOUND
All southbound traffic is disallowed.
Definition road_type.h:75
All the roadtype-specific information is stored here.
static const RoadTypeInfo _original_roadtypes[]
Global Roadtype definition.
Definition roadtypes.h:19
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:58
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:57
static constexpr int GetSlopeMaxZ(Slope s)
Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
Definition slope_func.h:160
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:415
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:126
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition slope_func.h:369
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:99
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:61
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:56
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:58
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:57
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:55
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
@ FOUNDATION_LEVELED
The tile is leveled up to a flat slope.
Definition slope_type.h:95
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:94
@ FOUNDATION_INCLINED_X
The tile has an along X-axis inclined foundation.
Definition slope_type.h:96
@ FOUNDATION_INCLINED_Y
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:97
static const uint32_t VALID_LEVEL_CROSSING_SLOPES
Constant bitset with safe slopes for building a level crossing.
Definition slope_type.h:86
Functions related to sound.
@ SND_21_ROAD_WORKS
31 == 0x1F Road reconstruction animation
Definition sound_type.h:78
void DrawRailTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence in GUI with railroad specifics.
Definition sprite.h:105
void DrawRailTileSeq(const struct TileInfo *ti, const DrawTileSprites *dts, TransparencyOption to, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence on tile with railroad specifics.
Definition sprite.h:95
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1609
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
Definition sprites.h:272
static const PaletteID PALETTE_TO_BARE_LAND
sets colour to bare land stuff for rail, road and crossings
Definition sprites.h:1597
static const SpriteID SPR_ONEWAY_BASE
One way road sprites.
Definition sprites.h:293
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:277
EncodedString GetEncodedStringWithArgs(StringID str, std::span< const StringParameter > params)
Encode a string with its parameters into an encoded string.
Definition strings.cpp:102
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
VehicleType type
Type of vehicle.
bool value
tells if the bool cheat is active or not
Definition cheat_type.h:18
Cheat magic_bulldozer
dynamite industries, objects
Definition cheat_type.h:27
SoundSettings sound
sound effect settings
GUISettings gui
settings related to the GUI
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
std::array< uint32_t, RAILTYPE_END > rail
Count of company owned track bits for each rail type.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
bool build_on_slopes
allow building on slopes
bool extra_dynamite
extra dynamite
bool crossing_with_competitor
allow building of level crossings with competitor roads or rails
TimerGameCalendar::Date build_date
Date of construction.
Definition depot_base.h:26
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:46
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:47
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:185
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:265
Tile description for the 'land area information' tool.
Definition tile_cmd.h:52
uint16_t rail_speed
Speed limit of rail (bridges and track)
Definition tile_cmd.h:65
StringID str
Description of the tile.
Definition tile_cmd.h:53
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:57
std::array< Owner, 4 > owner
Name of the owner(s)
Definition tile_cmd.h:55
uint16_t tram_speed
Speed limit of tram (bridges and track)
Definition tile_cmd.h:69
StringID roadtype
Type of road on the tile.
Definition tile_cmd.h:66
StringID tramtype
Type of tram on the tile.
Definition tile_cmd.h:68
StringID railtype
Type of rail on the tile.
Definition tile_cmd.h:64
uint16_t road_speed
Speed limit of road (bridges and track)
Definition tile_cmd.h:67
std::array< StringID, 4 > owner_type
Type of each owner.
Definition tile_cmd.h:56
Tile information, used while rendering the tile.
Definition tile_cmd.h:43
int z
Height.
Definition tile_cmd.h:48
int x
X position of the tile in unit coordinates.
Definition tile_cmd.h:44
Slope tileh
Slope of the tile.
Definition tile_cmd.h:46
TileIndex tile
Tile index.
Definition tile_cmd.h:47
int y
Y position of the tile in unit coordinates.
Definition tile_cmd.h:45
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:159
std::array< uint32_t, HZB_END > 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.
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition tile_cmd.h:21
@ VETSB_ENTERED_WORMHOLE
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition tile_cmd.h:37
@ VETSB_CONTINUE
Bit sets of the above specified bits.
Definition tile_cmd.h:35
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.
HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile)
Returns the bit corresponding to the town zone of the specified tile.
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:959
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?
void MakeDefaultName(T *obj)
Set the default name for a depot/waypoint.
Definition town.h:246
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:69
@ TRACKDIR_Y_SE
Y-axis and direction to south-east.
Definition track_type.h:70
@ TRACKDIR_X_SW
X-axis and direction to south-west.
Definition track_type.h:77
@ TRACKDIR_Y_NW
Y-axis and direction to north-west.
Definition track_type.h:78
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:98
@ TRACKDIR_BIT_Y_NW
Track y-axis, direction north-west.
Definition track_type.h:108
@ TRACKDIR_BIT_X_NE
Track x-axis, direction north-east.
Definition track_type.h:100
@ TRACKDIR_BIT_Y_SE
Track y-axis, direction south-east.
Definition track_type.h:101
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:99
@ TRACKDIR_BIT_X_SW
Track x-axis, direction south-west.
Definition track_type.h:107
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:543
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1545
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition vehicle.cpp:502
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:572
@ 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:673
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:566
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:589
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:3224
@ 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.
@ ZOOM_LVL_DETAIL
All zoom levels below or equal to this will result in details on the screen, like road-work,...
Definition zoom_type.h:38