# vehicle_base.h

Go to the documentation of this file.

    00001 /* $Id: vehicle_base.h 18929 2010-01-27 20:07:29Z frosch $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #ifndef VEHICLE_BASE_H
    00013 #define VEHICLE_BASE_H
    00014
    00015 #include "track_type.h"
    00016 #include "direction_type.h"
    00017 #include "command_type.h"
    00018 #include "order_base.h"
    00019 #include "cargopacket.h"
    00020 #include "texteff.hpp"
    00021 #include "engine_type.h"
    00022 #include "order_func.h"
    00023 #include "transport_type.h"
    00024
    00025 enum VehStatus {
    00026   VS_HIDDEN          = 0x01,
    00027   VS_STOPPED         = 0x02,
    00028   VS_UNCLICKABLE     = 0x04,
    00029   VS_DEFPAL          = 0x08,
    00030   VS_TRAIN_SLOWING   = 0x10,
    00031   VS_SHADOW          = 0x20,
    00032   VS_AIRCRAFT_BROKEN = 0x40,
    00033   VS_CRASHED         = 0x80,
    00034 };
    00035
    00036 enum VehicleFlags {
    00037   VF_LOADING_FINISHED,
    00038   VF_CARGO_UNLOADING,
    00039   VF_BUILT_AS_PROTOTYPE,
    00040   VF_TIMETABLE_STARTED,
    00041   VF_AUTOFILL_TIMETABLE,
    00042   VF_AUTOFILL_PRES_WAIT_TIME,
    00043 };
    00044
    00046 struct VehicleCache {
    00047   uint8 cache_valid;
    00048   uint32 cached_var40;
    00049   uint32 cached_var41;
    00050   uint32 cached_var42;
    00051   uint32 cached_var43;
    00052 };
    00053
    00054 typedef Pool<Vehicle, VehicleID, 512, 64000> VehiclePool;
    00055 extern VehiclePool _vehicle_pool;
    00056
    00057 /* Some declarations of functions, so we can make them friendly */
    00058 struct SaveLoad;
    00059 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
    00060 struct LoadgameState;
    00061 extern bool LoadOldVehicle(LoadgameState *ls, int num);
    00062 extern bool AfterLoadGame();
    00063 extern void FixOldVehicles();
    00064
    00065 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
    00066 private:
    00067   Vehicle *next;
    00068   Vehicle *previous;
    00069   Vehicle *first;
    00070
    00071   Vehicle *next_shared;
    00072   Vehicle *previous_shared;
    00073 public:
    00074   friend const SaveLoad *GetVehicleDescription(VehicleType vt);
    00075   friend bool AfterLoadGame();
    00076   friend void FixOldVehicles();
    00077   friend void AfterLoadVehicles(bool part_of_load);
    00078   friend bool LoadOldVehicle(LoadgameState *ls, int num);
    00079
    00080   char *name;
    00081
    00082   TileIndex tile;
    00083
    00089   TileIndex dest_tile;
    00090
    00091   Money profit_this_year;
    00092   Money profit_last_year;
    00093   Money value;
    00094
    00095   CargoPayment *cargo_payment;
    00096
    00097   /* Used for timetabling. */
    00098   uint32 current_order_time;
    00099   int32 lateness_counter;
    00100   Date timetable_start;
    00101
    00102   /* Boundaries for the current position in the world and a next hash link.
    00103    * NOSAVE: All of those can be updated with VehiclePositionChanged() */
    00104   Rect coord;
    00105   Vehicle *next_hash, **prev_hash;
    00106   Vehicle *next_new_hash, **prev_new_hash;
    00107   Vehicle **old_new_hash;
    00108
    00109   SpriteID colourmap; // NOSAVE: cached colour mapping
    00110
    00111   /* Related to age and service time */
    00112   Year build_year;
    00113   Date age;     // Age in days
    00114   Date max_age; // Maximum age
    00115   Date date_of_last_service;
    00116   Date service_interval;
    00117   uint16 reliability;
    00118   uint16 reliability_spd_dec;
    00119   byte breakdown_ctr;
    00120   byte breakdown_delay;
    00121   byte breakdowns_since_last_service;
    00122   byte breakdown_chance;
    00123
    00124   int32 x_pos;             // coordinates
    00125   int32 y_pos;
    00126   byte z_pos;
    00127   DirectionByte direction; // facing
    00128
    00129   OwnerByte owner;         // which company owns the vehicle?
    00130   byte spritenum;          // currently displayed sprite index
    00131                            // 0xfd == custom sprite, 0xfe == custom second head sprite
    00132                            // 0xff == reserved for another custom sprite
    00133   uint16 cur_image;        // sprite number for this vehicle
    00134   byte x_extent;           // x-extent of vehicle bounding box
    00135   byte y_extent;           // y-extent of vehicle bounding box
    00136   byte z_extent;           // z-extent of vehicle bounding box
    00137   int8 x_offs;             // x offset for vehicle sprite
    00138   int8 y_offs;             // y offset for vehicle sprite
    00139   EngineID engine_type;
    00140
    00141   TextEffectID fill_percent_te_id; // a text-effect id to a loading indicator object
    00142   UnitID unitnumber;       // unit number, for display purposes only
    00143
    00144   uint16 max_speed;
    00145   uint16 cur_speed;
    00146   byte subspeed;
    00147   byte acceleration;
    00148   uint32 motion_counter;
    00149   byte progress;
    00150
    00151   /* for randomized variational spritegroups
    00152    * bitmask used to resolve them; parts of it get reseeded when triggers
    00153    * of corresponding spritegroups get matched */
    00154   byte random_bits;
    00155   byte waiting_triggers;
    00156
    00157   StationID last_station_visited;
    00158
    00159   CargoID cargo_type;
    00160   byte cargo_subtype;
    00161   uint16 cargo_cap;
    00162   VehicleCargoList cargo;
    00163
    00164   byte day_counter;
    00165   byte tick_counter;
    00166   byte running_ticks;
    00167
    00168   byte vehstatus;
    00169   Order current_order;
    00170   VehicleOrderID cur_order_index;
    00171
    00172   union {
    00173     OrderList *list;
    00174     Order     *old;
    00175   } orders;
    00176
    00177   byte vehicle_flags;
    00178
    00180   uint16 load_unload_ticks;
    00181
    00182   GroupID group_id;
    00183
    00184   byte subtype;
    00185
    00186   VehicleCache vcache;
    00187
    00189   Vehicle(VehicleType type = VEH_INVALID);
    00190
    00192   void PreDestructor();
    00194   virtual ~Vehicle();
    00195
    00196   void BeginLoading();
    00197   void LeaveStation();
    00198
    00204   void HandleLoading(bool mode = false);
    00205
    00210   virtual const char *GetTypeString() const { return "base vehicle"; }
    00211
    00220   virtual void MarkDirty() {}
    00221
    00227   virtual void UpdateDeltaXY(Direction direction) {}
    00228
    00233   virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
    00234
    00238   virtual void PlayLeaveStationSound() const {}
    00239
    00243   virtual bool IsPrimaryVehicle() const { return false; }
    00244
    00250   virtual SpriteID GetImage(Direction direction) const { return 0; }
    00251
    00256   FORCEINLINE void InvalidateNewGRFCache()
    00257   {
    00258     this->vcache.cache_valid = 0;
    00259   }
    00260
    00265   FORCEINLINE void InvalidateNewGRFCacheOfChain()
    00266   {
    00267     for (Vehicle *u = this; u != NULL; u = u->Next()) {
    00268       u->InvalidateNewGRFCache();
    00269     }
    00270   }
    00271
    00276   virtual int GetDisplaySpeed() const { return 0; }
    00277
    00282   virtual int GetDisplayMaxSpeed() const { return 0; }
    00283
    00288   virtual Money GetRunningCost() const { return 0; }
    00289
    00294   virtual bool IsInDepot() const { return false; }
    00295
    00300   virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
    00301
    00306   virtual bool Tick() { return true; };
    00307
    00311   virtual void OnNewDay() {};
    00312
    00318   virtual uint Crash(bool flooded = false);
    00319
    00325   inline void UpdateViewport(bool moved, bool turned)
    00326   {
    00327     extern void VehicleMove(Vehicle *v, bool update_viewport);
    00328
    00329     if (turned) this->UpdateDeltaXY(this->direction);
    00330     SpriteID old_image = this->cur_image;
    00331     this->cur_image = this->GetImage(this->direction);
    00332     if (moved || this->cur_image != old_image) VehicleMove(this, true);
    00333   }
    00334
    00347   virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
    00348
    00353   Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
    00354
    00359   Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
    00360
    00365   Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
    00366
    00371   void SetNext(Vehicle *next);
    00372
    00378   inline Vehicle *Next() const { return this->next; }
    00379
    00385   inline Vehicle *Previous() const { return this->previous; }
    00386
    00391   inline Vehicle *First() const { return this->first; }
    00392
    00397   inline Vehicle *Last()
    00398   {
    00399     Vehicle *v = this;
    00400     while (v->Next() != NULL) v = v->Next();
    00401     return v;
    00402   }
    00403
    00408   inline const Vehicle *Last() const
    00409   {
    00410     const Vehicle *v = this;
    00411     while (v->Next() != NULL) v = v->Next();
    00412     return v;
    00413   }
    00414
    00419   inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
    00420
    00426   void AddToShared(Vehicle *shared_chain);
    00427
    00431   void RemoveFromShared();
    00432
    00437   inline Vehicle *NextShared() const { return this->next_shared; }
    00438
    00443   inline Vehicle *PreviousShared() const { return this->previous_shared; }
    00444
    00449   inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
    00450
    00455   inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
    00456
    00461   inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
    00462
    00469   inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
    00470   {
    00471     this->unitnumber = src->unitnumber;
    00472
    00473     this->cur_order_index = src->cur_order_index;
    00474     this->current_order = src->current_order;
    00475     this->dest_tile  = src->dest_tile;
    00476
    00477     this->profit_this_year = src->profit_this_year;
    00478     this->profit_last_year = src->profit_last_year;
    00479
    00480     this->current_order_time = src->current_order_time;
    00481     this->lateness_counter = src->lateness_counter;
    00482     this->timetable_start = src->timetable_start;
    00483
    00484     if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
    00485     if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
    00486     if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
    00487
    00488     this->service_interval = src->service_interval;
    00489   }
    00490
    00491   bool NeedsAutorenewing(const Company *c) const;
    00492
    00499   bool NeedsServicing() const;
    00500
    00506   bool NeedsAutomaticServicing() const;
    00507
    00515   virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
    00516
    00525   virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
    00526
    00533   CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
    00534
    00539   void IncrementOrderIndex()
    00540   {
    00541     this->cur_order_index++;
    00542     if (this->cur_order_index >= this->GetNumOrders()) this->cur_order_index = 0;
    00543     InvalidateVehicleOrder(this, 0);
    00544   }
    00545
    00551   inline Order *GetOrder(int index) const
    00552   {
    00553     return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
    00554   }
    00555
    00560   inline Order *GetLastOrder() const
    00561   {
    00562     return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
    00563   }
    00564
    00565   bool IsEngineCountable() const;
    00566 };
    00567
    00568 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
    00569 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
    00570
    00575 template <class T, VehicleType Type>
    00576 struct SpecializedVehicle : public Vehicle {
    00577   static const VehicleType EXPECTED_TYPE = Type;
    00578
    00582   FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
    00583
    00588   FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
    00589
    00594   FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
    00595
    00600   FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
    00601
    00606   FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
    00607
    00612   FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
    00613
    00614
    00620   static FORCEINLINE bool IsValidID(size_t index)
    00621   {
    00622     return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
    00623   }
    00624
    00629   static FORCEINLINE T *Get(size_t index)
    00630   {
    00631     return (T *)Vehicle::Get(index);
    00632   }
    00633
    00638   static FORCEINLINE T *GetIfValid(size_t index)
    00639   {
    00640     return IsValidID(index) ? Get(index) : NULL;
    00641   }
    00642
    00648   static FORCEINLINE T *From(Vehicle *v)
    00649   {
    00650     assert(v->type == Type);
    00651     return (T *)v;
    00652   }
    00653
    00659   static FORCEINLINE const T *From(const Vehicle *v)
    00660   {
    00661     assert(v->type == Type);
    00662     return (const T *)v;
    00663   }
    00664 };
    00665
    00666 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
    00667
    00671 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
    00672   uint16 image_override;
    00673   VehicleID big_ufo_destroyer_target;
    00674
    00676   DisasterVehicle() : SpecializedVehicle<DisasterVehicle, VEH_DISASTER>() {}
    00678   virtual ~DisasterVehicle() {}
    00679
    00680   const char *GetTypeString() const { return "disaster vehicle"; }
    00681   void UpdateDeltaXY(Direction direction);
    00682   bool Tick();
    00683 };
    00684
    00685 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
    00686
    00688 struct FreeUnitIDGenerator {
    00689   bool *cache;
    00690   UnitID maxid;
    00691   UnitID curid;
    00692
    00699   FreeUnitIDGenerator(VehicleType type, CompanyID owner);
    00700
    00702   UnitID NextID();
    00703
    00705   ~FreeUnitIDGenerator() { free(this->cache); }
    00706 };
    00707
    00708 static const int32 INVALID_COORD = 0x7fffffff;
    00709
    00710 #endif /* VEHICLE_BASE_H */