OpenTTD Source: src/rail_cmd.cpp Source File

OpenTTD Source 15.3

rail_cmd.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "stdafx.h"
11#include "viewport_func.h"
12#include "command_func.h"
13#include "depot_base.h"
14#include "pathfinder/yapf/yapf_cache.h"
15#include "newgrf_debug.h"
16#include "newgrf_railtype.h"
17#include "train.h"
18#include "autoslope.h"
19#include "water.h"
20#include "tunnelbridge_map.h"
21#include "vehicle_func.h"
22#include "sound_func.h"
23#include "tunnelbridge.h"
24#include "elrail_func.h"
25#include "town.h"
26#include "pbs.h"
27#include "company_base.h"
28#include "core/backup_type.hpp"
29#include "core/container_func.hpp"
30#include "timer/timer_game_calendar.h"
31#include "strings_func.h"
32#include "company_gui.h"
33#include "object_map.h"
34#include "rail_cmd.h"
35#include "landscape_cmd.h"
36
37#include "table/strings.h"
38#include "table/railtypes.h"
39#include "table/track_land.h"
40
41#include "safeguards.h"
42
44 typedef std::vector<Train *> TrainList;
45
46 RailTypeInfo _railtypes[RAILTYPE_END];
47std::vector<RailType> _sorted_railtypes;
48 RailTypes _railtypes_hidden_mask;
49
51 enum SignalOffsets {
52 SIGNAL_TO_SOUTHWEST,
53 SIGNAL_TO_NORTHEAST,
54 SIGNAL_TO_SOUTHEAST,
55 SIGNAL_TO_NORTHWEST,
56 SIGNAL_TO_EAST,
57 SIGNAL_TO_WEST,
58 SIGNAL_TO_SOUTH,
59 SIGNAL_TO_NORTH,
60};
61
65 void ResetRailTypes()
66{
67 static_assert(std::size(_original_railtypes) <= std::size(_railtypes));
68
69 auto insert = std::copy(std::begin(_original_railtypes), std::end(_original_railtypes), std::begin(_railtypes));
70 std::fill(insert, std::end(_railtypes), RailTypeInfo{});
71
72 _railtypes_hidden_mask = {};
73}
74
75void ResolveRailTypeGUISprites(RailTypeInfo *rti)
76{
77 SpriteID cursors_base = GetCustomRailSprite(rti, INVALID_TILE, RTSG_CURSORS);
78 if (cursors_base != 0) {
79 rti->gui_sprites.build_ns_rail = cursors_base + 0;
80 rti->gui_sprites.build_x_rail = cursors_base + 1;
81 rti->gui_sprites.build_ew_rail = cursors_base + 2;
82 rti->gui_sprites.build_y_rail = cursors_base + 3;
83 rti->gui_sprites.auto_rail = cursors_base + 4;
84 rti->gui_sprites.build_depot = cursors_base + 5;
85 rti->gui_sprites.build_tunnel = cursors_base + 6;
86 rti->gui_sprites.convert_rail = cursors_base + 7;
87 rti->cursor.rail_ns = cursors_base + 8;
88 rti->cursor.rail_swne = cursors_base + 9;
89 rti->cursor.rail_ew = cursors_base + 10;
90 rti->cursor.rail_nwse = cursors_base + 11;
91 rti->cursor.autorail = cursors_base + 12;
92 rti->cursor.depot = cursors_base + 13;
93 rti->cursor.tunnel = cursors_base + 14;
94 rti->cursor.convert = cursors_base + 15;
95 }
96
97 /* Array of default GUI signal sprite numbers. */
98 const SpriteID _signal_lookup[2][SIGTYPE_END] = {
99 {SPR_IMG_SIGNAL_ELECTRIC_NORM, SPR_IMG_SIGNAL_ELECTRIC_ENTRY, SPR_IMG_SIGNAL_ELECTRIC_EXIT,
100 SPR_IMG_SIGNAL_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_PBS, SPR_IMG_SIGNAL_ELECTRIC_PBS_OWAY},
101
102 {SPR_IMG_SIGNAL_SEMAPHORE_NORM, SPR_IMG_SIGNAL_SEMAPHORE_ENTRY, SPR_IMG_SIGNAL_SEMAPHORE_EXIT,
103 SPR_IMG_SIGNAL_SEMAPHORE_COMBO, SPR_IMG_SIGNAL_SEMAPHORE_PBS, SPR_IMG_SIGNAL_SEMAPHORE_PBS_OWAY},
104 };
105
106 for (SignalType type = SIGTYPE_BLOCK; type < SIGTYPE_END; type = (SignalType)(type + 1)) {
107 for (SignalVariant var = SIG_ELECTRIC; var <= SIG_SEMAPHORE; var = (SignalVariant)(var + 1)) {
108 SpriteID red = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_RED, true);
109 SpriteID green = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_GREEN, true);
110 rti->gui_sprites.signals[type][var][0] = (red != 0) ? red + SIGNAL_TO_SOUTH : _signal_lookup[var][type];
111 rti->gui_sprites.signals[type][var][1] = (green != 0) ? green + SIGNAL_TO_SOUTH : _signal_lookup[var][type] + 1;
112 }
113 }
114}
115
122 static bool CompareRailTypes(const RailType &first, const RailType &second)
123{
124 return GetRailTypeInfo(first)->sorting_order < GetRailTypeInfo(second)->sorting_order;
125}
126
130 void InitRailTypes()
131{
132 _sorted_railtypes.clear();
133 for (RailTypeInfo &rti : _railtypes) {
134 RailType rt = rti.Index();
135
136 ResolveRailTypeGUISprites(&rti);
137 _railtypes_hidden_mask.Set(rt, rti.flags.Test(RailTypeFlag::Hidden));
138
139 if (rti.label == 0) continue;
140 _sorted_railtypes.push_back(rt);
141 }
142 std::sort(_sorted_railtypes.begin(), _sorted_railtypes.end(), CompareRailTypes);
143}
144
148 RailType AllocateRailType(RailTypeLabel label)
149{
150 auto it = std::ranges::find(_railtypes, 0, &RailTypeInfo::label);
151 if (it == std::end(_railtypes)) return INVALID_RAILTYPE;
152
153 RailTypeInfo &rti = *it;
154 RailType rt = rti.Index();
155
156 /* Set up new rail type based on default rail. */
157 rti = _original_railtypes[RAILTYPE_RAIL];
158 rti.label = label;
159 rti.alternate_labels.clear();
160
161 /* Make us compatible with ourself. */
162 rti.powered_railtypes = rt;
163 rti.compatible_railtypes = rt;
164
165 /* We also introduce ourself. */
166 rti.introduces_railtypes = rt;
167
168 /* Default sort order; order of allocation, but with some
169 * offsets so it's easier for NewGRF to pick a spot without
170 * changing the order of other (original) rail types.
171 * The << is so you can place other railtypes in between the
172 * other railtypes, the 7 is to be able to place something
173 * before the first (default) rail type. */
174 rti.sorting_order = rt << 4 | 7;
175
176 return rt;
177}
178
179static const uint8_t _track_sloped_sprites[14] = {
180 14, 15, 22, 13,
181 0, 21, 17, 12,
182 23, 0, 18, 20,
183 19, 16
184};
185
186
187/* 4
188 * ---------
189 * |\ /|
190 * | \ 1/ |
191 * | \ / |
192 * | \ / |
193 * 16| \ |32
194 * | / \2 |
195 * | / \ |
196 * | / \ |
197 * |/ \|
198 * ---------
199 * 8
200 */
201
202
203
204/* MAP2 byte: abcd???? => Signal On? Same coding as map3lo
205 * MAP3LO byte: abcd???? => Signal Exists?
206 * a and b are for diagonals, upper and left,
207 * one for each direction. (ie a == NE->SW, b ==
208 * SW->NE, or v.v., I don't know. b and c are
209 * similar for lower and right.
210 * MAP2 byte: ????abcd => Type of ground.
211 * MAP3LO byte: ????abcd => Type of rail.
212 * MAP5: 00abcdef => rail
213 * 01abcdef => rail w/ signals
214 * 10uuuuuu => unused
215 * 11uuuudd => rail depot
216 */
217
226 static CommandCost EnsureNoTrainOnTrack(TileIndex tile, Track track)
227{
228 TrackBits rail_bits = TrackToTrackBits(track);
229 return EnsureNoTrainOnTrackBits(tile, rail_bits);
230}
231
238 static CommandCost CheckTrackCombination(TileIndex tile, TrackBits to_build)
239{
240 if (!IsPlainRail(tile)) return CommandCost(STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION);
241
242 /* So, we have a tile with tracks on it (and possibly signals). Let's see
243 * what tracks first */
244 TrackBits current = GetTrackBits(tile); // The current track layout.
245 TrackBits future = current | to_build; // The track layout we want to build.
246
247 /* Are we really building something new? */
248 if (current == future) {
249 /* Nothing new is being built */
250 return CommandCost(STR_ERROR_ALREADY_BUILT);
251 }
252
253 /* Normally, we may overlap and any combination is valid */
254 return CommandCost();
255}
256
257
259 static const TrackBits _valid_tracks_without_foundation[15] = {
260 TRACK_BIT_ALL,
261 TRACK_BIT_RIGHT,
262 TRACK_BIT_UPPER,
263 TRACK_BIT_X,
264
265 TRACK_BIT_LEFT,
266 TRACK_BIT_NONE,
267 TRACK_BIT_Y,
268 TRACK_BIT_LOWER,
269
270 TRACK_BIT_LOWER,
271 TRACK_BIT_Y,
272 TRACK_BIT_NONE,
273 TRACK_BIT_LEFT,
274
275 TRACK_BIT_X,
276 TRACK_BIT_UPPER,
277 TRACK_BIT_RIGHT,
278};
279
281 static const TrackBits _valid_tracks_on_leveled_foundation[15] = {
282 TRACK_BIT_NONE,
283 TRACK_BIT_LEFT,
284 TRACK_BIT_LOWER,
285 TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_LEFT,
286
287 TRACK_BIT_RIGHT,
288 TRACK_BIT_ALL,
289 TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_RIGHT,
290 TRACK_BIT_ALL,
291
292 TRACK_BIT_UPPER,
293 TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_LEFT,
294 TRACK_BIT_ALL,
295 TRACK_BIT_ALL,
296
297 TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_RIGHT,
298 TRACK_BIT_ALL,
299 TRACK_BIT_ALL
300};
301
309 Foundation GetRailFoundation(Slope tileh, TrackBits bits)
310{
311 if (bits == TRACK_BIT_NONE) return FOUNDATION_NONE;
312
313 if (IsSteepSlope(tileh)) {
314 /* Test for inclined foundations */
315 if (bits == TRACK_BIT_X) return FOUNDATION_INCLINED_X;
316 if (bits == TRACK_BIT_Y) return FOUNDATION_INCLINED_Y;
317
318 /* Get higher track */
319 Corner highest_corner = GetHighestSlopeCorner(tileh);
320 TrackBits higher_track = CornerToTrackBits(highest_corner);
321
322 /* Only higher track? */
323 if (bits == higher_track) return HalftileFoundation(highest_corner);
324
325 /* Overlap with higher track? */
326 if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
327
328 /* either lower track or both higher and lower track */
329 return ((bits & higher_track) != 0 ? FOUNDATION_STEEP_BOTH : FOUNDATION_STEEP_LOWER);
330 } else {
331 if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
332
333 bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
334
335 Corner track_corner;
336 switch (bits) {
337 case TRACK_BIT_LEFT: track_corner = CORNER_W; break;
338 case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
339 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
340 case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
341
342 case TRACK_BIT_HORZ:
343 if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N);
344 if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S);
345 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
346
347 case TRACK_BIT_VERT:
348 if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W);
349 if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E);
350 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
351
352 case TRACK_BIT_X:
353 if (IsSlopeWithOneCornerRaised(tileh)) return FOUNDATION_INCLINED_X;
354 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
355
356 case TRACK_BIT_Y:
357 if (IsSlopeWithOneCornerRaised(tileh)) return FOUNDATION_INCLINED_Y;
358 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
359
360 default:
361 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
362 }
363 /* Single diagonal track */
364
365 /* Track must be at least valid on leveled foundation */
366 if (!valid_on_leveled) return FOUNDATION_INVALID;
367
368 /* If slope has three raised corners, build leveled foundation */
369 if (IsSlopeWithThreeCornersRaised(tileh)) return FOUNDATION_LEVELED;
370
371 /* If neighboured corners of track_corner are lowered, build halftile foundation */
372 if ((tileh & SlopeWithThreeCornersRaised(OppositeCorner(track_corner))) == SlopeWithOneCornerRaised(track_corner)) return HalftileFoundation(track_corner);
373
374 /* else special anti-zig-zag foundation */
375 return SpecialRailFoundation(track_corner);
376 }
377}
378
379
389 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile)
390{
391 /* don't allow building on the lower side of a coast */
392 if (GetFloodingBehaviour(tile) != FLOOD_NONE) {
393 if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
394 }
395
396 Foundation f_new = GetRailFoundation(tileh, rail_bits | existing);
397
398 /* check track/slope combination */
399 if ((f_new == FOUNDATION_INVALID) ||
400 ((f_new != FOUNDATION_NONE) && (!_settings_game.construction.build_on_slopes))) {
401 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
402 }
403
404 Foundation f_old = GetRailFoundation(tileh, existing);
405 return CommandCost(EXPENSES_CONSTRUCTION, f_new != f_old ? _price[PR_BUILD_FOUNDATION] : (Money)0);
406}
407
408/* Validate functions for rail building */
409static inline bool ValParamTrackOrientation(Track track)
410{
411 return IsValidTrack(track);
412}
413
423 CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType railtype, Track track, bool auto_remove_signals)
424{
425 CommandCost cost(EXPENSES_CONSTRUCTION);
426
427 if (!ValParamRailType(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
428
429 Slope tileh = GetTileSlope(tile);
430 TrackBits trackbit = TrackToTrackBits(track);
431
432 switch (GetTileType(tile)) {
433 case MP_RAILWAY: {
434 CommandCost ret = CheckTileOwnership(tile);
435 if (ret.Failed()) return ret;
436
437 if (!IsPlainRail(tile)) return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile); // just get appropriate error message
438
439 if (!IsCompatibleRail(GetRailType(tile), railtype)) return CommandCost(STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION);
440
441 ret = CheckTrackCombination(tile, trackbit);
442 if (ret.Succeeded()) ret = EnsureNoTrainOnTrack(tile, track);
443 if (ret.Failed()) return ret;
444
445 ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
446 if (ret.Failed()) return ret;
447 cost.AddCost(ret.GetCost());
448
449 if (HasSignals(tile) && TracksOverlap(GetTrackBits(tile) | TrackToTrackBits(track))) {
450 /* If adding the new track causes any overlap, all signals must be removed first */
451 if (!auto_remove_signals) return CommandCost(STR_ERROR_MUST_REMOVE_SIGNALS_FIRST);
452
453 for (Track track_it = TRACK_BEGIN; track_it < TRACK_END; track_it++) {
454 if (HasTrack(tile, track_it) && HasSignalOnTrack(tile, track_it)) {
455 CommandCost ret_remove_signals = Command<CMD_REMOVE_SINGLE_SIGNAL>::Do(flags, tile, track_it);
456 if (ret_remove_signals.Failed()) return ret_remove_signals;
457 cost.AddCost(ret_remove_signals.GetCost());
458 }
459 }
460 }
461
462 /* If the rail types don't match, try to convert only if engines of
463 * the new rail type are not powered on the present rail type and engines of
464 * the present rail type are powered on the new rail type. */
465 if (GetRailType(tile) != railtype && !HasPowerOnRail(railtype, GetRailType(tile))) {
466 if (HasPowerOnRail(GetRailType(tile), railtype)) {
467 ret = Command<CMD_CONVERT_RAIL>::Do(flags, tile, tile, railtype, false);
468 if (ret.Failed()) return ret;
469 cost.AddCost(ret.GetCost());
470 } else {
471 return CMD_ERROR;
472 }
473 }
474
475 if (flags.Test(DoCommandFlag::Execute)) {
476 SetRailGroundType(tile, RailGroundType::Barren);
477 TrackBits bits = GetTrackBits(tile);
478 SetTrackBits(tile, bits | trackbit);
479 /* Subtract old infrastructure count. */
480 uint pieces = CountBits(bits);
481 if (TracksOverlap(bits)) pieces *= pieces;
482 Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] -= pieces;
483 /* Add new infrastructure count. */
484 pieces = CountBits(bits | trackbit);
485 if (TracksOverlap(bits | trackbit)) pieces *= pieces;
486 Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] += pieces;
487 DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
488 }
489 break;
490 }
491
492 case MP_ROAD: {
493 /* Level crossings may only be built on these slopes */
494 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
495
496 if (!_settings_game.construction.crossing_with_competitor && _current_company != OWNER_DEITY) {
497 CommandCost ret = CheckTileOwnership(tile);
498 if (ret.Failed()) return ret;
499 }
500
501 CommandCost ret = EnsureNoVehicleOnGround(tile);
502 if (ret.Failed()) return ret;
503
504 if (IsNormalRoad(tile)) {
505 if (HasRoadWorks(tile)) return CommandCost(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
506
507 if (GetDisallowedRoadDirections(tile) != DRD_NONE) return CommandCost(STR_ERROR_CROSSING_ON_ONEWAY_ROAD);
508
509 if (RailNoLevelCrossings(railtype)) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL);
510
511 RoadType roadtype_road = GetRoadTypeRoad(tile);
512 RoadType roadtype_tram = GetRoadTypeTram(tile);
513
514 if (roadtype_road != INVALID_ROADTYPE && RoadNoLevelCrossing(roadtype_road)) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
515 if (roadtype_tram != INVALID_ROADTYPE && RoadNoLevelCrossing(roadtype_tram)) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD);
516
517 RoadBits road = GetRoadBits(tile, RTT_ROAD);
518 RoadBits tram = GetRoadBits(tile, RTT_TRAM);
519 if ((track == TRACK_X && ((road | tram) & ROAD_X) == 0) ||
520 (track == TRACK_Y && ((road | tram) & ROAD_Y) == 0)) {
521 Owner road_owner = GetRoadOwner(tile, RTT_ROAD);
522 Owner tram_owner = GetRoadOwner(tile, RTT_TRAM);
523 /* Disallow breaking end-of-line of someone else
524 * so trams can still reverse on this tile. */
525 if (Company::IsValidID(tram_owner) && HasExactlyOneBit(tram)) {
526 ret = CheckOwnership(tram_owner);
527 if (ret.Failed()) return ret;
528 }
529
530 uint num_new_road_pieces = (road != ROAD_NONE) ? 2 - CountBits(road) : 0;
531 if (num_new_road_pieces > 0) {
532 cost.AddCost(num_new_road_pieces * RoadBuildCost(roadtype_road));
533 }
534
535 uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0;
536 if (num_new_tram_pieces > 0) {
537 cost.AddCost(num_new_tram_pieces * RoadBuildCost(roadtype_tram));
538 }
539
540 if (flags.Test(DoCommandFlag::Execute)) {
541 MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile));
542 UpdateLevelCrossing(tile, false);
543 MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile));
544 Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR;
545 DirtyCompanyInfrastructureWindows(_current_company);
546 if (num_new_road_pieces > 0 && Company::IsValidID(road_owner)) {
547 Company::Get(road_owner)->infrastructure.road[roadtype_road] += num_new_road_pieces;
548 DirtyCompanyInfrastructureWindows(road_owner);
549 }
550 if (num_new_tram_pieces > 0 && Company::IsValidID(tram_owner)) {
551 Company::Get(tram_owner)->infrastructure.road[roadtype_tram] += num_new_tram_pieces;
552 DirtyCompanyInfrastructureWindows(tram_owner);
553 }
554 }
555 break;
556 }
557 }
558
559 if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) {
560 return CommandCost(STR_ERROR_ALREADY_BUILT);
561 }
562 [[fallthrough]];
563 }
564
565 default: {
566 /* Will there be flat water on the lower halftile? */
567 bool water_ground = IsTileType(tile, MP_WATER) && IsSlopeWithOneCornerRaised(tileh);
568
569 CommandCost ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile);
570 if (ret.Failed()) return ret;
571 cost.AddCost(ret.GetCost());
572
573 ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
574 if (ret.Failed()) return ret;
575 cost.AddCost(ret.GetCost());
576
577 if (water_ground) {
578 cost.AddCost(-_price[PR_CLEAR_WATER]);
579 cost.AddCost(_price[PR_CLEAR_ROUGH]);
580 }
581
582 if (flags.Test(DoCommandFlag::Execute)) {
583 MakeRailNormal(tile, _current_company, trackbit, railtype);
584 if (water_ground) {
585 SetRailGroundType(tile, RailGroundType::HalfTileWater);
586 if (IsPossibleDockingTile(tile)) CheckForDockingTile(tile);
587 }
588 Company::Get(_current_company)->infrastructure.rail[railtype]++;
589 DirtyCompanyInfrastructureWindows(_current_company);
590 }
591 break;
592 }
593 }
594
595 if (flags.Test(DoCommandFlag::Execute)) {
596 MarkTileDirtyByTile(tile);
597 AddTrackToSignalBuffer(tile, track, _current_company);
598 YapfNotifyTrackLayoutChange(tile, track);
599 }
600
601 cost.AddCost(RailBuildCost(railtype));
602 return cost;
603}
604
612 CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track track)
613{
614 CommandCost cost(EXPENSES_CONSTRUCTION);
615 bool crossing = false;
616
617 if (!ValParamTrackOrientation(track)) return CMD_ERROR;
618 TrackBits trackbit = TrackToTrackBits(track);
619
620 /* Need to read tile owner now because it may change when the rail is removed
621 * Also, in case of floods, _current_company != owner
622 * There may be invalid tiletype even in exec run (when removing long track),
623 * so do not call GetTileOwner(tile) in any case here */
624 Owner owner = INVALID_OWNER;
625
626 Train *v = nullptr;
627
628 switch (GetTileType(tile)) {
629 case MP_ROAD: {
630 if (!IsLevelCrossing(tile) || GetCrossingRailBits(tile) != trackbit) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
631
632 if (_current_company != OWNER_WATER) {
633 CommandCost ret = CheckTileOwnership(tile);
634 if (ret.Failed()) return ret;
635 }
636
637 if (!flags.Test(DoCommandFlag::Bankrupt)) {
638 CommandCost ret = EnsureNoVehicleOnGround(tile);
639 if (ret.Failed()) return ret;
640 }
641
642 cost.AddCost(RailClearCost(GetRailType(tile)));
643
644 if (flags.Test(DoCommandFlag::Execute)) {
645 UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(tile, GetCrossingRoadAxis(tile));
646
647 if (HasReservedTracks(tile, trackbit)) {
648 v = GetTrainForReservation(tile, track);
649 if (v != nullptr) FreeTrainTrackReservation(v);
650 }
651
652 owner = GetTileOwner(tile);
653 Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
654 DirtyCompanyInfrastructureWindows(owner);
655 MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypeRoad(tile), GetRoadTypeTram(tile), GetTownIndex(tile), GetRoadOwner(tile, RTT_ROAD), GetRoadOwner(tile, RTT_TRAM));
656 DeleteNewGRFInspectWindow(GSF_RAILTYPES, tile.base());
657 }
658 break;
659 }
660
661 case MP_RAILWAY: {
662 TrackBits present;
663 /* There are no rails present at depots. */
664 if (!IsPlainRail(tile)) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
665
666 if (_current_company != OWNER_WATER) {
667 CommandCost ret = CheckTileOwnership(tile);
668 if (ret.Failed()) return ret;
669 }
670
671 CommandCost ret = EnsureNoTrainOnTrack(tile, track);
672 if (ret.Failed()) return ret;
673
674 present = GetTrackBits(tile);
675 if ((present & trackbit) == 0) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
676 if (present == (TRACK_BIT_X | TRACK_BIT_Y)) crossing = true;
677
678 cost.AddCost(RailClearCost(GetRailType(tile)));
679
680 /* Charge extra to remove signals on the track, if they are there */
681 if (HasSignalOnTrack(tile, track)) {
682 cost.AddCost(Command<CMD_REMOVE_SINGLE_SIGNAL>::Do(flags, tile, track));
683 }
684
685 if (flags.Test(DoCommandFlag::Execute)) {
686 if (HasReservedTracks(tile, trackbit)) {
687 v = GetTrainForReservation(tile, track);
688 if (v != nullptr) FreeTrainTrackReservation(v);
689 }
690
691 owner = GetTileOwner(tile);
692
693 /* Subtract old infrastructure count. */
694 uint pieces = CountBits(present);
695 if (TracksOverlap(present)) pieces *= pieces;
696 Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= pieces;
697 /* Add new infrastructure count. */
698 present ^= trackbit;
699 pieces = CountBits(present);
700 if (TracksOverlap(present)) pieces *= pieces;
701 Company::Get(owner)->infrastructure.rail[GetRailType(tile)] += pieces;
702 DirtyCompanyInfrastructureWindows(owner);
703
704 if (present == 0) {
705 Slope tileh = GetTileSlope(tile);
706 /* If there is flat water on the lower halftile, convert the tile to shore so the water remains */
707 if (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh)) {
708 bool docking = IsDockingTile(tile);
709 MakeShore(tile);
710 SetDockingTile(tile, docking);
711 } else {
712 DoClearSquare(tile);
713 }
714 DeleteNewGRFInspectWindow(GSF_RAILTYPES, tile.base());
715 } else {
716 SetTrackBits(tile, present);
717 SetTrackReservation(tile, GetRailReservationTrackBits(tile) & present);
718 }
719 }
720 break;
721 }
722
723 default: return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
724 }
725
726 if (flags.Test(DoCommandFlag::Execute)) {
727 /* if we got that far, 'owner' variable is set correctly */
728 assert(Company::IsValidID(owner));
729
730 MarkTileDirtyByTile(tile);
731 if (crossing) {
732 /* crossing is set when only TRACK_BIT_X and TRACK_BIT_Y are set. As we
733 * are removing one of these pieces, we'll need to update signals for
734 * both directions explicitly, as after the track is removed it won't
735 * 'connect' with the other piece. */
736 AddTrackToSignalBuffer(tile, TRACK_X, owner);
737 AddTrackToSignalBuffer(tile, TRACK_Y, owner);
738 YapfNotifyTrackLayoutChange(tile, TRACK_X);
739 YapfNotifyTrackLayoutChange(tile, TRACK_Y);
740 } else {
741 AddTrackToSignalBuffer(tile, track, owner);
742 YapfNotifyTrackLayoutChange(tile, track);
743 }
744
745 if (v != nullptr) TryPathReserve(v, true);
746 }
747
748 return cost;
749}
750
751
759 bool FloodHalftile(TileIndex t)
760{
761 assert(IsPlainRailTile(t));
762
763 bool flooded = false;
764 if (GetRailGroundType(t) == RailGroundType::HalfTileWater) return flooded;
765
766 Slope tileh = GetTileSlope(t);
767 TrackBits rail_bits = GetTrackBits(t);
768
769 if (IsSlopeWithOneCornerRaised(tileh)) {
770 TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh)));
771
772 TrackBits to_remove = lower_track & rail_bits;
773 if (to_remove != TRACK_BIT_NONE) {
774 Backup<CompanyID> cur_company(_current_company, OWNER_WATER);
775 flooded = Command<CMD_REMOVE_SINGLE_RAIL>::Do(DoCommandFlag::Execute, t, FindFirstTrack(to_remove)).Succeeded();
776 cur_company.Restore();
777 if (!flooded) return flooded; // not yet floodable
778 rail_bits = rail_bits & ~to_remove;
779 if (rail_bits == TRACK_BIT_NONE) {
780 MakeShore(t);
781 MarkTileDirtyByTile(t);
782 return flooded;
783 }
784 }
785
786 if (IsNonContinuousFoundation(GetRailFoundation(tileh, rail_bits))) {
787 flooded = true;
788 SetRailGroundType(t, RailGroundType::HalfTileWater);
789 MarkTileDirtyByTile(t);
790 }
791 } else {
792 /* Make shore on steep slopes and 'three-corners-raised'-slopes. */
793 if (ApplyFoundationToSlope(GetRailFoundation(tileh, rail_bits), tileh) == 0) {
794 if (IsSteepSlope(tileh) || IsSlopeWithThreeCornersRaised(tileh)) {
795 flooded = true;
796 SetRailGroundType(t, RailGroundType::HalfTileWater);
797 MarkTileDirtyByTile(t);
798 }
799 }
800 }
801 return flooded;
802}
803
804static const TileIndexDiffC _trackdelta[] = {
805 { -1, 0 }, { 0, 1 }, { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, 1 },
806 { 0, 0 },
807 { 0, 0 },
808 { 1, 0 }, { 0, -1 }, { 0, -1 }, { 1, 0 }, { 0, -1 }, { -1, 0 },
809 { 0, 0 },
810 { 0, 0 }
811};
812
813
814static CommandCost ValidateAutoDrag(Trackdir *trackdir, TileIndex start, TileIndex end)
815{
816 int x = TileX(start);
817 int y = TileY(start);
818 int ex = TileX(end);
819 int ey = TileY(end);
820
821 if (!ValParamTrackOrientation(TrackdirToTrack(*trackdir))) return CMD_ERROR;
822
823 /* calculate delta x,y from start to end tile */
824 int dx = ex - x;
825 int dy = ey - y;
826
827 /* calculate delta x,y for the first direction */
828 int trdx = _trackdelta[*trackdir].x;
829 int trdy = _trackdelta[*trackdir].y;
830
831 if (!IsDiagonalTrackdir(*trackdir)) {
832 trdx += _trackdelta[*trackdir ^ 1].x;
833 trdy += _trackdelta[*trackdir ^ 1].y;
834 }
835
836 /* validate the direction */
837 while ((trdx <= 0 && dx > 0) ||
838 (trdx >= 0 && dx < 0) ||
839 (trdy <= 0 && dy > 0) ||
840 (trdy >= 0 && dy < 0)) {
841 if (!HasBit(*trackdir, 3)) { // first direction is invalid, try the other
842 SetBit(*trackdir, 3); // reverse the direction
843 trdx = -trdx;
844 trdy = -trdy;
845 } else { // other direction is invalid too, invalid drag
846 return CMD_ERROR;
847 }
848 }
849
850 /* (for diagonal tracks, this is already made sure of by above test), but:
851 * for non-diagonal tracks, check if the start and end tile are on 1 line */
852 if (!IsDiagonalTrackdir(*trackdir)) {
853 trdx = _trackdelta[*trackdir].x;
854 trdy = _trackdelta[*trackdir].y;
855 if (abs(dx) != abs(dy) && abs(dx) + abs(trdy) != abs(dy) + abs(trdx)) return CMD_ERROR;
856 }
857
858 return CommandCost();
859}
860
873 static CommandCost CmdRailTrackHelper(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, RailType railtype, Track track, bool remove, bool auto_remove_signals, bool fail_on_obstacle)
874{
875 CommandCost total_cost(EXPENSES_CONSTRUCTION);
876
877 if ((!remove && !ValParamRailType(railtype)) || !ValParamTrackOrientation(track)) return CMD_ERROR;
878 if (end_tile >= Map::Size() || tile >= Map::Size()) return CMD_ERROR;
879
880 Trackdir trackdir = TrackToTrackdir(track);
881
882 CommandCost ret = ValidateAutoDrag(&trackdir, tile, end_tile);
883 if (ret.Failed()) return ret;
884
885 bool had_success = false;
886 CommandCost last_error = CMD_ERROR;
887 for (;;) {
888 ret = remove ? Command<CMD_REMOVE_SINGLE_RAIL>::Do(flags, tile, TrackdirToTrack(trackdir)) : Command<CMD_BUILD_SINGLE_RAIL>::Do(flags, tile, railtype, TrackdirToTrack(trackdir), auto_remove_signals);
889 if (!remove && !fail_on_obstacle && last_error.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true;
890
891 if (ret.Failed()) {
892 last_error = std::move(ret);
893 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT && !remove) {
894 if (fail_on_obstacle) return last_error;
895 if (had_success) break; // Keep going if we haven't constructed any rail yet, skipping the start of the drag
896 }
897
898 /* Ownership errors are more important. */
899 if (last_error.GetErrorMessage() == STR_ERROR_OWNED_BY && remove) break;
900 } else {
901 had_success = true;
902 total_cost.AddCost(ret.GetCost());
903 }
904
905 if (tile == end_tile) break;
906
907 tile += ToTileIndexDiff(_trackdelta[trackdir]);
908
909 /* toggle railbit for the non-diagonal tracks */
910 if (!IsDiagonalTrackdir(trackdir)) ToggleBit(trackdir, 0);
911 }
912
913 if (had_success) return total_cost;
914 return last_error;
915}
916
930 CommandCost CmdBuildRailroadTrack(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RailType railtype, Track track, bool auto_remove_signals, bool fail_on_obstacle)
931{
932 return CmdRailTrackHelper(flags, start_tile, end_tile, railtype, track, false, auto_remove_signals, fail_on_obstacle);
933}
934
945 CommandCost CmdRemoveRailroadTrack(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, Track track)
946{
947 return CmdRailTrackHelper(flags, start_tile, end_tile, INVALID_RAILTYPE, track, true, false, false);
948}
949
961 CommandCost CmdBuildTrainDepot(DoCommandFlags flags, TileIndex tile, RailType railtype, DiagDirection dir)
962{
963 /* check railtype and valid direction for depot (0 through 3), 4 in total */
964 if (!ValParamRailType(railtype) || !IsValidDiagDirection(dir)) return CMD_ERROR;
965
966 Slope tileh = GetTileSlope(tile);
967
968 CommandCost cost(EXPENSES_CONSTRUCTION);
969
970 /* Prohibit construction if
971 * The tile is non-flat AND
972 * 1) build-on-slopes is disabled
973 * 2) the tile is steep i.e. spans two height levels
974 * 3) the exit points in the wrong direction
975 */
976
977 if (tileh != SLOPE_FLAT) {
978 if (!_settings_game.construction.build_on_slopes || !CanBuildDepotByTileh(dir, tileh)) {
979 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
980 }
981 cost.AddCost(_price[PR_BUILD_FOUNDATION]);
982 }
983
984 /* Allow the user to rotate the depot instead of having to destroy it and build it again */
985 bool rotate_existing_depot = false;
986 if (IsRailDepotTile(tile) && railtype == GetRailType(tile)) {
987 CommandCost ret = CheckTileOwnership(tile);
988 if (ret.Failed()) return ret;
989
990 if (dir == GetRailDepotDirection(tile)) return CommandCost();
991
992 ret = EnsureNoVehicleOnGround(tile);
993 if (ret.Failed()) return ret;
994
995 rotate_existing_depot = true;
996 }
997
998 if (!rotate_existing_depot) {
999 cost.AddCost(Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile));
1000 if (cost.Failed()) return cost;
1001
1002 if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1003
1004 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1005 }
1006
1007 if (flags.Test(DoCommandFlag::Execute)) {
1008 if (rotate_existing_depot) {
1009 SetRailDepotExitDirection(tile, dir);
1010 } else {
1011 Depot *d = new Depot(tile);
1012
1013 MakeRailDepot(tile, _current_company, d->index, dir, railtype);
1014 MakeDefaultName(d);
1015
1016 Company::Get(_current_company)->infrastructure.rail[railtype]++;
1017 DirtyCompanyInfrastructureWindows(_current_company);
1018 }
1019
1020 MarkTileDirtyByTile(tile);
1021 AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_company);
1022 YapfNotifyTrackLayoutChange(tile, DiagDirToDiagTrack(dir));
1023 }
1024
1025 cost.AddCost(_price[PR_BUILD_DEPOT_TRAIN]);
1026 cost.AddCost(RailBuildCost(railtype));
1027 return cost;
1028}
1029
1049 CommandCost CmdBuildSingleSignal(DoCommandFlags flags, TileIndex tile, Track track, SignalType sigtype, SignalVariant sigvar, bool convert_signal, bool skip_existing_signals, bool ctrl_pressed, SignalType cycle_start, SignalType cycle_stop, uint8_t num_dir_cycle, uint8_t signals_copy)
1050{
1051 if (sigtype > SIGTYPE_LAST || sigvar > SIG_SEMAPHORE) return CMD_ERROR;
1052 if (cycle_start > cycle_stop || cycle_stop > SIGTYPE_LAST) return CMD_ERROR;
1053
1054 if (ctrl_pressed) sigvar = (SignalVariant)(sigvar ^ SIG_SEMAPHORE);
1055
1056 /* You can only build signals on plain rail tiles, and the selected track must exist */
1057 if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) ||
1058 !HasTrack(tile, track)) {
1059 return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
1060 }
1061 /* Protect against invalid signal copying */
1062 if (signals_copy != 0 && (signals_copy & SignalOnTrack(track)) == 0) return CMD_ERROR;
1063
1064 CommandCost ret = CheckTileOwnership(tile);
1065 if (ret.Failed()) return ret;
1066
1067 /* See if this is a valid track combination for signals (no overlap) */
1068 if (TracksOverlap(GetTrackBits(tile))) return CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK);
1069
1070 /* In case we don't want to change an existing signal, return without error. */
1071 if (skip_existing_signals && HasSignalOnTrack(tile, track)) return CommandCost();
1072
1073 /* you can not convert a signal if no signal is on track */
1074 if (convert_signal && !HasSignalOnTrack(tile, track)) return CommandCost(STR_ERROR_THERE_ARE_NO_SIGNALS);
1075
1076 CommandCost cost;
1077 if (!HasSignalOnTrack(tile, track)) {
1078 /* build new signals */
1079 cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
1080 } else {
1081 if (signals_copy != 0 && sigvar != GetSignalVariant(tile, track)) {
1082 /* convert signals <-> semaphores */
1083 cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS] + _price[PR_CLEAR_SIGNALS]);
1084
1085 } else if (convert_signal) {
1086 /* convert button pressed */
1087 if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) {
1088 /* it costs money to change signal variant (light or semaphore) */
1089 cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS] + _price[PR_CLEAR_SIGNALS]);
1090 } else {
1091 /* it is free to change signal type (block, exit, entry, combo, path, etc) */
1092 cost = CommandCost();
1093 }
1094
1095 } else {
1096 /* it is free to change orientation or number of signals on the tile (for block/presignals which allow signals in both directions) */
1097 cost = CommandCost();
1098 }
1099 }
1100
1101 if (flags.Test(DoCommandFlag::Execute)) {
1102 Train *v = nullptr;
1103 /* The new/changed signal could block our path. As this can lead to
1104 * stale reservations, we clear the path reservation here and try
1105 * to redo it later on. */
1106 if (HasReservedTracks(tile, TrackToTrackBits(track))) {
1107 v = GetTrainForReservation(tile, track);
1108 if (v != nullptr) FreeTrainTrackReservation(v);
1109 }
1110
1111 if (!HasSignals(tile)) {
1112 /* there are no signals at all on this tile yet */
1113 SetHasSignals(tile, true);
1114 SetSignalStates(tile, 0xF); // all signals are on
1115 SetPresentSignals(tile, 0); // no signals built by default
1116 SetSignalType(tile, track, sigtype);
1117 SetSignalVariant(tile, track, sigvar);
1118 }
1119
1120 /* Subtract old signal infrastructure count. */
1121 Company::Get(GetTileOwner(tile))->infrastructure.signal -= CountBits(GetPresentSignals(tile));
1122
1123 if (signals_copy == 0) {
1124 if (!HasSignalOnTrack(tile, track)) {
1125 /* build new signals */
1126 SetPresentSignals(tile, GetPresentSignals(tile) | (IsPbsSignal(sigtype) ? KillFirstBit(SignalOnTrack(track)) : SignalOnTrack(track)));
1127 SetSignalType(tile, track, sigtype);
1128 SetSignalVariant(tile, track, sigvar);
1129 while (num_dir_cycle-- > 0) CycleSignalSide(tile, track);
1130 } else {
1131 if (convert_signal) {
1132 /* convert signal button pressed */
1133 if (ctrl_pressed) {
1134 /* toggle the present signal variant: SIG_ELECTRIC <-> SIG_SEMAPHORE */
1135 SetSignalVariant(tile, track, (GetSignalVariant(tile, track) == SIG_ELECTRIC) ? SIG_SEMAPHORE : SIG_ELECTRIC);
1136 /* Query current signal type so the check for PBS signals below works. */
1137 sigtype = GetSignalType(tile, track);
1138 } else {
1139 /* convert the present signal to the chosen type and variant */
1140 SetSignalType(tile, track, sigtype);
1141 SetSignalVariant(tile, track, sigvar);
1142 if (IsPbsSignal(sigtype) && (GetPresentSignals(tile) & SignalOnTrack(track)) == SignalOnTrack(track)) {
1143 SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | KillFirstBit(SignalOnTrack(track)));
1144 }
1145 }
1146
1147 } else if (ctrl_pressed) {
1148 /* cycle between cycle_start and cycle_end */
1149 sigtype = (SignalType)(GetSignalType(tile, track) + 1);
1150
1151 if (sigtype < cycle_start || sigtype > cycle_stop) sigtype = cycle_start;
1152
1153 SetSignalType(tile, track, sigtype);
1154 if (IsPbsSignal(sigtype) && (GetPresentSignals(tile) & SignalOnTrack(track)) == SignalOnTrack(track)) {
1155 SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | KillFirstBit(SignalOnTrack(track)));
1156 }
1157 } else {
1158 /* cycle the signal side: both -> left -> right -> both -> ... */
1159 CycleSignalSide(tile, track);
1160 /* Query current signal type so the check for PBS signals below works. */
1161 sigtype = GetSignalType(tile, track);
1162 }
1163 }
1164 } else {
1165 /* If CmdBuildManySignals is called with copying signals, just copy the
1166 * direction of the first signal given as parameter by CmdBuildManySignals */
1167 SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | (signals_copy & SignalOnTrack(track)));
1168 SetSignalVariant(tile, track, sigvar);
1169 SetSignalType(tile, track, sigtype);
1170 }
1171
1172 /* Add new signal infrastructure count. */
1173 Company::Get(GetTileOwner(tile))->infrastructure.signal += CountBits(GetPresentSignals(tile));
1174 DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
1175
1176 if (IsPbsSignal(sigtype)) {
1177 /* PBS signals should show red unless they are on reserved tiles without a train. */
1178 uint mask = GetPresentSignals(tile) & SignalOnTrack(track);
1179 SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((HasBit(GetRailReservationTrackBits(tile), track) && EnsureNoVehicleOnGround(tile).Succeeded() ? UINT_MAX : 0) & mask));
1180 }
1181 MarkTileDirtyByTile(tile);
1182 AddTrackToSignalBuffer(tile, track, _current_company);
1183 YapfNotifyTrackLayoutChange(tile, track);
1184 if (v != nullptr && v->track != TRACK_BIT_DEPOT) {
1185 /* Extend the train's path if it's not stopped or loading, or not at a safe position. */
1186 if (!((v->vehstatus.Test(VehState::Stopped) && v->cur_speed == 0) || v->current_order.IsType(OT_LOADING)) ||
1187 !IsSafeWaitingPosition(v, v->tile, v->GetVehicleTrackdir(), true, _settings_game.pf.forbid_90_deg)) {
1188 TryPathReserve(v, true);
1189 }
1190 }
1191 }
1192
1193 return cost;
1194}
1195
1196static bool AdvanceSignalAutoFill(TileIndex &tile, Trackdir &trackdir, bool remove)
1197{
1198 /* We only process starting tiles of tunnels or bridges so jump to the other end before moving further. */
1199 if (IsTileType(tile, MP_TUNNELBRIDGE)) tile = GetOtherTunnelBridgeEnd(tile);
1200
1201 tile = AddTileIndexDiffCWrap(tile, _trackdelta[trackdir]);
1202 if (tile == INVALID_TILE) return false;
1203
1204 /* Check for track bits on the new tile */
1205 TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
1206
1207 if (TracksOverlap(TrackdirBitsToTrackBits(trackdirbits))) return false;
1208 trackdirbits &= TrackdirReachesTrackdirs(trackdir);
1209
1210 /* No track bits, must stop */
1211 if (trackdirbits == TRACKDIR_BIT_NONE) return false;
1212
1213 /* Get the first track dir */
1214 trackdir = RemoveFirstTrackdir(&trackdirbits);
1215
1216 /* Any left? It's a junction so we stop */
1217 if (trackdirbits != TRACKDIR_BIT_NONE) return false;
1218
1219 switch (GetTileType(tile)) {
1220 case MP_RAILWAY:
1221 if (IsRailDepot(tile)) return false;
1222 if (!remove && HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) return false;
1223 break;
1224
1225 case MP_ROAD:
1226 if (!IsLevelCrossing(tile)) return false;
1227 break;
1228
1229 case MP_TUNNELBRIDGE: {
1230 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return false;
1231 if (GetTunnelBridgeDirection(tile) != TrackdirToExitdir(trackdir)) return false;
1232 break;
1233 }
1234
1235 default: return false;
1236 }
1237 return true;
1238}
1239
1255 static CommandCost CmdSignalTrackHelper(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, SignalType sigtype, SignalVariant sigvar, bool mode, bool remove, bool autofill, bool minimise_gaps, int signal_density)
1256{
1257 CommandCost total_cost(EXPENSES_CONSTRUCTION);
1258
1259 if (end_tile >= Map::Size() || !ValParamTrackOrientation(track)) return CMD_ERROR;
1260 if (signal_density == 0 || signal_density > 20) return CMD_ERROR;
1261 if (!remove && (sigtype > SIGTYPE_LAST || sigvar > SIG_SEMAPHORE)) return CMD_ERROR;
1262
1263 if (!IsPlainRailTile(tile)) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
1264 TileIndex start_tile = tile;
1265
1266 /* Interpret signal_density as the logical length of said amount of tiles in X/Y direction. */
1267 signal_density *= TILE_AXIAL_DISTANCE;
1268
1269 Trackdir trackdir = TrackToTrackdir(track);
1270 CommandCost ret = ValidateAutoDrag(&trackdir, tile, end_tile);
1271 if (ret.Failed()) return ret;
1272
1273 track = TrackdirToTrack(trackdir); // trackdir might have changed, keep track in sync
1274 Trackdir start_trackdir = trackdir;
1275
1276 /* Must start on a valid track to be able to avoid loops */
1277 if (!HasTrack(tile, track)) return CMD_ERROR;
1278
1279 uint8_t signals;
1280 /* copy the signal-style of the first rail-piece if existing */
1281 if (HasSignalOnTrack(tile, track)) {
1282 signals = GetPresentSignals(tile) & SignalOnTrack(track);
1283 assert(signals != 0);
1284
1285 /* copy signal/semaphores style (independent of CTRL) */
1286 sigvar = GetSignalVariant(tile, track);
1287
1288 sigtype = GetSignalType(tile, track);
1289 /* Don't but copy entry or exit-signal type */
1290 if (sigtype == SIGTYPE_ENTRY || sigtype == SIGTYPE_EXIT) sigtype = SIGTYPE_BLOCK;
1291 } else { // no signals exist, drag a two-way signal stretch
1292 signals = IsPbsSignal(sigtype) ? SignalAlongTrackdir(trackdir) : SignalOnTrack(track);
1293 }
1294
1295 uint8_t signal_dir = 0;
1296 if (signals & SignalAlongTrackdir(trackdir)) SetBit(signal_dir, 0);
1297 if (signals & SignalAgainstTrackdir(trackdir)) SetBit(signal_dir, 1);
1298
1299 /* signal_ctr - amount of tiles already processed
1300 * last_used_ctr - amount of tiles before previously placed signal
1301 * signals_density - setting to put signal on every Nth tile (double space on |, -- tracks)
1302 * last_suitable_ctr - amount of tiles before last possible signal place
1303 * last_suitable_tile - last tile where it is possible to place a signal
1304 * last_suitable_trackdir - trackdir of the last tile
1305 **********
1306 * trackdir - trackdir to build with autorail
1307 * semaphores - semaphores or signals
1308 * signals - is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
1309 * and convert all others to semaphore/signal
1310 * remove - 1 remove signals, 0 build signals */
1311 int signal_ctr = 0;
1312 int last_used_ctr = -signal_density; // to force signal at first tile
1313 int last_suitable_ctr = 0;
1314 TileIndex last_suitable_tile = INVALID_TILE;
1315 Trackdir last_suitable_trackdir = INVALID_TRACKDIR;
1316 CommandCost last_error = CMD_ERROR;
1317 bool had_success = false;
1318 auto build_signal = [&](TileIndex tile, Trackdir trackdir, bool test_only) {
1319 /* Pick the correct orientation for the track direction */
1320 uint8_t signals = 0;
1321 if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir);
1322 if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir);
1323
1324 DoCommandFlags do_flags = test_only ? DoCommandFlags{flags}.Reset(DoCommandFlag::Execute) : flags;
1325 CommandCost ret = remove ? Command<CMD_REMOVE_SINGLE_SIGNAL>::Do(do_flags, tile, TrackdirToTrack(trackdir)) : Command<CMD_BUILD_SINGLE_SIGNAL>::Do(do_flags, tile, TrackdirToTrack(trackdir), sigtype, sigvar, false, signal_ctr == 0, mode, SIGTYPE_BLOCK, SIGTYPE_BLOCK, 0, signals);
1326
1327 if (test_only) return ret.Succeeded();
1328
1329 if (ret.Succeeded()) {
1330 had_success = true;
1331 total_cost.AddCost(ret.GetCost());
1332 } else {
1333 /* The "No railway" error is the least important one. */
1334 if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK ||
1335 last_error.GetErrorMessage() == INVALID_STRING_ID) {
1336 last_error = ret;
1337 }
1338 }
1339 return ret.Succeeded();
1340 };
1341
1342 for (;;) {
1343 if (remove) {
1344 /* In remove mode last_* stuff doesn't matter, we simply try to clear every tile. */
1345 build_signal(tile, trackdir, false);
1346 } else if (minimise_gaps) {
1347 /* We're trying to minimize gaps wherever possible, so keep track of last suitable
1348 * position and use it if current gap exceeds required signal density. */
1349
1350 if (signal_ctr > last_used_ctr + signal_density && last_suitable_tile != INVALID_TILE) {
1351 /* We overshot so build a signal in last good location. */
1352 if (build_signal(last_suitable_tile, last_suitable_trackdir, false)) {
1353 last_suitable_tile = INVALID_TILE;
1354 last_used_ctr = last_suitable_ctr;
1355 }
1356 }
1357
1358 if (signal_ctr == last_used_ctr + signal_density) {
1359 /* Current gap matches the required density, build a signal. */
1360 if (build_signal(tile, trackdir, false)) {
1361 last_used_ctr = signal_ctr;
1362 last_suitable_tile = INVALID_TILE;
1363 }
1364 } else {
1365 /* Test tile for a potential signal spot. */
1366 if (build_signal(tile, trackdir, true)) {
1367 last_suitable_tile = tile;
1368 last_suitable_ctr = signal_ctr;
1369 last_suitable_trackdir = trackdir;
1370 }
1371 }
1372 } else if (signal_ctr >= last_used_ctr + signal_density) {
1373 /* We're always keeping regular interval between signals so doesn't matter whether we succeed or not. */
1374 build_signal(tile, trackdir, false);
1375 last_used_ctr = signal_ctr;
1376 }
1377
1378 if (autofill) {
1379 switch (GetTileType(tile)) {
1380 case MP_RAILWAY:
1381 signal_ctr += (IsDiagonalTrackdir(trackdir) ? TILE_AXIAL_DISTANCE : TILE_CORNER_DISTANCE);
1382 break;
1383
1384 case MP_ROAD:
1385 signal_ctr += TILE_AXIAL_DISTANCE;
1386 break;
1387
1388 case MP_TUNNELBRIDGE: {
1389 uint len = (GetTunnelBridgeLength(tile, GetOtherTunnelBridgeEnd(tile)) + 2) * TILE_AXIAL_DISTANCE;
1390 if (remove || minimise_gaps) {
1391 signal_ctr += len;
1392 } else {
1393 /* To keep regular interval we need to emulate placing signals on a bridge.
1394 * We start with TILE_AXIAL_DISTANCE as one bridge tile gets processed in the main loop. */
1395 signal_ctr += TILE_AXIAL_DISTANCE;
1396 for (uint i = TILE_AXIAL_DISTANCE; i < len; i += TILE_AXIAL_DISTANCE) {
1397 if (signal_ctr >= last_used_ctr + signal_density) last_used_ctr = signal_ctr;
1398 signal_ctr += TILE_AXIAL_DISTANCE;
1399 }
1400 }
1401 break;
1402 }
1403
1404 default: break;
1405 }
1406
1407 if (!AdvanceSignalAutoFill(tile, trackdir, remove)) break;
1408
1409 /* Prevent possible loops */
1410 if (tile == start_tile && trackdir == start_trackdir) break;
1411 } else {
1412 if (tile == end_tile) break;
1413
1414 signal_ctr += (IsDiagonalTrackdir(trackdir) ? TILE_AXIAL_DISTANCE : TILE_CORNER_DISTANCE);
1415 /* toggle railbit for the non-diagonal tracks (|, -- tracks) */
1416
1417 tile += ToTileIndexDiff(_trackdelta[trackdir]);
1418 if (!IsDiagonalTrackdir(trackdir)) ToggleBit(trackdir, 0);
1419 }
1420 }
1421
1422 /* We may end up with the current gap exceeding the signal density so fix that if needed. */
1423 if (!remove && minimise_gaps && signal_ctr > last_used_ctr + signal_density && last_suitable_tile != INVALID_TILE) {
1424 build_signal(last_suitable_tile, last_suitable_trackdir, false);
1425 }
1426
1427 return had_success ? total_cost : last_error;
1428}
1429
1446 CommandCost CmdBuildSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, SignalType sigtype, SignalVariant sigvar, bool mode, bool autofill, bool minimise_gaps, uint8_t signal_density)
1447{
1448 return CmdSignalTrackHelper(flags, tile, end_tile, track, sigtype, sigvar, mode, false, autofill, minimise_gaps, signal_density);
1449}
1450
1458 CommandCost CmdRemoveSingleSignal(DoCommandFlags flags, TileIndex tile, Track track)
1459{
1460 if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
1461 return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
1462 }
1463 if (!HasSignalOnTrack(tile, track)) {
1464 return CommandCost(STR_ERROR_THERE_ARE_NO_SIGNALS);
1465 }
1466
1467 /* Only water can remove signals from anyone */
1468 if (_current_company != OWNER_WATER) {
1469 CommandCost ret = CheckTileOwnership(tile);
1470 if (ret.Failed()) return ret;
1471 }
1472
1473 /* Do it? */
1474 if (flags.Test(DoCommandFlag::Execute)) {
1475 Train *v = nullptr;
1476 if (HasReservedTracks(tile, TrackToTrackBits(track))) {
1477 v = GetTrainForReservation(tile, track);
1478 } else if (IsPbsSignal(GetSignalType(tile, track))) {
1479 /* PBS signal, might be the end of a path reservation. */
1480 Trackdir td = TrackToTrackdir(track);
1481 for (int i = 0; v == nullptr && i < 2; i++, td = ReverseTrackdir(td)) {
1482 /* Only test the active signal side. */
1483 if (!HasSignalOnTrackdir(tile, ReverseTrackdir(td))) continue;
1484 TileIndex next = TileAddByDiagDir(tile, TrackdirToExitdir(td));
1485 TrackBits tracks = TrackdirBitsToTrackBits(TrackdirReachesTrackdirs(td));
1486 if (HasReservedTracks(next, tracks)) {
1487 v = GetTrainForReservation(next, TrackBitsToTrack(GetReservedTrackbits(next) & tracks));
1488 }
1489 }
1490 }
1491 Company::Get(GetTileOwner(tile))->infrastructure.signal -= CountBits(GetPresentSignals(tile));
1492 SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
1493 Company::Get(GetTileOwner(tile))->infrastructure.signal += CountBits(GetPresentSignals(tile));
1494 DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
1495
1496 /* removed last signal from tile? */
1497 if (GetPresentSignals(tile) == 0) {
1498 SetSignalStates(tile, 0);
1499 SetHasSignals(tile, false);
1500 SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores
1501 }
1502
1503 AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
1504 YapfNotifyTrackLayoutChange(tile, track);
1505 if (v != nullptr) TryPathReserve(v, false);
1506
1507 MarkTileDirtyByTile(tile);
1508 }
1509
1510 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_SIGNALS]);
1511}
1512
1524 CommandCost CmdRemoveSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, bool autofill)
1525{
1526 return CmdSignalTrackHelper(flags, tile, end_tile, track, SIGTYPE_BLOCK, SIG_ELECTRIC, false, true, autofill, false, 1); // bit 5 is remove bit
1527}
1528
1539 CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RailType totype, bool diagonal)
1540{
1541 TileIndex area_end = tile;
1542
1543 if (!ValParamRailType(totype)) return CMD_ERROR;
1544 if (area_start >= Map::Size()) return CMD_ERROR;
1545
1546 TrainList affected_trains;
1547
1548 CommandCost cost(EXPENSES_CONSTRUCTION);
1549 CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert.
1550 bool found_convertible_track = false; // whether we actually did convert some track (see bug #7633)
1551
1552 std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal);
1553 for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
1554 TileType tt = GetTileType(tile);
1555
1556 /* Check if there is any track on tile */
1557 switch (tt) {
1558 case MP_RAILWAY:
1559 break;
1560 case MP_STATION:
1561 if (!HasStationRail(tile)) continue;
1562 break;
1563 case MP_ROAD:
1564 if (!IsLevelCrossing(tile)) continue;
1565 if (RailNoLevelCrossings(totype)) {
1566 error.MakeError(STR_ERROR_CROSSING_DISALLOWED_RAIL);
1567 continue;
1568 }
1569 break;
1570 case MP_TUNNELBRIDGE:
1571 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
1572 break;
1573 default: continue;
1574 }
1575
1576 /* Original railtype we are converting from */
1577 RailType type = GetRailType(tile);
1578
1579 /* Converting to the same type or converting 'hidden' elrail -> rail */
1580 if (type == totype || (_settings_game.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
1581
1582 /* Trying to convert other's rail */
1583 CommandCost ret = CheckTileOwnership(tile);
1584 if (ret.Failed()) {
1585 error = std::move(ret);
1586 continue;
1587 }
1588
1589 std::vector<Train *> vehicles_affected;
1590
1591 /* Vehicle on the tile when not converting Rail <-> ElRail
1592 * Tunnels and bridges have special check later */
1593 if (tt != MP_TUNNELBRIDGE) {
1594 if (!IsCompatibleRail(type, totype)) {
1595 ret = IsPlainRailTile(tile) ? EnsureNoTrainOnTrackBits(tile, GetTrackBits(tile)) : EnsureNoVehicleOnGround(tile);
1596 if (ret.Failed()) {
1597 error = std::move(ret);
1598 continue;
1599 }
1600 }
1601 if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
1602 TrackBits reserved = GetReservedTrackbits(tile);
1603 Track track;
1604 while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
1605 Train *v = GetTrainForReservation(tile, track);
1606 if (v != nullptr && !HasPowerOnRail(v->railtypes, totype)) {
1607 /* No power on new rail type, reroute. */
1608 FreeTrainTrackReservation(v);
1609 vehicles_affected.push_back(v);
1610 }
1611 }
1612
1613 /* Update the company infrastructure counters. */
1614 if (!IsRailStationTile(tile) || !IsStationTileBlocked(tile)) {
1615 Company *c = Company::Get(GetTileOwner(tile));
1616 uint num_pieces = IsLevelCrossingTile(tile) ? LEVELCROSSING_TRACKBIT_FACTOR : 1;
1617 if (IsPlainRailTile(tile)) {
1618 TrackBits bits = GetTrackBits(tile);
1619 num_pieces = CountBits(bits);
1620 if (TracksOverlap(bits)) num_pieces *= num_pieces;
1621 }
1622 c->infrastructure.rail[type] -= num_pieces;
1623 c->infrastructure.rail[totype] += num_pieces;
1624 DirtyCompanyInfrastructureWindows(c->index);
1625 }
1626
1627 SetRailType(tile, totype);
1628 MarkTileDirtyByTile(tile);
1629 /* update power of train on this tile */
1630 for (Vehicle *v : VehiclesOnTile(tile)) {
1631 if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First());
1632 }
1633 }
1634 }
1635
1636 switch (tt) {
1637 case MP_RAILWAY:
1638 switch (GetRailTileType(tile)) {
1639 case RailTileType::Depot:
1640 if (flags.Test(DoCommandFlag::Execute)) {
1641 /* notify YAPF about the track layout change */
1642 YapfNotifyTrackLayoutChange(tile, GetRailDepotTrack(tile));
1643
1644 /* Update build vehicle window related to this depot */
1645 InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
1646 InvalidateWindowData(WC_BUILD_VEHICLE, tile);
1647 }
1648 found_convertible_track = true;
1649 cost.AddCost(RailConvertCost(type, totype));
1650 break;
1651
1652 default: // RailTileType::Normal, RailTileType::Signals
1653 if (flags.Test(DoCommandFlag::Execute)) {
1654 /* notify YAPF about the track layout change */
1655 TrackBits tracks = GetTrackBits(tile);
1656 while (tracks != TRACK_BIT_NONE) {
1657 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
1658 }
1659 }
1660 found_convertible_track = true;
1661 cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
1662 break;
1663 }
1664 break;
1665
1666 case MP_TUNNELBRIDGE: {
1667 TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
1668
1669 /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
1670 * it would cause assert because of different test and exec runs */
1671 if (endtile < tile) {
1672 if (diagonal) {
1673 if (DiagonalTileArea(area_start, area_end).Contains(endtile)) continue;
1674 } else {
1675 if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue;
1676 }
1677 }
1678
1679 /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
1680 if (!IsCompatibleRail(GetRailType(tile), totype)) {
1681 ret = TunnelBridgeIsFree(tile, endtile);
1682 if (ret.Failed()) {
1683 error = std::move(ret);
1684 continue;
1685 }
1686 }
1687
1688 if (flags.Test(DoCommandFlag::Execute)) {
1689 Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
1690 if (HasTunnelBridgeReservation(tile)) {
1691 Train *v = GetTrainForReservation(tile, track);
1692 if (v != nullptr && !HasPowerOnRail(v->railtypes, totype)) {
1693 /* No power on new rail type, reroute. */
1694 FreeTrainTrackReservation(v);
1695 vehicles_affected.push_back(v);
1696 }
1697 }
1698
1699 /* Update the company infrastructure counters. */
1700 uint num_pieces = (GetTunnelBridgeLength(tile, endtile) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
1701 Company *c = Company::Get(GetTileOwner(tile));
1702 c->infrastructure.rail[GetRailType(tile)] -= num_pieces;
1703 c->infrastructure.rail[totype] += num_pieces;
1704 DirtyCompanyInfrastructureWindows(c->index);
1705
1706 SetRailType(tile, totype);
1707 SetRailType(endtile, totype);
1708
1709 for (Vehicle *v : VehiclesOnTile(tile)) {
1710 if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First());
1711 }
1712 for (Vehicle *v : VehiclesOnTile(endtile)) {
1713 if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First());
1714 }
1715
1716 YapfNotifyTrackLayoutChange(tile, track);
1717 YapfNotifyTrackLayoutChange(endtile, track);
1718
1719 if (IsBridge(tile)) {
1720 MarkBridgeDirty(tile);
1721 } else {
1722 MarkTileDirtyByTile(tile);
1723 MarkTileDirtyByTile(endtile);
1724 }
1725 }
1726
1727 found_convertible_track = true;
1728 cost.AddCost((GetTunnelBridgeLength(tile, endtile) + 2) * RailConvertCost(type, totype));
1729 break;
1730 }
1731
1732 default: // MP_STATION, MP_ROAD
1733 if (flags.Test(DoCommandFlag::Execute)) {
1734 Track track = ((tt == MP_STATION) ? GetRailStationTrack(tile) : GetCrossingRailTrack(tile));
1735 YapfNotifyTrackLayoutChange(tile, track);
1736 }
1737
1738 found_convertible_track = true;
1739 cost.AddCost(RailConvertCost(type, totype));
1740 break;
1741 }
1742
1743 for (uint i = 0; i < vehicles_affected.size(); ++i) {
1744 TryPathReserve(vehicles_affected[i], true);
1745 }
1746 }
1747
1748 if (flags.Test(DoCommandFlag::Execute)) {
1749 /* Railtype changed, update trains as when entering different track */
1750 for (Train *v : affected_trains) {
1751 v->ConsistChanged(CCF_TRACK);
1752 }
1753 }
1754
1755 return found_convertible_track ? cost : error;
1756}
1757
1758static CommandCost RemoveTrainDepot(TileIndex tile, DoCommandFlags flags)
1759{
1760 if (_current_company != OWNER_WATER) {
1761 CommandCost ret = CheckTileOwnership(tile);
1762 if (ret.Failed()) return ret;
1763 }
1764
1765 CommandCost ret = EnsureNoVehicleOnGround(tile);
1766 if (ret.Failed()) return ret;
1767
1768 if (flags.Test(DoCommandFlag::Execute)) {
1769 /* read variables before the depot is removed */
1770 DiagDirection dir = GetRailDepotDirection(tile);
1771 Owner owner = GetTileOwner(tile);
1772 Train *v = nullptr;
1773
1774 if (HasDepotReservation(tile)) {
1775 v = GetTrainForReservation(tile, DiagDirToDiagTrack(dir));
1776 if (v != nullptr) FreeTrainTrackReservation(v);
1777 }
1778
1779 Company::Get(owner)->infrastructure.rail[GetRailType(tile)]--;
1780 DirtyCompanyInfrastructureWindows(owner);
1781
1782 delete Depot::GetByTile(tile);
1783 DoClearSquare(tile);
1784 AddSideToSignalBuffer(tile, dir, owner);
1785 YapfNotifyTrackLayoutChange(tile, DiagDirToDiagTrack(dir));
1786 if (v != nullptr) TryPathReserve(v, true);
1787 }
1788
1789 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_TRAIN]);
1790}
1791
1792static CommandCost ClearTile_Track(TileIndex tile, DoCommandFlags flags)
1793{
1794 CommandCost cost(EXPENSES_CONSTRUCTION);
1795
1796 if (flags.Test(DoCommandFlag::Auto)) {
1797 if (!IsTileOwner(tile, _current_company)) {
1798 return CommandCost(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
1799 }
1800
1801 if (IsPlainRail(tile)) {
1802 return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
1803 } else {
1804 return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
1805 }
1806 }
1807
1808 switch (GetRailTileType(tile)) {
1809 case RailTileType::Signals:
1810 case RailTileType::Normal: {
1811 Slope tileh = GetTileSlope(tile);
1812 /* Is there flat water on the lower halftile that gets cleared expensively? */
1813 bool water_ground = (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh));
1814
1815 TrackBits tracks = GetTrackBits(tile);
1816 while (tracks != TRACK_BIT_NONE) {
1817 Track track = RemoveFirstTrack(&tracks);
1818 CommandCost ret = Command<CMD_REMOVE_SINGLE_RAIL>::Do(flags, tile, track);
1819 if (ret.Failed()) return ret;
1820 cost.AddCost(ret.GetCost());
1821 }
1822
1823 /* When bankrupting, don't make water dirty, there could be a ship on lower halftile.
1824 * Same holds for non-companies clearing the tile, e.g. disasters. */
1825 if (water_ground && !flags.Test(DoCommandFlag::Bankrupt) && Company::IsValidID(_current_company)) {
1826 CommandCost ret = EnsureNoVehicleOnGround(tile);
1827 if (ret.Failed()) return ret;
1828
1829 /* The track was removed, and left a coast tile. Now also clear the water. */
1830 if (flags.Test(DoCommandFlag::Execute)) {
1831 DoClearSquare(tile);
1832 }
1833 cost.AddCost(_price[PR_CLEAR_WATER]);
1834 }
1835
1836 return cost;
1837 }
1838
1839 case RailTileType::Depot:
1840 return RemoveTrainDepot(tile, flags);
1841
1842 default:
1843 return CMD_ERROR;
1844 }
1845}
1846
1851 static uint GetSaveSlopeZ(uint x, uint y, Track track)
1852{
1853 switch (track) {
1854 case TRACK_UPPER: x &= ~0xF; y &= ~0xF; break;
1855 case TRACK_LOWER: x |= 0xF; y |= 0xF; break;
1856 case TRACK_LEFT: x |= 0xF; y &= ~0xF; break;
1857 case TRACK_RIGHT: x &= ~0xF; y |= 0xF; break;
1858 default: break;
1859 }
1860 return GetSlopePixelZ(x, y);
1861}
1862
1863static void DrawSingleSignal(TileIndex tile, const RailTypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos)
1864{
1865 bool side;
1866 switch (_settings_game.construction.train_signal_side) {
1867 case 0: side = false; break; // left
1868 case 2: side = true; break; // right
1869 default: side = _settings_game.vehicle.road_side != 0; break; // driving side
1870 }
1871 static const Point SignalPositions[2][12] = {
1872 { // Signals on the left side
1873 /* LEFT LEFT RIGHT RIGHT UPPER UPPER */
1874 { 8, 5}, {14, 1}, { 1, 14}, { 9, 11}, { 1, 0}, { 3, 10},
1875 /* LOWER LOWER X X Y Y */
1876 {11, 4}, {14, 14}, {11, 3}, { 4, 13}, { 3, 4}, {11, 13}
1877 }, { // Signals on the right side
1878 /* LEFT LEFT RIGHT RIGHT UPPER UPPER */
1879 {14, 1}, {12, 10}, { 4, 6}, { 1, 14}, {10, 4}, { 0, 1},
1880 /* LOWER LOWER X X Y Y */
1881 {14, 14}, { 5, 12}, {11, 13}, { 4, 3}, {13, 4}, { 3, 11}
1882 }
1883 };
1884
1885 uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x;
1886 uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y;
1887
1888 SignalType type = GetSignalType(tile, track);
1889 SignalVariant variant = GetSignalVariant(tile, track);
1890
1891 SpriteID sprite = GetCustomSignalSprite(rti, tile, type, variant, condition);
1892 if (sprite != 0) {
1893 sprite += image;
1894 } else {
1895 /* Normal electric signals are stored in a different sprite block than all other signals. */
1896 sprite = (type == SIGTYPE_BLOCK && variant == SIG_ELECTRIC) ? SPR_ORIGINAL_SIGNALS_BASE : SPR_SIGNALS_BASE - 16;
1897 sprite += type * 16 + variant * 64 + image * 2 + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0);
1898 }
1899
1900 AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, GetSaveSlopeZ(x, y, track), {{}, {1, 1, BB_HEIGHT_UNDER_BRIDGE}, {}});
1901}
1902
1904 struct FenceOffset : SpriteBounds {
1905 Corner height_ref;
1906
1907 constexpr FenceOffset(Corner height_ref, int8_t origin_x, int8_t origin_y, uint8_t extent_x, uint8_t extent_y) :
1908 SpriteBounds({origin_x, origin_y, 0}, {extent_x, extent_y, 4}, {}), height_ref(height_ref) {}
1909};
1910
1912 static const FenceOffset _fence_offsets[] = {
1913 { CORNER_INVALID, 0, 1, 16, 1 }, // RFO_FLAT_X_NW
1914 { CORNER_INVALID, 1, 0, 1, 16 }, // RFO_FLAT_Y_NE
1915 { CORNER_W, 8, 8, 1, 1 }, // RFO_FLAT_LEFT
1916 { CORNER_N, 8, 8, 1, 1 }, // RFO_FLAT_UPPER
1917 { CORNER_INVALID, 0, 1, 16, 1 }, // RFO_SLOPE_SW_NW
1918 { CORNER_INVALID, 1, 0, 1, 16 }, // RFO_SLOPE_SE_NE
1919 { CORNER_INVALID, 0, 1, 16, 1 }, // RFO_SLOPE_NE_NW
1920 { CORNER_INVALID, 1, 0, 1, 16 }, // RFO_SLOPE_NW_NE
1921 { CORNER_INVALID, 0, 15, 16, 1 }, // RFO_FLAT_X_SE
1922 { CORNER_INVALID, 15, 0, 1, 16 }, // RFO_FLAT_Y_SW
1923 { CORNER_E, 8, 8, 1, 1 }, // RFO_FLAT_RIGHT
1924 { CORNER_S, 8, 8, 1, 1 }, // RFO_FLAT_LOWER
1925 { CORNER_INVALID, 0, 15, 16, 1 }, // RFO_SLOPE_SW_SE
1926 { CORNER_INVALID, 15, 0, 1, 16 }, // RFO_SLOPE_SE_SW
1927 { CORNER_INVALID, 0, 15, 16, 1 }, // RFO_SLOPE_NE_SE
1928 { CORNER_INVALID, 15, 0, 1, 16 }, // RFO_SLOPE_NW_SW
1929};
1930
1938 static void DrawTrackFence(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites, RailFenceOffset rfo)
1939{
1940 int z = ti->z;
1941 if (_fence_offsets[rfo].height_ref != CORNER_INVALID) {
1942 z += GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), _fence_offsets[rfo].height_ref);
1943 }
1944 AddSortableSpriteToDraw(psid.sprite + (rfo % num_sprites), psid.pal, ti->x, ti->y, z, _fence_offsets[rfo]);
1945}
1946
1950 static void DrawTrackFence_NW(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
1951{
1952 RailFenceOffset rfo = RFO_FLAT_X_NW;
1953 if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_SLOPE_SW_NW : RFO_SLOPE_NE_NW;
1954 DrawTrackFence(ti, psid, num_sprites, rfo);
1955}
1956
1960 static void DrawTrackFence_SE(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
1961{
1962 RailFenceOffset rfo = RFO_FLAT_X_SE;
1963 if (ti->tileh & SLOPE_SE) rfo = (ti->tileh & SLOPE_S) ? RFO_SLOPE_SW_SE : RFO_SLOPE_NE_SE;
1964 DrawTrackFence(ti, psid, num_sprites, rfo);
1965}
1966
1970 static void DrawTrackFence_NE(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
1971{
1972 RailFenceOffset rfo = RFO_FLAT_Y_NE;
1973 if (ti->tileh & SLOPE_NE) rfo = (ti->tileh & SLOPE_E) ? RFO_SLOPE_SE_NE : RFO_SLOPE_NW_NE;
1974 DrawTrackFence(ti, psid, num_sprites, rfo);
1975}
1976
1980 static void DrawTrackFence_SW(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
1981{
1982 RailFenceOffset rfo = RFO_FLAT_Y_SW;
1983 if (ti->tileh & SLOPE_SW) rfo = (ti->tileh & SLOPE_S) ? RFO_SLOPE_SE_SW : RFO_SLOPE_NW_SW;
1984 DrawTrackFence(ti, psid, num_sprites, rfo);
1985}
1986
1992 static void DrawTrackDetails(const TileInfo *ti, const RailTypeInfo *rti, PaletteID pal)
1993{
1994 /* Base sprite for track fences.
1995 * Note: Halftile slopes only have fences on the upper part. */
1996 uint num_sprites = 0;
1997 PalSpriteID psid{
1998 .sprite = GetCustomRailSprite(rti, ti->tile, RTSG_FENCES, IsHalftileSlope(ti->tileh) ? TCX_UPPER_HALFTILE : TCX_NORMAL, &num_sprites),
1999 .pal = pal,
2000 };
2001 if (psid.sprite == 0) {
2002 psid.sprite = SPR_TRACK_FENCE_FLAT_X;
2003 num_sprites = 8;
2004 }
2005
2006 assert(num_sprites > 0);
2007
2008 switch (GetRailGroundType(ti->tile)) {
2009 case RailGroundType::FenceNW: DrawTrackFence_NW(ti, psid, num_sprites); break;
2010 case RailGroundType::FenceSE: DrawTrackFence_SE(ti, psid, num_sprites); break;
2011 case RailGroundType::FenceSENW: DrawTrackFence_NW(ti, psid, num_sprites);
2012 DrawTrackFence_SE(ti, psid, num_sprites); break;
2013 case RailGroundType::FenceNE: DrawTrackFence_NE(ti, psid, num_sprites); break;
2014 case RailGroundType::FenceSW: DrawTrackFence_SW(ti, psid, num_sprites); break;
2015 case RailGroundType::FenceNESW: DrawTrackFence_NE(ti, psid, num_sprites);
2016 DrawTrackFence_SW(ti, psid, num_sprites); break;
2017 case RailGroundType::FenceVert1: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_LEFT); break;
2018 case RailGroundType::FenceVert2: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_RIGHT); break;
2019 case RailGroundType::FenceHoriz1: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_UPPER); break;
2020 case RailGroundType::FenceHoriz2: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_LOWER); break;
2021 case RailGroundType::HalfTileWater: {
2022 Corner track_corner;
2023 if (IsHalftileSlope(ti->tileh)) {
2024 /* Steep slope or one-corner-raised slope with halftile foundation */
2025 track_corner = GetHalftileSlopeCorner(ti->tileh);
2026 } else {
2027 /* Three-corner-raised slope */
2028 track_corner = OppositeCorner(GetHighestSlopeCorner(ComplementSlope(ti->tileh)));
2029 }
2030 switch (track_corner) {
2031 case CORNER_W: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_LEFT); break;
2032 case CORNER_S: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_LOWER); break;
2033 case CORNER_E: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_RIGHT); break;
2034 case CORNER_N: DrawTrackFence(ti, psid, num_sprites, RFO_FLAT_UPPER); break;
2035 default: NOT_REACHED();
2036 }
2037 break;
2038 }
2039 default: break;
2040 }
2041}
2042
2043/* SubSprite for drawing the track halftile of 'three-corners-raised'-sloped rail sprites. */
2044static const int INF = 1000; // big number compared to tilesprite size
2045static const SubSprite _halftile_sub_sprite[4] = {
2046 { -INF , -INF , 32 - 33, INF }, // CORNER_W, clip 33 pixels from right
2047 { -INF , 0 + 7, INF , INF }, // CORNER_S, clip 7 pixels from top
2048 { -31 + 33, -INF , INF , INF }, // CORNER_E, clip 33 pixels from left
2049 { -INF , -INF , INF , 30 - 23 } // CORNER_N, clip 23 pixels from bottom
2050};
2051
2052static inline void DrawTrackSprite(SpriteID sprite, PaletteID pal, const TileInfo *ti, Slope s)
2053{
2054 DrawGroundSprite(sprite, pal, nullptr, 0, (ti->tileh & s) ? -8 : 0);
2055}
2056
2057static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeInfo *rti)
2058{
2059 RailGroundType rgt = GetRailGroundType(ti->tile);
2060 Foundation f = GetRailFoundation(ti->tileh, track);
2061 Corner halftile_corner = CORNER_INVALID;
2062
2063 if (IsNonContinuousFoundation(f)) {
2064 /* Save halftile corner */
2065 halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
2066 /* Draw lower part first */
2067 track &= ~CornerToTrackBits(halftile_corner);
2068 f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE);
2069 }
2070
2071 DrawFoundation(ti, f);
2072 /* DrawFoundation modifies ti */
2073
2074 /* Draw ground */
2075 if (rgt == RailGroundType::HalfTileWater) {
2076 if (track != TRACK_BIT_NONE || IsSteepSlope(ti->tileh)) {
2077 /* three-corner-raised slope or steep slope with track on upper part */
2078 DrawShoreTile(ti->tileh);
2079 } else {
2080 /* single-corner-raised slope with track on upper part */
2081 DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
2082 }
2083 } else {
2084 SpriteID image;
2085
2086 switch (rgt) {
2087 case RailGroundType::Barren: image = SPR_FLAT_BARE_LAND; break;
2088 case RailGroundType::SnowOrDesert: image = SPR_FLAT_SNOW_DESERT_TILE; break;
2089 default: image = SPR_FLAT_GRASS_TILE; break;
2090 }
2091
2092 image += SlopeToSpriteOffset(ti->tileh);
2093
2094 DrawGroundSprite(image, PAL_NONE);
2095 }
2096
2097 bool no_combine = ti->tileh == SLOPE_FLAT && rti->flags.Test(RailTypeFlag::NoSpriteCombine);
2098 SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
2099 SpriteID ground = GetCustomRailSprite(rti, ti->tile, no_combine ? RTSG_GROUND_COMPLETE : RTSG_GROUND);
2100 TrackBits pbs = _settings_client.gui.show_track_reservation ? GetRailReservationTrackBits(ti->tile) : TRACK_BIT_NONE;
2101
2102 if (track == TRACK_BIT_NONE) {
2103 /* Half-tile foundation, no track here? */
2104 } else if (no_combine) {
2105 /* Use trackbits as direct index from ground sprite, subtract 1
2106 * because there is no sprite for no bits. */
2107 DrawGroundSprite(ground + track - 1, PAL_NONE);
2108
2109 /* Draw reserved track bits */
2110 if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
2111 if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
2112 if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N);
2113 if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S);
2114 if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E);
2115 if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W);
2116 } else if (ti->tileh == SLOPE_NW && track == TRACK_BIT_Y) {
2117 DrawGroundSprite(ground + RTO_SLOPE_NW, PAL_NONE);
2118 if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_NW, PALETTE_CRASH);
2119 } else if (ti->tileh == SLOPE_NE && track == TRACK_BIT_X) {
2120 DrawGroundSprite(ground + RTO_SLOPE_NE, PAL_NONE);
2121 if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_NE, PALETTE_CRASH);
2122 } else if (ti->tileh == SLOPE_SE && track == TRACK_BIT_Y) {
2123 DrawGroundSprite(ground + RTO_SLOPE_SE, PAL_NONE);
2124 if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_SE, PALETTE_CRASH);
2125 } else if (ti->tileh == SLOPE_SW && track == TRACK_BIT_X) {
2126 DrawGroundSprite(ground + RTO_SLOPE_SW, PAL_NONE);
2127 if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_SW, PALETTE_CRASH);
2128 } else {
2129 switch (track) {
2130 /* Draw single ground sprite when not overlapping. No track overlay
2131 * is necessary for these sprites. */
2132 case TRACK_BIT_X: DrawGroundSprite(ground + RTO_X, PAL_NONE); break;
2133 case TRACK_BIT_Y: DrawGroundSprite(ground + RTO_Y, PAL_NONE); break;
2134 case TRACK_BIT_UPPER: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); break;
2135 case TRACK_BIT_LOWER: DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break;
2136 case TRACK_BIT_RIGHT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); break;
2137 case TRACK_BIT_LEFT: DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break;
2138 case TRACK_BIT_CROSS: DrawGroundSprite(ground + RTO_CROSSING_XY, PAL_NONE); break;
2139 case TRACK_BIT_HORZ: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N);
2140 DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break;
2141 case TRACK_BIT_VERT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E);
2142 DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break;
2143
2144 default:
2145 /* We're drawing a junction tile */
2146 if ((track & TRACK_BIT_3WAY_NE) == 0) {
2147 DrawGroundSprite(ground + RTO_JUNCTION_SW, PAL_NONE);
2148 } else if ((track & TRACK_BIT_3WAY_SW) == 0) {
2149 DrawGroundSprite(ground + RTO_JUNCTION_NE, PAL_NONE);
2150 } else if ((track & TRACK_BIT_3WAY_NW) == 0) {
2151 DrawGroundSprite(ground + RTO_JUNCTION_SE, PAL_NONE);
2152 } else if ((track & TRACK_BIT_3WAY_SE) == 0) {
2153 DrawGroundSprite(ground + RTO_JUNCTION_NW, PAL_NONE);
2154 } else {
2155 DrawGroundSprite(ground + RTO_JUNCTION_NSEW, PAL_NONE);
2156 }
2157
2158 /* Mask out PBS bits as we shall draw them afterwards anyway. */
2159 track &= ~pbs;
2160
2161 /* Draw regular track bits */
2162 if (track & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PAL_NONE);
2163 if (track & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PAL_NONE);
2164 if (track & TRACK_BIT_UPPER) DrawGroundSprite(overlay + RTO_N, PAL_NONE);
2165 if (track & TRACK_BIT_LOWER) DrawGroundSprite(overlay + RTO_S, PAL_NONE);
2166 if (track & TRACK_BIT_RIGHT) DrawGroundSprite(overlay + RTO_E, PAL_NONE);
2167 if (track & TRACK_BIT_LEFT) DrawGroundSprite(overlay + RTO_W, PAL_NONE);
2168 }
2169
2170 /* Draw reserved track bits */
2171 if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
2172 if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
2173 if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N);
2174 if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S);
2175 if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E);
2176 if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W);
2177 }
2178
2179 if (IsValidCorner(halftile_corner)) {
2180 DrawFoundation(ti, HalftileFoundation(halftile_corner));
2181 overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY, TCX_UPPER_HALFTILE);
2182 ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND, TCX_UPPER_HALFTILE);
2183
2184 /* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */
2185 Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner));
2186
2187 SpriteID image;
2188 switch (rgt) {
2189 case RailGroundType::Barren: image = SPR_FLAT_BARE_LAND; break;
2190 case RailGroundType::SnowOrDesert:
2191 case RailGroundType::HalfTileSnow: image = SPR_FLAT_SNOW_DESERT_TILE; break;
2192 default: image = SPR_FLAT_GRASS_TILE; break;
2193 }
2194
2195 image += SlopeToSpriteOffset(fake_slope);
2196
2197 DrawGroundSprite(image, PAL_NONE, &(_halftile_sub_sprite[halftile_corner]));
2198
2199 track = CornerToTrackBits(halftile_corner);
2200
2201 int offset;
2202 switch (track) {
2203 default: NOT_REACHED();
2204 case TRACK_BIT_UPPER: offset = RTO_N; break;
2205 case TRACK_BIT_LOWER: offset = RTO_S; break;
2206 case TRACK_BIT_RIGHT: offset = RTO_E; break;
2207 case TRACK_BIT_LEFT: offset = RTO_W; break;
2208 }
2209
2210 DrawTrackSprite(ground + offset, PAL_NONE, ti, fake_slope);
2211 if (_settings_client.gui.show_track_reservation && HasReservedTracks(ti->tile, track)) {
2212 DrawTrackSprite(overlay + offset, PALETTE_CRASH, ti, fake_slope);
2213 }
2214 }
2215}
2216
2224 static int GetJunctionGroundSpriteOffset(TrackBits track)
2225{
2226 /* If none of the tracks end up in the NE corner, return the ground sprite
2227 * where the NE of the tile is not covered. Repeat for the other directions.
2228 * What remains are junctions where all directions are covered. */
2229 if ((track & TRACK_BIT_3WAY_NE) == 0) return 0;
2230 if ((track & TRACK_BIT_3WAY_SW) == 0) return 1;
2231 if ((track & TRACK_BIT_3WAY_NW) == 0) return 2;
2232 if ((track & TRACK_BIT_3WAY_SE) == 0) return 3;
2233 return 4;
2234}
2235
2241 static void DrawTrackBits(TileInfo *ti, TrackBits track)
2242{
2243 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
2244
2245 if (rti->UsesOverlay()) {
2246 DrawTrackBitsOverlay(ti, track, rti);
2247 return;
2248 }
2249
2250 RailGroundType rgt = GetRailGroundType(ti->tile);
2251 Foundation f = GetRailFoundation(ti->tileh, track);
2252 Corner halftile_corner = CORNER_INVALID;
2253
2254 if (IsNonContinuousFoundation(f)) {
2255 /* Save halftile corner */
2256 halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
2257 /* Draw lower part first */
2258 track &= ~CornerToTrackBits(halftile_corner);
2259 f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE);
2260 }
2261
2262 DrawFoundation(ti, f);
2263 /* DrawFoundation modifies ti */
2264
2265 SpriteID image;
2266 PaletteID pal = PAL_NONE;
2267 const SubSprite *sub = nullptr;
2268 bool junction = false;
2269
2270 /* Select the sprite to use. */
2271 if (track == 0) {
2272 /* Clear ground (only track on halftile foundation) */
2273 if (rgt == RailGroundType::HalfTileWater) {
2274 if (IsSteepSlope(ti->tileh)) {
2275 DrawShoreTile(ti->tileh);
2276 image = 0;
2277 } else {
2278 image = SPR_FLAT_WATER_TILE;
2279 }
2280 } else {
2281 switch (rgt) {
2282 case RailGroundType::Barren: image = SPR_FLAT_BARE_LAND; break;
2283 case RailGroundType::SnowOrDesert: image = SPR_FLAT_SNOW_DESERT_TILE; break;
2284 default: image = SPR_FLAT_GRASS_TILE; break;
2285 }
2286 image += SlopeToSpriteOffset(ti->tileh);
2287 }
2288 } else {
2289 if (ti->tileh != SLOPE_FLAT) {
2290 /* track on non-flat ground */
2291 image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
2292 } else {
2293 /* track on flat ground */
2294 switch (track) {
2295 /* single track, select combined track + ground sprite*/
2296 case TRACK_BIT_Y: image = rti->base_sprites.track_y; break;
2297 case TRACK_BIT_X: image = rti->base_sprites.track_y + 1; break;
2298 case TRACK_BIT_UPPER: image = rti->base_sprites.track_y + 2; break;
2299 case TRACK_BIT_LOWER: image = rti->base_sprites.track_y + 3; break;
2300 case TRACK_BIT_RIGHT: image = rti->base_sprites.track_y + 4; break;
2301 case TRACK_BIT_LEFT: image = rti->base_sprites.track_y + 5; break;
2302 case TRACK_BIT_CROSS: image = rti->base_sprites.track_y + 6; break;
2303
2304 /* double diagonal track, select combined track + ground sprite*/
2305 case TRACK_BIT_HORZ: image = rti->base_sprites.track_ns; break;
2306 case TRACK_BIT_VERT: image = rti->base_sprites.track_ns + 1; break;
2307
2308 /* junction, select only ground sprite, handle track sprite later */
2309 default:
2310 junction = true;
2311 image = rti->base_sprites.ground + GetJunctionGroundSpriteOffset(track);
2312 break;
2313 }
2314 }
2315
2316 switch (rgt) {
2317 case RailGroundType::Barren: pal = PALETTE_TO_BARE_LAND; break;
2318 case RailGroundType::SnowOrDesert: image += rti->snow_offset; break;
2319 case RailGroundType::HalfTileWater: {
2320 /* three-corner-raised slope */
2321 DrawShoreTile(ti->tileh);
2322 Corner track_corner = OppositeCorner(GetHighestSlopeCorner(ComplementSlope(ti->tileh)));
2323 sub = &(_halftile_sub_sprite[track_corner]);
2324 break;
2325 }
2326 default: break;
2327 }
2328 }
2329
2330 if (image != 0) DrawGroundSprite(image, pal, sub);
2331
2332 /* Draw track pieces individually for junction tiles */
2333 if (junction) {
2334 if (track & TRACK_BIT_X) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
2335 if (track & TRACK_BIT_Y) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE);
2336 if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
2337 if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
2338 if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
2339 if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
2340 }
2341
2342 /* PBS debugging, draw reserved tracks darker */
2343 if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation) {
2344 /* Get reservation, but mask track on halftile slope */
2345 TrackBits pbs = GetRailReservationTrackBits(ti->tile) & track;
2346 if (pbs & TRACK_BIT_X) {
2347 if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) {
2348 DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH);
2349 } else {
2350 DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH);
2351 }
2352 }
2353 if (pbs & TRACK_BIT_Y) {
2354 if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) {
2355 DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH);
2356 } else {
2357 DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH);
2358 }
2359 }
2360 if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_N ? -(int)TILE_HEIGHT : 0);
2361 if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_S ? -(int)TILE_HEIGHT : 0);
2362 if (pbs & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_W ? -(int)TILE_HEIGHT : 0);
2363 if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_E ? -(int)TILE_HEIGHT : 0);
2364 }
2365
2366 if (IsValidCorner(halftile_corner)) {
2367 DrawFoundation(ti, HalftileFoundation(halftile_corner));
2368
2369 /* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */
2370 Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner));
2371 image = _track_sloped_sprites[fake_slope - 1] + rti->base_sprites.track_y;
2372 pal = PAL_NONE;
2373 switch (rgt) {
2374 case RailGroundType::Barren: pal = PALETTE_TO_BARE_LAND; break;
2375 case RailGroundType::SnowOrDesert:
2376 case RailGroundType::HalfTileSnow: image += rti->snow_offset; break; // higher part has snow in this case too
2377 default: break;
2378 }
2379 DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner]));
2380
2381 if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasReservedTracks(ti->tile, CornerToTrackBits(halftile_corner))) {
2382 static const uint8_t _corner_to_track_sprite[] = {3, 1, 2, 0};
2383 DrawGroundSprite(_corner_to_track_sprite[halftile_corner] + rti->base_sprites.single_n, PALETTE_CRASH, nullptr, 0, -(int)TILE_HEIGHT);
2384 }
2385 }
2386}
2387
2388static void DrawSignals(TileIndex tile, TrackBits rails, const RailTypeInfo *rti)
2389{
2390 auto MAYBE_DRAW_SIGNAL = [&](uint8_t signalbit, SignalOffsets image, uint pos, Track track) {
2391 if (IsSignalPresent(tile, signalbit)) DrawSingleSignal(tile, rti, track, GetSingleSignalState(tile, signalbit), image, pos);
2392 };
2393
2394 if (!(rails & TRACK_BIT_Y)) {
2395 if (!(rails & TRACK_BIT_X)) {
2396 if (rails & TRACK_BIT_LEFT) {
2397 MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, TRACK_LEFT);
2398 MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, TRACK_LEFT);
2399 }
2400 if (rails & TRACK_BIT_RIGHT) {
2401 MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, TRACK_RIGHT);
2402 MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, TRACK_RIGHT);
2403 }
2404 if (rails & TRACK_BIT_UPPER) {
2405 MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, TRACK_UPPER);
2406 MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, TRACK_UPPER);
2407 }
2408 if (rails & TRACK_BIT_LOWER) {
2409 MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, TRACK_LOWER);
2410 MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, TRACK_LOWER);
2411 }
2412 } else {
2413 MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, TRACK_X);
2414 MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, TRACK_X);
2415 }
2416 } else {
2417 MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, TRACK_Y);
2418 MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, TRACK_Y);
2419 }
2420}
2421
2422static void DrawTile_Track(TileInfo *ti)
2423{
2424 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
2425 BridgePillarFlags blocked_pillars{};
2426 PaletteID pal = GetCompanyPalette(GetTileOwner(ti->tile));
2427
2428 if (IsPlainRail(ti->tile)) {
2429 TrackBits rails = GetTrackBits(ti->tile);
2430
2431 DrawTrackBits(ti, rails);
2432
2433 if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti, rti, pal);
2434
2435 if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
2436
2437 if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails, rti);
2438
2439 if (IsBridgeAbove(ti->tile)) {
2440 if ((rails & TRACK_BIT_3WAY_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
2441 if ((rails & TRACK_BIT_3WAY_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
2442 if ((rails & TRACK_BIT_3WAY_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
2443 if ((rails & TRACK_BIT_3WAY_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
2444 }
2445 } else {
2446 /* draw depot */
2447 const DrawTileSprites *dts;
2448 DiagDirection dir = GetRailDepotDirection(ti->tile);
2449
2450 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
2451
2452 if (IsInvisibilitySet(TO_BUILDINGS)) {
2453 /* Draw rail instead of depot */
2454 dts = &_depot_invisible_gfx_table[dir];
2455 } else {
2456 dts = &_depot_gfx_table[dir];
2457 }
2458
2459 SpriteID image;
2460 if (rti->UsesOverlay()) {
2461 image = SPR_FLAT_GRASS_TILE;
2462 } else {
2463 image = dts->ground.sprite;
2464 if (image != SPR_FLAT_GRASS_TILE) image += rti->GetRailtypeSpriteOffset();
2465 }
2466
2467 /* Adjust ground tile for desert and snow. */
2468 if (IsSnowRailGround(ti->tile)) {
2469 if (image != SPR_FLAT_GRASS_TILE) {
2470 image += rti->snow_offset; // tile with tracks
2471 } else {
2472 image = SPR_FLAT_SNOW_DESERT_TILE; // flat ground
2473 }
2474 }
2475
2476 DrawGroundSprite(image, GroundSpritePaletteTransform(image, PAL_NONE, pal));
2477
2478 if (rti->UsesOverlay()) {
2479 SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND);
2480
2481 switch (GetRailDepotDirection(ti->tile)) {
2482 case DIAGDIR_NE:
2483 if (!IsInvisibilitySet(TO_BUILDINGS)) break;
2484 [[fallthrough]];
2485 case DIAGDIR_SW:
2486 DrawGroundSprite(ground + RTO_X, PAL_NONE);
2487 break;
2488 case DIAGDIR_NW:
2489 if (!IsInvisibilitySet(TO_BUILDINGS)) break;
2490 [[fallthrough]];
2491 case DIAGDIR_SE:
2492 DrawGroundSprite(ground + RTO_Y, PAL_NONE);
2493 break;
2494 default:
2495 break;
2496 }
2497
2498 if (_settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) {
2499 SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
2500
2501 switch (GetRailDepotDirection(ti->tile)) {
2502 case DIAGDIR_NE:
2503 if (!IsInvisibilitySet(TO_BUILDINGS)) break;
2504 [[fallthrough]];
2505 case DIAGDIR_SW:
2506 DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
2507 break;
2508 case DIAGDIR_NW:
2509 if (!IsInvisibilitySet(TO_BUILDINGS)) break;
2510 [[fallthrough]];
2511 case DIAGDIR_SE:
2512 DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
2513 break;
2514 default:
2515 break;
2516 }
2517 }
2518 } else {
2519 /* PBS debugging, draw reserved tracks darker */
2520 if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) {
2521 switch (GetRailDepotDirection(ti->tile)) {
2522 case DIAGDIR_NE:
2523 if (!IsInvisibilitySet(TO_BUILDINGS)) break;
2524 [[fallthrough]];
2525 case DIAGDIR_SW:
2526 DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH);
2527 break;
2528 case DIAGDIR_NW:
2529 if (!IsInvisibilitySet(TO_BUILDINGS)) break;
2530 [[fallthrough]];
2531 case DIAGDIR_SE:
2532 DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH);
2533 break;
2534 default:
2535 break;
2536 }
2537 }
2538 }
2539 int depot_sprite = GetCustomRailSprite(rti, ti->tile, RTSG_DEPOT);
2540 int relocation = depot_sprite != 0 ? depot_sprite - SPR_RAIL_DEPOT_SE_1 : rti->GetRailtypeSpriteOffset();
2541
2542 if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
2543
2544 DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, pal);
2545 /* Depots can't have bridges above so no blocked pillars. */
2546 }
2547 DrawBridgeMiddle(ti, blocked_pillars);
2548}
2549
2550void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype)
2551{
2552 const DrawTileSprites *dts = &_depot_gfx_table[dir];
2553 const RailTypeInfo *rti = GetRailTypeInfo(railtype);
2554 SpriteID image = rti->UsesOverlay() ? SPR_FLAT_GRASS_TILE : dts->ground.sprite;
2555 uint32_t offset = rti->GetRailtypeSpriteOffset();
2556
2557 if (image != SPR_FLAT_GRASS_TILE) image += offset;
2558 PaletteID palette = GetCompanyPalette(_local_company);
2559
2560 DrawSprite(image, PAL_NONE, x, y);
2561
2562 if (rti->UsesOverlay()) {
2563 SpriteID ground = GetCustomRailSprite(rti, INVALID_TILE, RTSG_GROUND);
2564
2565 switch (dir) {
2566 case DIAGDIR_SW: DrawSprite(ground + RTO_X, PAL_NONE, x, y); break;
2567 case DIAGDIR_SE: DrawSprite(ground + RTO_Y, PAL_NONE, x, y); break;
2568 default: break;
2569 }
2570 }
2571 int depot_sprite = GetCustomRailSprite(rti, INVALID_TILE, RTSG_DEPOT);
2572 if (depot_sprite != 0) offset = depot_sprite - SPR_RAIL_DEPOT_SE_1;
2573
2574 DrawRailTileSeqInGUI(x, y, dts, offset, 0, palette);
2575}
2576
2577static int GetSlopePixelZ_Track(TileIndex tile, uint x, uint y, bool)
2578{
2579 if (IsPlainRail(tile)) {
2580 auto [tileh, z] = GetTilePixelSlope(tile);
2581 if (tileh == SLOPE_FLAT) return z;
2582
2583 z += ApplyPixelFoundationToSlope(GetRailFoundation(tileh, GetTrackBits(tile)), tileh);
2584 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
2585 } else {
2586 return GetTileMaxPixelZ(tile);
2587 }
2588}
2589
2590static Foundation GetFoundation_Track(TileIndex tile, Slope tileh)
2591{
2592 return IsPlainRail(tile) ? GetRailFoundation(tileh, GetTrackBits(tile)) : FlatteningFoundation(tileh);
2593}
2594
2595static void TileLoop_Track(TileIndex tile)
2596{
2597 RailGroundType old_ground = GetRailGroundType(tile);
2598 RailGroundType new_ground;
2599
2600 if (old_ground == RailGroundType::HalfTileWater) {
2601 TileLoop_Water(tile);
2602 return;
2603 }
2604
2605 switch (_settings_game.game_creation.landscape) {
2606 case LandscapeType::Arctic: {
2607 auto [slope, z] = GetTileSlopeZ(tile);
2608 bool half = false;
2609
2610 /* for non-flat track, use lower part of track
2611 * in other cases, use the highest part with track */
2612 if (IsPlainRail(tile)) {
2613 TrackBits track = GetTrackBits(tile);
2614 Foundation f = GetRailFoundation(slope, track);
2615
2616 switch (f) {
2617 case FOUNDATION_NONE:
2618 /* no foundation - is the track on the upper side of three corners raised tile? */
2619 if (IsSlopeWithThreeCornersRaised(slope)) z++;
2620 break;
2621
2622 case FOUNDATION_INCLINED_X:
2623 case FOUNDATION_INCLINED_Y:
2624 /* sloped track - is it on a steep slope? */
2625 if (IsSteepSlope(slope)) z++;
2626 break;
2627
2628 case FOUNDATION_STEEP_LOWER:
2629 /* only lower part of steep slope */
2630 z++;
2631 break;
2632
2633 default:
2634 /* if it is a steep slope, then there is a track on higher part */
2635 if (IsSteepSlope(slope)) z++;
2636 z++;
2637 break;
2638 }
2639
2640 half = IsInsideMM(f, FOUNDATION_STEEP_BOTH, FOUNDATION_HALFTILE_N + 1);
2641 } else {
2642 /* is the depot on a non-flat tile? */
2643 if (slope != SLOPE_FLAT) z++;
2644 }
2645
2646 /* 'z' is now the lowest part of the highest track bit -
2647 * for sloped track, it is 'z' of lower part
2648 * for two track bits, it is 'z' of higher track bit
2649 * For non-continuous foundations (and STEEP_BOTH), 'half' is set */
2650 if (z > GetSnowLine()) {
2651 if (half && z - GetSnowLine() == 1) {
2652 /* track on non-continuous foundation, lower part is not under snow */
2653 new_ground = RailGroundType::HalfTileSnow;
2654 } else {
2655 new_ground = RailGroundType::SnowOrDesert;
2656 }
2657 goto set_ground;
2658 }
2659 break;
2660 }
2661
2662 case LandscapeType::Tropic:
2663 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
2664 new_ground = RailGroundType::SnowOrDesert;
2665 goto set_ground;
2666 }
2667 break;
2668
2669 default:
2670 break;
2671 }
2672
2673 new_ground = RailGroundType::Grass;
2674
2675 if (IsPlainRail(tile) && old_ground != RailGroundType::Barren) { // wait until bottom is green
2676 /* determine direction of fence */
2677 TrackBits rail = GetTrackBits(tile);
2678
2679 Owner owner = GetTileOwner(tile);
2680 DiagDirections fences{};
2681
2682 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
2683 static const TrackBits dir_to_trackbits[DIAGDIR_END] = {TRACK_BIT_3WAY_NE, TRACK_BIT_3WAY_SE, TRACK_BIT_3WAY_SW, TRACK_BIT_3WAY_NW};
2684
2685 /* Track bit on this edge => no fence. */
2686 if ((rail & dir_to_trackbits[d]) != TRACK_BIT_NONE) continue;
2687
2688 TileIndex tile2 = tile + TileOffsByDiagDir(d);
2689
2690 /* Show fences if it's a house, industry, object, road, tunnelbridge or not owned by us. */
2691 if (!IsValidTile(tile2) || IsTileType(tile2, MP_HOUSE) || IsTileType(tile2, MP_INDUSTRY) ||
2692 IsTileType(tile2, MP_ROAD) || (IsTileType(tile2, MP_OBJECT) && !IsObjectType(tile2, OBJECT_OWNED_LAND)) || IsTileType(tile2, MP_TUNNELBRIDGE) || !IsTileOwner(tile2, owner)) {
2693 fences.Set(d);
2694 }
2695 }
2696
2697 switch (fences.base()) {
2698 case DiagDirections{}.base(): break;
2699 case DiagDirections{DIAGDIR_NE}.base(): new_ground = RailGroundType::FenceNE; break;
2700 case DiagDirections{DIAGDIR_SE}.base(): new_ground = RailGroundType::FenceSE; break;
2701 case DiagDirections{DIAGDIR_SW}.base(): new_ground = RailGroundType::FenceSW; break;
2702 case DiagDirections{DIAGDIR_NW}.base(): new_ground = RailGroundType::FenceNW; break;
2703 case DiagDirections{DIAGDIR_NE, DIAGDIR_SW}.base(): new_ground = RailGroundType::FenceNESW; break;
2704 case DiagDirections{DIAGDIR_SE, DIAGDIR_NW}.base(): new_ground = RailGroundType::FenceSENW; break;
2705 case DiagDirections{DIAGDIR_NE, DIAGDIR_SE}.base(): new_ground = RailGroundType::FenceVert1; break;
2706 case DiagDirections{DIAGDIR_NE, DIAGDIR_NW}.base(): new_ground = RailGroundType::FenceHoriz2; break;
2707 case DiagDirections{DIAGDIR_SE, DIAGDIR_SW}.base(): new_ground = RailGroundType::FenceHoriz1; break;
2708 case DiagDirections{DIAGDIR_SW, DIAGDIR_NW}.base(): new_ground = RailGroundType::FenceVert2; break;
2709 default: NOT_REACHED();
2710 }
2711 }
2712
2713set_ground:
2714 if (old_ground != new_ground) {
2715 SetRailGroundType(tile, new_ground);
2716 MarkTileDirtyByTile(tile);
2717 }
2718}
2719
2720
2721static TrackStatus GetTileTrackStatus_Track(TileIndex tile, TransportType mode, uint, DiagDirection side)
2722{
2723 /* Case of half tile slope with water. */
2724 if (mode == TRANSPORT_WATER && IsPlainRail(tile) && GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(GetTileSlope(tile))) {
2725 TrackBits tb = GetTrackBits(tile);
2726 switch (tb) {
2727 default: NOT_REACHED();
2728 case TRACK_BIT_UPPER: tb = TRACK_BIT_LOWER; break;
2729 case TRACK_BIT_LOWER: tb = TRACK_BIT_UPPER; break;
2730 case TRACK_BIT_LEFT: tb = TRACK_BIT_RIGHT; break;
2731 case TRACK_BIT_RIGHT: tb = TRACK_BIT_LEFT; break;
2732 }
2733 return CombineTrackStatus(TrackBitsToTrackdirBits(tb), TRACKDIR_BIT_NONE);
2734 }
2735
2736 if (mode != TRANSPORT_RAIL) return 0;
2737
2738 TrackBits trackbits = TRACK_BIT_NONE;
2739 TrackdirBits red_signals = TRACKDIR_BIT_NONE;
2740
2741 switch (GetRailTileType(tile)) {
2742 default: NOT_REACHED();
2743 case RailTileType::Normal:
2744 trackbits = GetTrackBits(tile);
2745 break;
2746
2747 case RailTileType::Signals: {
2748 trackbits = GetTrackBits(tile);
2749 uint8_t a = GetPresentSignals(tile);
2750 uint b = GetSignalStates(tile);
2751
2752 b &= a;
2753
2754 /* When signals are not present (in neither direction),
2755 * we pretend them to be green. Otherwise, it depends on
2756 * the signal type. For signals that are only active from
2757 * one side, we set the missing signals explicitly to
2758 * `green'. Otherwise, they implicitly become `red'. */
2759 if (!IsOnewaySignal(tile, TRACK_UPPER) || (a & SignalOnTrack(TRACK_UPPER)) == 0) b |= ~a & SignalOnTrack(TRACK_UPPER);
2760 if (!IsOnewaySignal(tile, TRACK_LOWER) || (a & SignalOnTrack(TRACK_LOWER)) == 0) b |= ~a & SignalOnTrack(TRACK_LOWER);
2761
2762 if ((b & 0x8) == 0) red_signals |= (TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E);
2763 if ((b & 0x4) == 0) red_signals |= (TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_UPPER_W);
2764 if ((b & 0x2) == 0) red_signals |= (TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_E);
2765 if ((b & 0x1) == 0) red_signals |= (TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_W);
2766
2767 break;
2768 }
2769
2770 case RailTileType::Depot: {
2771 DiagDirection dir = GetRailDepotDirection(tile);
2772
2773 if (side != INVALID_DIAGDIR && side != dir) break;
2774
2775 trackbits = DiagDirToDiagTrackBits(dir);
2776 break;
2777 }
2778 }
2779
2780 return CombineTrackStatus(TrackBitsToTrackdirBits(trackbits), red_signals);
2781}
2782
2783static bool ClickTile_Track(TileIndex tile)
2784{
2785 if (!IsRailDepot(tile)) return false;
2786
2787 ShowDepotWindow(tile, VEH_TRAIN);
2788 return true;
2789}
2790
2791static void GetTileDesc_Track(TileIndex tile, TileDesc &td)
2792{
2793 const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
2794 td.rail_speed = rti->max_speed;
2795 td.railtype = rti->strings.name;
2796 td.owner[0] = GetTileOwner(tile);
2797 switch (GetRailTileType(tile)) {
2798 case RailTileType::Normal:
2799 td.str = STR_LAI_RAIL_DESCRIPTION_TRACK;
2800 break;
2801
2802 case RailTileType::Signals: {
2803 static const StringID signal_type[6][6] = {
2804 {
2805 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS,
2806 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS,
2807 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS,
2808 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS,
2809 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS,
2810 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS
2811 },
2812 {
2813 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS,
2814 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS,
2815 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS,
2816 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS,
2817 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS,
2818 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS
2819 },
2820 {
2821 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS,
2822 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS,
2823 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS,
2824 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS,
2825 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS,
2826 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS
2827 },
2828 {
2829 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS,
2830 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS,
2831 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS,
2832 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS,
2833 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS,
2834 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS
2835 },
2836 {
2837 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS,
2838 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS,
2839 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS,
2840 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS,
2841 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS,
2842 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS
2843 },
2844 {
2845 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS,
2846 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS,
2847 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS,
2848 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS,
2849 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS,
2850 STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS
2851 }
2852 };
2853
2854 SignalType primary_signal;
2855 SignalType secondary_signal;
2856 if (HasSignalOnTrack(tile, TRACK_UPPER)) {
2857 primary_signal = GetSignalType(tile, TRACK_UPPER);
2858 secondary_signal = HasSignalOnTrack(tile, TRACK_LOWER) ? GetSignalType(tile, TRACK_LOWER) : primary_signal;
2859 } else {
2860 secondary_signal = primary_signal = GetSignalType(tile, TRACK_LOWER);
2861 }
2862
2863 td.str = signal_type[secondary_signal][primary_signal];
2864 break;
2865 }
2866
2867 case RailTileType::Depot:
2868 td.str = STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT;
2869 if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) {
2870 if (td.rail_speed > 0) {
2871 td.rail_speed = std::min<uint16_t>(td.rail_speed, 61);
2872 } else {
2873 td.rail_speed = 61;
2874 }
2875 }
2876 td.build_date = Depot::GetByTile(tile)->build_date;
2877 break;
2878
2879 default:
2880 NOT_REACHED();
2881 }
2882}
2883
2884static void ChangeTileOwner_Track(TileIndex tile, Owner old_owner, Owner new_owner)
2885{
2886 if (!IsTileOwner(tile, old_owner)) return;
2887
2888 if (new_owner != INVALID_OWNER) {
2889 /* Update company infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
2890 uint num_pieces = 1;
2891 if (IsPlainRail(tile)) {
2892 TrackBits bits = GetTrackBits(tile);
2893 num_pieces = CountBits(bits);
2894 if (TracksOverlap(bits)) num_pieces *= num_pieces;
2895 }
2896 RailType rt = GetRailType(tile);
2897 Company::Get(old_owner)->infrastructure.rail[rt] -= num_pieces;
2898 Company::Get(new_owner)->infrastructure.rail[rt] += num_pieces;
2899
2900 if (HasSignals(tile)) {
2901 uint num_sigs = CountBits(GetPresentSignals(tile));
2902 Company::Get(old_owner)->infrastructure.signal -= num_sigs;
2903 Company::Get(new_owner)->infrastructure.signal += num_sigs;
2904 }
2905
2906 SetTileOwner(tile, new_owner);
2907 } else {
2908 Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile);
2909 }
2910}
2911
2912static const uint8_t _fractcoords_behind[4] = { 0x8F, 0x8, 0x80, 0xF8 };
2913static const uint8_t _fractcoords_enter[4] = { 0x8A, 0x48, 0x84, 0xA8 };
2914static const int8_t _deltacoord_leaveoffset[8] = {
2915 -1, 0, 1, 0, /* x */
2916 0, 1, 0, -1 /* y */
2917};
2918
2919
2926 int TicksToLeaveDepot(const Train *v)
2927{
2928 DiagDirection dir = GetRailDepotDirection(v->tile);
2929 int length = v->CalcNextVehicleOffset();
2930
2931 switch (dir) {
2932 case DIAGDIR_NE: return ((int)(v->x_pos & 0x0F) - ((_fractcoords_enter[dir] & 0x0F) - (length + 1)));
2933 case DIAGDIR_SE: return -((int)(v->y_pos & 0x0F) - ((_fractcoords_enter[dir] >> 4) + (length + 1)));
2934 case DIAGDIR_SW: return -((int)(v->x_pos & 0x0F) - ((_fractcoords_enter[dir] & 0x0F) + (length + 1)));
2935 case DIAGDIR_NW: return ((int)(v->y_pos & 0x0F) - ((_fractcoords_enter[dir] >> 4) - (length + 1)));
2936 default: NOT_REACHED();
2937 }
2938}
2939
2944 static VehicleEnterTileStates VehicleEnter_Track(Vehicle *u, TileIndex tile, int x, int y)
2945{
2946 /* This routine applies only to trains in depot tiles. */
2947 if (u->type != VEH_TRAIN || !IsRailDepotTile(tile)) return {};
2948
2949 /* Depot direction. */
2950 DiagDirection dir = GetRailDepotDirection(tile);
2951
2952 uint8_t fract_coord = (x & 0xF) + ((y & 0xF) << 4);
2953
2954 /* Make sure a train is not entering the tile from behind. */
2955 if (_fractcoords_behind[dir] == fract_coord) return VehicleEnterTileState::CannotEnter;
2956
2957 Train *v = Train::From(u);
2958
2959 /* Leaving depot? */
2960 if (v->direction == DiagDirToDir(dir)) {
2961 /* Calculate the point where the following wagon should be activated. */
2962 int length = v->CalcNextVehicleOffset();
2963
2964 uint8_t fract_coord_leave =
2965 ((_fractcoords_enter[dir] & 0x0F) + // x
2966 (length + 1) * _deltacoord_leaveoffset[dir]) +
2967 (((_fractcoords_enter[dir] >> 4) + // y
2968 ((length + 1) * _deltacoord_leaveoffset[dir + 4])) << 4);
2969
2970 if (fract_coord_leave == fract_coord) {
2971 /* Leave the depot. */
2972 if ((v = v->Next()) != nullptr) {
2973 v->vehstatus.Reset(VehState::Hidden);
2974 v->track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
2975 }
2976 }
2977 } else if (_fractcoords_enter[dir] == fract_coord) {
2978 /* Entering depot. */
2979 assert(DiagDirToDir(ReverseDiagDir(dir)) == v->direction);
2980 v->track = TRACK_BIT_DEPOT,
2981 v->vehstatus.Set(VehState::Hidden);
2982 v->direction = ReverseDir(v->direction);
2983 if (v->Next() == nullptr) VehicleEnterDepot(v->First());
2984 v->tile = tile;
2985
2986 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
2987 return VehicleEnterTileState::EnteredWormhole;
2988 }
2989
2990 return {};
2991}
2992
3004 static CommandCost TestAutoslopeOnRailTile(TileIndex tile, DoCommandFlags flags, int z_old, Slope tileh_old, int z_new, Slope tileh_new, TrackBits rail_bits)
3005{
3006 if (!_settings_game.construction.build_on_slopes || !AutoslopeEnabled()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
3007
3008 /* Is the slope-rail_bits combination valid in general? I.e. is it safe to call GetRailFoundation() ? */
3009 if (CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile).Failed()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
3010
3011 /* Get the slopes on top of the foundations */
3012 z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), tileh_old);
3013 z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), tileh_new);
3014
3015 Corner track_corner;
3016 switch (rail_bits) {
3017 case TRACK_BIT_LEFT: track_corner = CORNER_W; break;
3018 case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
3019 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
3020 case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
3021
3022 /* Surface slope must not be changed */
3023 default:
3024 if (z_old != z_new || tileh_old != tileh_new) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
3025 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3026 }
3027
3028 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
3029 z_old += GetSlopeZInCorner(RemoveHalftileSlope(tileh_old), track_corner);
3030 z_new += GetSlopeZInCorner(RemoveHalftileSlope(tileh_new), track_corner);
3031 if (z_old != z_new) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
3032
3033 CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3034 /* Make the ground dirty, if surface slope has changed */
3035 if (tileh_old != tileh_new) {
3036 /* If there is flat water on the lower halftile add the cost for clearing it */
3037 if (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh_old)) cost.AddCost(_price[PR_CLEAR_WATER]);
3038 if (flags.Test(DoCommandFlag::Execute)) SetRailGroundType(tile, RailGroundType::Barren);
3039 }
3040 return cost;
3041}
3042
3043static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
3044{
3045 auto [tileh_old, z_old] = GetTileSlopeZ(tile);
3046 if (IsPlainRail(tile)) {
3047 TrackBits rail_bits = GetTrackBits(tile);
3048 /* Is there flat water on the lower halftile that must be cleared expensively? */
3049 bool was_water = (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh_old));
3050
3051 /* Allow clearing the water only if there is no ship */
3052 if (was_water && HasVehicleOnTile(tile, [](const Vehicle *v) {
3053 return v->type == VEH_SHIP;
3054 })) return CommandCost(STR_ERROR_SHIP_IN_THE_WAY);
3055
3056 /* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
3057 CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
3058
3059 /* When there is only a single horizontal/vertical track, one corner can be terraformed. */
3060 Corner allowed_corner;
3061 switch (rail_bits) {
3062 case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break;
3063 case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break;
3064 case TRACK_BIT_LEFT: allowed_corner = CORNER_E; break;
3065 case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break;
3066 default: return autoslope_result;
3067 }
3068
3069 Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
3070
3071 /* Do not allow terraforming if allowed_corner is part of anti-zig-zag foundations */
3072 if (tileh_old != SLOPE_NS && tileh_old != SLOPE_EW && IsSpecialRailFoundation(f_old)) return autoslope_result;
3073
3074 /* Everything is valid, which only changes allowed_corner */
3075 for (Corner corner = (Corner)0; corner < CORNER_END; corner = (Corner)(corner + 1)) {
3076 if (allowed_corner == corner) continue;
3077 if (z_old + GetSlopeZInCorner(tileh_old, corner) != z_new + GetSlopeZInCorner(tileh_new, corner)) return autoslope_result;
3078 }
3079
3080 /* Make the ground dirty */
3081 if (flags.Test(DoCommandFlag::Execute)) SetRailGroundType(tile, RailGroundType::Barren);
3082
3083 /* allow terraforming */
3084 return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price[PR_CLEAR_WATER] : (Money)0);
3085 } else if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() &&
3086 AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) {
3087 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3088 }
3089 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
3090}
3091
3092static CommandCost CheckBuildAbove_Track(TileIndex tile, DoCommandFlags flags, Axis, int)
3093{
3094 if (IsPlainRail(tile)) return CommandCost();
3095 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
3096}
3097
3098extern const TileTypeProcs _tile_type_rail_procs = {
3099 DrawTile_Track, // draw_tile_proc
3100 GetSlopePixelZ_Track, // get_slope_z_proc
3101 ClearTile_Track, // clear_tile_proc
3102 nullptr, // add_accepted_cargo_proc
3103 GetTileDesc_Track, // get_tile_desc_proc
3104 GetTileTrackStatus_Track, // get_tile_track_status_proc
3105 ClickTile_Track, // click_tile_proc
3106 nullptr, // animate_tile_proc
3107 TileLoop_Track, // tile_loop_proc
3108 ChangeTileOwner_Track, // change_tile_owner_proc
3109 nullptr, // add_produced_cargo_proc
3110 VehicleEnter_Track, // vehicle_enter_tile_proc
3111 GetFoundation_Track, // get_foundation_proc
3112 TerraformTile_Track, // terraform_tile_proc
3113 CheckBuildAbove_Track, // check_build_above_proc
3114};
autoslope.h
Functions related to autoslope.
AutoslopeCheckForEntranceEdge
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
AutoslopeEnabled
bool AutoslopeEnabled()
Tests if autoslope is enabled for _current_company.
Definition autoslope.h:65
backup_type.hpp
Class for backupping variables and making sure they are restored later.
HasExactlyOneBit
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
Definition bitmath_func.hpp:254
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition bitmath_func.hpp:121
CountBits
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
Definition bitmath_func.hpp:238
HasBit
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
ToggleBit
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
Definition bitmath_func.hpp:157
KillFirstBit
constexpr T KillFirstBit(T value)
Clear the first bit in an integer.
Definition bitmath_func.hpp:226
DrawBridgeMiddle
void DrawBridgeMiddle(const TileInfo *ti, BridgePillarFlags blocked_pillars)
Draw the middle bits of a bridge.
Definition tunnelbridge_cmd.cpp:1614
IsBridgeAbove
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
IsBridge
bool IsBridge(Tile t)
Checks if this is a bridge, instead of a tunnel.
Definition bridge_map.h:24
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
BaseBitSet::base
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
Definition base_bitset_type.hpp:219
BaseBitSet::Reset
constexpr Timpl & Reset()
Reset all bits.
Definition base_bitset_type.hpp:83
BaseBitSet::Set
constexpr Timpl & Set()
Set all bits.
Definition base_bitset_type.hpp:40
CommandCost
Common return value for all commands.
Definition command_type.h:24
CommandCost::Succeeded
bool Succeeded() const
Did this command succeed?
Definition command_type.h:168
CommandCost::AddCost
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition command_type.h:98
CommandCost::MakeError
void MakeError(StringID message)
Makes this CommandCost behave like an error command.
Definition command_type.h:136
CommandCost::GetCost
Money GetCost() const
The costs as made up to this moment.
Definition command_type.h:118
CommandCost::Failed
bool Failed() const
Did this command fail?
Definition command_type.h:177
CommandCost::GetErrorMessage
StringID GetErrorMessage() const
Returns the error message of a command.
Definition command_type.h:148
EnumBitSet< RailType, uint64_t >
OverflowSafeInt< int64_t >
RailTypeInfo
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:115
RailTypeInfo::Index
RailType Index() const
Get the RailType for this RailTypeInfo.
Definition rail.cpp:26
RailTypeInfo::single_x
SpriteID single_x
single piece of rail in X direction, without ground
Definition rail.h:125
RailTypeInfo::max_speed
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:220
RailTypeInfo::build_tunnel
SpriteID build_tunnel
button for building a tunnel
Definition rail.h:148
RailTypeInfo::rail_swne
CursorID rail_swne
Cursor for building rail in X direction.
Definition rail.h:155
RailTypeInfo::convert_rail
SpriteID convert_rail
button for converting rail
Definition rail.h:149
RailTypeInfo::convert
CursorID convert
Cursor for converting track.
Definition rail.h:161
RailTypeInfo::depot
CursorID depot
Cursor for building a depot.
Definition rail.h:159
RailTypeInfo::powered_railtypes
RailTypes powered_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype generates power
Definition rail.h:177
RailTypeInfo::introduces_railtypes
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced.
Definition rail.h:255
RailTypeInfo::ground
SpriteID ground
ground sprite for a 3-way switch
Definition rail.h:124
RailTypeInfo::rail_nwse
CursorID rail_nwse
Cursor for building rail in Y direction.
Definition rail.h:157
RailTypeInfo::build_x_rail
SpriteID build_x_rail
button for building single rail in X direction
Definition rail.h:143
RailTypeInfo::sorting_order
uint8_t sorting_order
The sorting order of this railtype for the toolbar dropdown.
Definition rail.h:260
RailTypeInfo::label
RailTypeLabel label
Unique 32 bit rail type identifier.
Definition rail.h:225
RailTypeInfo::single_n
SpriteID single_n
single piece of rail in the northern corner
Definition rail.h:127
RailTypeInfo::rail_ew
CursorID rail_ew
Cursor for building rail in E-W direction.
Definition rail.h:156
RailTypeInfo::auto_rail
SpriteID auto_rail
button for the autorail construction
Definition rail.h:146
RailTypeInfo::autorail
CursorID autorail
Cursor for autorail tool.
Definition rail.h:158
RailTypeInfo::single_y
SpriteID single_y
single piece of rail in Y direction, without ground
Definition rail.h:126
RailTypeInfo::name
StringID name
Name of this rail type.
Definition rail.h:165
RailTypeInfo::compatible_railtypes
RailTypes compatible_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel
Definition rail.h:180
RailTypeInfo::GetRailtypeSpriteOffset
uint GetRailtypeSpriteOffset() const
Offset between the current railtype and normal rail.
Definition rail.h:286
RailTypeInfo::single_s
SpriteID single_s
single piece of rail in the southern corner
Definition rail.h:128
RailTypeInfo::flags
RailTypeFlags flags
Bit mask of rail type flags.
Definition rail.h:200
RailTypeInfo::signals
SpriteID signals[SIGTYPE_END][2][2]
signal GUI sprites (type, variant, state)
Definition rail.h:150
RailTypeInfo::build_ew_rail
SpriteID build_ew_rail
button for building single rail in E-W direction
Definition rail.h:144
RailTypeInfo::build_y_rail
SpriteID build_y_rail
button for building single rail in Y direction
Definition rail.h:145
RailTypeInfo::alternate_labels
FlatSet< RailTypeLabel > alternate_labels
Rail type labels this type provides in addition to the main label.
Definition rail.h:230
RailTypeInfo::strings
struct RailTypeInfo::@22 strings
Strings associated with the rail type.
RailTypeInfo::base_sprites
struct RailTypeInfo::@19 base_sprites
Struct containing the main sprites.
RailTypeInfo::track_ns
SpriteID track_ns
two pieces of rail in North and South corner (East-West direction)
Definition rail.h:123
RailTypeInfo::cursor
struct RailTypeInfo::@21 cursor
Cursors associated with the rail type.
RailTypeInfo::snow_offset
SpriteID snow_offset
sprite number difference between a piece of track on a snowy ground and the corresponding one on norm...
Definition rail.h:174
RailTypeInfo::track_y
SpriteID track_y
single piece of rail in Y direction, with ground
Definition rail.h:122
RailTypeInfo::gui_sprites
struct RailTypeInfo::@20 gui_sprites
struct containing the sprites for the rail GUI.
RailTypeInfo::build_depot
SpriteID build_depot
button for building depots
Definition rail.h:147
RailTypeInfo::single_w
SpriteID single_w
single piece of rail in the western corner
Definition rail.h:130
RailTypeInfo::single_e
SpriteID single_e
single piece of rail in the eastern corner
Definition rail.h:129
RailTypeInfo::build_ns_rail
SpriteID build_ns_rail
button for building single rail in N-S direction
Definition rail.h:142
RailTypeInfo::rail_ns
CursorID rail_ns
Cursor for building rail in N-S direction.
Definition rail.h:154
RailTypeInfo::tunnel
SpriteID tunnel
tunnel sprites base
Definition rail.h:133
RailTypeInfo::single_sloped
SpriteID single_sloped
single piece of rail for slopes
Definition rail.h:131
TileIterator::Create
static std::unique_ptr< TileIterator > Create(TileIndex corner1, TileIndex corner2, bool diagonal)
Create either an OrthogonalTileIterator or DiagonalTileIterator given the diagonal parameter.
Definition tilearea.cpp:291
VehiclesOnTile
Iterate over all vehicles on a tile.
Definition vehicle_func.h:53
command_func.h
Functions related to commands.
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition command_func.h:28
DoCommandFlag::Auto
@ Auto
don't allow building on structures
DoCommandFlag::Execute
@ Execute
execute the given command
DoCommandFlag::Bankrupt
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
company_base.h
Definition of stuff that is very close to a company, like the company struct itself.
CheckTileOwnership
CommandCost CheckTileOwnership(TileIndex tile)
Check whether the current owner owns the stuff on the given tile.
Definition company_cmd.cpp:404
GetCompanyPalette
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
Definition company_cmd.cpp:164
CheckOwnership
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
Definition company_cmd.cpp:381
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition company_cmd.cpp:55
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
DirtyCompanyInfrastructureWindows
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
Definition company_gui.cpp:2318
company_gui.h
GUI Functions related to companies.
OWNER_DEITY
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
Definition company_type.h:28
INVALID_OWNER
static constexpr Owner INVALID_OWNER
An invalid owner.
Definition company_type.h:30
OWNER_WATER
static constexpr Owner OWNER_WATER
The tile/execution is done by "water".
Definition company_type.h:27
container_func.hpp
Some simple functions to help with accessing containers.
include
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
Definition container_func.hpp:24
depot_base.h
Base for all depots (except hangars)
CanBuildDepotByTileh
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
ShowDepotWindow
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
Definition depot_gui.cpp:1183
DiagDirToDir
Direction DiagDirToDir(DiagDirection dir)
Convert a DiagDirection to a Direction.
Definition direction_func.h:182
ReverseDiagDir
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Definition direction_func.h:118
ReverseDir
Direction ReverseDir(Direction d)
Return the reverse of a direction.
Definition direction_func.h:54
IsValidDiagDirection
bool IsValidDiagDirection(DiagDirection d)
Checks if an integer value is a valid DiagDirection.
Definition direction_func.h:21
DiagDirToAxis
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
Definition direction_func.h:214
Axis
Axis
Allow incrementing of DiagDirDiff variables.
Definition direction_type.h:123
AXIS_X
@ AXIS_X
The X axis.
Definition direction_type.h:124
AXIS_Y
@ AXIS_Y
The y axis.
Definition direction_type.h:125
DiagDirection
DiagDirection
Enumeration for diagonal directions.
Definition direction_type.h:78
DIAGDIR_NE
@ DIAGDIR_NE
Northeast, upper right on your monitor.
Definition direction_type.h:80
DIAGDIR_NW
@ DIAGDIR_NW
Northwest.
Definition direction_type.h:83
DIAGDIR_SE
@ DIAGDIR_SE
Southeast.
Definition direction_type.h:81
DIAGDIR_END
@ DIAGDIR_END
Used for iterations.
Definition direction_type.h:84
DIAGDIR_BEGIN
@ DIAGDIR_BEGIN
Used for iterations.
Definition direction_type.h:79
INVALID_DIAGDIR
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
Definition direction_type.h:85
DIAGDIR_SW
@ DIAGDIR_SW
Southwest.
Definition direction_type.h:82
LEVELCROSSING_TRACKBIT_FACTOR
static const uint LEVELCROSSING_TRACKBIT_FACTOR
Multiplier for how many regular track bits a level crossing counts.
Definition economy_type.h:239
EXPENSES_CONSTRUCTION
@ EXPENSES_CONSTRUCTION
Construction costs.
Definition economy_type.h:179
TUNNELBRIDGE_TRACKBIT_FACTOR
static const uint TUNNELBRIDGE_TRACKBIT_FACTOR
Multiplier for how many regular track bits a tunnel/bridge counts.
Definition economy_type.h:237
DrawRailCatenary
void DrawRailCatenary(const TileInfo *ti)
Draws overhead wires and pylons for electric railways.
Definition elrail.cpp:550
elrail_func.h
header file for electrified rail specific functions
HasRailCatenaryDrawn
bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition elrail_func.h:30
DrawSprite
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:1034
SpriteID
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
PaletteID
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
GetSnowLine
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition landscape.cpp:606
MarkTileDirtyByTile
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition viewport.cpp:2128
GetPartialPixelZ
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Definition landscape.cpp:232
GetTileTrackStatus
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition landscape.cpp:560
DrawFoundation
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition landscape.cpp:429
GetSlopeZInCorner
int GetSlopeZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition landscape.cpp:340
ApplyFoundationToSlope
uint ApplyFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.cpp:174
GetSlopePixelZ
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition landscape.cpp:307
ApplyPixelFoundationToSlope
uint ApplyPixelFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.h:128
GetSlopePixelZInCorner
int GetSlopePixelZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition landscape.h:55
landscape_cmd.h
Command definitions related to landscape (slopes etc.).
AddTileIndexDiffCWrap
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition map_func.h:528
ToTileIndexDiff
TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
Return the offset between two tiles from a TileIndexDiffC struct.
Definition map_func.h:453
TileAddByDiagDir
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:624
TileY
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:438
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:428
TileOffsByDiagDir
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:583
IsInsideMM
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition math_func.hpp:267
abs
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
TCX_UPPER_HALFTILE
@ TCX_UPPER_HALFTILE
Querying information about the upper part of a tile with halftile foundation.
Definition newgrf_commons.h:26
TCX_NORMAL
@ TCX_NORMAL
Nothing special.
Definition newgrf_commons.h:25
newgrf_debug.h
Functions/types related to NewGRF debugging.
DeleteNewGRFInspectWindow
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
Definition newgrf_debug_gui.cpp:726
GetCustomSignalSprite
SpriteID GetCustomSignalSprite(const RailTypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui)
Get the sprite to draw for a given signal.
Definition newgrf_railtype.cpp:131
GetCustomRailSprite
SpriteID GetCustomRailSprite(const RailTypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
Definition newgrf_railtype.cpp:106
newgrf_railtype.h
NewGRF handling of rail types.
object_map.h
Map accessors for object tiles.
IsObjectType
bool IsObjectType(Tile t, ObjectType type)
Check whether the object on a tile is of a specific type.
Definition object_map.h:25
OBJECT_OWNED_LAND
static const ObjectType OBJECT_OWNED_LAND
Owned land 'flag'.
Definition object_type.h:21
DO_FULL_DETAIL
@ DO_FULL_DETAIL
Also draw details of track and roads.
Definition openttd.h:50
GetTrainForReservation
Train * GetTrainForReservation(TileIndex tile, Track track)
Find the train which has reserved a specific path.
Definition pbs.cpp:331
GetReservedTrackbits
TrackBits GetReservedTrackbits(TileIndex t)
Get the reserved trackbits for any tile, regardless of type.
Definition pbs.cpp:24
IsSafeWaitingPosition
bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
Determine whether a certain track on a tile is a safe position to end a path.
Definition pbs.cpp:381
pbs.h
PBS support routines.
HasReservedTracks
bool HasReservedTracks(TileIndex tile, TrackBits tracks)
Check whether some of tracks is reserved on a tile.
Definition pbs.h:58
ValParamRailType
bool ValParamRailType(const RailType rail)
Validate functions for rail building.
Definition rail.cpp:90
RailConvertCost
Money RailConvertCost(RailType from, RailType to)
Calculates the cost of rail conversion.
Definition rail.h:456
RailClearCost
Money RailClearCost(RailType railtype)
Returns the 'cost' of clearing the specified railtype.
Definition rail.h:439
RailBuildCost
Money RailBuildCost(RailType railtype)
Returns the cost of building the specified railtype.
Definition rail.h:428
RailFenceOffset
RailFenceOffset
Offsets from base sprite for fence sprites.
Definition rail.h:93
RFO_FLAT_RIGHT
@ RFO_FLAT_RIGHT
Slope FLAT, Track RIGHT, Fence W.
Definition rail.h:104
RFO_FLAT_Y_NE
@ RFO_FLAT_Y_NE
Slope FLAT, Track Y, Fence NE.
Definition rail.h:95
RFO_SLOPE_NW_SW
@ RFO_SLOPE_NW_SW
Slope NW, Track Y, Fence SW.
Definition rail.h:109
RFO_FLAT_X_SE
@ RFO_FLAT_X_SE
Slope FLAT, Track X, Fence SE.
Definition rail.h:102
RFO_SLOPE_NW_NE
@ RFO_SLOPE_NW_NE
Slope NW, Track Y, Fence NE.
Definition rail.h:101
RFO_SLOPE_SE_SW
@ RFO_SLOPE_SE_SW
Slope SE, Track Y, Fence SW.
Definition rail.h:107
RFO_SLOPE_NE_SE
@ RFO_SLOPE_NE_SE
Slope NE, Track X, Fence SE.
Definition rail.h:108
RFO_FLAT_LOWER
@ RFO_FLAT_LOWER
Slope FLAT, Track LOWER, Fence N.
Definition rail.h:105
RFO_SLOPE_SW_SE
@ RFO_SLOPE_SW_SE
Slope SW, Track X, Fence SE.
Definition rail.h:106
RFO_FLAT_UPPER
@ RFO_FLAT_UPPER
Slope FLAT, Track UPPER, Fence S.
Definition rail.h:97
RFO_SLOPE_SE_NE
@ RFO_SLOPE_SE_NE
Slope SE, Track Y, Fence NE.
Definition rail.h:99
RFO_FLAT_Y_SW
@ RFO_FLAT_Y_SW
Slope FLAT, Track Y, Fence SW.
Definition rail.h:103
RFO_FLAT_LEFT
@ RFO_FLAT_LEFT
Slope FLAT, Track LEFT, Fence E.
Definition rail.h:96
RFO_SLOPE_NE_NW
@ RFO_SLOPE_NE_NW
Slope NE, Track X, Fence NW.
Definition rail.h:100
RFO_FLAT_X_NW
@ RFO_FLAT_X_NW
Slope FLAT, Track X, Fence NW.
Definition rail.h:94
RFO_SLOPE_SW_NW
@ RFO_SLOPE_SW_NW
Slope SW, Track X, Fence NW.
Definition rail.h:98
IsCompatibleRail
bool IsCompatibleRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType can drive on a tile with a given RailType.
Definition rail.h:351
HasPowerOnRail
bool HasPowerOnRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType got power on a tile with a given RailType.
Definition rail.h:376
GetRailTypeInfo
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
RailTypeFlag::Hidden
@ Hidden
Bit number for hiding from selection.
RailTypeFlag::NoSpriteCombine
@ NoSpriteCombine
Bit number for using non-combined junctions.
RTSG_GROUND
@ RTSG_GROUND
Main group of ground images.
Definition rail.h:43
RTSG_CURSORS
@ RTSG_CURSORS
Cursor and toolbar icon images.
Definition rail.h:41
RTSG_GROUND_COMPLETE
@ RTSG_GROUND_COMPLETE
Complete ground images.
Definition rail.h:53
RTSG_OVERLAY
@ RTSG_OVERLAY
Images for overlaying track.
Definition rail.h:42
RTSG_DEPOT
@ RTSG_DEPOT
Depot images.
Definition rail.h:49
RTSG_FENCES
@ RTSG_FENCES
Fence images.
Definition rail.h:50
RTO_Y
@ RTO_Y
Piece of rail in Y direction.
Definition rail.h:63
RTO_S
@ RTO_S
Piece of rail in southern corner.
Definition rail.h:65
RTO_JUNCTION_NE
@ RTO_JUNCTION_NE
Ballast for junction 'pointing' NE.
Definition rail.h:74
RTO_JUNCTION_NSEW
@ RTO_JUNCTION_NSEW
Ballast for full junction.
Definition rail.h:77
RTO_JUNCTION_SW
@ RTO_JUNCTION_SW
Ballast for junction 'pointing' SW.
Definition rail.h:73
RTO_SLOPE_SE
@ RTO_SLOPE_SE
Piece of rail on slope with south-east raised.
Definition rail.h:69
RTO_E
@ RTO_E
Piece of rail in eastern corner.
Definition rail.h:66
RTO_W
@ RTO_W
Piece of rail in western corner.
Definition rail.h:67
RTO_CROSSING_XY
@ RTO_CROSSING_XY
Crossing of X and Y rail, with ballast.
Definition rail.h:72
RTO_SLOPE_SW
@ RTO_SLOPE_SW
Piece of rail on slope with south-west raised.
Definition rail.h:70
RTO_SLOPE_NW
@ RTO_SLOPE_NW
Piece of rail on slope with north-west raised.
Definition rail.h:71
RTO_JUNCTION_NW
@ RTO_JUNCTION_NW
Ballast for junction 'pointing' NW.
Definition rail.h:76
RTO_JUNCTION_SE
@ RTO_JUNCTION_SE
Ballast for junction 'pointing' SE.
Definition rail.h:75
RTO_SLOPE_NE
@ RTO_SLOPE_NE
Piece of rail on slope with north-east raised.
Definition rail.h:68
RTO_X
@ RTO_X
Piece of rail in X direction.
Definition rail.h:62
RTO_N
@ RTO_N
Piece of rail in northern corner.
Definition rail.h:64
RailNoLevelCrossings
bool RailNoLevelCrossings(RailType rt)
Test if a RailType disallows build of level crossings.
Definition rail.h:398
CmdRemoveSignalTrack
CommandCost CmdRemoveSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, bool autofill)
Remove signals on a stretch of track.
Definition rail_cmd.cpp:1524
TicksToLeaveDepot
int TicksToLeaveDepot(const Train *v)
Compute number of ticks when next wagon will leave a depot.
Definition rail_cmd.cpp:2926
CheckTrackCombination
static CommandCost CheckTrackCombination(TileIndex tile, TrackBits to_build)
Check that the new track bits may be built.
Definition rail_cmd.cpp:238
CmdRailTrackHelper
static CommandCost CmdRailTrackHelper(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, RailType railtype, Track track, bool remove, bool auto_remove_signals, bool fail_on_obstacle)
Build or remove a stretch of railroad tracks.
Definition rail_cmd.cpp:873
CmdBuildTrainDepot
CommandCost CmdBuildTrainDepot(DoCommandFlags flags, TileIndex tile, RailType railtype, DiagDirection dir)
Build a train depot.
Definition rail_cmd.cpp:961
GetSaveSlopeZ
static uint GetSaveSlopeZ(uint x, uint y, Track track)
Get surface height in point (x,y) On tiles with halftile foundations move (x,y) to a safe point wrt.
Definition rail_cmd.cpp:1851
CmdBuildSingleSignal
CommandCost CmdBuildSingleSignal(DoCommandFlags flags, TileIndex tile, Track track, SignalType sigtype, SignalVariant sigvar, bool convert_signal, bool skip_existing_signals, bool ctrl_pressed, SignalType cycle_start, SignalType cycle_stop, uint8_t num_dir_cycle, uint8_t signals_copy)
Build signals, alternate between double/single, signal/semaphore, pre/exit/combo-signals,...
Definition rail_cmd.cpp:1049
CmdBuildRailroadTrack
CommandCost CmdBuildRailroadTrack(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RailType railtype, Track track, bool auto_remove_signals, bool fail_on_obstacle)
Build rail on a stretch of track.
Definition rail_cmd.cpp:930
CmdBuildSignalTrack
CommandCost CmdBuildSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, SignalType sigtype, SignalVariant sigvar, bool mode, bool autofill, bool minimise_gaps, uint8_t signal_density)
Build signals on a stretch of track.
Definition rail_cmd.cpp:1446
FloodHalftile
bool FloodHalftile(TileIndex t)
Called from water_cmd if a non-flat rail-tile gets flooded and should be converted to shore.
Definition rail_cmd.cpp:759
AllocateRailType
RailType AllocateRailType(RailTypeLabel label)
Allocate a new rail type label.
Definition rail_cmd.cpp:148
CheckRailSlope
static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile)
Tests if a track can be build on a tile.
Definition rail_cmd.cpp:389
CmdRemoveSingleRail
CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track track)
Remove a single piece of track.
Definition rail_cmd.cpp:612
_sorted_railtypes
std::vector< RailType > _sorted_railtypes
Sorted list of rail types.
Definition rail_cmd.cpp:47
CmdRemoveSingleSignal
CommandCost CmdRemoveSingleSignal(DoCommandFlags flags, TileIndex tile, Track track)
Remove signals.
Definition rail_cmd.cpp:1458
_valid_tracks_without_foundation
static const TrackBits _valid_tracks_without_foundation[15]
Valid TrackBits on a specific (non-steep)-slope without foundation.
Definition rail_cmd.cpp:259
_valid_tracks_on_leveled_foundation
static const TrackBits _valid_tracks_on_leveled_foundation[15]
Valid TrackBits on a specific (non-steep)-slope with leveled foundation.
Definition rail_cmd.cpp:281
EnsureNoTrainOnTrack
static CommandCost EnsureNoTrainOnTrack(TileIndex tile, Track track)
Tests if a vehicle interacts with the specified track.
Definition rail_cmd.cpp:226
CmdSignalTrackHelper
static CommandCost CmdSignalTrackHelper(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, SignalType sigtype, SignalVariant sigvar, bool mode, bool remove, bool autofill, bool minimise_gaps, int signal_density)
Build many signals by dragging; AutoSignals.
Definition rail_cmd.cpp:1255
DrawTrackBits
static void DrawTrackBits(TileInfo *ti, TrackBits track)
Draw ground sprite and track bits.
Definition rail_cmd.cpp:2241
DrawTrackDetails
static void DrawTrackDetails(const TileInfo *ti, const RailTypeInfo *rti, PaletteID pal)
Draw track fences.
Definition rail_cmd.cpp:1992
SignalOffsets
SignalOffsets
Enum holding the signal offset in the sprite sheet according to the side it is representing.
Definition rail_cmd.cpp:51
CmdRemoveRailroadTrack
CommandCost CmdRemoveRailroadTrack(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, Track track)
Build rail on a stretch of track.
Definition rail_cmd.cpp:945
CmdBuildSingleRail
CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType railtype, Track track, bool auto_remove_signals)
Build a single piece of rail.
Definition rail_cmd.cpp:423
CmdConvertRail
CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RailType totype, bool diagonal)
Convert one rail type to the other.
Definition rail_cmd.cpp:1539
InitRailTypes
void InitRailTypes()
Resolve sprites of custom rail types.
Definition rail_cmd.cpp:130
DrawTrackFence_SW
static void DrawTrackFence_SW(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
Draw fence at SW border matching the tile slope.
Definition rail_cmd.cpp:1980
VehicleEnter_Track
static VehicleEnterTileStates VehicleEnter_Track(Vehicle *u, TileIndex tile, int x, int y)
Tile callback routine when vehicle enters tile.
Definition rail_cmd.cpp:2944
ResetRailTypes
void ResetRailTypes()
Reset all rail type information to its default values.
Definition rail_cmd.cpp:65
TestAutoslopeOnRailTile
static CommandCost TestAutoslopeOnRailTile(TileIndex tile, DoCommandFlags flags, int z_old, Slope tileh_old, int z_new, Slope tileh_new, TrackBits rail_bits)
Tests if autoslope is allowed.
Definition rail_cmd.cpp:3004
_fence_offsets
static const FenceOffset _fence_offsets[]
Offsets for drawing fences.
Definition rail_cmd.cpp:1912
GetJunctionGroundSpriteOffset
static int GetJunctionGroundSpriteOffset(TrackBits track)
Returns which of the 5 junction-'Rail underlays' to use for the given track bits.
Definition rail_cmd.cpp:2224
CompareRailTypes
static bool CompareRailTypes(const RailType &first, const RailType &second)
Compare railtypes based on their sorting order.
Definition rail_cmd.cpp:122
DrawTrackFence_NW
static void DrawTrackFence_NW(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
Draw fence at NW border matching the tile slope.
Definition rail_cmd.cpp:1950
GetRailFoundation
Foundation GetRailFoundation(Slope tileh, TrackBits bits)
Checks if a track combination is valid on a specific slope and returns the needed foundation.
Definition rail_cmd.cpp:309
DrawTrackFence_NE
static void DrawTrackFence_NE(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
Draw fence at NE border matching the tile slope.
Definition rail_cmd.cpp:1970
DrawTrackFence_SE
static void DrawTrackFence_SE(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites)
Draw fence at SE border matching the tile slope.
Definition rail_cmd.cpp:1960
TrainList
std::vector< Train * > TrainList
Helper type for lists/vectors of trains.
Definition rail_cmd.cpp:44
DrawTrackFence
static void DrawTrackFence(const TileInfo *ti, const PalSpriteID &psid, uint num_sprites, RailFenceOffset rfo)
Draw a track fence.
Definition rail_cmd.cpp:1938
rail_cmd.h
Command definitions for rail.
GetRailTileType
static RailTileType GetRailTileType(Tile t)
Returns the RailTileType (normal with or without signals, waypoint or depot).
Definition rail_map.h:36
IsPlainRail
static bool IsPlainRail(Tile t)
Returns whether this is plain rails, with or without signals.
Definition rail_map.h:49
GetSignalStates
uint GetSignalStates(Tile tile)
Set the states of the signals (Along/AgainstTrackDir)
Definition rail_map.h:361
MakeRailDepot
void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RailType rail_type)
Make a rail depot.
Definition rail_map.h:551
GetRailType
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
HasSignalOnTrackdir
bool HasSignalOnTrackdir(Tile tile, Trackdir trackdir)
Checks for the presence of signals along the given trackdir on the given rail tile.
Definition rail_map.h:425
IsRailDepot
static bool IsRailDepot(Tile t)
Is this rail tile a rail depot?
Definition rail_map.h:95
GetTrackBits
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition rail_map.h:136
IsPlainRailTile
static bool IsPlainRailTile(Tile t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition rail_map.h:60
RailTileType::Normal
@ Normal
Normal rail tile without signals.
RailTileType::Depot
@ Depot
Depot (one entrance)
RailTileType::Signals
@ Signals
Normal rail tile with signals.
GetRailDepotTrack
Track GetRailDepotTrack(Tile t)
Returns the track of a depot, ignoring direction.
Definition rail_map.h:182
SetTrackReservation
void SetTrackReservation(Tile t, TrackBits b)
Sets the reserved track bits of the tile.
Definition rail_map.h:209
IsSignalPresent
bool IsSignalPresent(Tile t, uint8_t signalbit)
Checks whether the given signals is present.
Definition rail_map.h:403
GetRailDepotDirection
DiagDirection GetRailDepotDirection(Tile t)
Returns the direction the depot is facing to.
Definition rail_map.h:171
SetTrackBits
void SetTrackBits(Tile t, TrackBits b)
Sets the track bits of the given tile.
Definition rail_map.h:147
RailGroundType
RailGroundType
The ground 'under' the rail.
Definition rail_map.h:484
RailGroundType::FenceSENW
@ FenceSENW
Grass with a fence at the NW and SE edges.
RailGroundType::FenceVert2
@ FenceVert2
Grass with a fence at the western side.
RailGroundType::HalfTileSnow
@ HalfTileSnow
Snow only on higher part of slope (steep or one corner raised)
RailGroundType::Barren
@ Barren
Nothing (dirt)
RailGroundType::FenceNESW
@ FenceNESW
Grass with a fence at the NE and SW edges.
RailGroundType::FenceHoriz2
@ FenceHoriz2
Grass with a fence at the northern side.
RailGroundType::SnowOrDesert
@ SnowOrDesert
Icy or sandy.
RailGroundType::HalfTileWater
@ HalfTileWater
Grass with a fence and shore or water on the free halftile.
RailGroundType::FenceVert1
@ FenceVert1
Grass with a fence at the eastern side.
RailGroundType::FenceNW
@ FenceNW
Grass with a fence at the NW edge.
RailGroundType::FenceSE
@ FenceSE
Grass with a fence at the SE edge.
RailGroundType::FenceNE
@ FenceNE
Grass with a fence at the NE edge.
RailGroundType::Grass
@ Grass
Grassy.
RailGroundType::FenceSW
@ FenceSW
Grass with a fence at the SW edge.
RailGroundType::FenceHoriz1
@ FenceHoriz1
Grass with a fence at the southern side.
GetPresentSignals
uint GetPresentSignals(Tile tile)
Get whether the given signals are present (Along/AgainstTrackDir)
Definition rail_map.h:392
HasSignalOnTrack
bool HasSignalOnTrack(Tile tile, Track track)
Checks for the presence of signals (either way) on the given track on the given rail tile.
Definition rail_map.h:412
IsOnewaySignal
bool IsOnewaySignal(Tile t, Track track)
One-way signals can't be passed the 'wrong' way.
Definition rail_map.h:318
SetPresentSignals
void SetPresentSignals(Tile tile, uint signals)
Set whether the given signals are present (Along/AgainstTrackDir)
Definition rail_map.h:382
SetRailDepotExitDirection
void SetRailDepotExitDirection(Tile tile, DiagDirection dir)
Sets the exit direction of a rail depot.
Definition rail_map.h:537
GetRailReservationTrackBits
TrackBits GetRailReservationTrackBits(Tile t)
Returns the reserved track bits of the tile.
Definition rail_map.h:194
HasDepotReservation
bool HasDepotReservation(Tile t)
Get the reservation state of the depot.
Definition rail_map.h:257
SetHasSignals
void SetHasSignals(Tile tile, bool signals)
Add/remove the 'has signal' bit from the RailTileType.
Definition rail_map.h:83
HasSignals
bool HasSignals(Tile t)
Checks if a rail tile has signals.
Definition rail_map.h:72
IsRailDepotTile
static bool IsRailDepotTile(Tile t)
Is this tile rail tile and a rail depot?
Definition rail_map.h:105
HasTrack
bool HasTrack(Tile tile, Track track)
Returns whether the given track is present on the given tile.
Definition rail_map.h:160
GetSingleSignalState
SignalState GetSingleSignalState(Tile t, uint8_t signalbit)
Get the state of a single signal.
Definition rail_map.h:372
SetSignalStates
void SetSignalStates(Tile tile, uint state)
Set the states of the signals (Along/AgainstTrackDir)
Definition rail_map.h:351
SetRailType
void SetRailType(Tile t, RailType r)
Sets the rail type of the given tile.
Definition rail_map.h:125
RailType
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
RAILTYPE_END
@ RAILTYPE_END
Used for iterations.
Definition rail_type.h:31
INVALID_RAILTYPE
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition rail_type.h:32
RAILTYPE_ELECTRIC
@ RAILTYPE_ELECTRIC
Electric rails.
Definition rail_type.h:28
RAILTYPE_RAIL
@ RAILTYPE_RAIL
Standard non-electric rails.
Definition rail_type.h:27
railtypes.h
All the railtype-specific information is stored here.
_original_railtypes
static const RailTypeInfo _original_railtypes[]
Global Railtype definition.
Definition railtypes.h:21
RoadNoLevelCrossing
bool RoadNoLevelCrossing(RoadType roadtype)
Test if road disallows level crossings.
Definition road.h:283
RoadBuildCost
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition road.h:240
UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval
void UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(TileIndex tile, Axis road_axis)
Update adjacent level crossing tiles in this multi-track crossing, due to removal of a level crossing...
Definition train_cmd.cpp:1840
MarkDirtyAdjacentLevelCrossingTiles
void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis)
Find adjacent level crossing tiles in this multi-track crossing and mark them dirty.
Definition train_cmd.cpp:1823
UpdateLevelCrossing
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).
Definition train_cmd.cpp:1791
IsLevelCrossingTile
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition road_map.h:79
GetRoadBits
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:112
GetCrossingRoadAxis
Axis GetCrossingRoadAxis(Tile t)
Get the road axis of a level crossing.
Definition road_map.h:309
GetCrossingRailBits
TrackBits GetCrossingRailBits(Tile tile)
Get the rail track bits of a level crossing.
Definition road_map.h:352
GetCrossingRailTrack
Track GetCrossingRailTrack(Tile tile)
Get the rail track of a level crossing.
Definition road_map.h:342
GetDisallowedRoadDirections
DisallowedRoadDirections GetDisallowedRoadDirections(Tile t)
Gets the disallowed directions.
Definition road_map.h:285
MakeRoadNormal
void MakeRoadNormal(Tile t, RoadBits bits, RoadType road_rt, RoadType tram_rt, TownID town, Owner road, Owner tram)
Make a normal road tile.
Definition road_map.h:620
MakeRoadCrossing
void MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadType road_rt, RoadType tram_rt, TownID town)
Make a level crossing.
Definition road_map.h:646
GetCrossingRoadBits
RoadBits GetCrossingRoadBits(Tile tile)
Get the road bits of a level crossing.
Definition road_map.h:332
GetRoadOwner
Owner GetRoadOwner(Tile t, RoadTramType rtt)
Get the owner of a specific road type.
Definition road_map.h:218
IsLevelCrossing
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition road_map.h:69
IsNormalRoad
static bool IsNormalRoad(Tile t)
Return whether a tile is a normal road.
Definition road_map.h:48
HasRoadWorks
bool HasRoadWorks(Tile t)
Check if a tile has road works.
Definition road_map.h:493
RoadBits
RoadBits
Enumeration for the road parts on a tile.
Definition road_type.h:56
ROAD_NONE
@ ROAD_NONE
No road-part is build.
Definition road_type.h:57
ROAD_Y
@ ROAD_Y
Full road along the y-axis (north-west + south-east)
Definition road_type.h:63
ROAD_X
@ ROAD_X
Full road along the x-axis (south-west + north-east)
Definition road_type.h:62
RTT_ROAD
@ RTT_ROAD
Road road type.
Definition road_type.h:38
RTT_TRAM
@ RTT_TRAM
Tram road type.
Definition road_type.h:39
RoadType
RoadType
The different roadtypes we support.
Definition road_type.h:23
INVALID_ROADTYPE
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
DRD_NONE
@ DRD_NONE
None of the directions are disallowed.
Definition road_type.h:78
safeguards.h
A number of safeguards to prevent using unsafe methods.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
AddTrackToSignalBuffer
void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
Add track to signal update buffer.
Definition signal.cpp:589
AddSideToSignalBuffer
void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
Add side of tile to signal update buffer.
Definition signal.cpp:621
SignalAgainstTrackdir
uint8_t SignalAgainstTrackdir(Trackdir trackdir)
Maps a trackdir to the bit that stores its status in the map arrays, in the direction against the tra...
Definition signal_func.h:32
SignalAlongTrackdir
uint8_t SignalAlongTrackdir(Trackdir trackdir)
Maps a trackdir to the bit that stores its status in the map arrays, in the direction along with the ...
Definition signal_func.h:22
SignalOnTrack
uint8_t SignalOnTrack(Track track)
Maps a Track to the bits that store the status of the two signals that can be present on the given tr...
Definition signal_func.h:42
SignalType
SignalType
Type of signal, i.e.
Definition signal_type.h:23
SIGTYPE_ENTRY
@ SIGTYPE_ENTRY
presignal block entry
Definition signal_type.h:25
SIGTYPE_EXIT
@ SIGTYPE_EXIT
presignal block exit
Definition signal_type.h:26
SIGTYPE_BLOCK
@ SIGTYPE_BLOCK
block signal
Definition signal_type.h:24
SignalState
SignalState
These are states in which a signal can be.
Definition signal_type.h:42
SIGNAL_STATE_RED
@ SIGNAL_STATE_RED
The signal is red.
Definition signal_type.h:43
SIGNAL_STATE_GREEN
@ SIGNAL_STATE_GREEN
The signal is green.
Definition signal_type.h:44
SignalVariant
SignalVariant
Variant of the signal, i.e.
Definition signal_type.h:16
SIG_SEMAPHORE
@ SIG_SEMAPHORE
Old-fashioned semaphore signal.
Definition signal_type.h:18
SIG_ELECTRIC
@ SIG_ELECTRIC
Light signal.
Definition signal_type.h:17
IsSpecialRailFoundation
bool IsSpecialRailFoundation(Foundation f)
Tests if a foundation is a special rail foundation for single horizontal/vertical track.
Definition slope_func.h:345
SlopeWithThreeCornersRaised
Slope SlopeWithThreeCornersRaised(Corner corner)
Returns the slope with all except one corner raised.
Definition slope_func.h:206
OppositeCorner
Corner OppositeCorner(Corner corner)
Returns the opposite corner.
Definition slope_func.h:184
GetHalftileSlopeCorner
static constexpr Corner GetHalftileSlopeCorner(Slope s)
Returns the leveled halftile of a halftile slope.
Definition slope_func.h:148
RemoveHalftileSlope
static constexpr Slope RemoveHalftileSlope(Slope s)
Removes a halftile slope from a slope.
Definition slope_func.h:60
IsSlopeWithOneCornerRaised
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
SlopeToSpriteOffset
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:415
IsNonContinuousFoundation
bool IsNonContinuousFoundation(Foundation f)
Tests if a foundation is a non-continuous foundation, i.e.
Definition slope_func.h:320
GetHighestSlopeCorner
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:126
GetHalftileFoundationCorner
Corner GetHalftileFoundationCorner(Foundation f)
Returns the halftile corner of a halftile-foundation.
Definition slope_func.h:333
IsValidCorner
static constexpr bool IsValidCorner(Corner corner)
Rangecheck for Corner enumeration.
Definition slope_func.h:24
IsSteepSlope
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
IsSlopeWithThreeCornersRaised
bool IsSlopeWithThreeCornersRaised(Slope s)
Tests if a specific slope has exactly three corners raised.
Definition slope_func.h:195
FlatteningFoundation
Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition slope_func.h:369
IsHalftileSlope
static constexpr bool IsHalftileSlope(Slope s)
Checks for non-continuous slope on halftile foundations.
Definition slope_func.h:47
HalftileFoundation
Foundation HalftileFoundation(Corner corner)
Returns the halftile foundation for single horizontal/vertical track.
Definition slope_func.h:391
SpecialRailFoundation
Foundation SpecialRailFoundation(Corner corner)
Returns the special rail foundation for single horizontal/vertical track.
Definition slope_func.h:403
ComplementSlope
Slope ComplementSlope(Slope s)
Return the complement of a slope.
Definition slope_func.h:76
SlopeWithOneCornerRaised
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:99
Corner
Corner
Enumeration of tile corners.
Definition slope_type.h:22
Slope
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
SLOPE_W
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:50
SLOPE_ELEVATED
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:61
SLOPE_NS
@ SLOPE_NS
north and south corner are raised
Definition slope_type.h:60
SLOPE_E
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:52
SLOPE_S
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:51
SLOPE_N
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:53
SLOPE_SW
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:56
SLOPE_FLAT
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
SLOPE_NE
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:58
SLOPE_SE
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:57
SLOPE_NW
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:55
SLOPE_EW
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:59
Foundation
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
FOUNDATION_LEVELED
@ FOUNDATION_LEVELED
The tile is leveled up to a flat slope.
Definition slope_type.h:95
FOUNDATION_NONE
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:94
FOUNDATION_INCLINED_X
@ FOUNDATION_INCLINED_X
The tile has an along X-axis inclined foundation.
Definition slope_type.h:96
FOUNDATION_STEEP_BOTH
@ FOUNDATION_STEEP_BOTH
The tile has a steep slope. The lowest corner is raised by a foundation and the upper halftile is lev...
Definition slope_type.h:101
FOUNDATION_INCLINED_Y
@ FOUNDATION_INCLINED_Y
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:97
FOUNDATION_STEEP_LOWER
@ FOUNDATION_STEEP_LOWER
The tile has a steep slope. The lowest corner is raised by a foundation to allow building railroad on...
Definition slope_type.h:98
FOUNDATION_HALFTILE_N
@ FOUNDATION_HALFTILE_N
Level north halftile non-continuously.
Definition slope_type.h:105
FOUNDATION_INVALID
@ FOUNDATION_INVALID
Used inside "rail_cmd.cpp" to indicate invalid slope/track combination.
Definition slope_type.h:113
VALID_LEVEL_CROSSING_SLOPES
static const uint32_t VALID_LEVEL_CROSSING_SLOPES
Constant bitset with safe slopes for building a level crossing.
Definition slope_type.h:86
sound_func.h
Functions related to sound.
DrawRailTileSeqInGUI
void DrawRailTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence in GUI with railroad specifics.
Definition sprite.h:105
DrawRailTileSeq
void DrawRailTileSeq(const struct TileInfo *ti, const DrawTileSprites *dts, TransparencyOption to, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence on tile with railroad specifics.
Definition sprite.h:95
GroundSpritePaletteTransform
PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition sprite.h:174
PALETTE_CRASH
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1619
PALETTE_TO_BARE_LAND
static const PaletteID PALETTE_TO_BARE_LAND
sets colour to bare land stuff for rail, road and crossings
Definition sprites.h:1607
IsRailStationTile
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
Definition station_map.h:102
GetRailStationTrack
Track GetRailStationTrack(Tile t)
Get the rail track of a rail station tile.
Definition station_map.h:515
IsStationTileBlocked
bool IsStationTileBlocked(Tile t)
Is tile t a blocked tile?
Definition station_map.h:431
HasStationRail
bool HasStationRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
Definition station_map.h:135
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
strings_func.h
Functions related to OTTD's strings.
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
INVALID_STRING_ID
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition strings_type.h:20
Backup
Class to backup a specific variable and restore it later.
Definition backup_type.hpp:21
Backup::Restore
void Restore()
Restore the variable.
Definition backup_type.hpp:110
BaseVehicle::type
VehicleType type
Type of vehicle.
Definition vehicle_type.h:51
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition settings_type.h:650
CommandHelper
Definition command_func.h:84
CompanyInfrastructure::rail
std::array< uint32_t, RAILTYPE_END > rail
Count of company owned track bits for each rail type.
Definition company_base.h:33
Company
Definition company_base.h:127
Company::infrastructure
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition company_base.h:141
ConstructionSettings::build_on_slopes
bool build_on_slopes
allow building on slopes
Definition settings_type.h:411
ConstructionSettings::crossing_with_competitor
bool crossing_with_competitor
allow building of level crossings with competitor roads or rails
Definition settings_type.h:420
ConstructionSettings::train_signal_side
uint8_t train_signal_side
show signals on left / driving / right side
Definition settings_type.h:416
Coord2D< int >
Coord2D::y
T y
Y coordinate.
Definition geometry_type.hpp:35
Coord2D::x
T x
X coordinate.
Definition geometry_type.hpp:34
Coord3D::x
T x
X coordinate.
Definition geometry_type.hpp:44
Coord3D::y
T y
Y coordinate.
Definition geometry_type.hpp:45
Coord3D::z
T z
Z coordinate.
Definition geometry_type.hpp:46
Depot
Definition depot_base.h:20
Depot::build_date
TimerGameCalendar::Date build_date
Date of construction.
Definition depot_base.h:26
DiagonalTileArea
Represents a diagonal tile area.
Definition tilearea_type.h:70
DrawTileSprites
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:52
DrawTileSprites::ground
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:53
FenceOffset
Offsets for drawing fences.
Definition rail_cmd.cpp:1904
FenceOffset::height_ref
Corner height_ref
Corner to use height offset from.
Definition rail_cmd.cpp:1905
GUISettings::show_track_reservation
bool show_track_reservation
highlight reserved tracks.
Definition settings_type.h:220
GameCreationSettings::landscape
LandscapeType landscape
the landscape we're currently in
Definition settings_type.h:395
GameSettings::pf
PathfinderSettings pf
settings for all pathfinders
Definition settings_type.h:639
GameSettings::construction
ConstructionSettings construction
construction of things in-game
Definition settings_type.h:635
GameSettings::game_creation
GameCreationSettings game_creation
settings used during the creation of a game (map)
Definition settings_type.h:634
GameSettings::vehicle
VehicleSettings vehicle
options for vehicles
Definition settings_type.h:641
Map::Size
static uint Size()
Get the size of the map.
Definition map_func.h:290
Order::IsType
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
OrthogonalTileArea
Represents the covered area of e.g.
Definition tilearea_type.h:18
PalSpriteID
Combination of a palette sprite and a 'real' sprite.
Definition gfx_type.h:22
PalSpriteID::sprite
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PalSpriteID::pal
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:24
PathfinderSettings::forbid_90_deg
bool forbid_90_deg
forbid trains to make 90 deg turns
Definition settings_type.h:493
PoolID< uint8_t, struct CompanyIDTag, 0xF, 0xFF >
Pool::PoolItem<&_company_pool >::Get
static Titem * Get(auto index)
Returns Titem with given index.
Definition pool_type.hpp:387
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition pool_type.hpp:286
Pool::PoolItem<&_depot_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition pool_type.hpp:357
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
SpecializedVehicle::Next
T * Next() const
Get next vehicle in the chain.
Definition vehicle_base.h:1049
SpecializedVehicle::From
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Definition vehicle_base.h:1134
SpecializedVehicle::First
T * First() const
Get the first vehicle in the chain.
Definition vehicle_base.h:1031
SpriteBounds
Definition sprite.h:18
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
SubSprite
Used to only draw a part of the sprite.
Definition gfx_type.h:278
TileDesc
Tile description for the 'land area information' tool.
Definition tile_cmd.h:36
TileDesc::rail_speed
uint16_t rail_speed
Speed limit of rail (bridges and track)
Definition tile_cmd.h:49
TileDesc::str
StringID str
Description of the tile.
Definition tile_cmd.h:37
TileDesc::build_date
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:41
TileDesc::owner
std::array< Owner, 4 > owner
Name of the owner(s)
Definition tile_cmd.h:39
TileDesc::railtype
StringID railtype
Type of rail on the tile.
Definition tile_cmd.h:48
TileIndexDiffC
A pair-construct of a TileIndexDiff.
Definition map_type.h:31
TileIndexDiffC::x
int16_t x
The x value of the coordinate.
Definition map_type.h:32
TileIndexDiffC::y
int16_t y
The y value of the coordinate.
Definition map_type.h:33
TileInfo
Tile information, used while rendering the tile.
Definition tile_cmd.h:30
TileInfo::tileh
Slope tileh
Slope of the tile.
Definition tile_cmd.h:31
TileInfo::tile
TileIndex tile
Tile index.
Definition tile_cmd.h:32
TileTypeProcs
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:152
Train
'Train' is either a loco or a wagon.
Definition train.h:91
Train::GetVehicleTrackdir
Trackdir GetVehicleTrackdir() const override
Get the tracks of the train vehicle.
Definition train_cmd.cpp:4226
Train::CalcNextVehicleOffset
int CalcNextVehicleOffset() const
Calculate the offset from this vehicle's center to the following center taking the vehicle lengths in...
Definition train.h:174
VehicleSettings::train_acceleration_model
uint8_t train_acceleration_model
realistic acceleration for trains
Definition settings_type.h:520
VehicleSettings::road_side
uint8_t road_side
the side of the road vehicles drive on
Definition settings_type.h:535
VehicleSettings::disable_elrails
bool disable_elrails
when true, the elrails are disabled
Definition settings_type.h:525
Vehicle
Vehicle data structure.
Definition vehicle_base.h:205
Vehicle::direction
Direction direction
facing
Definition vehicle_base.h:268
Vehicle::vehstatus
VehStates vehstatus
Status.
Definition vehicle_base.h:309
Vehicle::current_order
Order current_order
The current order (+ status, like: loading)
Definition vehicle_base.h:311
Vehicle::y_pos
int32_t y_pos
y coordinate.
Definition vehicle_base.h:266
Vehicle::x_pos
int32_t x_pos
x coordinate.
Definition vehicle_base.h:265
Vehicle::cur_speed
uint16_t cur_speed
current speed
Definition vehicle_base.h:283
Vehicle::tile
TileIndex tile
Current tile index.
Definition vehicle_base.h:225
VehicleEnterTileState::CannotEnter
@ CannotEnter
The vehicle cannot enter the tile.
VehicleEnterTileState::EnteredWormhole
@ EnteredWormhole
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
GetTileSlopeZ
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.cpp:55
IsTileType
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
IsTileOwner
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
GetTileOwner
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
SetTileOwner
void SetTileOwner(Tile tile, Owner owner)
Sets the owner of a tile.
Definition tile_map.h:198
GetTileMaxPixelZ
int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition tile_map.h:312
GetTilePixelSlope
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition tile_map.h:289
IsValidTile
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
GetTropicZone
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
GetTileSlope
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
GetTileType
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
TROPICZONE_DESERT
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
INVALID_TILE
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
TILE_SIZE
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
TILE_HEIGHT
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
TileType
TileType
The different types of tiles.
Definition tile_type.h:47
MP_ROAD
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
MP_STATION
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
MP_TUNNELBRIDGE
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
MP_HOUSE
@ MP_HOUSE
A house by a town.
Definition tile_type.h:51
MP_WATER
@ MP_WATER
Water tile.
Definition tile_type.h:54
MP_RAILWAY
@ MP_RAILWAY
A railway.
Definition tile_type.h:49
MP_INDUSTRY
@ MP_INDUSTRY
Part of an industry.
Definition tile_type.h:56
MP_OBJECT
@ MP_OBJECT
Contains objects such as transmitters and owned land.
Definition tile_type.h:58
timer_game_calendar.h
Definition of the game-calendar-timer.
town.h
Base of the town class.
MakeDefaultName
void MakeDefaultName(T *obj)
Set the default name for a depot/waypoint.
Definition town.h:284
GetTownIndex
TownID GetTownIndex(Tile t)
Get the index of which town this house/street is attached to.
Definition town_map.h:23
TrackToTrackdir
Trackdir TrackToTrackdir(Track track)
Returns a Trackdir for the given Track.
Definition track_func.h:279
RemoveFirstTrackdir
Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
Removes first Trackdir from TrackdirBits and returns it.
Definition track_func.h:156
TrackdirToTrack
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition track_func.h:262
CornerToTrackBits
TrackBits CornerToTrackBits(Corner corner)
Returns a single horizontal/vertical trackbit that is in a specific tile corner.
Definition track_func.h:99
TrackToTrackBits
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition track_func.h:77
TrackBitsToTrackdirBits
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:319
TrackStatusToTrackdirBits
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition track_func.h:352
TrackBitsToTrack
Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition track_func.h:193
ReverseTrackdir
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:247
CombineTrackStatus
TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition track_func.h:388
TracksOverlap
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition track_func.h:645
TrackdirReachesTrackdirs
TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir)
Maps a trackdir to the trackdirs that can be reached from it (ie, when entering the next tile.
Definition track_func.h:584
IsValidTrack
bool IsValidTrack(Track track)
Checks if a Track is valid.
Definition track_func.h:28
FindFirstTrack
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or INVALID_TRACK.
Definition track_func.h:177
IsDiagonalTrackdir
bool IsDiagonalTrackdir(Trackdir trackdir)
Checks if a given Trackdir is diagonal.
Definition track_func.h:631
DiagDirToDiagTrackBits
TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track bits incidating with that diagdir.
Definition track_func.h:524
RemoveFirstTrack
Track RemoveFirstTrack(TrackBits *tracks)
Removes first Track from TrackBits and returns it.
Definition track_func.h:131
TrackdirToExitdir
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition track_func.h:439
DiagDirToDiagTrack
Track DiagDirToDiagTrack(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track incidating with that diagdir.
Definition track_func.h:512
TrackdirBitsToTrackBits
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition track_func.h:308
track_land.h
Sprites to use and how to display them for train depot tiles.
TrackBits
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
TRACK_BIT_UPPER
@ TRACK_BIT_UPPER
Upper track.
Definition track_type.h:39
TRACK_BIT_DEPOT
@ TRACK_BIT_DEPOT
Bitflag for a depot.
Definition track_type.h:53
TRACK_BIT_LEFT
@ TRACK_BIT_LEFT
Left track.
Definition track_type.h:41
TRACK_BIT_Y
@ TRACK_BIT_Y
Y-axis track.
Definition track_type.h:38
TRACK_BIT_CROSS
@ TRACK_BIT_CROSS
X-Y-axis cross.
Definition track_type.h:43
TRACK_BIT_HORZ
@ TRACK_BIT_HORZ
Upper and lower track.
Definition track_type.h:44
TRACK_BIT_NONE
@ TRACK_BIT_NONE
No track.
Definition track_type.h:36
TRACK_BIT_3WAY_NW
@ TRACK_BIT_3WAY_NW
"Arrow" to the north-west
Definition track_type.h:49
TRACK_BIT_X
@ TRACK_BIT_X
X-axis track.
Definition track_type.h:37
TRACK_BIT_LOWER
@ TRACK_BIT_LOWER
Lower track.
Definition track_type.h:40
TRACK_BIT_ALL
@ TRACK_BIT_ALL
All possible tracks.
Definition track_type.h:50
TRACK_BIT_3WAY_NE
@ TRACK_BIT_3WAY_NE
"Arrow" to the north-east
Definition track_type.h:46
TRACK_BIT_RIGHT
@ TRACK_BIT_RIGHT
Right track.
Definition track_type.h:42
TRACK_BIT_3WAY_SW
@ TRACK_BIT_3WAY_SW
"Arrow" to the south-west
Definition track_type.h:48
TRACK_BIT_VERT
@ TRACK_BIT_VERT
Left and right track.
Definition track_type.h:45
TRACK_BIT_3WAY_SE
@ TRACK_BIT_3WAY_SE
"Arrow" to the south-east
Definition track_type.h:47
Trackdir
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:66
INVALID_TRACKDIR
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:85
TrackdirBits
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:97
TRACKDIR_BIT_LEFT_S
@ TRACKDIR_BIT_LEFT_S
Track left, direction south.
Definition track_type.h:103
TRACKDIR_BIT_Y_NW
@ TRACKDIR_BIT_Y_NW
Track y-axis, direction north-west.
Definition track_type.h:107
TRACKDIR_BIT_UPPER_E
@ TRACKDIR_BIT_UPPER_E
Track upper, direction east.
Definition track_type.h:101
TRACKDIR_BIT_X_NE
@ TRACKDIR_BIT_X_NE
Track x-axis, direction north-east.
Definition track_type.h:99
TRACKDIR_BIT_LOWER_E
@ TRACKDIR_BIT_LOWER_E
Track lower, direction east.
Definition track_type.h:102
TRACKDIR_BIT_LEFT_N
@ TRACKDIR_BIT_LEFT_N
Track left, direction north.
Definition track_type.h:110
TRACKDIR_BIT_RIGHT_S
@ TRACKDIR_BIT_RIGHT_S
Track right, direction south.
Definition track_type.h:104
TRACKDIR_BIT_Y_SE
@ TRACKDIR_BIT_Y_SE
Track y-axis, direction south-east.
Definition track_type.h:100
TRACKDIR_BIT_NONE
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
TRACKDIR_BIT_RIGHT_N
@ TRACKDIR_BIT_RIGHT_N
Track right, direction north.
Definition track_type.h:111
TRACKDIR_BIT_UPPER_W
@ TRACKDIR_BIT_UPPER_W
Track upper, direction west.
Definition track_type.h:108
TRACKDIR_BIT_LOWER_W
@ TRACKDIR_BIT_LOWER_W
Track lower, direction west.
Definition track_type.h:109
TRACKDIR_BIT_X_SW
@ TRACKDIR_BIT_X_SW
Track x-axis, direction south-west.
Definition track_type.h:106
Track
Track
These are used to specify a single track.
Definition track_type.h:19
INVALID_TRACK
@ INVALID_TRACK
Flag for an invalid track.
Definition track_type.h:28
TRACK_Y
@ TRACK_Y
Track along the y-axis (north-west to south-east)
Definition track_type.h:22
TRACK_LOWER
@ TRACK_LOWER
Track in the lower corner of the tile (south)
Definition track_type.h:24
TRACK_END
@ TRACK_END
Used for iterations.
Definition track_type.h:27
TRACK_LEFT
@ TRACK_LEFT
Track in the left corner of the tile (west)
Definition track_type.h:25
TRACK_RIGHT
@ TRACK_RIGHT
Track in the right corner of the tile (east)
Definition track_type.h:26
TRACK_BEGIN
@ TRACK_BEGIN
Used for iterations.
Definition track_type.h:20
TRACK_X
@ TRACK_X
Track along the x-axis (north-east to south-west)
Definition track_type.h:21
TRACK_UPPER
@ TRACK_UPPER
Track in the upper corner of the tile (north)
Definition track_type.h:23
train.h
Base for the train class.
CCF_TRACK
static constexpr ConsistChangeFlags CCF_TRACK
Valid changes while vehicle is driving, and possibly changing tracks.
Definition train.h:52
TryPathReserve
bool TryPathReserve(Train *v, bool mark_as_stuck=false, bool first_tile_okay=false)
Try to reserve a path to a safe position.
Definition train_cmd.cpp:2899
FreeTrainTrackReservation
void FreeTrainTrackReservation(const Train *v)
Free the reserved path in front of a vehicle.
Definition train_cmd.cpp:2419
_display_opt
uint8_t _display_opt
What do we want to draw/do?
Definition transparency_gui.cpp:26
IsInvisibilitySet
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...
Definition transparency.h:61
TO_BUILDINGS
@ TO_BUILDINGS
company buildings - depots, stations, HQ, ...
Definition transparency.h:28
TransportType
TransportType
Available types of transport.
Definition transport_type.h:17
TRANSPORT_RAIL
@ TRANSPORT_RAIL
Transport by train.
Definition transport_type.h:25
TRANSPORT_WATER
@ TRANSPORT_WATER
Transport over water.
Definition transport_type.h:27
tunnelbridge.h
Header file for things common for tunnels and bridges.
MarkBridgeDirty
void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
Mark bridge tiles dirty.
Definition tunnelbridge_cmd.cpp:64
GetTunnelBridgeLength
uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
Calculates the length of a tunnel or a bridge (without end tiles)
Definition tunnelbridge.h:25
tunnelbridge_map.h
Functions that have tunnels and bridges in common.
GetTunnelBridgeDirection
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
Definition tunnelbridge_map.h:26
HasTunnelBridgeReservation
bool HasTunnelBridgeReservation(Tile t)
Get the reservation state of the rail tunnel/bridge.
Definition tunnelbridge_map.h:91
GetTunnelBridgeTransportType
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
Definition tunnelbridge_map.h:39
GetOtherTunnelBridgeEnd
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
Definition tunnelbridge_map.h:78
EnsureNoVehicleOnGround
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition vehicle.cpp:527
VehicleEnterDepot
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1520
EnsureNoTrainOnTrackBits
CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
Tests if a vehicle interacts with the specified track bits.
Definition vehicle.cpp:575
TunnelBridgeIsFree
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:551
VehState::Hidden
@ Hidden
Vehicle is not visible.
VehState::Stopped
@ Stopped
Vehicle is stopped by the player.
vehicle_func.h
Functions related to vehicles.
HasVehicleOnTile
bool HasVehicleOnTile(TileIndex tile, UnaryPred &&predicate)
Loop over vehicles on a tile, and check whether a predicate is true for any of them.
Definition vehicle_func.h:106
VEH_SHIP
@ VEH_SHIP
Ship vehicle type.
Definition vehicle_type.h:27
VEH_TRAIN
@ VEH_TRAIN
Train vehicle type.
Definition vehicle_type.h:25
AddSortableSpriteToDraw
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:663
DrawGroundSprite
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition viewport.cpp:579
viewport_func.h
Functions related to (drawing on) viewports.
BB_HEIGHT_UNDER_BRIDGE
static constexpr int BB_HEIGHT_UNDER_BRIDGE
Some values for constructing bounding boxes (BB).
Definition viewport_type.h:92
water.h
Functions related to water (management)
TileLoop_Water
void TileLoop_Water(TileIndex tile)
Let a water tile floods its diagonal adjoining tiles called from tunnelbridge_cmd,...
Definition water_cmd.cpp:1269
FLOOD_NONE
@ FLOOD_NONE
The tile does not flood neighboured tiles.
Definition water.h:20
GetFloodingBehaviour
FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
Returns the behaviour of a tile during flooding.
Definition water_cmd.cpp:1115
CheckForDockingTile
void CheckForDockingTile(TileIndex t)
Mark the supplied tile as a docking tile if it is suitable for docking.
Definition water_cmd.cpp:194
MakeShore
void MakeShore(Tile t)
Helper function to make a coast tile.
Definition water_map.h:383
IsDockingTile
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:373
SetDockingTile
void SetDockingTile(Tile t, bool b)
Set the docking tile state of a tile.
Definition water_map.h:363
InvalidateWindowData
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:3297
WC_VEHICLE_DEPOT
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition window_type.h:356
WC_BUILD_VEHICLE
@ WC_BUILD_VEHICLE
Build vehicle; Window numbers:
Definition window_type.h:394
yapf_cache.h
Entry point for OpenTTD to YAPF's cache.
YapfNotifyTrackLayoutChange
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.
Definition yapf_rail.cpp:665