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 base_station_base.h Base classes/functions for base stations. */ 9 10 #ifndef BASE_STATION_BASE_H 11 #define BASE_STATION_BASE_H 12 13 #include "core/pool_type.hpp" 14 #include "command_type.h" 15 #include "viewport_type.h" 16 #include "station_map.h" 17 18 typedef Pool<BaseStation, StationID, 32, 64000> StationPool; 19 extern StationPool _station_pool; 20 21 struct StationSpecList { 22 const StationSpec *spec; 23 uint32 grfid; ///< GRF ID of this custom station 24 uint8 localidx; ///< Station ID within GRF of station 25 }; 26 27 28 /** StationRect - used to track station spread out rectangle - cheaper than scanning whole map */ 29 struct StationRect : public Rect { 30 enum StationRectMode 31 { 32 ADD_TEST = 0, 33 ADD_TRY, 34 ADD_FORCE 35 }; 36 37 StationRect(); 38 void MakeEmpty(); 39 bool PtInExtendedRect(int x, int y, int distance = 0) const; 40 bool IsEmpty() const; 41 CommandCost BeforeAddTile(TileIndex tile, StationRectMode mode); 42 CommandCost BeforeAddRect(TileIndex tile, int w, int h, StationRectMode mode); 43 bool AfterRemoveTile(BaseStation *st, TileIndex tile); 44 bool AfterRemoveRect(BaseStation *st, TileArea ta); 45 46 static bool ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a); 47 48 StationRect& operator = (const Rect &src); 49 }; 50 51 /** Base class for all station-ish types */ 52 struct BaseStation : StationPool::PoolItem<&_station_pool> { 53 TileIndex xy; ///< Base tile of the station 54 TrackedViewportSign sign; ///< NOSAVE: Dimensions of sign 55 byte delete_ctr; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted. 56 57 std::string name; ///< Custom name 58 StringID string_id; ///< Default name (town area) of station 59 mutable std::string cached_name; ///< NOSAVE: Cache of the resolved name of the station, if not using a custom name 60 61 Town *town; ///< The town this station is associated with 62 Owner owner; ///< The owner of this station 63 StationFacility facilities; ///< The facilities that this station has 64 65 uint8 num_specs; ///< Number of specs in the speclist 66 StationSpecList *speclist; ///< List of station specs of this station 67 68 Date build_date; ///< Date of construction 69 70 uint16 random_bits; ///< Random bits assigned to this station 71 byte waiting_triggers; ///< Waiting triggers (NewGRF) for this station 72 uint8 cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen. 73 CargoTypes cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask 74 75 TileArea train_station; ///< Tile area the train 'station' part covers 76 StationRect rect; ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions 77 78 /** 79 * Initialize the base station. 80 * @param tile The location of the station sign 81 */ BaseStationBaseStation82 BaseStation(TileIndex tile) : 83 xy(tile), 84 train_station(INVALID_TILE, 0, 0) 85 { 86 } 87 88 virtual ~BaseStation(); 89 90 /** 91 * Check whether a specific tile belongs to this station. 92 * @param tile the tile to check 93 * @return true if the tile belongs to this station 94 */ 95 virtual bool TileBelongsToRailStation(TileIndex tile) const = 0; 96 97 /** 98 * Helper function to get a NewGRF variable that isn't implemented by the base class. 99 * @param object the resolver object related to this query 100 * @param variable that is queried 101 * @param parameter parameter for that variable 102 * @param available will return false if ever the variable asked for does not exist 103 * @return the value stored in the corresponding variable 104 */ 105 virtual uint32 GetNewGRFVariable(const struct ResolverObject &object, byte variable, byte parameter, bool *available) const = 0; 106 107 /** 108 * Update the coordinated of the sign (as shown in the viewport). 109 */ 110 virtual void UpdateVirtCoord() = 0; 111 GetCachedNameBaseStation112 inline const char *GetCachedName() const 113 { 114 if (!this->name.empty()) return this->name.c_str(); 115 if (this->cached_name.empty()) this->FillCachedName(); 116 return this->cached_name.c_str(); 117 } 118 MoveSignBaseStation119 virtual void MoveSign(TileIndex new_xy) 120 { 121 this->xy = new_xy; 122 this->UpdateVirtCoord(); 123 } 124 125 /** 126 * Get the tile area for a given station type. 127 * @param ta tile area to fill. 128 * @param type the type of the area 129 */ 130 virtual void GetTileArea(TileArea *ta, StationType type) const = 0; 131 132 133 /** 134 * Obtain the length of a platform 135 * @pre tile must be a rail station tile 136 * @param tile A tile that contains the platform in question 137 * @return The length of the platform 138 */ 139 virtual uint GetPlatformLength(TileIndex tile) const = 0; 140 141 /** 142 * Determines the REMAINING length of a platform, starting at (and including) 143 * the given tile. 144 * @param tile the tile from which to start searching. Must be a rail station tile 145 * @param dir The direction in which to search. 146 * @return The platform length 147 */ 148 virtual uint GetPlatformLength(TileIndex tile, DiagDirection dir) const = 0; 149 150 /** 151 * Get the base station belonging to a specific tile. 152 * @param tile The tile to get the base station from. 153 * @return the station associated with that tile. 154 */ GetByTileBaseStation155 static inline BaseStation *GetByTile(TileIndex tile) 156 { 157 return BaseStation::Get(GetStationIndex(tile)); 158 } 159 160 /** 161 * Check whether the base station currently is in use; in use means 162 * that it is not scheduled for deletion and that it still has some 163 * facilities left. 164 * @return true if still in use 165 */ IsInUseBaseStation166 inline bool IsInUse() const 167 { 168 return (this->facilities & ~FACIL_WAYPOINT) != 0; 169 } 170 171 static void PostDestructor(size_t index); 172 173 private: 174 void FillCachedName() const; 175 }; 176 177 /** 178 * Class defining several overloaded accessors so we don't 179 * have to cast base stations that often 180 */ 181 template <class T, bool Tis_waypoint> 182 struct SpecializedStation : public BaseStation { 183 static const StationFacility EXPECTED_FACIL = Tis_waypoint ? FACIL_WAYPOINT : FACIL_NONE; ///< Specialized type 184 185 /** 186 * Set station type correctly 187 * @param tile The base tile of the station. 188 */ 189 inline SpecializedStation<T, Tis_waypoint>(TileIndex tile) : BaseStationSpecializedStation190 BaseStation(tile) 191 { 192 this->facilities = EXPECTED_FACIL; 193 } 194 195 /** 196 * Helper for checking whether the given station is of this type. 197 * @param st the station to check. 198 * @return true if the station is the type we expect it to be. 199 */ IsExpectedSpecializedStation200 static inline bool IsExpected(const BaseStation *st) 201 { 202 return (st->facilities & FACIL_WAYPOINT) == EXPECTED_FACIL; 203 } 204 205 /** 206 * Tests whether given index is a valid index for station of this type 207 * @param index tested index 208 * @return is this index valid index of T? 209 */ IsValidIDSpecializedStation210 static inline bool IsValidID(size_t index) 211 { 212 return BaseStation::IsValidID(index) && IsExpected(BaseStation::Get(index)); 213 } 214 215 /** 216 * Gets station with given index 217 * @return pointer to station with given index casted to T * 218 */ GetSpecializedStation219 static inline T *Get(size_t index) 220 { 221 return (T *)BaseStation::Get(index); 222 } 223 224 /** 225 * Returns station if the index is a valid index for this station type 226 * @return pointer to station with given index if it's a station of this type 227 */ GetIfValidSpecializedStation228 static inline T *GetIfValid(size_t index) 229 { 230 return IsValidID(index) ? Get(index) : nullptr; 231 } 232 233 /** 234 * Get the station belonging to a specific tile. 235 * @param tile The tile to get the station from. 236 * @return the station associated with that tile. 237 */ GetByTileSpecializedStation238 static inline T *GetByTile(TileIndex tile) 239 { 240 return GetIfValid(GetStationIndex(tile)); 241 } 242 243 /** 244 * Converts a BaseStation to SpecializedStation with type checking. 245 * @param st BaseStation pointer 246 * @return pointer to SpecializedStation 247 */ FromSpecializedStation248 static inline T *From(BaseStation *st) 249 { 250 assert(IsExpected(st)); 251 return (T *)st; 252 } 253 254 /** 255 * Converts a const BaseStation to const SpecializedStation with type checking. 256 * @param st BaseStation pointer 257 * @return pointer to SpecializedStation 258 */ FromSpecializedStation259 static inline const T *From(const BaseStation *st) 260 { 261 assert(IsExpected(st)); 262 return (const T *)st; 263 } 264 265 /** 266 * Returns an iterable ensemble of all valid stations of type T 267 * @param from index of the first station to consider 268 * @return an iterable ensemble of all valid stations of type T 269 */ 270 static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); } 271 }; 272 273 #endif /* BASE_STATION_BASE_H */ 274