tron@2186: /* $Id$ */ tron@2186: truelight@0: #ifndef VEHICLE_H truelight@0: #define VEHICLE_H truelight@0: truelight@1279: #include "pool.h" truelight@1024: #include "order.h" matthijs@1944: #include "rail.h" tron@577: matthijs@1763: enum { matthijs@1752: VEH_Train = 0x10, matthijs@1752: VEH_Road = 0x11, matthijs@1752: VEH_Ship = 0x12, matthijs@1752: VEH_Aircraft = 0x13, matthijs@1752: VEH_Special = 0x14, matthijs@1752: VEH_Disaster = 0x15, matthijs@1763: } ; matthijs@1752: matthijs@1752: enum VehStatus { matthijs@1752: VS_HIDDEN = 1, matthijs@1752: VS_STOPPED = 2, matthijs@1752: VS_UNCLICKABLE = 4, matthijs@1752: VS_DEFPAL = 0x8, matthijs@1752: VS_TRAIN_SLOWING = 0x10, matthijs@1752: VS_DISASTER = 0x20, matthijs@1752: VS_AIRCRAFT_BROKEN = 0x40, matthijs@1752: VS_CRASHED = 0x80, matthijs@1752: }; matthijs@1752: matthijs@1752: // 1 and 3 do not appear to be used matthijs@1752: typedef enum TrainSubtypes { Darkvater@1770: TS_Front_Engine = 0, // Leading engine of a train Darkvater@1770: TS_Not_First = 2, // Wagon or additional engine Darkvater@1770: TS_Free_Car = 4, // First in a wagon chain (in depot) matthijs@1752: } TrainSubtype; matthijs@1752: matthijs@1752: /* Effect vehicle types */ matthijs@1752: typedef enum EffectVehicle { matthijs@1752: EV_CHIMNEY_SMOKE = 0, matthijs@1752: EV_STEAM_SMOKE = 1, matthijs@1752: EV_DIESEL_SMOKE = 2, matthijs@1752: EV_ELECTRIC_SPARK = 3, matthijs@1752: EV_SMOKE = 4, matthijs@1752: EV_EXPLOSION_LARGE = 5, matthijs@1752: EV_BREAKDOWN_SMOKE = 6, matthijs@1752: EV_EXPLOSION_SMALL = 7, matthijs@1752: EV_BULLDOZER = 8, matthijs@1752: EV_BUBBLE = 9 matthijs@1752: } EffectVehicle; matthijs@1752: truelight@0: typedef struct VehicleRail { truelight@0: uint16 last_speed; // NOSAVE: only used in UI truelight@0: uint16 crash_anim_pos; truelight@193: uint16 days_since_order_progr; truelight@193: hackykid@1905: // cached values, recalculated on load and each time a vehicle is added to/removed from the consist. hackykid@1905: uint16 cached_max_speed; // max speed of the consist. (minimum of the max speed of all vehicles in the consist) hackykid@1905: uint32 cached_power; // total power of the consist. hackykid@1922: uint8 cached_veh_length; // length of this vehicle in units of 1/8 of normal length, cached because this can be set by a callback hackykid@1905: // cached values, recalculated when the cargo on a train changes (in addition to the conditions above) hackykid@1905: uint16 cached_weight; // total weight of the consist. hackykid@1905: uint16 cached_veh_weight; // weight of the vehicle. truelight@0: truelight@0: // NOSAVE: for wagon override - id of the first engine in train truelight@0: // 0xffff == not in train Darkvater@1796: EngineID first_engine; truelight@0: truelight@0: byte track; truelight@0: byte force_proceed; truelight@0: byte railtype; truelight@0: truelight@0: byte flags; hackykid@2008: hackykid@2008: byte pbs_status; hackykid@2115: TileIndex pbs_end_tile; hackykid@2115: Trackdir pbs_end_trackdir; truelight@0: } VehicleRail; truelight@0: truelight@0: enum { truelight@954: VRF_REVERSING = 0, truelight@0: truelight@0: // used to calculate if train is going up or down truelight@954: VRF_GOINGUP = 1, truelight@954: VRF_GOINGDOWN = 2, hackykid@1908: hackykid@1908: // used to store if a wagon is powered or not hackykid@1908: VRF_POWEREDWAGON = 3, truelight@0: }; truelight@0: truelight@0: typedef struct VehicleAir { truelight@0: uint16 crashed_counter; truelight@0: byte pos; truelight@0: byte previous_pos; truelight@817: uint16 targetairport; truelight@0: byte state; truelight@0: } VehicleAir; truelight@0: truelight@0: typedef struct VehicleRoad { truelight@0: byte state; truelight@0: byte frame; truelight@0: uint16 unk2; truelight@0: byte overtaking; truelight@0: byte overtaking_ctr; truelight@0: uint16 crashed_ctr; truelight@0: byte reverse_ctr; celestar@1217: struct RoadStop *slot; celestar@1217: byte slotindex; celestar@1217: byte slot_age; truelight@0: } VehicleRoad; truelight@0: truelight@0: typedef struct VehicleSpecial { truelight@0: uint16 unk0; truelight@0: byte unk2; truelight@0: } VehicleSpecial; truelight@0: truelight@0: typedef struct VehicleDisaster { truelight@0: uint16 image_override; truelight@0: uint16 unk2; truelight@0: } VehicleDisaster; truelight@0: truelight@0: typedef struct VehicleShip { truelight@0: byte state; truelight@0: } VehicleShip; truelight@0: truelight@0: // not used ATM truelight@0: struct WorldSprite { truelight@0: struct WorldSprite *next; // next sprite in hash chain truelight@0: uint16 image; // sprite number for this vehicle truelight@0: truelight@0: // screen coordinates truelight@0: int16 left, top, right, bottom; truelight@193: truelight@0: // world coordinates truelight@0: int16 x; truelight@0: int16 y; truelight@0: byte z; truelight@0: truelight@0: int8 x_offs; // x offset for vehicle sprite truelight@0: int8 y_offs; // y offset for vehicle sprite truelight@0: truelight@0: byte width; // width of vehicle sprite truelight@0: byte height; // height of vehicle sprite truelight@0: byte depth; // depth of vehicle sprite truelight@0: truelight@0: byte flags; // draw flags truelight@0: }; truelight@0: truelight@0: struct Vehicle { matthijs@1763: byte type; // type, ie roadven,train,ship,aircraft,special matthijs@1752: byte subtype; // subtype (Filled with values from EffectVehicles or TrainSubTypes)(Filled with values from EffectVehicles or TrainSubTypes) truelight@0: Darkvater@1765: VehicleID index; // NOSAVE: Index in vehicle array truelight@0: truelight@0: Vehicle *next; // next celestar@1601: Vehicle *first; // NOSAVE: pointer to the first vehicle in the chain truelight@0: truelight@0: StringID string_id; // Displayed string truelight@0: truelight@1282: UnitID unitnumber; // unit number, for display purposes only Darkvater@1786: PlayerID owner; // which player owns the vehicle? truelight@0: truelight@0: TileIndex tile; // Current tile index truelight@0: TileIndex dest_tile; // Heading for this tile truelight@0: tron@1174: int32 x_pos; // coordinates tron@1174: int32 y_pos; truelight@0: byte z_pos; truelight@0: byte direction; // facing truelight@0: truelight@0: byte spritenum; // currently displayed sprite index truelight@0: // 0xfd == custom sprite, 0xfe == custom second head sprite truelight@0: // 0xff == reserved for another custom sprite tron@445: uint16 cur_image; // sprite number for this vehicle truelight@0: byte sprite_width;// width of vehicle sprite truelight@0: byte sprite_height;// height of vehicle sprite truelight@0: byte z_height; // z-height of vehicle sprite truelight@0: int8 x_offs; // x offset for vehicle sprite truelight@0: int8 y_offs; // y offset for vehicle sprite Darkvater@1770: EngineID engine_type; truelight@0: tron@445: // for randomized variational spritegroups tron@445: // bitmask used to resolve them; parts of it get reseeded when triggers tron@445: // of corresponding spritegroups get matched tron@445: byte random_bits; tron@445: byte waiting_triggers; // triggers to be yet matched tron@445: truelight@0: uint16 max_speed; // maximum speed truelight@0: uint16 cur_speed; // current speed truelight@0: byte subspeed; // fractional speed truelight@0: byte acceleration; // used by train & aircraft truelight@0: byte progress; truelight@0: truelight@0: byte vehstatus; // Status truelight@817: uint16 last_station_visited; truelight@193: truelight@0: byte cargo_type; // type of cargo this vehicle is carrying truelight@0: byte cargo_days; // how many days have the pieces been in transit truelight@1266: uint16 cargo_source;// source of cargo truelight@0: uint16 cargo_cap; // total capacity truelight@0: uint16 cargo_count;// how many pieces are used truelight@0: truelight@0: byte day_counter; // increased by one for each day truelight@0: byte tick_counter;// increased by one for each tick truelight@0: truelight@1024: /* Begin Order-stuff */ Darkvater@1786: Order current_order; //! The current order (+ status, like: loading) Darkvater@1786: OrderID cur_order_index; //! The index to the current order truelight@1024: Darkvater@1786: Order *orders; //! Pointer to the first order for this vehicle Darkvater@1786: OrderID num_orders; //! How many orders there are in the list truelight@1024: Darkvater@1786: Vehicle *next_shared; //! If not NULL, this points to the next vehicle that shared the order Darkvater@1786: Vehicle *prev_shared; //! If not NULL, this points to the prev vehicle that shared the order truelight@1024: /* End Order-stuff */ truelight@0: truelight@0: // Boundaries for the current position in the world and a next hash link. truelight@0: // NOSAVE: All of those can be updated with VehiclePositionChanged() tron@849: int32 left_coord; tron@849: int32 top_coord; tron@849: int32 right_coord; tron@849: int32 bottom_coord; truelight@0: uint16 next_hash; truelight@0: truelight@0: // Related to age and service time truelight@0: uint16 age; // Age in days truelight@0: uint16 max_age; // Maximum age truelight@0: uint16 date_of_last_service; truelight@0: uint16 service_interval; truelight@0: uint16 reliability; truelight@0: uint16 reliability_spd_dec; truelight@0: byte breakdown_ctr; truelight@0: byte breakdown_delay; truelight@0: byte breakdowns_since_last_service; truelight@0: byte breakdown_chance; truelight@0: byte build_year; truelight@0: truelight@0: uint16 load_unload_time_rem; truelight@193: truelight@0: int32 profit_this_year; truelight@0: int32 profit_last_year; truelight@0: uint32 value; truelight@0: truelight@0: union { truelight@0: VehicleRail rail; truelight@0: VehicleAir air; truelight@0: VehicleRoad road; truelight@0: VehicleSpecial special; truelight@0: VehicleDisaster disaster; truelight@0: VehicleShip ship; truelight@0: } u; truelight@0: }; truelight@0: Darkvater@1765: #define is_custom_sprite(x) (x >= 0xFD) Darkvater@1765: #define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD) Darkvater@1765: #define IS_CUSTOM_SECONDHEAD_SPRITE(x) (x == 0xFE) truelight@0: truelight@0: typedef void VehicleTickProc(Vehicle *v); truelight@0: typedef void *VehicleFromPosProc(Vehicle *v, void *data); truelight@0: bjarni@578: void VehicleServiceInDepot(Vehicle *v); tron@1093: Vehicle *AllocateVehicle(void); tron@1093: Vehicle *ForceAllocateVehicle(void); tron@1093: Vehicle *ForceAllocateSpecialVehicle(void); truelight@0: void UpdateVehiclePosHash(Vehicle *v, int x, int y); truelight@0: void VehiclePositionChanged(Vehicle *v); tron@1093: void AfterLoadVehicles(void); truelight@0: Vehicle *GetLastVehicleInChain(Vehicle *v); tron@1475: Vehicle *GetPrevVehicleInChain(const Vehicle *v); tron@1475: Vehicle *GetFirstVehicleInChain(const Vehicle *v); truelight@0: int CountVehiclesInChain(Vehicle *v); truelight@0: void DeleteVehicle(Vehicle *v); truelight@0: void DeleteVehicleChain(Vehicle *v); truelight@0: void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc); tron@1093: void CallVehicleTicks(void); truelight@1605: Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z); truelight@0: tron@1093: void InitializeTrains(void); truelight@0: truelight@0: bool CanFillVehicle(Vehicle *v); Darkvater@1802: bool CanRefitTo(const Vehicle *v, CargoID cid_to); truelight@0: truelight@0: void ViewportAddVehicles(DrawPixelInfo *dpi); truelight@0: tron@1977: void TrainEnterDepot(Vehicle *v, TileIndex tile); truelight@0: bjarni@1060: void AddRearEngineToMultiheadedTrain(Vehicle *v, Vehicle *u, bool building) ; bjarni@1060: truelight@0: /* train_cmd.h */ tron@1475: int GetTrainImage(const Vehicle *v, byte direction); Darkvater@1790: int GetAircraftImage(const Vehicle *v, byte direction); Darkvater@1790: int GetRoadVehImage(const Vehicle *v, byte direction); Darkvater@1790: int GetShipImage(const Vehicle *v, byte direction); truelight@0: tron@1359: Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type); tron@1359: Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type); tron@1359: Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type); truelight@0: tron@1977: uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y); truelight@0: truelight@0: void VehicleInTheWayErrMsg(Vehicle *v); truelight@0: Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z); tron@1587: TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v); truelight@0: tron@1977: bool UpdateSignalsOnSegment(TileIndex tile, byte direction); tron@1977: void SetSignalsOnBothDir(TileIndex tile, byte track); truelight@0: tron@2116: Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y); truelight@0: //uint GetVehicleWeight(Vehicle *v); truelight@0: truelight@0: void DecreaseVehicleValue(Vehicle *v); truelight@0: void CheckVehicleBreakdown(Vehicle *v); truelight@0: void AgeVehicle(Vehicle *v); bjarni@842: void MaybeReplaceVehicle(Vehicle *v); truelight@0: truelight@0: void BeginVehicleMove(Vehicle *v); truelight@0: void EndVehicleMove(Vehicle *v); truelight@0: truelight@0: bool IsAircraftHangarTile(TileIndex tile); truelight@0: void ShowAircraftViewWindow(Vehicle *v); truelight@0: truelight@1282: UnitID GetFreeUnitNumber(byte type); truelight@0: truelight@0: int LoadUnloadVehicle(Vehicle *v); truelight@0: hackykid@1905: void TrainConsistChanged(Vehicle *v); truelight@0: void UpdateTrainAcceleration(Vehicle *v); Darkvater@1790: int32 GetTrainRunningCost(const Vehicle *v); truelight@0: tron@1472: int CheckTrainStoppedInDepot(const Vehicle *v); truelight@0: tron@593: bool VehicleNeedsService(const Vehicle *v); tron@593: truelight@0: typedef struct GetNewVehiclePosResult { truelight@0: int x,y; tron@1977: TileIndex old_tile; tron@1977: TileIndex new_tile; truelight@0: } GetNewVehiclePosResult; truelight@0: matthijs@1752: /** matthijs@1752: * Returns the Trackdir on which the vehicle is currently located. matthijs@1752: * Works for trains and ships. matthijs@1752: * Currently works only sortof for road vehicles, since they have a fuzzy matthijs@1752: * concept of being "on" a trackdir. Dunno really what it returns for a road matthijs@1752: * vehicle that is halfway a tile, never really understood that part. For road matthijs@1752: * vehicles that are at the beginning or end of the tile, should just return matthijs@1752: * the diagonal trackdir on which they are driving. I _think_. matthijs@1752: * For other vehicles types, or vehicles with no clear trackdir (such as those matthijs@1752: * in depots), returns 0xFF. matthijs@1752: */ matthijs@1944: Trackdir GetVehicleTrackdir(const Vehicle* v); matthijs@1752: truelight@0: /* returns true if staying in the same tile */ truelight@0: bool GetNewVehiclePos(Vehicle *v, GetNewVehiclePosResult *gp); truelight@0: byte GetDirectionTowards(Vehicle *v, int x, int y); truelight@0: truelight@0: #define BEGIN_ENUM_WAGONS(v) do { truelight@0: #define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL); truelight@0: truelight@0: /* vehicle.c */ truelight@919: VARDEF SortStruct *_vehicle_sort; truelight@919: truelight@1279: extern MemoryPool _vehicle_pool; truelight@1279: truelight@1279: /** truelight@1279: * Get the pointer to the vehicle with index 'index' truelight@1279: */ truelight@1279: static inline Vehicle *GetVehicle(VehicleID index) truelight@919: { truelight@1279: return (Vehicle*)GetItemFromPool(&_vehicle_pool, index); truelight@919: } truelight@919: truelight@1279: /** truelight@1279: * Get the current size of the VehiclePool truelight@1279: */ truelight@1279: static inline uint16 GetVehiclePoolSize(void) truelight@1279: { truelight@1279: return _vehicle_pool.total_items; truelight@1279: } truelight@1279: truelight@1279: #define FOR_ALL_VEHICLES_FROM(v, start) for (v = GetVehicle(start); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) truelight@1279: #define FOR_ALL_VEHICLES(v) FOR_ALL_VEHICLES_FROM(v, 0) truelight@1279: truelight@1279: /** matthijs@1330: * Check if a Vehicle really exists. matthijs@1330: */ Darkvater@1770: static inline bool IsValidVehicle(const Vehicle *v) matthijs@1330: { matthijs@1330: return v->type != 0; matthijs@1330: } matthijs@1330: matthijs@1330: /** truelight@1279: * Check if an index is a vehicle-index (so between 0 and max-vehicles) truelight@1279: * truelight@1279: * @return Returns true if the vehicle-id is in range truelight@1279: */ bjarni@1237: static inline bool IsVehicleIndex(uint index) bjarni@1237: { Darkvater@1765: if (index < GetVehiclePoolSize()) return true; truelight@1279: truelight@1279: return false; bjarni@1237: } bjarni@1237: truelight@1024: /* Returns order 'index' of a vehicle or NULL when it doesn't exists */ truelight@1024: static inline Order *GetVehicleOrder(const Vehicle *v, int index) truelight@1024: { truelight@1024: Order *order = v->orders; truelight@1024: Darkvater@1765: if (index < 0) return NULL; truelight@1024: truelight@1024: while (order != NULL && index-- > 0) truelight@1024: order = order->next; truelight@1024: truelight@1024: return order; truelight@1024: } truelight@1024: truelight@1024: /* Returns the last order of a vehicle, or NULL if it doesn't exists */ truelight@1024: static inline Order *GetLastVehicleOrder(const Vehicle *v) truelight@1024: { truelight@1024: Order *order = v->orders; truelight@1024: Darkvater@1765: if (order == NULL) return NULL; truelight@1024: truelight@1024: while (order->next != NULL) truelight@1024: order = order->next; truelight@1024: truelight@1024: return order; truelight@1024: } truelight@1024: truelight@1024: /* Get the first vehicle of a shared-list, so we only have to walk forwards */ truelight@1024: static inline Vehicle *GetFirstVehicleFromSharedList(Vehicle *v) truelight@1024: { truelight@1024: Vehicle *u = v; truelight@1024: while (u->prev_shared != NULL) truelight@1024: u = u->prev_shared; truelight@1024: truelight@1024: return u; truelight@1024: } truelight@0: truelight@0: // NOSAVE: Can be regenerated by inspecting the vehicles. truelight@0: VARDEF VehicleID _vehicle_position_hash[0x1000]; truelight@0: truelight@0: // NOSAVE: Return values from various commands. truelight@0: VARDEF VehicleID _new_train_id; truelight@0: VARDEF VehicleID _new_wagon_id; truelight@0: VARDEF VehicleID _new_aircraft_id; truelight@0: VARDEF VehicleID _new_ship_id; truelight@0: VARDEF VehicleID _new_roadveh_id; truelight@0: VARDEF uint16 _aircraft_refit_capacity; truelight@0: VARDEF byte _cmd_build_rail_veh_score; truelight@0: VARDEF byte _cmd_build_rail_veh_var1; truelight@0: truelight@0: // for each player, for each vehicle type, keep a list of the vehicles. truelight@0: //VARDEF Vehicle *_vehicle_arr[8][4]; truelight@0: Darkvater@1765: #define INVALID_VEHICLE 0xFFFF truelight@0: darkvater@755: /* A lot of code calls for the invalidation of the status bar, which is widget 5. darkvater@755: * Best is to have a virtual value for it when it needs to change again */ darkvater@755: #define STATUS_BAR 5 darkvater@755: truelight@0: #endif /* VEHICLE_H */