1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /** @file script_station.hpp Everything to query and build stations. */
9 
10 #ifndef SCRIPT_STATION_HPP
11 #define SCRIPT_STATION_HPP
12 
13 #include "script_road.hpp"
14 #include "script_basestation.hpp"
15 #include "../../station_type.h"
16 
17 /**
18  * Class that handles all station related functions.
19  * @api ai game
20  */
21 class ScriptStation : public ScriptBaseStation {
22 public:
23 	/**
24 	 * All station related error messages.
25 	 */
26 	enum ErrorMessages {
27 		/** Base for station related errors */
28 		ERR_STATION_BASE = ScriptError::ERR_CAT_STATION << ScriptError::ERR_CAT_BIT_SIZE,
29 
30 		/** The station is build too close to another station, airport or dock */
31 		ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION, // [STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT, STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK]
32 
33 		/** There are too many stations, airports and docks in the game */
34 		ERR_STATION_TOO_MANY_STATIONS,            // [STR_ERROR_TOO_MANY_STATIONS_LOADING, STR_ERROR_TOO_MANY_TRUCK_STOPS, STR_ERROR_TOO_MANY_BUS_STOPS]
35 
36 		/** There are too many stations, airports of docks in a town */
37 		ERR_STATION_TOO_MANY_STATIONS_IN_TOWN,    // [STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT]
38 	};
39 
40 	/**
41 	 * Type of stations known in the game.
42 	 */
43 	enum StationType {
44 		/* Note: these values represent part of the in-game StationFacility enum */
45 		STATION_TRAIN      = (int)::FACIL_TRAIN,      ///< Train station
46 		STATION_TRUCK_STOP = (int)::FACIL_TRUCK_STOP, ///< Truck station
47 		STATION_BUS_STOP   = (int)::FACIL_BUS_STOP,   ///< Bus station
48 		STATION_AIRPORT    = (int)::FACIL_AIRPORT,    ///< Airport
49 		STATION_DOCK       = (int)::FACIL_DOCK,       ///< Dock
50 		STATION_ANY        = STATION_TRAIN | STATION_TRUCK_STOP | STATION_BUS_STOP | STATION_AIRPORT | STATION_DOCK, ///< All station types
51 	};
52 
53 	/**
54 	 * Checks whether the given station is valid and owned by you.
55 	 * @param station_id The station to check.
56 	 * @return True if and only if the station is valid.
57 	 */
58 	static bool IsValidStation(StationID station_id);
59 
60 	/**
61 	 * Get the owner of a station.
62 	 * @param station_id The station to get the owner of.
63 	 * @pre IsValidStation(station_id).
64 	 * @return The owner the station has.
65 	 * @api -ai
66 	 */
67 	static ScriptCompany::CompanyID GetOwner(StationID station_id);
68 
69 	/**
70 	 * Get the StationID of a tile, if there is a station.
71 	 * @param tile The tile to find the stationID of
72 	 * @return StationID of the station.
73 	 * @post Use IsValidStation() to see if the station is valid.
74 	 */
75 	static StationID GetStationID(TileIndex tile);
76 
77 	/**
78 	 * See how much cargo there is waiting on a station.
79 	 * @param station_id The station to get the cargo-waiting of.
80 	 * @param cargo_id The cargo to get the cargo-waiting of.
81 	 * @pre IsValidStation(station_id).
82 	 * @pre IsValidCargo(cargo_id).
83 	 * @return The amount of units waiting at the station.
84 	 */
85 	static int32 GetCargoWaiting(StationID station_id, CargoID cargo_id);
86 
87 	/**
88 	 * See how much cargo with a specific source station there is waiting on a station.
89 	 * @param station_id The station to get the cargo-waiting of.
90 	 * @param from_station_id The source station of the cargo. Pass STATION_INVALID to get cargo of which the source has been deleted.
91 	 * @param cargo_id The cargo to get the cargo-waiting of.
92 	 * @pre IsValidStation(station_id).
93 	 * @pre IsValidStation(from_station_id) || from_station_id == STATION_INVALID.
94 	 * @pre IsValidCargo(cargo_id).
95 	 * @return The amount of units waiting at the station originating from from_station_id.
96 	 * @note source station means, the station where cargo was first loaded.
97 	 */
98 	static int32 GetCargoWaitingFrom(StationID station_id, StationID from_station_id, CargoID cargo_id);
99 
100 	/**
101 	 * See how much cargo with a specific via-station there is waiting on a station.
102 	 * @param station_id The station to get the cargo-waiting of.
103 	 * @param via_station_id The next station the cargo is going to. Pass STATION_INVALID to get waiting cargo for "via any station".
104 	 * @param cargo_id The cargo to get the cargo-waiting of.
105 	 * @pre IsValidStation(station_id).
106 	 * @pre IsValidStation(via_station_id) || via_station_id == STATION_INVALID.
107 	 * @pre IsValidCargo(cargo_id).
108 	 * @return The amount of units waiting at the station with via_station_id as next hop.
109 	 * @note if ScriptCargo.GetCargoDistributionType(cargo_id) == ScriptCargo.DT_MANUAL, then all waiting cargo will have STATION_INVALID as next hop.
110 	 */
111 	static int32 GetCargoWaitingVia(StationID station_id, StationID via_station_id, CargoID cargo_id);
112 
113 	/**
114 	 * See how much cargo with a specific via-station and source station there is waiting on a station.
115 	 * @param station_id The station to get the cargo-waiting of.
116 	 * @param from_station_id The source station of the cargo. Pass STATION_INVALID to get cargo of which the source has been deleted.
117 	 * @param via_station_id The next station the cargo is going to. Pass STATION_INVALID to get waiting cargo for "via any station".
118 	 * @param cargo_id The cargo to get the cargo-waiting of.
119 	 * @pre IsValidStation(station_id).
120 	 * @pre IsValidStation(from_station_id) || from_station_id == STATION_INVALID.
121 	 * @pre IsValidStation(via_station_id) || via_station_id == STATION_INVALID.
122 	 * @pre IsValidCargo(cargo_id).
123 	 * @return The amount of units waiting at the station with from_station_id as source and via_station_id as next hop.
124 	 * @note if ScriptCargo.GetCargoDistributionType(cargo_id) == ScriptCargo.DT_MANUAL, then all waiting cargo will have STATION_INVALID as next hop.
125 	 */
126 	static int32 GetCargoWaitingFromVia(StationID station_id, StationID from_station_id, StationID via_station_id, CargoID cargo_id);
127 
128 	/**
129 	 * See how much cargo was planned to pass (including production and consumption) this station per month.
130 	 * @param station_id The station to get the planned flow for.
131 	 * @param cargo_id The cargo type to get the planned flow for.
132 	 * @pre IsValidStation(station_id).
133 	 * @pre IsValidCargo(cargo_id).
134 	 * @return The amount of cargo units planned to pass the station per month.
135 	 */
136 	static int32 GetCargoPlanned(StationID station_id, CargoID cargo_id);
137 
138 	/**
139 	 * See how much cargo from the specified origin was planned to pass (including production and consumption) this station per month.
140 	 * @param station_id The station to get the planned flow for.
141 	 * @param from_station_id The station the cargo originates at.
142 	 * @param cargo_id The cargo type to get the planned flow for.
143 	 * @pre IsValidStation(station_id).
144 	 * @pre IsValidStation(from_station_id) || from_station_id == STATION_INVALID.
145 	 * @pre IsValidCargo(cargo_id).
146 	 * @return The amount of cargo units from the specified origin planned to pass the station per month.
147 	 */
148 	static int32 GetCargoPlannedFrom(StationID station_id, StationID from_station_id, CargoID cargo_id);
149 
150 	/**
151 	 * See how much cargo was planned to pass (including production and consumption) this station per month, heading for the specified next hop.
152 	 * @param station_id The station to get the planned flow for.
153 	 * @param via_station_id The next station the cargo will go on to.
154 	 * @param cargo_id The cargo type to get the planned flow for.
155 	 * @pre IsValidStation(station_id).
156 	 * @pre IsValidStation(via_station_id) || via_station_id == STATION_INVALID.
157 	 * @pre IsValidCargo(cargo_id).
158 	 * @return The amount of cargo units planned to pass the station per month, going via the specified next hop.
159 	 * @note Cargo planned to go "via" the same station that's being queried is actually planned to be consumed there.
160 	 */
161 	static int32 GetCargoPlannedVia(StationID station_id, StationID via_station_id, CargoID cargo_id);
162 
163 	/**
164 	 * See how much cargo from the specified origin was planned to pass this station per month,
165 	 * heading for the specified next hop.
166 	 * @param station_id The station to get the planned flow for.
167 	 * @param from_station_id The station the cargo originates at.
168 	 * @param via_station_id The next station the cargo will go on to.
169 	 * @param cargo_id The cargo type to get the planned flow for.
170 	 * @pre IsValidStation(station_id).
171 	 * @pre IsValidStation(from_station_id) || from_station_id == STATION_INVALID.
172 	 * @pre IsValidStation(via_station_id) || via_station_id == STATION_INVALID.
173 	 * @pre IsValidCargo(cargo_id).
174 	 * @return The amount of cargo units from the specified origin planned to pass the station per month, going via the specified next hop.
175 	 * @note Cargo planned to go "via" the same station that's being queried is actually planned to be consumed there.
176 	 * @note Cargo planned to pass "from" the same station that's being queried is actually produced there.
177 	 */
178 	static int32 GetCargoPlannedFromVia(StationID station_id, StationID from_station_id, StationID via_station_id, CargoID cargo_id);
179 
180 	/**
181 	 * Check whether the given cargo at the given station a rating.
182 	 * @param station_id The station to get the cargo-rating state of.
183 	 * @param cargo_id The cargo to get the cargo-rating state of.
184 	 * @pre IsValidStation(station_id).
185 	 * @pre IsValidCargo(cargo_id).
186 	 * @return True if the cargo has a rating, otherwise false.
187 	 */
188 	static bool HasCargoRating(StationID station_id, CargoID cargo_id);
189 
190 	/**
191 	 * See how high the rating is of a cargo on a station.
192 	 * @param station_id The station to get the cargo-rating of.
193 	 * @param cargo_id The cargo to get the cargo-rating of.
194 	 * @pre IsValidStation(station_id).
195 	 * @pre IsValidCargo(cargo_id).
196 	 * @pre HasCargoRating(station_id, cargo_id).
197 	 * @return The rating in percent of the cargo on the station.
198 	 */
199 	static int32 GetCargoRating(StationID station_id, CargoID cargo_id);
200 
201 	/**
202 	 * Get the coverage radius of this type of station.
203 	 * @param station_type The type of station.
204 	 * @pre station_type != STATION_AIRPORT.
205 	 * @return The radius in tiles.
206 	 * @note Coverage radius of airports needs to be requested via ScriptAirport::GetAirportCoverageRadius(), as it requires AirportType.
207 	 */
208 	static int32 GetCoverageRadius(ScriptStation::StationType station_type);
209 
210 	/**
211 	 * Get the coverage radius of this station.
212 	 * @param station_id The station to get the coverage radius of.
213 	 * @pre IsValidStation(station_id).
214 	 * @return The radius in tiles.
215 	 */
216 	static int32 GetStationCoverageRadius(StationID station_id);
217 
218 	/**
219 	 * Get the manhattan distance from the tile to the ScriptStation::GetLocation()
220 	 *  of the station.
221 	 * @param station_id The station to get the distance to.
222 	 * @param tile The tile to get the distance to.
223 	 * @pre IsValidStation(station_id).
224 	 * @return The distance between station and tile.
225 	 */
226 	static int32 GetDistanceManhattanToTile(StationID station_id, TileIndex tile);
227 
228 	/**
229 	 * Get the square distance from the tile to the ScriptStation::GetLocation()
230 	 *  of the station.
231 	 * @param station_id The station to get the distance to.
232 	 * @param tile The tile to get the distance to.
233 	 * @pre IsValidStation(station_id).
234 	 * @return The distance between station and tile.
235 	 */
236 	static int32 GetDistanceSquareToTile(StationID station_id, TileIndex tile);
237 
238 	/**
239 	 * Find out if this station is within the rating influence of a town.
240 	 *  The service quality of stations with signs within this radius
241 	 *  influences the rating of the town.
242 	 * @param station_id The station to check.
243 	 * @param town_id The town to check.
244 	 * @return True if the tile is within the rating influence of the town.
245 	 */
246 	static bool IsWithinTownInfluence(StationID station_id, TownID town_id);
247 
248 	/**
249 	 * Check if any part of the station contains a station of the type
250 	 *  StationType
251 	 * @param station_id The station to look at.
252 	 * @param station_type The StationType to look for.
253 	 * @return True if the station has a station part of the type StationType.
254 	 */
255 	static bool HasStationType(StationID station_id, StationType station_type);
256 
257 	/**
258 	 * Check if any part of the station contains a station of the type
259 	 *  RoadType.
260 	 * @param station_id The station to look at.
261 	 * @param road_type The RoadType to look for.
262 	 * @return True if the station has a station part of the type RoadType.
263 	 */
264 	static bool HasRoadType(StationID station_id, ScriptRoad::RoadType road_type);
265 
266 	/**
267 	 * Get the town that was nearest to the given station when the station was built.
268 	 * @param station_id The station to look at.
269 	 * @return The TownID of the town whose center tile was closest to the station
270 	 *  at the time the station was built.
271 	 * @note There is no guarantee that the station is even near the returned town
272 	 *  nor that the returns town is closest to the station now. A station that was
273 	 *  'walked' to the other end of the map will still return the same town. Also,
274 	 *  towns grow, towns change. So don't depend on this value too much.
275 	 */
276 	static TownID GetNearestTown(StationID station_id);
277 
278 	/**
279 	 * Get the open/closed state of an airport.
280 	 * @param station_id The airport to look at.
281 	 * @pre IsValidStation(station_id).
282 	 * @pre HasStationType(station_id, STATION_AIRPORT).
283 	 * @return True if the airport is currently closed to incoming traffic.
284 	 */
285 	static bool IsAirportClosed(StationID station_id);
286 
287 	/**
288 	 * Toggle the open/closed state of an airport.
289 	 * @param station_id The airport to modify.
290 	 * @pre IsValidStation(station_id).
291 	 * @pre HasStationType(station_id, STATION_AIRPORT).
292 	 * @return True if the state was toggled successfully.
293 	 */
294 	static bool OpenCloseAirport(StationID station_id);
295 
296 private:
297 	template<bool Tfrom, bool Tvia>
298 	static bool IsCargoRequestValid(StationID station_id, StationID from_station_id,
299 			StationID via_station_id, CargoID cargo_id);
300 
301 	template<bool Tfrom, bool Tvia>
302 	static int32 CountCargoWaiting(StationID station_id, StationID from_station_id,
303 			StationID via_station_id, CargoID cargo_id);
304 
305 	template<bool Tfrom, bool Tvia>
306 	static int32 CountCargoPlanned(StationID station_id, StationID from_station_id,
307 			StationID via_station_id, CargoID cargo_id);
308 
309 };
310 
311 DECLARE_ENUM_AS_BIT_SET(ScriptStation::StationType)
312 
313 #endif /* SCRIPT_STATION_HPP */
314