2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file script_tilelist.cpp Implementation of ScriptTileList and friends. */
10 #include "../../stdafx.h"
11 #include "script_tilelist.hpp"
12 #include "script_industry.hpp"
13 #include "../../industry.h"
14 #include "../../station_base.h"
16 #include "../../safeguards.h"
18 void ScriptTileList::AddRectangle(TileIndex t1
, TileIndex t2
)
20 if (!::IsValidTile(t1
)) return;
21 if (!::IsValidTile(t2
)) return;
24 for (TileIndex t
: ta
) this->AddItem(t
.base());
27 void ScriptTileList::AddTile(TileIndex tile
)
29 if (!::IsValidTile(tile
)) return;
31 this->AddItem(tile
.base());
34 void ScriptTileList::RemoveRectangle(TileIndex t1
, TileIndex t2
)
36 if (!::IsValidTile(t1
)) return;
37 if (!::IsValidTile(t2
)) return;
40 for (TileIndex t
: ta
) this->RemoveItem(t
.base());
43 void ScriptTileList::RemoveTile(TileIndex tile
)
45 if (!::IsValidTile(tile
)) return;
47 this->RemoveItem(tile
.base());
51 * Helper to get list of tiles that will cover an industry's production or acceptance.
52 * @param i Industry in question
53 * @param radius Catchment radius to test
54 * @param bta BitmapTileArea to fill
56 static void FillIndustryCatchment(const Industry
*i
, SQInteger radius
, BitmapTileArea
&bta
)
58 for (TileIndex cur_tile
: i
->location
) {
59 if (!::IsTileType(cur_tile
, MP_INDUSTRY
) || ::GetIndustryIndex(cur_tile
) != i
->index
) continue;
61 int tx
= TileX(cur_tile
);
62 int ty
= TileY(cur_tile
);
63 for (int y
= -radius
; y
<= radius
; y
++) {
64 if (ty
+ y
< 0 || ty
+ y
> (int)Map::MaxY()) continue;
65 for (int x
= -radius
; x
<= radius
; x
++) {
66 if (tx
+ x
< 0 || tx
+ x
> (int)Map::MaxX()) continue;
67 TileIndex tile
= TileXY(tx
+ x
, ty
+ y
);
68 if (!IsValidTile(tile
)) continue;
69 if (::IsTileType(tile
, MP_INDUSTRY
) && ::GetIndustryIndex(tile
) == i
->index
) continue;
76 ScriptTileList_IndustryAccepting::ScriptTileList_IndustryAccepting(IndustryID industry_id
, SQInteger radius
)
78 if (!ScriptIndustry::IsValidIndustry(industry_id
) || radius
<= 0) return;
80 const Industry
*i
= ::Industry::Get(industry_id
);
82 /* Check if this industry is only served by its neutral station */
83 if (i
->neutral_station
!= nullptr && !_settings_game
.station
.serve_neutral_industries
) return;
85 /* Check if this industry accepts anything */
86 if (!i
->IsCargoAccepted()) return;
88 if (!_settings_game
.station
.modified_catchment
) radius
= CA_UNMODIFIED
;
90 BitmapTileArea
bta(TileArea(i
->location
).Expand(radius
));
91 FillIndustryCatchment(i
, radius
, bta
);
93 BitmapTileIterator
it(bta
);
94 for (TileIndex cur_tile
= it
; cur_tile
!= INVALID_TILE
; cur_tile
= ++it
) {
95 /* Only add the tile if it accepts the cargo (sometimes just 1 tile of an
96 * industry triggers the acceptance). */
97 CargoArray acceptance
= ::GetAcceptanceAroundTiles(cur_tile
, 1, 1, radius
);
98 if (std::none_of(std::begin(i
->accepted
), std::end(i
->accepted
), [&acceptance
](const auto &a
) { return ::IsValidCargoID(a
.cargo
) && acceptance
[a
.cargo
] != 0; })) continue;
100 this->AddTile(cur_tile
);
104 ScriptTileList_IndustryProducing::ScriptTileList_IndustryProducing(IndustryID industry_id
, SQInteger radius
)
106 if (!ScriptIndustry::IsValidIndustry(industry_id
) || radius
<= 0) return;
108 const Industry
*i
= ::Industry::Get(industry_id
);
110 /* Check if this industry is only served by its neutral station */
111 if (i
->neutral_station
!= nullptr && !_settings_game
.station
.serve_neutral_industries
) return;
113 /* Check if this industry produces anything */
114 if (!i
->IsCargoProduced()) return;
116 if (!_settings_game
.station
.modified_catchment
) radius
= CA_UNMODIFIED
;
118 BitmapTileArea
bta(TileArea(i
->location
).Expand(radius
));
119 FillIndustryCatchment(i
, radius
, bta
);
121 BitmapTileIterator
it(bta
);
122 for (TileIndex cur_tile
= it
; cur_tile
!= INVALID_TILE
; cur_tile
= ++it
) {
123 this->AddTile(cur_tile
);
127 ScriptTileList_StationType::ScriptTileList_StationType(StationID station_id
, ScriptStation::StationType station_type
)
129 if (!ScriptStation::IsValidStation(station_id
)) return;
131 const StationRect
*rect
= &::Station::Get(station_id
)->rect
;
133 uint station_type_value
= 0;
134 /* Convert ScriptStation::StationType to ::StationType, but do it in a
135 * bitmask, so we can scan for multiple entries at the same time. */
136 if ((station_type
& ScriptStation::STATION_TRAIN
) != 0) station_type_value
|= (1 << ::STATION_RAIL
);
137 if ((station_type
& ScriptStation::STATION_TRUCK_STOP
) != 0) station_type_value
|= (1 << ::STATION_TRUCK
);
138 if ((station_type
& ScriptStation::STATION_BUS_STOP
) != 0) station_type_value
|= (1 << ::STATION_BUS
);
139 if ((station_type
& ScriptStation::STATION_AIRPORT
) != 0) station_type_value
|= (1 << ::STATION_AIRPORT
) | (1 << ::STATION_OILRIG
);
140 if ((station_type
& ScriptStation::STATION_DOCK
) != 0) station_type_value
|= (1 << ::STATION_DOCK
) | (1 << ::STATION_OILRIG
);
142 TileArea
ta(::TileXY(rect
->left
, rect
->top
), rect
->Width(), rect
->Height());
143 for (TileIndex cur_tile
: ta
) {
144 if (!::IsTileType(cur_tile
, MP_STATION
)) continue;
145 if (::GetStationIndex(cur_tile
) != station_id
) continue;
146 if (!HasBit(station_type_value
, ::GetStationType(cur_tile
))) continue;
147 this->AddTile(cur_tile
);
151 ScriptTileList_StationCoverage::ScriptTileList_StationCoverage(StationID station_id
)
153 if (!ScriptStation::IsValidStation(station_id
)) return;
155 const BitmapTileArea
&ta
= ::Station::Get(station_id
)->catchment_tiles
;
156 if (ta
.tile
== INVALID_TILE
) return;
158 BitmapTileIterator
it(ta
);
159 for (TileIndex tile
= it
; tile
!= INVALID_TILE
; tile
= ++it
) {