tron@2186: /* $Id$ */ tron@2186: truelight@0: #ifndef STATION_H truelight@0: #define STATION_H truelight@0: tron@2154: #include "player.h" truelight@1272: #include "pool.h" darkvater@405: #include "sprite.h" matthijs@1247: #include "tile.h" truelight@0: #include "vehicle.h" truelight@0: truelight@0: typedef struct GoodsEntry { truelight@0: uint16 waiting_acceptance; truelight@0: byte days_since_pickup; truelight@0: byte rating; truelight@1266: uint16 enroute_from; truelight@0: byte enroute_time; truelight@0: byte last_speed; truelight@0: byte last_age; celestar@1935: int32 feeder_profit; truelight@0: } GoodsEntry; truelight@0: celestar@1217: typedef enum RoadStopType { celestar@1217: RS_BUS, celestar@1217: RS_TRUCK celestar@1217: } RoadStopType; celestar@1217: truelight@1266: enum { truelight@1266: INVALID_STATION = 0xFFFF, truelight@1266: INVALID_SLOT = 0xFFFF, truelight@1266: NUM_SLOTS = 2, truelight@1266: ROAD_STOP_LIMIT = 8, truelight@1266: }; celestar@1217: celestar@1551: typedef uint16 StationID; celestar@1551: celestar@1217: typedef struct RoadStop { celestar@1217: TileIndex xy; celestar@1217: bool used; celestar@1217: byte status; celestar@1217: uint32 index; celestar@1217: uint16 slot[NUM_SLOTS]; celestar@1551: StationID station; celestar@1217: uint8 type; celestar@1217: struct RoadStop *next; celestar@1217: struct RoadStop *prev; celestar@1217: } RoadStop; celestar@1217: truelight@0: struct Station { truelight@0: TileIndex xy; celestar@1217: RoadStop *bus_stops; celestar@1217: RoadStop *truck_stops; truelight@0: TileIndex train_tile; truelight@0: TileIndex airport_tile; truelight@0: TileIndex dock_tile; truelight@0: Town *town; truelight@0: uint16 string_id; truelight@0: truelight@0: ViewportSign sign; truelight@0: truelight@0: uint16 had_vehicle_of_type; truelight@193: truelight@0: byte time_since_load; truelight@0: byte time_since_unload; truelight@0: byte delete_ctr; truelight@0: byte owner; truelight@0: byte facilities; truelight@0: byte airport_type; truelight@0: truelight@0: // trainstation width/height truelight@0: byte trainst_w, trainst_h; truelight@0: darkvater@393: byte class_id; // custom graphics station class darkvater@393: byte stat_id; // custom graphics station id in the @class_id class truelight@0: uint16 build_date; truelight@0: truelight@0: //uint16 airport_flags; darkvater@393: uint32 airport_flags; celestar@1551: StationID index; truelight@0: truelight@0: VehicleID last_vehicle; truelight@0: GoodsEntry goods[NUM_CARGO]; celestar@1217: celestar@1217: /* Stuff that is no longer used, but needed for conversion */ celestar@1217: TileIndex bus_tile_obsolete; celestar@1217: TileIndex lorry_tile_obsolete; celestar@1217: celestar@1217: byte truck_stop_status_obsolete; celestar@1217: byte bus_stop_status_obsolete; celestar@1217: byte blocked_months_obsolete; truelight@0: }; truelight@0: truelight@0: enum { truelight@0: FACIL_TRAIN = 1, truelight@0: FACIL_TRUCK_STOP = 2, truelight@0: FACIL_BUS_STOP = 4, truelight@0: FACIL_AIRPORT = 8, truelight@0: FACIL_DOCK = 0x10, truelight@0: }; truelight@0: truelight@0: enum { truelight@0: // HVOT_PENDING_DELETE = 1<<0, // not needed anymore truelight@0: HVOT_TRAIN = 1<<1, truelight@0: HVOT_BUS = 1 << 2, truelight@0: HVOT_TRUCK = 1 << 3, celestar@1217: HVOT_AIRCRAFT = 1 << 4, truelight@0: HVOT_SHIP = 1 << 5, matthijs@1751: /* This bit is used to mark stations. No, it does not belong here, but what matthijs@1751: * can we do? ;-) */ truelight@0: HVOT_BUOY = 1 << 6 truelight@0: }; truelight@0: Celestar@568: enum { Celestar@568: CA_BUS = 3, Celestar@568: CA_TRUCK = 3, Celestar@568: CA_AIR_OILPAD = 3, Celestar@568: CA_TRAIN = 4, Celestar@568: CA_AIR_HELIPORT = 4, Celestar@568: CA_AIR_SMALL = 4, Celestar@568: CA_AIR_LARGE = 5, Celestar@568: CA_DOCK = 5, tron@915: CA_AIR_METRO = 6, Celestar@568: CA_AIR_INTER = 8, tron@915: }; Celestar@568: truelight@0: void ModifyStationRatingAround(TileIndex tile, byte owner, int amount, uint radius); truelight@0: truelight@1024: TileIndex GetStationTileForVehicle(const Vehicle *v, const Station *st); dominik@55: truelight@0: void ShowStationViewWindow(int station); tron@1093: void UpdateAllStationVirtCoord(void); truelight@0: truelight@919: VARDEF SortStruct *_station_sort; truelight@919: truelight@1272: extern MemoryPool _station_pool; truelight@1272: truelight@1272: /** truelight@1272: * Get the pointer to the station with index 'index' truelight@1272: */ celestar@1551: static inline Station *GetStation(StationID index) truelight@919: { truelight@1272: return (Station*)GetItemFromPool(&_station_pool, index); truelight@919: } truelight@919: truelight@1272: /** truelight@1272: * Get the current size of the StationPool truelight@1272: */ truelight@1272: static inline uint16 GetStationPoolSize(void) truelight@1272: { truelight@1272: return _station_pool.total_items; truelight@1272: } truelight@1272: tron@1718: static inline bool IsStationIndex(uint index) tron@1718: { tron@1718: return index < GetStationPoolSize(); tron@1718: } tron@1718: truelight@1272: #define FOR_ALL_STATIONS_FROM(st, start) for (st = GetStation(start); st != NULL; st = (st->index + 1 < GetStationPoolSize()) ? GetStation(st->index + 1) : NULL) truelight@1272: #define FOR_ALL_STATIONS(st) FOR_ALL_STATIONS_FROM(st, 0) truelight@919: truelight@1284: truelight@1284: /* Stuff for ROADSTOPS */ truelight@1284: truelight@1284: extern MemoryPool _roadstop_pool; truelight@1284: truelight@1284: /** truelight@1284: * Get the pointer to the roadstop with index 'index' truelight@1284: */ truelight@1284: static inline RoadStop *GetRoadStop(uint index) truelight@1284: { truelight@1284: return (RoadStop*)GetItemFromPool(&_roadstop_pool, index); truelight@1284: } truelight@1284: truelight@1284: /** truelight@1284: * Get the current size of the RoadStoptPool truelight@1284: */ truelight@1284: static inline uint16 GetRoadStopPoolSize(void) truelight@1284: { truelight@1284: return _roadstop_pool.total_items; truelight@1284: } truelight@1284: truelight@1284: #define FOR_ALL_ROADSTOPS_FROM(rs, start) for (rs = GetRoadStop(start); rs != NULL; rs = (rs->index + 1 < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1) : NULL) truelight@1284: #define FOR_ALL_ROADSTOPS(rs) FOR_ALL_ROADSTOPS_FROM(rs, 0) truelight@1284: truelight@1284: /* End of stuff for ROADSTOPS */ truelight@1284: truelight@1284: darkvater@243: VARDEF bool _station_sort_dirty[MAX_PLAYERS]; darkvater@243: VARDEF bool _global_station_sort_dirty; truelight@0: tron@1424: void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile, int w, int h, int rad); tron@1424: void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile, int w, int h, int rad); tron@1977: uint GetStationPlatforms(Station *st, TileIndex tile); darkvater@384: darkvater@384: tron@449: /* Station layout for given dimensions - it is a two-dimensional array tron@449: * where index is computed as (x * platforms) + platform. */ tron@449: typedef byte *StationLayout; tron@449: tron@1477: typedef enum StationClass { tron@1477: STAT_CLASS_NONE, // unused station slot or so tron@1477: STAT_CLASS_DFLT, // default station class tron@1477: STAT_CLASS_WAYP, // waypoints tron@1477: tron@1477: /* TODO: When we actually support custom classes, they are tron@1477: * going to be allocated dynamically (with some classid->sclass tron@1477: * mapping, there's a TTDPatch limit on 16 custom classes in tron@1477: * the whole game at the same time) with base at tron@1477: * STAT_CLASS_CUSTOM. --pasky */ tron@1477: STAT_CLASS_CUSTOM, // some custom class tron@1477: } StationClass; tron@1477: tron@1477: typedef struct StationSpec { darkvater@400: uint32 grfid; darkvater@400: int localidx; // per-GRFFile station index + 1; SetCustomStation() takes care of this darkvater@400: tron@1477: StationClass sclass; darkvater@400: tron@449: /* Bitmask of platform numbers/lengths available for the station. Bits tron@449: * 0..6 correspond to 1..7, while bit 7 corresponds to >7 platforms or tron@449: * lenght. */ tron@449: byte allowed_platforms; tron@449: byte allowed_lengths; tron@449: tron@449: /* Custom sprites */ darkvater@399: byte tiles; tron@449: /* 00 = plain platform tron@449: * 02 = platform with building tron@449: * 04 = platform with roof, left side tron@449: * 06 = platform with roof, right side tron@449: * tron@449: * These numbers are used for stations in NE-SW direction, or these tron@449: * numbers plus one for stations in the NW-SE direction. */ darkvater@399: DrawTileSprites renderdata[8]; darkvater@403: tron@449: /* Custom layouts */ tron@449: /* The layout array is organized like [lenghts][platforms], both being tron@449: * dynamic arrays, the field itself is length*platforms array containing tron@449: * indexes to @renderdata (only even numbers allowed) for the given tron@449: * station tile. */ tron@449: /* @lengths is length of the @platforms and @layouts arrays, that is tron@449: * number of maximal length for which the layout is defined (since tron@449: * arrays are indexed from 0, the length itself is at [length - 1]). */ tron@449: byte lengths; tron@449: /* @platforms is array of number of platforms defined for each length. tron@449: * Zero means no platforms defined. */ tron@449: byte *platforms; tron@449: /* @layout is @layouts-sized array of @platforms-sized arrays, tron@449: * containing pointers to length*platforms-sized arrays or NULL if tron@449: * default OTTD station layout should be used for stations of these tron@449: * dimensions. */ tron@449: StationLayout **layouts; tron@449: darkvater@408: /* Sprite offsets for renderdata->seq->image. spritegroup[0] is default Darkvater@1802: * whilst spritegroup[1] is "GC_PURCHASE". */ tron@1477: SpriteGroup spritegroup[2]; tron@1477: } StationSpec; darkvater@399: darkvater@400: /* Here, @stid is local per-GRFFile station index. If spec->localidx is not yet darkvater@400: * set, it gets new dynamically allocated global index and spec->localidx is darkvater@400: * set to @stid, otherwise we take it as that we are replacing it and try to darkvater@400: * search for it first (that isn't much fast but we do it only very seldom). */ tron@1477: void SetCustomStation(byte stid, StationSpec *spec); darkvater@400: /* Here, @stid is global station index (in continous range 0..GetCustomStationsCount()) darkvater@400: * (lookup is therefore very fast as we do this very frequently). */ tron@1477: StationSpec *GetCustomStation(StationClass sclass, byte stid); darkvater@408: /* Get sprite offset for a given custom station and station structure (may be darkvater@408: * NULL if ctype is set - that means we are in a build dialog). The station darkvater@408: * structure is used for variational sprite groups. */ tron@1477: uint32 GetCustomStationRelocation(StationSpec *spec, Station *stat, byte ctype); tron@1477: int GetCustomStationsCount(StationClass sclass); celestar@389: celestar@1217: RoadStop * GetRoadStopByTile(TileIndex tile, RoadStopType type); celestar@1368: static inline int GetRoadStopType(TileIndex tile) celestar@1368: { tron@2049: return (_m[tile].m5 < 0x47) ? RS_TRUCK : RS_BUS; celestar@1368: } celestar@1368: celestar@1217: uint GetNumRoadStops(const Station *st, RoadStopType type); celestar@1217: RoadStop * GetPrimaryRoadStop(const Station *st, RoadStopType type); truelight@1284: RoadStop * AllocateRoadStop( void ); Darkvater@1680: void ClearSlot(Vehicle *v, RoadStop *rs); celestar@1217: tron@1977: static inline bool IsTrainStationTile(TileIndex tile) tron@1977: { tron@2049: return IsTileType(tile, MP_STATION) && IS_BYTE_INSIDE(_m[tile].m5, 0, 8); matthijs@1247: } matthijs@1247: tron@1685: static inline bool IsCompatibleTrainStationTile(TileIndex tile, TileIndex ref) tron@1685: { tron@1685: assert(IsTrainStationTile(ref)); tron@1685: return tron@1685: IsTrainStationTile(tile) && tron@2049: (_m[tile].m3 & 0x0F) == (_m[ref].m3 & 0x0F) && // same rail type? tron@2049: (_m[tile].m5 & 0x01) == (_m[ref].m5 & 0x01); // same direction? tron@1685: } tron@1685: matthijs@1751: static inline bool IsRoadStationTile(TileIndex tile) { tron@2049: return IsTileType(tile, MP_STATION) && IS_BYTE_INSIDE(_m[tile].m5, 0x43, 0x4B); matthijs@1247: } matthijs@1247: matthijs@1330: /** matthijs@1330: * Check if a station really exists. matthijs@1330: */ Darkvater@1742: static inline bool IsValidStation(const Station *st) matthijs@1330: { Darkvater@1742: return st->xy != 0; /* XXX: Replace by INVALID_TILE someday */ matthijs@1330: } matthijs@1330: matthijs@1751: static inline bool IsBuoy(const Station* st) matthijs@1751: { matthijs@1751: return st->had_vehicle_of_type & HVOT_BUOY; /* XXX: We should really ditch this ugly coding and switch to something sane... */ matthijs@1751: } matthijs@1751: matthijs@1751: static inline bool IsBuoyTile(TileIndex tile) { tron@2049: return IsTileType(tile, MP_STATION) && _m[tile].m5 == 0x52; matthijs@1751: } matthijs@1751: matthijs@1247: /* Get's the direction the station exit points towards. Ie, returns 0 for a matthijs@1247: * station with the exit NE. */ tron@1977: static inline byte GetRoadStationDir(TileIndex tile) tron@1977: { matthijs@1247: assert(IsRoadStationTile(tile)); tron@2049: return (_m[tile].m5 - 0x43) & 3; matthijs@1247: } matthijs@1247: truelight@0: #endif /* STATION_H */