OpenTTD Source 20260531-master-g0e951f3528
waypoint_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
9
10#include "stdafx.h"
11
12#include "command_func.h"
13#include "landscape.h"
14#include "bridge_map.h"
15#include "town.h"
16#include "waypoint_base.h"
19#include "tilehighlight_func.h"
20#include "strings_func.h"
21#include "viewport_func.h"
22#include "viewport_kdtree.h"
23#include "station_kdtree.h"
24#include "window_func.h"
26#include "vehicle_func.h"
27#include "string_func.h"
28#include "company_func.h"
29#include "newgrf_debug.h"
30#include "newgrf_station.h"
31#include "newgrf_roadstop.h"
32#include "company_base.h"
33#include "water.h"
34#include "company_gui.h"
35#include "waypoint_cmd.h"
36#include "landscape_cmd.h"
37#include "station_layout_type.h"
38
39#include "widgets/misc_widget.h"
40
41#include "table/strings.h"
42
43#include "safeguards.h"
44
49{
50 Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
51 if (this->sign.kdtree_valid) _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeWaypoint(this->index));
52
53 this->sign.UpdatePosition(pt.x, pt.y - 32 * ZOOM_BASE, GetString(STR_WAYPOINT_NAME, this->index));
54
55 _viewport_sign_kdtree.Insert(ViewportSignKdtreeItem::MakeWaypoint(this->index));
56
57 /* Recenter viewport */
58 InvalidateWindowData(WindowClass::WaypointView, this->index);
59}
60
66{
67 if (this->xy == new_xy) return;
68
69 this->BaseStation::MoveSign(new_xy);
70}
71
80static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile, StringID str, CompanyID cid, bool is_road)
81{
82 Waypoint *best = nullptr;
83 uint thres = 8;
84
85 for (Waypoint *wp : Waypoint::Iterate()) {
86 if (!wp->IsInUse() && wp->string_id == str && wp->owner == cid && HasBit(wp->waypoint_flags, WPF_ROAD) == is_road) {
87 uint cur_dist = DistanceManhattan(tile, wp->xy);
88
89 if (cur_dist < thres) {
90 thres = cur_dist;
91 best = wp;
92 }
93 }
94 }
95
96 return best;
97}
98
107{
108 /* The axis for rail waypoints is easy. */
109 if (IsRailWaypointTile(tile)) return GetRailStationAxis(tile);
110
111 /* Non-plain rail type, no valid axis for waypoints. */
113
114 switch (GetTrackBits(tile)) {
115 case TRACK_BIT_X: return Axis::X;
116 case TRACK_BIT_Y: return Axis::Y;
117 default: return Axis::Invalid;
118 }
119}
120
129{
130 /* The axis for existing road waypoints is easy. */
131 if (IsRoadWaypointTile(tile)) return GetDriveThroughStopAxis(tile);
132
133 /* Non-plain road type, no valid axis for waypoints. */
134 if (!IsNormalRoadTile(tile)) return Axis::Invalid;
135
136 RoadBits bits = GetAllRoadBits(tile);
137
138 if (!bits.Any(ROAD_Y)) return Axis::X;
139 if (!bits.Any(ROAD_X)) return Axis::Y;
140
141 return Axis::Invalid;
142}
143
144extern CommandCost ClearTile_Station(TileIndex tile, DoCommandFlags flags);
145
153static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *waypoint)
154{
155 /* if waypoint is set, then we have special handling to allow building on top of already existing waypoints.
156 * so waypoint points to StationID::Invalid() if we can build on any waypoint.
157 * Or it points to a waypoint if we're only allowed to build on exactly that waypoint. */
158 if (waypoint != nullptr && IsTileType(tile, TileType::Station)) {
159 if (!IsRailWaypoint(tile)) {
160 return ClearTile_Station(tile, DoCommandFlag::Auto); // get error message
161 } else {
162 StationID wp = GetStationIndex(tile);
163 if (*waypoint == StationID::Invalid()) {
164 *waypoint = wp;
165 } else if (*waypoint != wp) {
166 return CommandCost(STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING);
167 }
168 }
169 }
170
171 if (GetAxisForNewRailWaypoint(tile) != axis) return CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK);
172
173 Owner owner = GetTileOwner(tile);
174 CommandCost ret = CheckOwnership(owner);
175 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile);
176 if (ret.Failed()) return ret;
177
178 Slope tileh = GetTileSlope(tile);
179 if (tileh != SLOPE_FLAT &&
180 (!_settings_game.construction.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << to_underlying(axis))) || !(tileh & ~(0x3 << to_underlying(axis))))) {
181 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
182 }
183
184 return CommandCost();
185}
186
187extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road);
188extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta);
189extern CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, const RoadStopSpec *roadstopspec, Axis axis, DiagDirection ddir, StationID *est, RoadType rt, Money unit_cost);
192
193extern CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlags flags, int replacement_spec_index);
194
196template <>
198{
199 /* Use predefined layout if it exists. Mask bit zero which will indicate axis. */
200 if (!stl.layout.empty()) return this->stl.layout[this->position] & ~1;
201
202 return 0;
203}
204
219CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axis axis, uint8_t width, uint8_t height, StationClassID spec_class, uint16_t spec_index, StationID station_to_join, bool adjacent)
220{
221 if (!IsValidAxis(axis)) return CMD_ERROR;
222 /* Check if the given station class is valid */
223 if (spec_class.base() >= StationClass::GetClassCount()) return CMD_ERROR;
224 const StationClass *cls = StationClass::Get(spec_class);
225 if (!IsWaypointClass(*cls)) return CMD_ERROR;
226 if (spec_index >= cls->GetSpecCount()) return CMD_ERROR;
227
228 /* The number of parts to build */
229 uint8_t count = axis == Axis::X ? height : width;
230
231 if ((axis == Axis::X ? width : height) != 1) return CMD_ERROR;
232 if (count == 0 || count > _settings_game.station.station_spread) return CMD_ERROR;
233
234 bool reuse = (station_to_join != NEW_STATION);
235 if (!reuse) station_to_join = StationID::Invalid();
236 bool distant_join = (station_to_join != StationID::Invalid());
237
238 if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR;
239
240 TileArea new_location(start_tile, width, height);
241
242 /* only AddCost for non-existing waypoints */
244 for (TileIndex cur_tile : new_location) {
246 }
247
248 /* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
249 StationID est = StationID::Invalid();
250
251 const StationSpec *spec = StationClass::Get(spec_class)->GetSpec(spec_index);
253
254 /* Check whether the tiles we're building on are valid rail or not. */
255 TileIndexDiff offset = TileOffsByAxis(OtherAxis(axis));
256 for (auto [i, it, tile] = std::make_tuple(0, stl.begin(), start_tile); i < count; ++i, ++it, tile += offset) {
257 CommandCost ret = IsValidTileForWaypoint(tile, axis, &est);
258 if (ret.Failed()) return ret;
259
260 StationGfx gfx = *it + to_underlying(axis);
261 if (spec != nullptr) {
262 uint32_t platinfo = GetPlatformInfo(gfx, count, 1, i, 0, false);
263 /* As the station is not yet completely finished, the station does not yet exist. */
264 uint16_t callback = GetStationCallback(CBID_STATION_BUILD_TILE_LAYOUT, platinfo, 0, spec, nullptr, INVALID_TILE);
265 if (callback != CALLBACK_FAILED && callback <= UINT8_MAX) gfx = (callback & ~1) + to_underlying(axis);
266 }
267
269 if (ret.Failed()) return ret;
270 }
271
272 Waypoint *wp = nullptr;
273 CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, new_location, &wp, false);
274 if (ret.Failed()) return ret;
275
276 /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
277 TileIndex center_tile = start_tile + (count / 2) * offset;
278 if (wp == nullptr && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT, _current_company, false);
279
280 if (wp != nullptr) {
281 /* Reuse an existing waypoint. */
282 if (wp->owner != _current_company) return CommandCost(STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT);
283
284 /* Check if we want to expand an already existing waypoint. */
285 if (wp->train_station.tile != INVALID_TILE) {
286 ret = CanExpandRailStation(wp, new_location);
287 if (ret.Failed()) return ret;
288 }
289
290 ret = wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TEST);
291 if (ret.Failed()) return ret;
292 } else {
293 /* Check if we can create a new waypoint. */
294 if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING);
295 }
296
297 /* Check if we can allocate a custom spec to this waypoint. */
298 auto specindex = AllocateSpecToStation(spec, wp);
299 if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS);
300
301 if (flags.Test(DoCommandFlag::Execute)) {
302 if (wp == nullptr) {
303 wp = Waypoint::Create(start_tile);
304 } else if (!wp->IsInUse()) {
305 /* Move existing (recently deleted) waypoint to the new location */
306 wp->xy = start_tile;
307 }
308 wp->owner = GetTileOwner(start_tile);
309
310 wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY);
311 if (specindex.has_value()) AssignSpecToStation(spec, wp, *specindex);
312
313 wp->delete_ctr = 0;
316 wp->string_id = STR_SV_STNAME_WAYPOINT;
317 wp->train_station = new_location;
318
319 if (wp->town == nullptr) MakeDefaultName(wp);
320
321 wp->UpdateVirtCoord();
322
323 Company *c = Company::Get(wp->owner);
324 for (auto [i, it, tile] = std::make_tuple(0, stl.begin(), start_tile); i < count; ++i, ++it, tile += offset) {
325 uint8_t old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0;
327 bool reserved = IsTileType(tile, TileType::Railway) ?
330 MakeRailWaypoint(tile, wp->owner, wp->index, axis, *it, GetRailType(tile));
331 SetCustomStationSpecIndex(tile, *specindex);
332
333 if (spec != nullptr) {
334 uint32_t platinfo = GetPlatformInfo(*it + to_underlying(axis), count, 1, i, 0, false);
335
336 /* As the station is not yet completely finished, the station does not yet exist. */
337 uint16_t callback = GetStationCallback(CBID_STATION_BUILD_TILE_LAYOUT, platinfo, 0, spec, nullptr, tile);
338 if (callback != CALLBACK_FAILED) {
339 if (callback <= UINT8_MAX) {
340 SetStationGfx(tile, (callback & ~1) + to_underlying(axis));
341 } else {
343 }
344 }
345 }
346
347 SetRailStationTileFlags(tile, spec);
348
349 SetRailStationReservation(tile, reserved);
351
352 DeallocateSpecFromStation(wp, old_specindex);
353 if (spec == nullptr) DeleteNewGRFInspectWindow(GrfSpecFeature::Stations, tile);
355 }
357 }
358
359 return cost;
360}
361
375CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axis axis, uint8_t width, uint8_t height, RoadStopClassID spec_class, uint16_t spec_index, StationID station_to_join, bool adjacent)
376{
377 if (!IsValidAxis(axis)) return CMD_ERROR;
378 /* Check if the given station class is valid */
379 if (spec_class.base() >= RoadStopClass::GetClassCount()) return CMD_ERROR;
380 const RoadStopClass *cls = RoadStopClass::Get(spec_class);
381 if (!IsWaypointClass(*cls)) return CMD_ERROR;
382 if (spec_index >= cls->GetSpecCount()) return CMD_ERROR;
383
384 const RoadStopSpec *roadstopspec = RoadStopClass::Get(spec_class)->GetSpec(spec_index);
385
386 /* The number of parts to build */
387 uint8_t count = axis == Axis::X ? height : width;
388
389 if ((axis == Axis::X ? width : height) != 1) return CMD_ERROR;
390 if (count == 0 || count > _settings_game.station.station_spread) return CMD_ERROR;
391
392 bool reuse = (station_to_join != NEW_STATION);
393 if (!reuse) station_to_join = StationID::Invalid();
394 bool distant_join = (station_to_join != StationID::Invalid());
395
396 if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR;
397
398 TileArea roadstop_area(start_tile, width, height);
399
400 /* Total road stop cost. */
401 Money unit_cost;
402 if (roadstopspec != nullptr) {
403 unit_cost = roadstopspec->GetBuildCost(Price::BuildStationTruck);
404 } else {
405 unit_cost = _price[Price::BuildStationTruck];
406 }
407 StationID est = StationID::Invalid();
408 CommandCost cost = CalculateRoadStopCost(roadstop_area, flags, true, StationType::RoadWaypoint, roadstopspec, axis, AxisToDiagDir(axis), &est, INVALID_ROADTYPE, unit_cost);
409 if (cost.Failed()) return cost;
410
411 Waypoint *wp = nullptr;
412 CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, roadstop_area, &wp, true);
413 if (ret.Failed()) return ret;
414
415 /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
416 TileIndex center_tile = start_tile + (count / 2) * TileOffsByAxis(OtherAxis(axis));
417 if (wp == nullptr && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT, _current_company, true);
418
419 if (wp != nullptr) {
420 /* Reuse an existing waypoint. */
421 if (!HasBit(wp->waypoint_flags, WPF_ROAD)) return CMD_ERROR;
422 if (wp->owner != _current_company) return CommandCost(STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT);
423
424 ret = wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TEST);
425 if (ret.Failed()) return ret;
426 } else {
427 /* Check if we can create a new waypoint. */
428 if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING);
429 }
430
431 /* Check if we can allocate a custom spec to this waypoint. */
432 auto specindex = AllocateSpecToRoadStop(roadstopspec, wp);
433 if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS);
434
435 if (flags.Test(DoCommandFlag::Execute)) {
436 if (wp == nullptr) {
437 wp = Waypoint::Create(start_tile);
439 } else if (!wp->IsInUse()) {
440 /* Move existing (recently deleted) waypoint to the new location */
441 wp->xy = start_tile;
442 }
444
445 wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY);
446 if (specindex.has_value()) AssignSpecToRoadStop(roadstopspec, wp, *specindex);
447
448 if (roadstopspec != nullptr) {
449 /* Include this road stop spec's animation trigger bitmask
450 * in the station's cached copy. */
451 wp->cached_roadstop_anim_triggers.Set(roadstopspec->animation.triggers);
452 }
453
454 wp->delete_ctr = 0;
457 wp->string_id = STR_SV_STNAME_WAYPOINT;
458
459 if (wp->town == nullptr) MakeDefaultName(wp);
460
461 wp->UpdateVirtCoord();
462
463 /* Check every tile in the area. */
464 for (TileIndex cur_tile : roadstop_area) {
465 /* Get existing road types and owners before any tile clearing */
466 RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RoadTramType::Road) : INVALID_ROADTYPE;
467 RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RoadTramType::Tram) : INVALID_ROADTYPE;
468 Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RoadTramType::Road) : _current_company;
469 Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RoadTramType::Tram) : _current_company;
470
471 if (IsRoadWaypointTile(cur_tile)) {
472 RemoveRoadWaypointStop(cur_tile, flags, *specindex);
473 }
474
475 wp->road_waypoint_area.Add(cur_tile);
476
477 wp->rect.BeforeAddTile(cur_tile, StationRect::ADD_TRY);
478
479 /* Update company infrastructure counts. If the current tile is a normal road tile, remove the old
480 * bits first. */
481 if (IsNormalRoadTile(cur_tile)) {
482 UpdateCompanyRoadInfrastructure(road_rt, road_owner, -static_cast<int>(GetRoadBits(cur_tile, RoadTramType::Road).Count()));
483 UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -static_cast<int>(GetRoadBits(cur_tile, RoadTramType::Tram).Count()));
484 }
485
488
489 MakeDriveThroughRoadStop(cur_tile, wp->owner, road_owner, tram_owner, wp->index, StationType::RoadWaypoint, road_rt, tram_rt, axis);
490 SetCustomRoadStopSpecIndex(cur_tile, *specindex);
491 if (roadstopspec != nullptr) wp->SetRoadStopRandomBits(cur_tile, 0);
492
493 Company::Get(wp->owner)->infrastructure.station++;
494
495 MarkTileDirtyByTile(cur_tile);
496 }
498 }
499 return cost;
500}
501
508CommandCost CmdBuildBuoy(DoCommandFlags flags, TileIndex tile)
509{
510 if (!HasTileWaterGround(tile)) return CommandCost(STR_ERROR_SITE_UNSUITABLE);
511 if (CommandCost ret = IsBuoyBridgeAboveOk(tile); ret.Failed()) return ret;
512
513 if (!IsTileFlat(tile)) return CommandCost(STR_ERROR_SITE_UNSUITABLE);
514
515 /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
516 Waypoint *wp = FindDeletedWaypointCloseTo(tile, STR_SV_STNAME_BUOY, OWNER_NONE, false);
517 if (wp == nullptr && !Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING);
518
520 if (!IsWaterTile(tile)) {
521 CommandCost ret = Command<Commands::LandscapeClear>::Do(flags | DoCommandFlag::Auto, tile);
522 if (ret.Failed()) return ret;
523 cost.AddCost(ret.GetCost());
524 }
525
526 if (flags.Test(DoCommandFlag::Execute)) {
527 if (wp == nullptr) {
528 wp = Waypoint::Create(tile);
529 } else {
530 /* Move existing (recently deleted) buoy to the new location */
531 wp->xy = tile;
532 InvalidateWindowData(WindowClass::WaypointView, wp->index);
533 }
534 wp->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
535
536 wp->string_id = STR_SV_STNAME_BUOY;
537
539 wp->owner = OWNER_NONE;
540
542
543 if (wp->town == nullptr) MakeDefaultName(wp);
544
545 MakeBuoy(tile, wp->index, GetWaterClass(tile));
549
550 wp->UpdateVirtCoord();
551 InvalidateWindowData(WindowClass::WaypointView, wp->index);
552 }
553
554 return cost;
555}
556
564CommandCost RemoveBuoy(TileIndex tile, DoCommandFlags flags)
565{
566 /* XXX: strange stuff, allow clearing as invalid company when clearing landscape */
568
569 Waypoint *wp = Waypoint::GetByTile(tile);
570
571 if (HasStationInUse(wp->index, false, _current_company)) return CommandCost(STR_ERROR_BUOY_IS_IN_USE);
572 /* remove the buoy if there is a ship on tile when company goes bankrupt... */
573 if (!flags.Test(DoCommandFlag::Bankrupt)) {
575 if (ret.Failed()) return ret;
576 }
577
578 if (flags.Test(DoCommandFlag::Execute)) {
580
581 InvalidateWindowData(WindowClass::WaypointView, wp->index);
582
583 /* We have to set the water tile's state to the same state as before the
584 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
585 * remove it and flood the land (if the canal edge is at level 0) */
586 MakeWaterKeepingClass(tile, GetTileOwner(tile));
587
588 wp->rect.AfterRemoveTile(wp, tile);
589
590 wp->UpdateVirtCoord();
591 wp->delete_ctr = 0;
592 }
593
595}
596
602static bool IsUniqueWaypointName(const std::string &name)
603{
604 for (const Waypoint *wp : Waypoint::Iterate()) {
605 if (!wp->name.empty() && wp->name == name) return false;
606 }
607
608 return true;
609}
610
618CommandCost CmdRenameWaypoint(DoCommandFlags flags, StationID waypoint_id, const std::string &text)
619{
620 Waypoint *wp = Waypoint::GetIfValid(waypoint_id);
621 if (wp == nullptr) return CMD_ERROR;
622
623 if (wp->owner != OWNER_NONE) {
625 if (ret.Failed()) return ret;
626 }
627
628 bool reset = text.empty();
629
630 if (!reset) {
632 if (!IsUniqueWaypointName(text)) return CommandCost(STR_ERROR_NAME_MUST_BE_UNIQUE);
633 }
634
635 if (flags.Test(DoCommandFlag::Execute)) {
636 if (reset) {
637 wp->name.clear();
638 } else {
639 wp->name = text;
640 }
641
642 wp->UpdateVirtCoord();
643 }
644 return CommandCost();
645}
646
654std::tuple<CommandCost, StationID> CmdMoveWaypointName(DoCommandFlags flags, StationID waypoint_id, TileIndex tile)
655{
656 Waypoint *wp = Waypoint::GetIfValid(waypoint_id);
657 if (wp == nullptr) return { CMD_ERROR, StationID::Invalid() };
658
659 if (wp->owner != OWNER_NONE) {
661 if (ret.Failed()) return { ret, StationID::Invalid() };
662 }
663
664 const StationRect *r = &wp->rect;
665 if (!r->PtInExtendedRect(TileX(tile), TileY(tile))) {
666 return { CommandCost(STR_ERROR_SITE_UNSUITABLE), StationID::Invalid() };
667 }
668
669 bool other_station = false;
670 /* Check if the tile is the base tile of another station */
671 ForAllStationsRadius(tile, 0, [&](BaseStation *st) {
672 if (st != nullptr) {
673 if (st != wp && st->xy == tile) other_station = true;
674 }
675 });
676 if (other_station) return { CommandCost(STR_ERROR_SITE_UNSUITABLE), StationID::Invalid() };
677
678 if (flags.Test(DoCommandFlag::Execute)) {
679 wp->MoveSign(tile);
680
681 wp->UpdateVirtCoord();
682 }
683 return { CommandCost(), waypoint_id };
684}
685
691void CcMoveWaypointName(Commands, const CommandCost &result, StationID waypoint_id)
692{
693 if (result.Failed()) return;
694
696 Waypoint *wp = Waypoint::Get(waypoint_id);
698}
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Map accessor functions for bridges.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
const Tspec * GetSpec(uint index) const
Get a spec from the class at a given index.
uint GetSpecCount() const
Get the number of allocated specs within the class.
static NewGRFClass * Get(StationClassID class_index)
const RailStationTileLayout & stl
Station tile layout being iterated.
uint position
Position within iterator.
StationGfx operator*() const
Dereference operator.
static Date date
Current date in days (day counter).
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Auto
don't allow building on structures
@ Execute
execute the given command
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
Commands
List of commands.
Definition of stuff that is very close to a company, like the company struct itself.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
static constexpr Owner OWNER_NONE
The tile has no ownership.
bool IsValidAxis(Axis d)
Checks if an integer value is a valid Axis.
DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
Axis OtherAxis(Axis a)
Select the other axis as provided.
Axis
Enumeration for the two axis X and Y.
@ X
The X axis.
@ Invalid
Flag for an invalid Axis.
@ Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:106
static const uint ROAD_STOP_TRACKBIT_FACTOR
Multiplier for how many regular track bits a bay stop counts.
@ Construction
Construction costs.
@ BuildStationTruck
Price for building lorry stations.
@ BuildWaypointBuoy
Price for building new buoys.
@ ClearWaypointBuoy
Price for destroying buoys.
@ BuildWaypointRail
Price for building new rail waypoints.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Functions related to OTTD's landscape.
Point RemapCoords2(int x, int y)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
Definition landscape.h:97
Command definitions related to landscape (slopes etc.).
#define Point
Macro that prevents name conflicts between included headers.
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:169
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:559
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
Types related to the misc widgets.
@ Stations
Stations feature.
Definition newgrf.h:78
uint8_t StationGfx
Copy from station_map.h.
@ CBID_STATION_BUILD_TILE_LAYOUT
Called when building a station to customize the tile layout.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Functions/types related to NewGRF debugging.
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
std::optional< uint8_t > AllocateSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st)
Allocate a RoadStopSpec to a Station.
void AssignSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st, uint8_t specindex)
Assign a previously allocated RoadStopSpec specindex to a Station.
NewGRF definitions and structures for road stops.
bool IsWaypointClass(const RoadStopClass &cls)
Test if a RoadStopClass is the waypoint class.
PoolID< uint16_t, struct RoadStopClassIDTag, UINT16_MAX, UINT16_MAX > RoadStopClassID
Class IDs for stations.
void AssignSpecToStation(const StationSpec *spec, BaseStation *st, uint8_t specindex)
Assign a previously allocated StationSpec specindex to a Station.
void DeallocateSpecFromStation(BaseStation *st, uint8_t specindex)
Deallocate a StationSpec from a Station.
uint32_t GetPlatformInfo(StationGfx gfx, int platforms, int length, int platform, int position, bool centred)
Evaluate a tile's position within a station, and return the result in a bit-stuffed format.
std::optional< uint8_t > AllocateSpecToStation(const StationSpec *spec, BaseStation *st)
Allocate a StationSpec to a Station.
Header file for NewGRF stations.
NewGRFClass< StationSpec, StationClassID > StationClass
Class containing information relating to station classes.
PoolID< uint16_t, struct StationClassIDTag, UINT16_MAX, UINT16_MAX > StationClassID
Class IDs for stations.
static RailTileType GetRailTileType(Tile t)
Returns the RailTileType (normal with or without signals, waypoint or depot).
Definition rail_map.h:36
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition rail_map.h:136
@ Normal
Normal rail tile without signals.
Definition rail_map.h:24
TrackBits GetRailReservationTrackBits(Tile t)
Returns the reserved track bits of the tile.
Definition rail_map.h:194
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
Update road infrastructure counts for a company.
Definition road_cmd.cpp:183
bool MayHaveRoad(Tile t)
Test whether a tile can have road/tram types.
Definition road_map.cpp:21
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:112
RoadBits GetAllRoadBits(Tile tile)
Get all set RoadBits on the given tile.
Definition road_map.h:125
RoadType GetRoadType(Tile t, RoadTramType rtt)
Get the road type for the given RoadTramType.
Definition road_map.h:175
static bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:58
Owner GetRoadOwner(Tile t, RoadTramType rtt)
Get the owner of a specific road type.
Definition road_map.h:244
static constexpr RoadBits ROAD_X
Full road along the x-axis (south-west + north-east).
Definition road_type.h:66
EnumBitSet< RoadBit, uint8_t > RoadBits
Bitset of RoadBit elements.
Definition road_type.h:64
static constexpr RoadBits ROAD_Y
Full road along the y-axis (north-west + south-east).
Definition road_type.h:67
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
@ Tram
Tram type.
Definition road_type.h:39
@ Road
Road type.
Definition road_type.h:38
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
Slope
Enumeration for the slope-type.
Definition slope_type.h:53
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:54
CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *spec, StationType type, StationGfx layout)
Test if a rail station can be built below a bridge.
CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta)
Check whether we can expand the rail part of the given station.
CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road)
Find a nearby waypoint that joins this waypoint.
CommandCost IsBuoyBridgeAboveOk(TileIndex tile)
Test if a buoy can be built below a bridge.
CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlags flags, int replacement_spec_index=-1)
Remove a road waypoint.
bool HasStationInUse(StationID station, bool include_company, CompanyID company)
Tests whether the company's vehicles have this station in orders.
void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec)
Set rail station tile flags for the given tile.
CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, const RoadStopSpec *roadstopspec, Axis axis, DiagDirection ddir, StationID *station, RoadType rt, Money unit_cost)
Calculates cost of new road stops within the area.
@ Count
by amount of cargo
Declarations for accessing the k-d tree of stations.
void ForAllStationsRadius(TileIndex center, uint radius, Func func)
Call a function on all stations whose sign is within a radius of a center tile.
Functions related to station layouts.
void SetStationGfx(Tile t, StationGfx gfx)
Set the station graphics of this tile.
Definition station_map.h:80
void SetCustomStationSpecIndex(Tile t, uint8_t specindex)
Set the custom station spec for this tile.
bool IsRailWaypointTile(Tile t)
Is this tile a station tile and a rail waypoint?
void MakeDriveThroughRoadStop(Tile t, Owner station, Owner road, Owner tram, StationID sid, StationType rst, RoadType road_rt, RoadType tram_rt, Axis a)
Make the given tile a drivethrough roadstop tile.
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
bool HasStationTileRail(Tile t)
Has this station tile a rail?
uint GetCustomStationSpecIndex(Tile t)
Get the custom station spec for this tile.
bool IsRailWaypoint(Tile t)
Is this station tile a rail waypoint?
void SetRailStationReservation(Tile t, bool b)
Set the reservation state of the rail station.
Axis GetRailStationAxis(Tile t)
Get the rail direction of a rail station.
void MakeRailWaypoint(Tile t, Owner o, StationID sid, Axis a, uint8_t section, RailType rt)
Make the given tile a rail waypoint tile.
bool IsRoadWaypointTile(Tile t)
Is this tile a station tile and a road waypoint?
Axis GetDriveThroughStopAxis(Tile t)
Gets the axis of the drive through stop.
void MakeBuoy(Tile t, StationID sid, WaterClass wc)
Make the given tile a buoy tile.
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
void SetCustomRoadStopSpecIndex(Tile t, uint8_t specindex)
Set the custom road stop spec for this tile.
@ Dock
Station with a dock.
@ TruckStop
Station with truck stops.
@ Train
Station with train station.
@ BusStop
Station with bus stops.
StationType
Station types.
@ RailWaypoint
Waypoint for trains.
@ RoadWaypoint
Waypoint for trucks and busses.
static const uint MAX_LENGTH_STATION_NAME_CHARS
The maximum length of a station name in characters including '\0'.
Definition of base types and functions in a cross-platform compatible way.
size_t Utf8StringLength(std::string_view str)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition string.cpp:351
Functions related to low-level strings.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
Base class for all station-ish types.
StringID string_id
Default name (town area) of station.
TileIndex xy
Base tile of the station.
virtual void MoveSign(TileIndex new_xy)
Move this station's main coordinate somewhere else.
StationFacilities facilities
The facilities that this station has.
TileArea train_station
Tile area the train 'station' part covers.
Owner owner
The owner of this station.
uint8_t delete_ctr
Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is ...
StationAnimationTriggers cached_roadstop_anim_triggers
NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing sh...
StationRect rect
NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions.
bool IsInUse() const
Check whether the base station currently is in use; in use means that it is not scheduled for deletio...
Town * town
The town this station is associated with.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
TrackedViewportSign sign
NOSAVE: Dimensions of sign.
TimerGameCalendar::Date build_date
Date of construction.
std::string name
Custom name.
uint32_t station
Count of company owned station tiles.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
T y
Y coordinate.
T x
X coordinate.
uint32_t grfid
grfid that introduced this entity.
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition tilearea.cpp:43
TileIndex tile
The base tile of the area.
static Company * Get(auto index)
Road stop specification.
Money GetBuildCost(Price category) const
Get the cost for building a road stop of this type.
static Waypoint * Create(Targs &&... args)
static Pool::IterateWrapper< Waypoint > Iterate(size_t from=0)
static Waypoint * Get(auto index)
static Waypoint * GetIfValid(auto index)
StationRect - used to track station spread out rectangle - cheaper than scanning whole map.
bool PtInExtendedRect(int x, int y, int distance=0) const
Determines whether a given point (x, y) is within a certain distance of the station rectangle.
Definition station.cpp:567
Station specification.
CargoGRFFileProps grf_prop
Link to NewGRF.
Representation of a waypoint.
TileArea road_waypoint_area
Tile area the road waypoint part covers.
uint16_t waypoint_flags
Waypoint flags, see WaypointFlags.
void MoveSign(TileIndex new_xy) override
Move the waypoint main coordinate somewhere else.
void UpdateVirtCoord() override
Update the virtual coords needed to draw the waypoint sign.
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition tile_map.cpp:94
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
@ Station
A tile of a station or airport.
Definition tile_type.h:54
@ Railway
A tile with railway.
Definition tile_type.h:50
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
Definition of the game-calendar-timer.
Base of the town class.
void MakeDefaultName(T *obj)
Set the default name for a depot/waypoint.
Definition town.h:333
Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track Axis::X -> TRACK_X Axis::Y -> TRACK_Y Uses the fact that t...
Definition track_func.h:66
@ TRACK_BIT_Y
Y-axis track.
Definition track_type.h:45
@ TRACK_BIT_X
X-axis track.
Definition track_type.h:44
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition vehicle.cpp:557
Functions related to vehicles.
void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel)
Select or deselect waypoint for coverage area highlight.
Functions related to (drawing on) viewports.
Declarations for accessing the k-d tree of viewports.
Functions related to water management.
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:98
void CheckForDockingTile(TileIndex t)
Mark the supplied tile as a docking tile if it is suitable for docking.
bool HasTileWaterGround(Tile t)
Checks whether the tile has water at the ground.
Definition water_map.h:353
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:114
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:192
Handles dividing the water in the map into regions to assist pathfinding.
Base of waypoints.
@ WPF_ROAD
This is a road waypoint.
static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *waypoint)
Check whether the given tile is suitable for a waypoint.
CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axis axis, uint8_t width, uint8_t height, RoadStopClassID spec_class, uint16_t spec_index, StationID station_to_join, bool adjacent)
Build a road waypoint on an existing road.
CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axis axis, uint8_t width, uint8_t height, StationClassID spec_class, uint16_t spec_index, StationID station_to_join, bool adjacent)
Convert existing rail to waypoint.
void CcMoveWaypointName(Commands, const CommandCost &result, StationID waypoint_id)
Callback function that is called after a name is moved.
CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *spec, StationType type, StationGfx layout)
Test if a rail station can be built below a bridge.
std::tuple< CommandCost, StationID > CmdMoveWaypointName(DoCommandFlags flags, StationID waypoint_id, TileIndex tile)
Move a waypoint name.
CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta)
Check whether we can expand the rail part of the given station.
Axis GetAxisForNewRailWaypoint(TileIndex tile)
Get the axis for a new rail waypoint.
Axis GetAxisForNewRoadWaypoint(TileIndex tile)
Get the axis for a new road waypoint.
CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road)
Find a nearby waypoint that joins this waypoint.
CommandCost IsBuoyBridgeAboveOk(TileIndex tile)
Test if a buoy can be built below a bridge.
CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlags flags, int replacement_spec_index)
Remove a road waypoint.
CommandCost RemoveBuoy(TileIndex tile, DoCommandFlags flags)
Remove a buoy.
CommandCost ClearTile_Station(TileIndex tile, DoCommandFlags flags)
Tile callback function signature for clearing a tile.
CommandCost CmdRenameWaypoint(DoCommandFlags flags, StationID waypoint_id, const std::string &text)
Rename a waypoint.
CommandCost CmdBuildBuoy(DoCommandFlags flags, TileIndex tile)
Build a buoy.
static bool IsUniqueWaypointName(const std::string &name)
Check whether the name is unique amongst the waypoints.
static Waypoint * FindDeletedWaypointCloseTo(TileIndex tile, StringID str, CompanyID cid, bool is_road)
Find a deleted waypoint close to a tile.
CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, const RoadStopSpec *roadstopspec, Axis axis, DiagDirection ddir, StationID *est, RoadType rt, Money unit_cost)
Calculates cost of new road stops within the area.
Command definitions related to waypoints.
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:3322
Window functions not directly related to making/drawing windows.
Entry point for OpenTTD to YAPF's cache.
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.