OpenTTD Source 20241222-master-gc72542431a
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 (HasBit(rti->flags, ROTF_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 = ROTFB_NONE;
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, DoCommandFlag 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 SetDParam(0, t->index);
307 return CommandCost(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
308 }
309 rating_decrease = RATING_ROAD_DOWN_STEP_INNER;
310 }
311 ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM, flags);
312
313 return CommandCost();
314}
315
316
325static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadTramType rtt, bool town_check)
326{
327 assert(pieces != ROAD_NONE);
328
329 RoadType existing_rt = MayHaveRoad(tile) ? GetRoadType(tile, rtt) : INVALID_ROADTYPE;
330 /* The tile doesn't have the given road type */
331 if (existing_rt == INVALID_ROADTYPE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
332
333 switch (GetTileType(tile)) {
334 case MP_ROAD: {
336 if (ret.Failed()) return ret;
337 break;
338 }
339
340 case MP_STATION: {
341 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
342
344 if (ret.Failed()) return ret;
345 break;
346 }
347
348 case MP_TUNNELBRIDGE: {
351 if (ret.Failed()) return ret;
352 break;
353 }
354
355 default:
356 return CMD_ERROR;
357 }
358
359 CommandCost ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rtt), rtt, flags, town_check);
360 if (ret.Failed()) return ret;
361
362 if (!IsTileType(tile, MP_ROAD)) {
363 /* If it's the last roadtype, just clear the whole tile */
364 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
365
367 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
368 /* Removing any roadbit in the bridge axis removes the roadtype (that's the behaviour remove-long-roads needs) */
369 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);
370
371 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
372 /* Pay for *every* tile of the bridge or tunnel */
373 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
374 cost.AddCost(len * 2 * RoadClearCost(existing_rt));
375 if (flags & DC_EXEC) {
376 /* A full diagonal road tile has two road bits. */
377 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
378
379 SetRoadType(other_end, rtt, INVALID_ROADTYPE);
380 SetRoadType(tile, rtt, INVALID_ROADTYPE);
381
382 /* If the owner of the bridge sells all its road, also move the ownership
383 * to the owner of the other roadtype, unless the bridge owner is a town. */
384 Owner other_owner = GetRoadOwner(tile, OtherRoadTramType(rtt));
385 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
386 SetTileOwner(tile, other_owner);
387 SetTileOwner(other_end, other_owner);
388 }
389
390 /* Mark tiles dirty that have been repaved */
391 if (IsBridge(tile)) {
392 MarkBridgeDirty(tile);
393 } else {
395 MarkTileDirtyByTile(other_end);
396 }
397 }
398 } else {
399 assert(IsDriveThroughStopTile(tile));
400 cost.AddCost(RoadClearCost(existing_rt) * 2);
401 if (flags & DC_EXEC) {
402 /* A full diagonal road tile has two road bits. */
403 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
404 SetRoadType(tile, rtt, INVALID_ROADTYPE);
406 }
407 }
408 return cost;
409 }
410
411 switch (GetRoadTileType(tile)) {
412 case ROAD_TILE_NORMAL: {
413 Slope tileh = GetTileSlope(tile);
414
415 /* Steep slopes behave the same as slopes with one corner raised. */
416 if (IsSteepSlope(tileh)) {
418 }
419
420 RoadBits present = GetRoadBits(tile, rtt);
421 const RoadBits other = GetRoadBits(tile, OtherRoadTramType(rtt));
422 const Foundation f = GetRoadFoundation(tileh, present);
423
424 if (HasRoadWorks(tile) && _current_company != OWNER_WATER) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
425
426 /* Autocomplete to a straight road
427 * @li if the bits of the other roadtypes result in another foundation
428 * @li if build on slopes is disabled */
429 if ((IsStraightRoad(other) && (other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
431 pieces |= MirrorRoadBits(pieces);
432 }
433
434 /* limit the bits to delete to the existing bits. */
435 pieces &= present;
436 if (pieces == ROAD_NONE) return CommandCost((rtt == RTT_TRAM) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
437
438 /* Now set present what it will be after the remove */
439 present ^= pieces;
440
441 /* Check for invalid RoadBit combinations on slopes */
442 if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
443 (present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == present) {
444 return CMD_ERROR;
445 }
446
447 if (flags & DC_EXEC) {
448 if (HasRoadWorks(tile)) {
449 /* flooding tile with road works, don't forget to remove the effect vehicle too */
450 assert(_current_company == OWNER_WATER);
452 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
453 delete v;
454 }
455 }
456 }
457
458 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)CountBits(pieces));
459
460 if (present == ROAD_NONE) {
461 /* No other road type, just clear tile. */
462 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
463 /* Includes MarkTileDirtyByTile() */
464 DoClearSquare(tile);
465 } else {
466 if (rtt == RTT_ROAD && IsRoadOwner(tile, rtt, OWNER_TOWN)) {
467 /* Update nearest-town index */
468 const Town *town = CalcClosestTownFromTile(tile);
469 SetTownIndex(tile, town == nullptr ? INVALID_TOWN : town->index);
470 }
471 if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE);
472 SetRoadBits(tile, ROAD_NONE, rtt);
473 SetRoadType(tile, rtt, INVALID_ROADTYPE);
475 }
476 } else {
477 /* When bits are removed, you *always* end up with something that
478 * is not a complete straight road tile. However, trams do not have
479 * onewayness, so they cannot remove it either. */
480 if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE);
481 SetRoadBits(tile, present, rtt);
483 }
484 }
485
486 CommandCost cost(EXPENSES_CONSTRUCTION, CountBits(pieces) * RoadClearCost(existing_rt));
487 /* If we build a foundation we have to pay for it. */
488 if (f == FOUNDATION_NONE && GetRoadFoundation(tileh, present) != FOUNDATION_NONE) cost.AddCost(_price[PR_BUILD_FOUNDATION]);
489
490 return cost;
491 }
492
493 case ROAD_TILE_CROSSING: {
494 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
495 return CMD_ERROR;
496 }
497
498 if (flags & DC_EXEC) {
500
501 /* A full diagonal road tile has two road bits. */
502 UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
503
504 Track railtrack = GetCrossingRailTrack(tile);
505 if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
506 TrackBits tracks = GetCrossingRailBits(tile);
507 bool reserved = HasCrossingReservation(tile);
508 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
509 if (reserved) SetTrackReservation(tile, tracks);
510
511 /* Update rail count for level crossings. The plain track should still be accounted
512 * for, so only subtract the difference to the level crossing cost. */
514 if (c != nullptr) {
517 }
518 } else {
519 SetRoadType(tile, rtt, INVALID_ROADTYPE);
520 }
522 YapfNotifyTrackLayoutChange(tile, railtrack);
523 }
524 return CommandCost(EXPENSES_CONSTRUCTION, RoadClearCost(existing_rt) * 2);
525 }
526
527 default:
528 case ROAD_TILE_DEPOT:
529 return CMD_ERROR;
530 }
531}
532
533
545static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
546{
547 /* Remove already build pieces */
548 CLRBITS(*pieces, existing);
549
550 /* If we can't build anything stop here */
551 if (*pieces == ROAD_NONE) return CMD_ERROR;
552
553 /* All RoadBit combos are valid on flat land */
554 if (tileh == SLOPE_FLAT) return CommandCost();
555
556 /* Steep slopes behave the same as slopes with one corner raised. */
557 if (IsSteepSlope(tileh)) {
559 }
560
561 /* Save the merge of all bits of the current type */
562 RoadBits type_bits = existing | *pieces;
563
564 /* Roads on slopes */
565 if (_settings_game.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
566
567 /* If we add leveling we've got to pay for it */
568 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
569
570 return CommandCost();
571 }
572
573 /* Autocomplete uphill roads */
574 *pieces |= MirrorRoadBits(*pieces);
575 type_bits = existing | *pieces;
576
577 /* Uphill roads */
578 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
579 (_invalid_tileh_slopes_road[1][tileh] & (other | type_bits)) == ROAD_NONE) {
580
581 /* Slopes with foundation ? */
582 if (IsSlopeWithOneCornerRaised(tileh)) {
583
584 /* Prevent build on slopes if it isn't allowed */
586
587 /* If we add foundation we've got to pay for it */
588 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
589
590 return CommandCost();
591 }
592 } else {
593 if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
594 return CommandCost();
595 }
596 }
597 return CMD_ERROR;
598}
599
611{
612 CompanyID company = _current_company;
614
615 RoadBits existing = ROAD_NONE;
616 RoadBits other_bits = ROAD_NONE;
617
618 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
619 * if a non-company is building the road */
620 if ((Company::IsValidID(company) && town_id != 0) || (company == OWNER_TOWN && !Town::IsValidID(town_id)) || (company == OWNER_DEITY && town_id != 0)) return CMD_ERROR;
621 if (company != OWNER_TOWN) {
622 const Town *town = CalcClosestTownFromTile(tile);
623 town_id = (town != nullptr) ? town->index : INVALID_TOWN;
624
625 if (company == OWNER_DEITY) {
626 company = OWNER_TOWN;
627
628 /* If we are not within a town, we are not owned by the town */
629 if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
630 company = OWNER_NONE;
631 }
632 }
633 }
634
635 /* do not allow building 'zero' road bits, code wouldn't handle it */
636 if (pieces == ROAD_NONE || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR;
637 if (!ValParamRoadType(rt)) return CMD_ERROR;
638
639 Slope tileh = GetTileSlope(tile);
640 RoadTramType rtt = GetRoadTramType(rt);
641
642 bool need_to_clear = false;
643 switch (GetTileType(tile)) {
644 case MP_ROAD:
645 switch (GetRoadTileType(tile)) {
646 case ROAD_TILE_NORMAL: {
647 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
648
649 other_bits = GetRoadBits(tile, OtherRoadTramType(rtt));
650 if (!HasTileRoadType(tile, rtt)) break;
651
652 existing = GetRoadBits(tile, rtt);
653 bool crossing = !IsStraightRoad(existing | pieces);
654 if (rtt == RTT_ROAD && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
655 /* Junctions cannot be one-way */
656 return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
657 }
658 if ((existing & pieces) == pieces) {
659 /* We only want to set the (dis)allowed road directions */
660 if (toggle_drd != DRD_NONE && rtt == RTT_ROAD) {
661 if (crossing) return CommandCost(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
662
663 Owner owner = GetRoadOwner(tile, rtt);
664 if (owner != OWNER_NONE) {
665 CommandCost ret = CheckOwnership(owner, tile);
666 if (ret.Failed()) return ret;
667 }
668
670 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
671
672 /* We allow removing disallowed directions to break up
673 * deadlocks, but adding them can break articulated
674 * vehicles. As such, only when less is disallowed,
675 * i.e. bits are removed, we skip the vehicle check. */
676 if (CountBits(dis_existing) <= CountBits(dis_new)) {
678 if (ret.Failed()) return ret;
679 }
680
681 /* Ignore half built tiles */
682 if ((flags & DC_EXEC) && IsStraightRoad(existing)) {
683 SetDisallowedRoadDirections(tile, dis_new);
685 }
686 return CommandCost();
687 }
688 return CommandCost(STR_ERROR_ALREADY_BUILT);
689 }
690 /* Disallow breaking end-of-line of someone else
691 * so trams can still reverse on this tile. */
692 if (rtt == RTT_TRAM && HasExactlyOneBit(existing)) {
693 Owner owner = GetRoadOwner(tile, rtt);
694 if (Company::IsValidID(owner)) {
695 CommandCost ret = CheckOwnership(owner);
696 if (ret.Failed()) return ret;
697 }
698 }
699 break;
700 }
701
703 if (RoadNoLevelCrossing(rt)) {
704 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
705 }
706
707 other_bits = GetCrossingRoadBits(tile);
708 if (pieces & ComplementRoadBits(other_bits)) goto do_clear;
709 pieces = other_bits; // we need to pay for both roadbits
710
711 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
712 break;
713
714 case ROAD_TILE_DEPOT:
715 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
716 goto do_clear;
717
718 default: NOT_REACHED();
719 }
720 break;
721
722 case MP_RAILWAY: {
723 if (IsSteepSlope(tileh)) {
724 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
725 }
726
727 /* Level crossings may only be built on these slopes */
728 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
729 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
730 }
731
734 if (ret.Failed()) return ret;
735 }
736
737 if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
738
739 if (RoadNoLevelCrossing(rt)) {
740 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
741 }
742
744 return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
745 }
746
747 Axis roaddir;
748 switch (GetTrackBits(tile)) {
749 case TRACK_BIT_X:
750 if (pieces & ROAD_X) goto do_clear;
751 roaddir = AXIS_Y;
752 break;
753
754 case TRACK_BIT_Y:
755 if (pieces & ROAD_Y) goto do_clear;
756 roaddir = AXIS_X;
757 break;
758
759 default: goto do_clear;
760 }
761
763 if (ret.Failed()) return ret;
764
765 if (flags & DC_EXEC) {
766 Track railtrack = AxisToTrack(OtherAxis(roaddir));
767 YapfNotifyTrackLayoutChange(tile, railtrack);
768 /* Update company infrastructure counts. A level crossing has two road bits. */
769 UpdateCompanyRoadInfrastructure(rt, company, 2);
770
771 /* Update rail count for level crossings. The plain track is already
772 * counted, so only add the difference to the level crossing cost. */
774 if (c != nullptr) {
777 }
778
779 /* Always add road to the roadtypes (can't draw without it) */
780 bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
781 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id);
782 SetCrossingReservation(tile, reserved);
783 UpdateLevelCrossing(tile, false);
786 }
788 }
789
790 case MP_STATION: {
791 if ((GetAnyRoadBits(tile, rtt) & pieces) == pieces) return CommandCost(STR_ERROR_ALREADY_BUILT);
792 if (!IsDriveThroughStopTile(tile)) goto do_clear;
793
795 if (pieces & ~curbits) goto do_clear;
796 pieces = curbits; // we need to pay for both roadbits
797
798 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
799 break;
800 }
801
802 case MP_TUNNELBRIDGE: {
803 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) goto do_clear;
804 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
805 if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
806 if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
807 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
809 if (ret.Failed()) return ret;
810 break;
811 }
812
813 default: {
814do_clear:;
815 need_to_clear = true;
816 break;
817 }
818 }
819
820 if (need_to_clear) {
822 if (ret.Failed()) return ret;
823 cost.AddCost(ret);
824 }
825
826 if (other_bits != pieces) {
827 /* Check the foundation/slopes when adding road/tram bits */
828 CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
829 /* Return an error if we need to build a foundation (ret != 0) but the
830 * current setting is turned off */
831 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
832 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
833 }
834 cost.AddCost(ret);
835 }
836
837 if (!need_to_clear) {
838 if (IsTileType(tile, MP_ROAD)) {
839 /* Don't put the pieces that already exist */
840 pieces &= ComplementRoadBits(existing);
841
842 /* Check if new road bits will have the same foundation as other existing road types */
843 if (IsNormalRoad(tile)) {
844 Slope slope = GetTileSlope(tile);
845 Foundation found_new = GetRoadFoundation(slope, pieces | existing);
846
847 RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt));
848 /* do not check if there are not road bits of given type */
849 if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) {
850 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
851 }
852 }
853 }
854
856 if (ret.Failed()) return ret;
857
858 if (IsNormalRoadTile(tile)) {
859 /* If the road types don't match, try to convert only if vehicles of
860 * the new road type are not powered on the present road type and vehicles of
861 * the present road type are powered on the new road type. */
862 RoadType existing_rt = GetRoadType(tile, rtt);
863 if (existing_rt != INVALID_ROADTYPE && existing_rt != rt) {
864 if (HasPowerOnRoad(rt, existing_rt)) {
865 rt = existing_rt;
866 } else if (HasPowerOnRoad(existing_rt, rt)) {
867 ret = Command<CMD_CONVERT_ROAD>::Do(flags, tile, tile, rt);
868 if (ret.Failed()) return ret;
869 cost.AddCost(ret);
870 } else {
871 return CMD_ERROR;
872 }
873 }
874 }
875 }
876
877 uint num_pieces = (!need_to_clear && IsTileType(tile, MP_TUNNELBRIDGE)) ?
878 /* There are 2 pieces on *every* tile of the bridge or tunnel */
879 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) :
880 /* Count pieces */
881 CountBits(pieces);
882
883 cost.AddCost(num_pieces * RoadBuildCost(rt));
884
885 if (flags & DC_EXEC) {
886 switch (GetTileType(tile)) {
887 case MP_ROAD: {
888 RoadTileType rttype = GetRoadTileType(tile);
889 if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) {
890 SetRoadType(tile, rtt, rt);
891 SetRoadOwner(tile, rtt, company);
892 if (rtt == RTT_ROAD) SetTownIndex(tile, town_id);
893 }
894 if (rttype != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rtt);
895 break;
896 }
897
898 case MP_TUNNELBRIDGE: {
899 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
900
901 SetRoadType(other_end, rtt, rt);
902 SetRoadType(tile, rtt, rt);
903 SetRoadOwner(other_end, rtt, company);
904 SetRoadOwner(tile, rtt, company);
905
906 /* Mark tiles dirty that have been repaved */
907 if (IsBridge(tile)) {
908 MarkBridgeDirty(tile);
909 } else {
910 MarkTileDirtyByTile(other_end);
912 }
913 break;
914 }
915
916 case MP_STATION: {
917 assert(IsDriveThroughStopTile(tile));
918 SetRoadType(tile, rtt, rt);
919 SetRoadOwner(tile, rtt, company);
920 break;
921 }
922
923 default:
924 MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company);
925 break;
926 }
927
928 /* Update company infrastructure count. */
930 UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), num_pieces);
931
932 if (rtt == RTT_ROAD && IsNormalRoadTile(tile)) {
933 existing |= pieces;
935 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
936 }
937
939 }
940 return cost;
941}
942
951{
952 tile += TileOffsByDiagDir(dir);
953 if (!IsValidTile(tile) || !MayHaveRoad(tile)) return false;
954
955 RoadTramType rtt = GetRoadTramType(rt);
956 RoadType existing = GetRoadType(tile, rtt);
957 if (existing == INVALID_ROADTYPE) return false;
958 if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false;
959
960 RoadBits bits = GetAnyRoadBits(tile, rtt, false);
961 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
962}
963
979CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
980{
981 if (start_tile >= Map::Size()) return CMD_ERROR;
982
983 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
984
985 /* Only drag in X or Y direction dictated by the direction variable */
986 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
987 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
988
989 DiagDirection dir = AxisToDiagDir(axis);
990
991 /* Swap direction, also the half-tile drag vars. */
992 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
993 dir = ReverseDiagDir(dir);
994 start_half = !start_half;
995 end_half = !end_half;
996 if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
997 }
998
999 /* On the X-axis, we have to swap the initial bits, so they
1000 * will be interpreted correctly in the GTTS. Furthermore
1001 * when you just 'click' on one tile to build them. */
1002 if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
1003
1005 CommandCost last_error = CMD_ERROR;
1006 TileIndex tile = start_tile;
1007 bool had_bridge = false;
1008 bool had_tunnel = false;
1009 bool had_success = false;
1010
1011 /* Start tile is the first tile clicked by the user. */
1012 for (;;) {
1013 RoadBits bits = AxisToRoadBits(axis);
1014
1015 /* Determine which road parts should be built. */
1016 if (!is_ai && start_tile != end_tile) {
1017 /* Only build the first and last roadbit if they can connect to something. */
1018 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1019 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1020 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1021 bits = DiagDirToRoadBits(dir);
1022 }
1023 } else {
1024 /* Road parts only have to be built at the start tile or at the end tile. */
1025 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1026 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1027 }
1028
1029 CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, 0);
1030 if (ret.Failed()) {
1031 last_error = ret;
1032 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1033 if (is_ai) return last_error;
1034 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1035 }
1036 } else {
1037 had_success = true;
1038 /* Only pay for the upgrade on one side of the bridges and tunnels */
1039 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
1040 if (IsBridge(tile)) {
1041 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1042 cost.AddCost(ret);
1043 }
1044 had_bridge = true;
1045 } else { // IsTunnel(tile)
1046 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1047 cost.AddCost(ret);
1048 }
1049 had_tunnel = true;
1050 }
1051 } else {
1052 cost.AddCost(ret);
1053 }
1054 }
1055
1056 if (tile == end_tile) break;
1057
1058 tile += TileOffsByDiagDir(dir);
1059 }
1060
1061 return had_success ? cost : last_error;
1062}
1063
1075std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlag flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
1076{
1078
1079 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
1080 if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 };
1081
1082 /* Only drag in X or Y direction dictated by the direction variable */
1083 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis
1084 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis
1085
1086 /* Swap start and ending tile, also the half-tile drag vars. */
1087 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
1088 std::swap(start_tile, end_tile);
1089 std::swap(start_half, end_half);
1090 }
1091
1092 Money money_available = GetAvailableMoneyForCommand();
1093 Money money_spent = 0;
1094 TileIndex tile = start_tile;
1095 CommandCost last_error = CMD_ERROR;
1096 bool had_success = false;
1097 /* Start tile is the small number. */
1098 for (;;) {
1099 RoadBits bits = AxisToRoadBits(axis);
1100
1101 if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
1102 if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
1103
1104 /* try to remove the halves. */
1105 if (bits != 0) {
1106 RoadTramType rtt = GetRoadTramType(rt);
1107 CommandCost ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rtt, true);
1108 if (ret.Succeeded()) {
1109 if (flags & DC_EXEC) {
1110 money_spent += ret.GetCost();
1111 if (money_spent > 0 && money_spent > money_available) {
1112 return { cost, std::get<0>(Command<CMD_REMOVE_LONG_ROAD>::Do(flags & ~DC_EXEC, end_tile, start_tile, rt, axis, start_half, end_half)).GetCost() };
1113 }
1114 RemoveRoad(tile, flags, bits, rtt, false);
1115 }
1116 cost.AddCost(ret);
1117 had_success = true;
1118 } else {
1119 /* Some errors are more equal than others. */
1120 switch (last_error.GetErrorMessage()) {
1121 case STR_ERROR_OWNED_BY:
1122 case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS:
1123 break;
1124 default:
1125 last_error = ret;
1126 }
1127 }
1128 }
1129
1130 if (tile == end_tile) break;
1131
1132 tile += TileOffsByAxis(axis);
1133 }
1134
1135 return { had_success ? cost : last_error, 0 };
1136}
1137
1150{
1151 if (!ValParamRoadType(rt) || !IsValidDiagDirection(dir)) return CMD_ERROR;
1152
1154
1155 Slope tileh = GetTileSlope(tile);
1156 if (tileh != SLOPE_FLAT) {
1158 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
1159 }
1160 cost.AddCost(_price[PR_BUILD_FOUNDATION]);
1161 }
1162
1163 /* Allow the user to rotate the depot instead of having to destroy it and build it again */
1164 bool rotate_existing_depot = false;
1165 if (IsRoadDepotTile(tile) && (HasRoadTypeTram(tile) ? rt == GetRoadTypeTram(tile) : rt == GetRoadTypeRoad(tile)))
1166 {
1167 CommandCost ret = CheckTileOwnership(tile);
1168 if (ret.Failed()) return ret;
1169
1170 if (dir == GetRoadDepotDirection(tile)) return CommandCost();
1171
1172 ret = EnsureNoVehicleOnGround(tile);
1173 if (ret.Failed()) return ret;
1174
1175 rotate_existing_depot = true;
1176 }
1177
1178 if (!rotate_existing_depot) {
1179 cost.AddCost(Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile));
1180 if (cost.Failed()) return cost;
1181
1182 if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1183
1184 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1185 }
1186
1187 if (flags & DC_EXEC) {
1188 if (rotate_existing_depot) {
1189 SetRoadDepotExitDirection(tile, dir);
1190 } else {
1191 Depot *dep = new Depot(tile);
1193 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1194 MakeDefaultName(dep);
1195
1196 /* A road depot has two road bits. */
1198 }
1199
1200 MarkTileDirtyByTile(tile);
1201 }
1202
1203 cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
1204 return cost;
1205}
1206
1207static CommandCost RemoveRoadDepot(TileIndex tile, DoCommandFlag flags)
1208{
1210 CommandCost ret = CheckTileOwnership(tile);
1211 if (ret.Failed()) return ret;
1212 }
1213
1215 if (ret.Failed()) return ret;
1216
1217 if (flags & DC_EXEC) {
1219 if (c != nullptr) {
1220 /* A road depot has two road bits. */
1221 RoadType rt = GetRoadTypeRoad(tile);
1222 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
1225 }
1226
1227 delete Depot::GetByTile(tile);
1228 DoClearSquare(tile);
1229 }
1230
1231 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_ROAD]);
1232}
1233
1234static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlag flags)
1235{
1236 switch (GetRoadTileType(tile)) {
1237 case ROAD_TILE_NORMAL: {
1238 RoadBits b = GetAllRoadBits(tile);
1239
1240 /* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */
1241 if ((HasExactlyOneBit(b) && GetRoadBits(tile, RTT_TRAM) == ROAD_NONE) || !(flags & DC_AUTO)) {
1243 for (RoadTramType rtt : _roadtramtypes) {
1244 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1245
1246 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rtt), rtt, true);
1247 if (tmp_ret.Failed()) return tmp_ret;
1248 ret.AddCost(tmp_ret);
1249 }
1250 return ret;
1251 }
1252 return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1253 }
1254
1255 case ROAD_TILE_CROSSING: {
1257
1258 if (flags & DC_AUTO) return CommandCost(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1259
1260 /* Must iterate over the roadtypes in a reverse manner because
1261 * tram tracks must be removed before the road bits. */
1262 for (RoadTramType rtt : { RTT_TRAM, RTT_ROAD }) {
1263 if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue;
1264
1265 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rtt, true);
1266 if (tmp_ret.Failed()) return tmp_ret;
1267 ret.AddCost(tmp_ret);
1268 }
1269
1270 if (flags & DC_EXEC) {
1272 }
1273 return ret;
1274 }
1275
1276 default:
1277 case ROAD_TILE_DEPOT:
1278 if (flags & DC_AUTO) {
1279 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1280 }
1281 return RemoveRoadDepot(tile, flags);
1282 }
1283}
1284
1285
1287 uint16_t image;
1288 uint8_t subcoord_x;
1289 uint8_t subcoord_y;
1290};
1291
1292#include "table/road_land.h"
1293
1302{
1303 /* Flat land and land without a road doesn't require a foundation */
1304 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1305
1306 /* Steep slopes behave the same as slopes with one corner raised. */
1307 if (IsSteepSlope(tileh)) {
1309 }
1310
1311 /* Leveled RoadBits on a slope */
1312 if ((_invalid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1313
1314 /* Straight roads without foundation on a slope */
1315 if (!IsSlopeWithOneCornerRaised(tileh) &&
1316 (_invalid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE)
1317 return FOUNDATION_NONE;
1318
1319 /* Roads on steep Slopes or on Slopes with one corner raised */
1321}
1322
1323const uint8_t _road_sloped_sprites[14] = {
1324 0, 0, 2, 0,
1325 0, 1, 0, 0,
1326 3, 0, 0, 0,
1327 0, 0
1328};
1329
1336static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
1337{
1338 if (slope != SLOPE_FLAT) {
1339 switch (slope) {
1340 case SLOPE_NE: return 11;
1341 case SLOPE_SE: return 12;
1342 case SLOPE_SW: return 13;
1343 case SLOPE_NW: return 14;
1344 default: NOT_REACHED();
1345 }
1346 } else {
1347 static const uint offsets[] = {
1348 0, 18, 17, 7,
1349 16, 0, 10, 5,
1350 15, 8, 1, 4,
1351 9, 3, 6, 2
1352 };
1353 return offsets[bits];
1354 }
1355}
1356
1366static bool DrawRoadAsSnowDesert(bool snow_or_desert, Roadside roadside)
1367{
1368 return (snow_or_desert &&
1369 !(_settings_game.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) &&
1370 roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS));
1371}
1372
1380{
1381 /* Don't draw the catenary under a low bridge */
1383 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1384
1385 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1386 }
1387
1388 if (CountBits(rb) > 2) {
1389 /* On junctions we check whether neighbouring tiles also have catenary, and possibly
1390 * do not draw catenary towards those neighbours, which do not have catenary. */
1391 RoadBits rb_new = ROAD_NONE;
1392 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
1393 if (rb & DiagDirToRoadBits(dir)) {
1394 TileIndex neighbour = TileAddByDiagDir(ti->tile, dir);
1395 if (MayHaveRoad(neighbour)) {
1396 RoadType rt_road = GetRoadTypeRoad(neighbour);
1397 RoadType rt_tram = GetRoadTypeTram(neighbour);
1398
1399 if ((rt_road != INVALID_ROADTYPE && HasRoadCatenary(rt_road)) ||
1400 (rt_tram != INVALID_ROADTYPE && HasRoadCatenary(rt_tram))) {
1401 rb_new |= DiagDirToRoadBits(dir);
1402 }
1403 }
1404 }
1405 }
1406 if (CountBits(rb_new) >= 2) rb = rb_new;
1407 }
1408
1409 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1412
1413 if (front != 0 || back != 0) {
1414 if (front != 0) front += GetRoadSpriteOffset(ti->tileh, rb);
1415 if (back != 0) back += GetRoadSpriteOffset(ti->tileh, rb);
1416 } else if (ti->tileh != SLOPE_FLAT) {
1417 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1418 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1419 } else {
1420 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb];
1421 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb];
1422 }
1423
1424 /* Catenary uses 1st company colour to help identify owner.
1425 * For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
1426 Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
1427 PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GENERAL_SPRITE_COLOUR(COLOUR_GREY) : COMPANY_SPRITE_COLOUR(owner));
1428 int z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
1429 if (back != 0) {
1430 /* The "back" sprite contains the west, north and east pillars.
1431 * We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
1432 * 3/8 is chosen so that sprites can somewhat graphically extend into the tile. */
1433 static const int INF = 1000;
1434 static const SubSprite west = { -INF, -INF, -12, INF };
1435 static const SubSprite north = { -12, -INF, 12, INF };
1436 static const SubSprite east = { 12, -INF, INF, INF };
1437 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 16, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 15, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_W), &west);
1438 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_N), &north);
1439 AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 16, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 15, GetSlopePixelZInCorner(ti->tileh, CORNER_E), &east);
1440 }
1441 if (front != 0) {
1442 /* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
1443 AddSortableSpriteToDraw(front, pal, ti->x, ti->y, 16, 16, z_wires + 1, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, z_wires);
1444 }
1445}
1446
1452{
1453 RoadBits road = ROAD_NONE;
1454 RoadBits tram = ROAD_NONE;
1455
1456 if (IsTileType(ti->tile, MP_ROAD)) {
1457 if (IsNormalRoad(ti->tile)) {
1458 road = GetRoadBits(ti->tile, RTT_ROAD);
1459 tram = GetRoadBits(ti->tile, RTT_TRAM);
1460 } else if (IsLevelCrossing(ti->tile)) {
1461 tram = road = (GetCrossingRailAxis(ti->tile) == AXIS_Y ? ROAD_X : ROAD_Y);
1462 }
1463 } else if (IsTileType(ti->tile, MP_STATION)) {
1464 if (IsAnyRoadStop(ti->tile)) {
1465 if (IsDriveThroughStopTile(ti->tile)) {
1466 Axis axis = GetDriveThroughStopAxis(ti->tile);
1467 tram = road = (axis == AXIS_X ? ROAD_X : ROAD_Y);
1468 } else {
1469 tram = road = DiagDirToRoadBits(GetBayRoadStopDir(ti->tile));
1470 }
1471 }
1472 } else {
1473 // No road here, no catenary to draw
1474 return;
1475 }
1476
1477 RoadType rt = GetRoadTypeRoad(ti->tile);
1478 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1479 DrawRoadTypeCatenary(ti, rt, road);
1480 }
1481
1482 rt = GetRoadTypeTram(ti->tile);
1483 if (rt != INVALID_ROADTYPE && HasRoadCatenaryDrawn(rt)) {
1484 DrawRoadTypeCatenary(ti, rt, tram);
1485 }
1486}
1487
1497static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
1498{
1499 int x = ti->x | dx;
1500 int y = ti->y | dy;
1501 int z = ti->z;
1502 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1503 AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z, transparent);
1504}
1505
1515void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
1516{
1517 if (draw_underlay) {
1518 /* Road underlay takes precedence over tram */
1519 if (road_rti != nullptr) {
1520 if (road_rti->UsesOverlay()) {
1521 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_GROUND);
1522 DrawGroundSprite(ground + road_offset, pal);
1523 }
1524 } else {
1525 if (tram_rti->UsesOverlay()) {
1526 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_GROUND);
1527 DrawGroundSprite(ground + tram_offset, pal);
1528 } else {
1529 DrawGroundSprite(SPR_TRAMWAY_TRAM + tram_offset, pal);
1530 }
1531 }
1532 }
1533
1534 /* Draw road overlay */
1535 if (road_rti != nullptr) {
1536 if (road_rti->UsesOverlay()) {
1537 SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_OVERLAY);
1538 if (ground != 0) DrawGroundSprite(ground + road_offset, pal);
1539 }
1540 }
1541
1542 /* Draw tram overlay */
1543 if (tram_rti != nullptr) {
1544 if (tram_rti->UsesOverlay()) {
1545 SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_OVERLAY);
1546 if (ground != 0) DrawGroundSprite(ground + tram_offset, pal);
1547 } else if (road_rti != nullptr) {
1548 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + tram_offset, pal);
1549 }
1550 }
1551}
1552
1562static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, bool snow_or_desert, PaletteID *pal)
1563{
1564 /* Draw bare ground sprite if no road or road uses overlay system. */
1565 if (rti == nullptr || rti->UsesOverlay()) {
1566 if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
1567 return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
1568 }
1569
1570 switch (roadside) {
1572 return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1573 case ROADSIDE_GRASS:
1574 case ROADSIDE_GRASS_ROAD_WORKS: return SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh);
1575 default: break; // Paved
1576 }
1577 }
1578
1579 /* Draw original road base sprite */
1580 SpriteID image = SPR_ROAD_Y + offset;
1581 if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
1582 image += 19;
1583 } else {
1584 switch (roadside) {
1585 case ROADSIDE_BARREN: *pal = PALETTE_TO_BARE_LAND; break;
1586 case ROADSIDE_GRASS: break;
1587 case ROADSIDE_GRASS_ROAD_WORKS: break;
1588 default: image -= 19; break; // Paved
1589 }
1590 }
1591
1592 return image;
1593}
1594
1605void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, Roadside roadside, bool snow_or_desert)
1606{
1607 /* Determine sprite offsets */
1608 uint road_offset = GetRoadSpriteOffset(ti->tileh, road);
1609 uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
1610
1611 /* Draw baseset underlay */
1612 PaletteID pal = PAL_NONE;
1613 SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, snow_or_desert, &pal);
1614 DrawGroundSprite(image, pal);
1615
1616 DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
1617}
1618
1623static void DrawRoadBits(TileInfo *ti)
1624{
1625 RoadBits road = GetRoadBits(ti->tile, RTT_ROAD);
1626 RoadBits tram = GetRoadBits(ti->tile, RTT_TRAM);
1627
1628 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1629 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1630 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1631 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1632
1633 if (ti->tileh != SLOPE_FLAT) {
1634 DrawFoundation(ti, GetRoadFoundation(ti->tileh, road | tram));
1635 /* DrawFoundation() modifies ti. */
1636 }
1637
1638 DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnow(ti->tile));
1639
1640 /* Draw one way */
1641 if (road_rti != nullptr) {
1643 if (drd != DRD_NONE) {
1644 SpriteID oneway = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ONEWAY);
1645
1646 if (oneway == 0) oneway = SPR_ONEWAY_BASE;
1647
1648 if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) {
1649 oneway += SPR_ONEWAY_SLOPE_N_OFFSET;
1650 } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) {
1651 oneway += SPR_ONEWAY_SLOPE_S_OFFSET;
1652 }
1653
1654 DrawGroundSpriteAt(oneway + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1655 }
1656 }
1657
1658 if (HasRoadWorks(ti->tile)) {
1659 /* Road works */
1660 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1661 return;
1662 }
1663
1664 /* Draw road, tram catenary */
1665 DrawRoadCatenary(ti);
1666
1667 /* Return if full detail is disabled, or we are zoomed fully out. */
1668 if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
1669
1670 /* Do not draw details (street lights, trees) under low bridge */
1671 Roadside roadside = GetRoadside(ti->tile);
1672 if (IsBridgeAbove(ti->tile) && (roadside == ROADSIDE_TREES || roadside == ROADSIDE_STREET_LIGHTS)) {
1673 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1674 int minz = GetTileMaxZ(ti->tile) + 2;
1675
1676 if (roadside == ROADSIDE_TREES) minz++;
1677
1678 if (height < minz) return;
1679 }
1680
1681 /* If there are no road bits, return, as there is nothing left to do */
1682 if (HasAtMostOneBit(road)) return;
1683
1684 /* Do not draw details when invisible. */
1685 if (roadside == ROADSIDE_TREES && IsInvisibilitySet(TO_TREES)) return;
1686 if (roadside == ROADSIDE_STREET_LIGHTS && IsInvisibilitySet(TO_HOUSES)) return;
1687
1688 /* Check whether details should be transparent. */
1689 bool is_transparent = false;
1690 if (roadside == ROADSIDE_TREES && IsTransparencySet(TO_TREES)) {
1691 is_transparent = true;
1692 }
1694 is_transparent = true;
1695 }
1696
1697 /* Draw extra details. */
1698 for (const DrawRoadTileStruct *drts = _road_display_table[roadside][road | tram]; drts->image != 0; drts++) {
1699 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
1700 }
1701}
1702
1704static void DrawTile_Road(TileInfo *ti)
1705{
1706 switch (GetRoadTileType(ti->tile)) {
1707 case ROAD_TILE_NORMAL:
1708 DrawRoadBits(ti);
1709 break;
1710
1711 case ROAD_TILE_CROSSING: {
1713
1714 Axis axis = GetCrossingRailAxis(ti->tile);
1715
1716 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1717
1718 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1719 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1720 const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1721 const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1722
1723 PaletteID pal = PAL_NONE;
1724
1725 /* Draw base ground */
1726 if (rti->UsesOverlay()) {
1727 SpriteID image = SPR_ROAD_Y + axis;
1728
1729 Roadside roadside = GetRoadside(ti->tile);
1730 if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
1731 image += 19;
1732 } else {
1733 switch (roadside) {
1734 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
1735 case ROADSIDE_GRASS: break;
1736 default: image -= 19; break; // Paved
1737 }
1738 }
1739
1740 DrawGroundSprite(image, pal);
1741 } else {
1742 SpriteID image = rti->base_sprites.crossing + axis;
1743 if (IsCrossingBarred(ti->tile)) image += 2;
1744
1745 Roadside roadside = GetRoadside(ti->tile);
1746 if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
1747 image += 8;
1748 } else {
1749 switch (roadside) {
1750 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break;
1751 case ROADSIDE_GRASS: break;
1752 default: image += 4; break; // Paved
1753 }
1754 }
1755
1756 DrawGroundSprite(image, pal);
1757 }
1758
1759 DrawRoadOverlays(ti, pal, road_rti, tram_rti, axis, axis);
1760
1761 /* Draw rail/PBS overlay */
1762 bool draw_pbs = _game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile);
1763 if (rti->UsesOverlay()) {
1764 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1765 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1766 DrawGroundSprite(rail, pal);
1767
1768 const Axis road_axis = GetCrossingRoadAxis(ti->tile);
1769 const DiagDirection dir1 = AxisToDiagDir(road_axis);
1770 const DiagDirection dir2 = ReverseDiagDir(dir1);
1771 uint adjacent_diagdirs = 0;
1772 for (DiagDirection dir : { dir1, dir2 }) {
1773 const TileIndex t = TileAddByDiagDir(ti->tile, dir);
1774 if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
1775 SetBit(adjacent_diagdirs, dir);
1776 }
1777 }
1778
1779 switch (adjacent_diagdirs) {
1780 case 0:
1781 DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1782 break;
1783
1784 case (1 << DIAGDIR_NE):
1785 DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE);
1786 break;
1787
1788 case (1 << DIAGDIR_SE):
1789 DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE);
1790 break;
1791
1792 case (1 << DIAGDIR_SW):
1793 DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE);
1794 break;
1795
1796 case (1 << DIAGDIR_NW):
1797 DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE);
1798 break;
1799
1800 default:
1801 /* Show no sprites */
1802 break;
1803 }
1804 } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) {
1805 /* Add another rail overlay, unless there is only the base road sprite. */
1806 pal = draw_pbs ? PALETTE_CRASH : PAL_NONE;
1808 DrawGroundSprite(rail, pal);
1809 }
1810
1811 /* Draw road, tram catenary */
1812 DrawRoadCatenary(ti);
1813
1814 /* Draw rail catenary */
1816
1817 break;
1818 }
1819
1820 default:
1821 case ROAD_TILE_DEPOT: {
1823
1824 PaletteID palette = COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile));
1825
1826 RoadType road_rt = GetRoadTypeRoad(ti->tile);
1827 RoadType tram_rt = GetRoadTypeTram(ti->tile);
1828 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt == INVALID_ROADTYPE ? tram_rt : road_rt);
1829
1830 int relocation = GetCustomRoadSprite(rti, ti->tile, ROTSG_DEPOT);
1831 bool default_gfx = relocation == 0;
1832 if (default_gfx) {
1833 if (HasBit(rti->flags, ROTF_CATENARY)) {
1834 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && road_rt == INVALID_ROADTYPE && !rti->UsesOverlay()) {
1835 /* Sprites with track only work for default tram */
1836 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1837 default_gfx = false;
1838 } else {
1839 /* Sprites without track are always better, if provided */
1840 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1841 }
1842 }
1843 } else {
1844 relocation -= SPR_ROAD_DEPOT;
1845 }
1846
1848 const DrawTileSprites *dts = &_road_depot[dir];
1849 DrawGroundSprite(dts->ground.sprite, PAL_NONE);
1850
1851 if (default_gfx) {
1853 if (rti->UsesOverlay()) {
1854 SpriteID ground = GetCustomRoadSprite(rti, ti->tile, ROTSG_OVERLAY);
1855 if (ground != 0) DrawGroundSprite(ground + offset, PAL_NONE);
1856 } else if (road_rt == INVALID_ROADTYPE) {
1857 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE);
1858 }
1859 }
1860
1861 DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, palette);
1862 break;
1863 }
1864 }
1865 DrawBridgeMiddle(ti);
1866}
1867
1875void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
1876{
1877 PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
1878
1879 const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
1880 int relocation = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_DEPOT);
1881 bool default_gfx = relocation == 0;
1882 if (default_gfx) {
1883 if (HasBit(rti->flags, ROTF_CATENARY)) {
1884 if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK && RoadTypeIsTram(rt) && !rti->UsesOverlay()) {
1885 /* Sprites with track only work for default tram */
1886 relocation = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_ROAD_DEPOT;
1887 default_gfx = false;
1888 } else {
1889 /* Sprites without track are always better, if provided */
1890 relocation = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_ROAD_DEPOT;
1891 }
1892 }
1893 } else {
1894 relocation -= SPR_ROAD_DEPOT;
1895 }
1896
1897 const DrawTileSprites *dts = &_road_depot[dir];
1898 DrawSprite(dts->ground.sprite, PAL_NONE, x, y);
1899
1900 if (default_gfx) {
1902 if (rti->UsesOverlay()) {
1904 if (ground != 0) DrawSprite(ground + offset, PAL_NONE, x, y);
1905 } else if (RoadTypeIsTram(rt)) {
1906 DrawSprite(SPR_TRAMWAY_OVERLAY + offset, PAL_NONE, x, y);
1907 }
1908 }
1909
1910 DrawRailTileSeqInGUI(x, y, dts, relocation, 0, palette);
1911}
1912
1919{
1920 assert(!invalidate || _generating_world);
1921
1922 for (const auto t : Map::Iterate()) {
1923 if (IsTileType(t, MP_ROAD) && !IsRoadDepot(t) && !HasTownOwnedRoad(t)) {
1924 TownID tid = INVALID_TOWN;
1925 if (!invalidate) {
1926 const Town *town = CalcClosestTownFromTile(t);
1927 if (town != nullptr) tid = town->index;
1928 }
1929 SetTownIndex(t, tid);
1930 }
1931 }
1932}
1933
1934static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, bool)
1935{
1936
1937 if (IsNormalRoad(tile)) {
1938 auto [tileh, z] = GetTilePixelSlope(tile);
1939 if (tileh == SLOPE_FLAT) return z;
1940
1942 z += ApplyPixelFoundationToSlope(f, tileh);
1943 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1944 } else {
1945 return GetTileMaxPixelZ(tile);
1946 }
1947}
1948
1949static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
1950{
1951 if (IsNormalRoad(tile)) {
1952 return GetRoadFoundation(tileh, GetAllRoadBits(tile));
1953 } else {
1954 return FlatteningFoundation(tileh);
1955 }
1956}
1957
1958static const Roadside _town_road_types[][2] = {
1964};
1965
1966static_assert(lengthof(_town_road_types) == HZB_END);
1967
1968static const Roadside _town_road_types_2[][2] = {
1974};
1975
1976static_assert(lengthof(_town_road_types_2) == HZB_END);
1977
1978
1979static void TileLoop_Road(TileIndex tile)
1980{
1982 case LT_ARCTIC: {
1983 /* 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. */
1984 int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileZ(tile);
1985 if (IsOnSnow(tile) != (tile_z > GetSnowLine())) {
1986 ToggleSnow(tile);
1987 MarkTileDirtyByTile(tile);
1988 }
1989 break;
1990 }
1991
1992 case LT_TROPIC:
1993 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
1994 ToggleDesert(tile);
1995 MarkTileDirtyByTile(tile);
1996 }
1997 break;
1998 }
1999
2000 if (IsRoadDepot(tile)) return;
2001
2002 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
2003 if (!HasRoadWorks(tile)) {
2004 HouseZonesBits grp = HZB_TOWN_EDGE;
2005
2006 if (t != nullptr) {
2007 grp = GetTownRadiusGroup(t, tile);
2008
2009 /* Show an animation to indicate road work */
2010 if (t->road_build_months != 0 &&
2011 (DistanceManhattan(t->xy, tile) < 8 || grp != HZB_TOWN_EDGE) &&
2012 IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) {
2013 if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
2014 StartRoadWorks(tile);
2015
2016 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
2018 TileX(tile) * TILE_SIZE + 7,
2019 TileY(tile) * TILE_SIZE + 7,
2020 0,
2021 EV_BULLDOZER);
2022 MarkTileDirtyByTile(tile);
2023 return;
2024 }
2025 }
2026 }
2027
2028 {
2029 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2030 const Roadside *new_rs = (_settings_game.game_creation.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp];
2031 Roadside cur_rs = GetRoadside(tile);
2032
2033 /* We have our desired type, do nothing */
2034 if (cur_rs == new_rs[0]) return;
2035
2036 /* We have the pre-type of the desired type, switch to the desired type */
2037 if (cur_rs == new_rs[1]) {
2038 cur_rs = new_rs[0];
2039 /* We have barren land, install the pre-type */
2040 } else if (cur_rs == ROADSIDE_BARREN) {
2041 cur_rs = new_rs[1];
2042 /* We're totally off limits, remove any installation and make barren land */
2043 } else {
2044 cur_rs = ROADSIDE_BARREN;
2045 }
2046 SetRoadside(tile, cur_rs);
2047 MarkTileDirtyByTile(tile);
2048 }
2049 } else if (IncreaseRoadWorksCounter(tile)) {
2050 TerminateRoadWorks(tile);
2051
2053 /* Generate a nicer town surface */
2054 const RoadBits old_rb = GetAnyRoadBits(tile, RTT_ROAD);
2055 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2056
2057 if (old_rb != new_rb) {
2058 RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), RTT_ROAD, true);
2059
2060 /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */
2061 if (new_rb == 0) {
2062 MarkTileDirtyByTile(tile);
2063 return;
2064 }
2065 }
2066 }
2067
2068 /* Possibly change road type */
2069 if (GetRoadOwner(tile, RTT_ROAD) == OWNER_TOWN) {
2071 if (rt != GetRoadTypeRoad(tile)) {
2072 SetRoadType(tile, RTT_ROAD, rt);
2073 }
2074 }
2075
2076 MarkTileDirtyByTile(tile);
2077 }
2078}
2079
2080static bool ClickTile_Road(TileIndex tile)
2081{
2082 if (!IsRoadDepot(tile)) return false;
2083
2085 return true;
2086}
2087
2088/* Converts RoadBits to TrackBits */
2089static const TrackBits _road_trackbits[16] = {
2090 TRACK_BIT_NONE, // ROAD_NONE
2091 TRACK_BIT_NONE, // ROAD_NW
2092 TRACK_BIT_NONE, // ROAD_SW
2093 TRACK_BIT_LEFT, // ROAD_W
2094 TRACK_BIT_NONE, // ROAD_SE
2095 TRACK_BIT_Y, // ROAD_Y
2096 TRACK_BIT_LOWER, // ROAD_S
2097 TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | ROAD_SW
2098 TRACK_BIT_NONE, // ROAD_NE
2099 TRACK_BIT_UPPER, // ROAD_N
2100 TRACK_BIT_X, // ROAD_X
2101 TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | ROAD_NW
2102 TRACK_BIT_RIGHT, // ROAD_E
2103 TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | ROAD_NE
2104 TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | ROAD_SE
2105 TRACK_BIT_ALL, // ROAD_ALL
2106};
2107
2108static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
2109{
2110 TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
2111 TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
2112 switch (mode) {
2113 case TRANSPORT_RAIL:
2114 if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
2115 break;
2116
2117 case TRANSPORT_ROAD: {
2118 RoadTramType rtt = (RoadTramType)sub_mode;
2119 if (!HasTileRoadType(tile, rtt)) break;
2120 switch (GetRoadTileType(tile)) {
2121 case ROAD_TILE_NORMAL: {
2122 const uint drd_to_multiplier[DRD_END] = { 0x101, 0x100, 0x1, 0x0 };
2123 RoadBits bits = GetRoadBits(tile, rtt);
2124
2125 /* no roadbit at this side of tile, return 0 */
2126 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break;
2127
2128 uint multiplier = drd_to_multiplier[(rtt == RTT_TRAM) ? DRD_NONE : GetDisallowedRoadDirections(tile)];
2129 if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier);
2130 break;
2131 }
2132
2133 case ROAD_TILE_CROSSING: {
2134 Axis axis = GetCrossingRoadAxis(tile);
2135
2136 if (side != INVALID_DIAGDIR && axis != DiagDirToAxis(side)) break;
2137
2138 trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis));
2139 if (IsCrossingBarred(tile)) {
2140 red_signals = trackdirbits;
2141 if (TrainOnCrossing(tile)) break;
2142
2143 auto mask_red_signal_bits_if_crossing_barred = [&](TileIndex t, TrackdirBits mask) {
2144 if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
2145 };
2146 /* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
2147 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE);
2148 /* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
2149 mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW);
2150 }
2151 break;
2152 }
2153
2154 default:
2155 case ROAD_TILE_DEPOT: {
2157
2158 if (side != INVALID_DIAGDIR && side != dir) break;
2159
2161 break;
2162 }
2163 }
2164 break;
2165 }
2166
2167 default: break;
2168 }
2169 return CombineTrackStatus(trackdirbits, red_signals);
2170}
2171
2172static const StringID _road_tile_strings[] = {
2173 STR_LAI_ROAD_DESCRIPTION_ROAD,
2174 STR_LAI_ROAD_DESCRIPTION_ROAD,
2175 STR_LAI_ROAD_DESCRIPTION_ROAD,
2176 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2177 STR_LAI_ROAD_DESCRIPTION_ROAD,
2178 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2179 STR_LAI_ROAD_DESCRIPTION_ROAD,
2180 STR_LAI_ROAD_DESCRIPTION_ROAD,
2181};
2182
2183static void GetTileDesc_Road(TileIndex tile, TileDesc *td)
2184{
2185 Owner rail_owner = INVALID_OWNER;
2186 Owner road_owner = INVALID_OWNER;
2187 Owner tram_owner = INVALID_OWNER;
2188
2189 RoadType road_rt = GetRoadTypeRoad(tile);
2190 RoadType tram_rt = GetRoadTypeTram(tile);
2191 if (road_rt != INVALID_ROADTYPE) {
2192 const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
2193 td->roadtype = rti->strings.name;
2194 td->road_speed = rti->max_speed / 2;
2195 road_owner = GetRoadOwner(tile, RTT_ROAD);
2196 }
2197 if (tram_rt != INVALID_ROADTYPE) {
2198 const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
2199 td->tramtype = rti->strings.name;
2200 td->tram_speed = rti->max_speed / 2;
2201 tram_owner = GetRoadOwner(tile, RTT_TRAM);
2202 }
2203
2204 switch (GetRoadTileType(tile)) {
2205 case ROAD_TILE_CROSSING: {
2206 td->str = STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING;
2207 rail_owner = GetTileOwner(tile);
2208
2209 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2210 td->railtype = rti->strings.name;
2211 td->rail_speed = rti->max_speed;
2212
2213 break;
2214 }
2215
2216 case ROAD_TILE_DEPOT:
2217 td->str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
2218 td->build_date = Depot::GetByTile(tile)->build_date;
2219 break;
2220
2221 default: {
2222 td->str = (road_rt != INVALID_ROADTYPE ? _road_tile_strings[GetRoadside(tile)] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
2223 break;
2224 }
2225 }
2226
2227 /* Now we have to discover, if the tile has only one owner or many:
2228 * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
2229 * - Compare the found owner with the other owners, and test if they differ.
2230 * Note: If road exists it will be the first_owner.
2231 */
2232 Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
2233 bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
2234
2235 if (mixed_owners) {
2236 /* Multiple owners */
2237 td->owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_RAIL_OWNER);
2238 td->owner[0] = rail_owner;
2239 td->owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_ROAD_OWNER);
2240 td->owner[1] = road_owner;
2241 td->owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_LAND_AREA_INFORMATION_TRAM_OWNER);
2242 td->owner[2] = tram_owner;
2243 } else {
2244 /* One to rule them all */
2245 td->owner[0] = first_owner;
2246 }
2247}
2248
2256
2257static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
2258{
2259 switch (GetRoadTileType(tile)) {
2260 case ROAD_TILE_DEPOT: {
2261 if (v->type != VEH_ROAD) break;
2262
2264 if (rv->frame == RVC_DEPOT_STOP_FRAME &&
2266 rv->state = RVSB_IN_DEPOT;
2267 rv->vehstatus |= VS_HIDDEN;
2268 rv->direction = ReverseDir(rv->direction);
2269 if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
2270 rv->tile = tile;
2271
2274 }
2275 break;
2276 }
2277
2278 default: break;
2279 }
2280 return VETSB_CONTINUE;
2281}
2282
2283
2284static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2285{
2286 if (IsRoadDepot(tile)) {
2287 if (GetTileOwner(tile) == old_owner) {
2288 if (new_owner == INVALID_OWNER) {
2290 } else {
2291 /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2292 RoadType rt = GetRoadTypeRoad(tile);
2293 if (rt == INVALID_ROADTYPE) rt = GetRoadTypeTram(tile);
2294 Company::Get(old_owner)->infrastructure.road[rt] -= 2;
2295 Company::Get(new_owner)->infrastructure.road[rt] += 2;
2296
2297 SetTileOwner(tile, new_owner);
2298 for (RoadTramType rtt : _roadtramtypes) {
2299 if (GetRoadOwner(tile, rtt) == old_owner) {
2300 SetRoadOwner(tile, rtt, new_owner);
2301 }
2302 }
2303 }
2304 }
2305 return;
2306 }
2307
2308 for (RoadTramType rtt : _roadtramtypes) {
2309 /* Update all roadtypes, no matter if they are present */
2310 if (GetRoadOwner(tile, rtt) == old_owner) {
2311 RoadType rt = GetRoadType(tile, rtt);
2312 if (rt != INVALID_ROADTYPE) {
2313 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
2314 uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt));
2315 Company::Get(old_owner)->infrastructure.road[rt] -= num_bits;
2316 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits;
2317 }
2318
2319 SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
2320 }
2321 }
2322
2323 if (IsLevelCrossing(tile)) {
2324 if (GetTileOwner(tile) == old_owner) {
2325 if (new_owner == INVALID_OWNER) {
2327 } else {
2328 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2329 Company::Get(old_owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
2330 Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
2331
2332 SetTileOwner(tile, new_owner);
2333 }
2334 }
2335 }
2336}
2337
2338static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2339{
2341 switch (GetRoadTileType(tile)) {
2342 case ROAD_TILE_CROSSING:
2343 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]);
2344 break;
2345
2346 case ROAD_TILE_DEPOT:
2347 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2348 break;
2349
2350 case ROAD_TILE_NORMAL: {
2351 RoadBits bits = GetAllRoadBits(tile);
2352 RoadBits bits_copy = bits;
2353 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2354 if (CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE).Succeeded()) {
2355 /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
2356 if (bits == bits_copy) {
2357 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2358
2359 /* Get the slope on top of the foundation */
2360 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), tileh_old);
2361 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), tileh_new);
2362
2363 /* The surface slope must not be changed */
2364 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2365 }
2366 }
2367 break;
2368 }
2369
2370 default: NOT_REACHED();
2371 }
2372 }
2373
2374 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
2375}
2376
2379{
2380 if (v->type != VEH_ROAD) return nullptr;
2381
2382 RoadVehicleList *affected_rvs = static_cast<RoadVehicleList*>(data);
2383 include(*affected_rvs, RoadVehicle::From(v)->First());
2384
2385 return nullptr;
2386}
2387
2394static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
2395{
2396 return (owner == OWNER_NONE || (owner == OWNER_TOWN && rtt == RTT_ROAD));
2397}
2398
2407static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
2408{
2409 // Scenario editor, maybe? Don't touch the owners when converting roadtypes...
2410 if (_current_company >= MAX_COMPANIES) return;
2411
2412 // We can't get a company from invalid owners but we can get ownership of roads without an owner
2413 if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
2414
2415 Company *c;
2416
2417 switch (owner) {
2418 case OWNER_NONE:
2419 SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company);
2421 break;
2422
2423 default:
2424 c = Company::Get(owner);
2425 c->infrastructure.road[from_type] -= num_pieces;
2426 c->infrastructure.road[to_type] += num_pieces;
2428 break;
2429 }
2430}
2431
2443{
2444 TileIndex area_end = tile;
2445
2446 if (!ValParamRoadType(to_type)) return CMD_ERROR;
2447 if (area_start >= Map::Size()) return CMD_ERROR;
2448
2449 RoadVehicleList affected_rvs;
2450 RoadTramType rtt = GetRoadTramType(to_type);
2451
2453 CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert.
2454 bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633)
2455
2456 std::unique_ptr<TileIterator> iter = std::make_unique<OrthogonalTileIterator>(area_start, area_end);
2457 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
2458 /* Is road present on tile? */
2459 if (!MayHaveRoad(tile)) continue;
2460
2461 /* Converting to the same subtype? */
2462 RoadType from_type = GetRoadType(tile, rtt);
2463 if (from_type == INVALID_ROADTYPE || from_type == to_type) continue;
2464
2465 /* Check if there is any infrastructure on tile */
2466 TileType tt = GetTileType(tile);
2467 switch (tt) {
2468 case MP_STATION:
2469 if (!IsAnyRoadStop(tile)) continue;
2470 break;
2471 case MP_ROAD:
2472 if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
2473 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD);
2474 continue;
2475 }
2476 break;
2477 case MP_TUNNELBRIDGE:
2478 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) continue;
2479 break;
2480 default: continue;
2481 }
2482
2483 /* Trying to convert other's road */
2484 Owner owner = GetRoadOwner(tile, rtt);
2485 if (!CanConvertUnownedRoadType(owner, rtt)) {
2486 CommandCost ret = CheckOwnership(owner, tile);
2487 if (ret.Failed()) {
2488 error = ret;
2489 continue;
2490 }
2491 }
2492
2493 /* Base the ability to replace town roads and bridges on the town's
2494 * acceptance of destructive actions. */
2495 if (owner == OWNER_TOWN) {
2498 if (ret.Failed()) {
2499 error = ret;
2500 continue;
2501 }
2502 }
2503
2504 /* Vehicle on the tile when not converting normal <-> powered
2505 * Tunnels and bridges have special check later */
2506 if (tt != MP_TUNNELBRIDGE) {
2507 if (!HasPowerOnRoad(from_type, to_type)) {
2509 if (ret.Failed()) {
2510 error = ret;
2511 continue;
2512 }
2513
2514 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2516 error.MakeError(STR_ERROR_OWNED_BY);
2517 continue;
2518 }
2519 }
2520
2521 uint num_pieces = CountBits(GetAnyRoadBits(tile, rtt));
2522 if (tt == MP_STATION && IsBayRoadStopTile(tile)) {
2523 num_pieces *= ROAD_STOP_TRACKBIT_FACTOR;
2524 } else if (tt == MP_ROAD && IsRoadDepot(tile)) {
2525 num_pieces *= ROAD_DEPOT_TRACKBIT_FACTOR;
2526 }
2527
2528 found_convertible_road = true;
2529 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2530
2531 if (flags & DC_EXEC) { // we can safely convert, too
2532 /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */
2533 if (owner == _current_company) {
2534 ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
2535 }
2536
2537 /* Perform the conversion */
2538 SetRoadType(tile, rtt, to_type);
2539 MarkTileDirtyByTile(tile);
2540
2541 /* update power of train on this tile */
2542 FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
2543
2544 if (IsRoadDepotTile(tile)) {
2545 /* Update build vehicle window related to this depot */
2548 }
2549 }
2550 } else {
2551 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
2552
2553 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
2554 * it would cause assert because of different test and exec runs */
2555 if (endtile < tile) {
2556 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
2557 }
2558
2559 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
2560 if (!HasPowerOnRoad(from_type, to_type)) {
2561 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
2562 if (ret.Failed()) {
2563 error = ret;
2564 continue;
2565 }
2566
2567 if (rtt == RTT_ROAD && owner == OWNER_TOWN) {
2569 error.MakeError(STR_ERROR_OWNED_BY);
2570 continue;
2571 }
2572 }
2573
2574 /* There are 2 pieces on *every* tile of the bridge or tunnel */
2575 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * 2;
2576 found_convertible_road = true;
2577 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type));
2578
2579 if (flags & DC_EXEC) {
2580 /* Update the company infrastructure counters. */
2581 if (owner == _current_company) {
2582 /* Each piece should be counted TUNNELBRIDGE_TRACKBIT_FACTOR times
2583 * for the infrastructure counters (cause of #8297). */
2584 ConvertRoadTypeOwner(tile, num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR, owner, from_type, to_type);
2585 SetTunnelBridgeOwner(tile, endtile, _current_company);
2586 }
2587
2588 /* Perform the conversion */
2589 SetRoadType(tile, rtt, to_type);
2590 SetRoadType(endtile, rtt, to_type);
2591
2592 FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
2593 FindVehicleOnPos(endtile, &affected_rvs, &UpdateRoadVehPowerProc);
2594
2595 if (IsBridge(tile)) {
2596 MarkBridgeDirty(tile);
2597 } else {
2598 MarkTileDirtyByTile(tile);
2599 MarkTileDirtyByTile(endtile);
2600 }
2601 }
2602 }
2603 }
2604
2605 if (flags & DC_EXEC) {
2606 /* Roadtype changed, update roadvehicles as when entering different track */
2607 for (RoadVehicle *v : affected_rvs) {
2608 v->CargoChanged();
2609 }
2610 }
2611
2612 return found_convertible_road ? cost : error;
2613}
2614
2615
2617extern const TileTypeProcs _tile_type_road_procs = {
2618 DrawTile_Road, // draw_tile_proc
2619 GetSlopePixelZ_Road, // get_slope_z_proc
2620 ClearTile_Road, // clear_tile_proc
2621 nullptr, // add_accepted_cargo_proc
2622 GetTileDesc_Road, // get_tile_desc_proc
2623 GetTileTrackStatus_Road, // get_tile_track_status_proc
2624 ClickTile_Road, // click_tile_proc
2625 nullptr, // animate_tile_proc
2626 TileLoop_Road, // tile_loop_proc
2627 ChangeTileOwner_Road, // change_tile_owner_proc
2628 nullptr, // add_produced_cargo_proc
2629 VehicleEnter_Road, // vehicle_enter_tile_proc
2630 GetFoundation_Road, // get_foundation_proc
2631 TerraformTile_Road, // terraform_tile_proc
2632};
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.
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.
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
StringID GetErrorMessage() const
Returns the error message of a command.
void MakeError(StringID message, StringID extra_message=INVALID_STRING_ID)
Makes this CommandCost behave like an error command.
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:127
SpriteID single_x
single piece of rail in X direction, without ground
Definition rail.h:137
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:231
struct RailTypeInfo::@23 base_sprites
Struct containing the main sprites.
struct RailTypeInfo::@26 strings
Strings associated with the rail type.
SpriteID crossing
level crossing, rail in X direction
Definition rail.h:144
SpriteID single_y
single piece of rail in Y direction, without ground
Definition rail.h:138
StringID name
Name of this rail type.
Definition rail.h:176
RoadTypeLabel label
Unique 32 bit road type identifier.
Definition road.h:147
RoadTypeLabelList alternate_labels
Road type labels this type provides in addition to the main label.
Definition road.h:152
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:122
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:177
struct RoadTypeInfo::@28 cursor
Cursors associated with the road type.
CursorID autoroad
Cursor for autorail tool.
Definition road.h:96
TimerGameCalendar::Date introduction_date
Introduction date.
Definition road.h:166
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
Definition road.h:182
RoadTypeFlags flags
Bit mask of road type flags.
Definition road.h:127
struct RoadTypeInfo::@29 strings
Strings associated with the rail type.
CursorID depot
Cursor for building a depot.
Definition road.h:97
CursorID road_nwse
Cursor for building rail in Y direction.
Definition road.h:95
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:142
StringID name
Name of this rail type.
Definition road.h:103
SpriteID build_y_road
button for building single rail in Y direction
Definition road.h:86
CursorID tunnel
Cursor for building a tunnel.
Definition road.h:98
SpriteID auto_road
button for the autoroad construction
Definition road.h:87
struct RoadTypeInfo::@27 gui_sprites
struct containing the sprites for the road GUI.
SpriteID convert_road
button for converting road types
Definition road.h:90
CursorID road_swne
Cursor for building rail in X direction.
Definition road.h:94
SpriteID build_x_road
button for building single rail in X direction
Definition road.h:85
SpriteID build_depot
button for building depots
Definition road.h:88
SpriteID build_tunnel
button for building a tunnel
Definition road.h:89
static Date date
Current date in days (day counter).
static constexpr TimerGame< struct Calendar >::Date INVALID_DATE
Representation of an invalid date.
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_NONE
no flag is set
@ DC_AUTO
don't allow building on structures
@ DC_NO_WATER
don't allow building on water
@ DC_BANKRUPT
company bankrupts, skip money check, skip vehicle on tile check in some cases
@ DC_EXEC
execute the given command
Definition of stuff that is very close to a company, like the company struct itself.
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.
void SetDParamsForOwnedBy(Owner owner, TileIndex tile)
Set the right DParams for STR_ERROR_OWNED_BY.
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.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
Owner
Enum for all companies/owners.
@ INVALID_OWNER
An invalid owner.
@ OWNER_DEITY
The object is owned by a superuser / goal script.
@ OWNER_NONE
The tile has no ownership.
@ OWNER_WATER
The tile/execution is done by "water".
@ OWNER_TOWN
A town owns the tile, or a town is expanding.
@ MAX_COMPANIES
Maximum number of companies.
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:67
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:988
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:18
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:19
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:163
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:146
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:467
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:608
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:552
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:567
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:404
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:84
Base for the NewGRF implementation.
bool HasGrfMiscBit(GrfMiscBit bit)
Check for grf miscellaneous bits.
Definition newgrf.h:187
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
Definition newgrf.h:171
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
@ RTSG_CROSSING
Level crossing overlay images.
Definition rail.h:57
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:307
bool RailNoLevelCrossings(RailType rt)
Test if a RailType disallows build of level crossings.
Definition rail.h:345
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
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
@ RAIL_TILE_NORMAL
Normal rail tile without signals.
Definition rail_map.h:24
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:242
@ ROTF_HIDDEN
Bit number for hidden from construction.
Definition road.h:41
@ ROTF_CATENARY
Bit number for adding catenary.
Definition road.h:38
Money RoadClearCost(RoadType roadtype)
Returns the cost of clearing the specified roadtype.
Definition road.h:263
@ ROTFB_NONE
All flags cleared.
Definition road.h:47
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:227
Money RoadConvertCost(RoadType from, RoadType to)
Calculates the cost of road conversion.
Definition road.h:281
@ ROTSG_ONEWAY
Optional: One-way indicator images.
Definition road.h:71
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition road.h:61
@ ROTSG_GROUND
Required: Main group of ground images.
Definition road.h:62
@ ROTSG_DEPOT
Optional: Depot images.
Definition road.h:68
@ ROTSG_CURSORS
Optional: Cursor and toolbar icon images.
Definition road.h:60
@ ROTSG_CATENARY_BACK
Optional: Catenary back.
Definition road.h:65
@ ROTSG_CATENARY_FRONT
Optional: Catenary front.
Definition road.h:64
bool RoadNoLevelCrossing(RoadType roadtype)
Test if road disallows level crossings.
Definition road.h:295
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:252
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 CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlag flags, bool town_check)
Is it allowed to remove the given road bits from the given tile?
Definition road_cmd.cpp:262
static const RoadBits _invalid_tileh_slopes_road[2][15]
Invalid RoadBits on slopes.
Definition road_cmd.cpp:202
CommandCost CmdBuildRoadDepot(DoCommandFlag flags, TileIndex tile, RoadType rt, DiagDirection dir)
Build a road depot.
static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadTramType rtt, bool town_check)
Delete a piece of road.
Definition road_cmd.cpp:325
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:950
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:545
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.
CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, RoadBits pieces, RoadType rt, DisallowedRoadDirections toggle_drd, TownID town_id)
Build a piece of road.
Definition road_cmd.cpp:610
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.
void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb)
Draws the catenary for the RoadType of the given tile.
void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
Draw the road depot sprite.
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
Update road infrastructure counts for a company.
Definition road_cmd.cpp: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.
std::tuple< CommandCost, Money > CmdRemoveLongRoad(DoCommandFlag flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
Remove a long piece of road.
CommandCost CmdBuildLongRoad(DoCommandFlag 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:979
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 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
CommandCost CmdConvertRoad(DoCommandFlag flags, TileIndex tile, TileIndex area_start, RoadType to_type)
Convert one road subtype to another.
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.
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
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
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 MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadType road_rt, RoadType tram_rt, uint town)
Make a level crossing.
Definition road_map.h:660
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
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:57
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
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:99
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:89
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1605
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:1593
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:280
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:104
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:58
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:59
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:179
bool show_track_reservation
highlight reserved tracks.
uint8_t 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:363
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:288
Represents the covered area of e.g.
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:24
Tindex index
Index of this pool item.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t 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:231
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
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
Owner owner[4]
Name of the owner(s)
Definition tile_cmd.h:55
StringID owner_type[4]
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:158
std::array< uint32_t, HZB_END > squared_town_zone_radius
UpdateTownRadius updates this given the house count.
Definition town.h:47
Town data structure.
Definition town.h:54
TileIndex xy
town center tile
Definition town.h:55
TownCache cache
Container for all cacheable data.
Definition town.h:57
uint8_t road_build_months
fund road reconstruction in action?
Definition town.h:99
Vehicle data structure.
Direction direction
facing
uint8_t 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
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
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
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.
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:176
@ TUNNELBRIDGE_REMOVE
Removal of a tunnel or bridge owned by the towb.
Definition town.h:177
void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags)
Changes town rating of the current company.
RoadType GetTownRoadType()
Get the road type that towns should build at this current moment.
Definition town_cmd.cpp:953
Town * CalcClosestTownFromTile(TileIndex tile, uint threshold=UINT_MAX)
Return the town closest to the given tile within threshold.
CommandCost CheckforTownRating(DoCommandFlag 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:254
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:65
static constexpr int RATING_ROAD_DOWN_STEP_INNER
removing a roadpiece in the middle
Definition town_type.h:64
static constexpr int RATING_ROAD_MINIMUM
minimum rating after removing town owned road
Definition town_type.h:66
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.
@ TO_BUILDINGS
company buildings - depots, stations, HQ, ...
@ TO_CATENARY
catenary
@ TO_TREES
trees
@ TO_HOUSES
town buildings
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...
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:546
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1552
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition vehicle.cpp:505
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:575
@ VS_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:671
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:564
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:587
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:3219
@ 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