# vehicle_base.h

Go to the documentation of this file.

    00001 /* $Id: vehicle_base.h 18402 2009-12-04 20:29:46Z rubidium $ */
    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 "vehicle_type.h"
    00016 #include "track_type.h"
    00017 #include "cargo_type.h"
    00018 #include "direction_type.h"
    00019 #include "gfx_type.h"
    00020 #include "command_type.h"
    00021 #include "date_type.h"
    00022 #include "company_base.h"
    00023 #include "company_type.h"
    00024 #include "core/pool_type.hpp"
    00025 #include "order_base.h"
    00026 #include "cargopacket.h"
    00027 #include "texteff.hpp"
    00028 #include "group_type.h"
    00029 #include "engine_type.h"
    00030 #include "order_func.h"
    00031 #include "transport_type.h"
    00032
    00033 enum VehStatus {
    00034   VS_HIDDEN          = 0x01,
    00035   VS_STOPPED         = 0x02,
    00036   VS_UNCLICKABLE     = 0x04,
    00037   VS_DEFPAL          = 0x08,
    00038   VS_TRAIN_SLOWING   = 0x10,
    00039   VS_SHADOW          = 0x20,
    00040   VS_AIRCRAFT_BROKEN = 0x40,
    00041   VS_CRASHED         = 0x80,
    00042 };
    00043
    00044 enum VehicleFlags {
    00045   VF_LOADING_FINISHED,
    00046   VF_CARGO_UNLOADING,
    00047   VF_BUILT_AS_PROTOTYPE,
    00048   VF_TIMETABLE_STARTED,
    00049   VF_AUTOFILL_TIMETABLE,
    00050   VF_AUTOFILL_PRES_WAIT_TIME,
    00051 };
    00052
    00054 struct VehicleCache {
    00055   uint8 cache_valid;
    00056   uint32 cached_var40;
    00057   uint32 cached_var41;
    00058   uint32 cached_var42;
    00059   uint32 cached_var43;
    00060 };
    00061
    00062 typedef Pool<Vehicle, VehicleID, 512, 64000> VehiclePool;
    00063 extern VehiclePool _vehicle_pool;
    00064
    00065 /* Some declarations of functions, so we can make them friendly */
    00066 struct SaveLoad;
    00067 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
    00068 struct LoadgameState;
    00069 extern bool LoadOldVehicle(LoadgameState *ls, int num);
    00070 extern bool AfterLoadGame();
    00071 extern void FixOldVehicles();
    00072
    00073 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
    00074 private:
    00075   Vehicle *next;
    00076   Vehicle *previous;
    00077   Vehicle *first;
    00078
    00079   Vehicle *next_shared;
    00080   Vehicle *previous_shared;
    00081 public:
    00082   friend const SaveLoad *GetVehicleDescription(VehicleType vt);
    00083   friend bool AfterLoadGame();
    00084   friend void FixOldVehicles();
    00085   friend void AfterLoadVehicles(bool part_of_load);
    00086   friend bool LoadOldVehicle(LoadgameState *ls, int num);
    00087
    00088   char *name;
    00089
    00090   TileIndex tile;
    00091
    00097   TileIndex dest_tile;
    00098
    00099   Money profit_this_year;
    00100   Money profit_last_year;
    00101   Money value;
    00102
    00103   CargoPayment *cargo_payment;
    00104
    00105   /* Used for timetabling. */
    00106   uint32 current_order_time;
    00107   int32 lateness_counter;
    00108   Date timetable_start;
    00109
    00110   /* Boundaries for the current position in the world and a next hash link.
    00111    * NOSAVE: All of those can be updated with VehiclePositionChanged() */
    00112   Rect coord;
    00113   Vehicle *next_hash, **prev_hash;
    00114   Vehicle *next_new_hash, **prev_new_hash;
    00115   Vehicle **old_new_hash;
    00116
    00117   SpriteID colourmap; // NOSAVE: cached colour mapping
    00118
    00119   /* Related to age and service time */
    00120   Year build_year;
    00121   Date age;     // Age in days
    00122   Date max_age; // Maximum age
    00123   Date date_of_last_service;
    00124   Date service_interval;
    00125   uint16 reliability;
    00126   uint16 reliability_spd_dec;
    00127   byte breakdown_ctr;
    00128   byte breakdown_delay;
    00129   byte breakdowns_since_last_service;
    00130   byte breakdown_chance;
    00131
    00132   int32 x_pos;             // coordinates
    00133   int32 y_pos;
    00134   byte z_pos;
    00135   DirectionByte direction; // facing
    00136
    00137   OwnerByte owner;         // which company owns the vehicle?
    00138   byte spritenum;          // currently displayed sprite index
    00139                            // 0xfd == custom sprite, 0xfe == custom second head sprite
    00140                            // 0xff == reserved for another custom sprite
    00141   uint16 cur_image;        // sprite number for this vehicle
    00142   byte x_extent;           // x-extent of vehicle bounding box
    00143   byte y_extent;           // y-extent of vehicle bounding box
    00144   byte z_extent;           // z-extent of vehicle bounding box
    00145   int8 x_offs;             // x offset for vehicle sprite
    00146   int8 y_offs;             // y offset for vehicle sprite
    00147   EngineID engine_type;
    00148
    00149   TextEffectID fill_percent_te_id; // a text-effect id to a loading indicator object
    00150   UnitID unitnumber;       // unit number, for display purposes only
    00151
    00152   uint16 max_speed;
    00153   uint16 cur_speed;
    00154   byte subspeed;
    00155   byte acceleration;
    00156   uint32 motion_counter;
    00157   byte progress;
    00158
    00159   /* for randomized variational spritegroups
    00160    * bitmask used to resolve them; parts of it get reseeded when triggers
    00161    * of corresponding spritegroups get matched */
    00162   byte random_bits;
    00163   byte waiting_triggers;
    00164
    00165   StationID last_station_visited;
    00166
    00167   CargoID cargo_type;
    00168   byte cargo_subtype;
    00169   uint16 cargo_cap;
    00170   VehicleCargoList cargo;
    00171
    00172   byte day_counter;
    00173   byte tick_counter;
    00174   byte running_ticks;
    00175
    00176   byte vehstatus;
    00177   Order current_order;
    00178   VehicleOrderID cur_order_index;
    00179
    00180   union {
    00181     OrderList *list;
    00182     Order     *old;
    00183   } orders;
    00184
    00185   byte vehicle_flags;
    00186
    00193   uint16 time_counter;
    00194
    00195   GroupID group_id;
    00196
    00197   byte subtype;
    00198
    00199   VehicleCache vcache;
    00200
    00202   Vehicle(VehicleType type = VEH_INVALID);
    00203
    00205   void PreDestructor();
    00207   virtual ~Vehicle();
    00208
    00209   void BeginLoading();
    00210   void LeaveStation();
    00211
    00217   void HandleLoading(bool mode = false);
    00218
    00223   virtual const char *GetTypeString() const { return "base vehicle"; }
    00224
    00233   virtual void MarkDirty() {}
    00234
    00240   virtual void UpdateDeltaXY(Direction direction) {}
    00241
    00246   virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
    00247
    00251   virtual void PlayLeaveStationSound() const {}
    00252
    00256   virtual bool IsPrimaryVehicle() const { return false; }
    00257
    00263   virtual SpriteID GetImage(Direction direction) const { return 0; }
    00264
    00269   FORCEINLINE void InvalidateNewGRFCache()
    00270   {
    00271     this->vcache.cache_valid = 0;
    00272   }
    00273
    00278   FORCEINLINE void InvalidateNewGRFCacheOfChain()
    00279   {
    00280     for (Vehicle *u = this; u != NULL; u = u->Next()) {
    00281       u->InvalidateNewGRFCache();
    00282     }
    00283   }
    00284
    00289   virtual int GetDisplaySpeed() const { return 0; }
    00290
    00295   virtual int GetDisplayMaxSpeed() const { return 0; }
    00296
    00301   virtual Money GetRunningCost() const { return 0; }
    00302
    00307   virtual bool IsInDepot() const { return false; }
    00308
    00313   virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
    00314
    00319   virtual bool Tick() { return true; };
    00320
    00324   virtual void OnNewDay() {};
    00325
    00331   virtual uint Crash(bool flooded = false);
    00332
    00338   inline void UpdateViewport(bool moved, bool turned)
    00339   {
    00340     extern void VehicleMove(Vehicle *v, bool update_viewport);
    00341
    00342     if (turned) this->UpdateDeltaXY(this->direction);
    00343     SpriteID old_image = this->cur_image;
    00344     this->cur_image = this->GetImage(this->direction);
    00345     if (moved || this->cur_image != old_image) VehicleMove(this, true);
    00346   }
    00347
    00360   virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
    00361
    00366   Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
    00367
    00372   Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
    00373
    00378   Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
    00379
    00384   void SetNext(Vehicle *next);
    00385
    00391   inline Vehicle *Next() const { return this->next; }
    00392
    00398   inline Vehicle *Previous() const { return this->previous; }
    00399
    00404   inline Vehicle *First() const { return this->first; }
    00405
    00410   inline Vehicle *Last()
    00411   {
    00412     Vehicle *v = this;
    00413     while (v->Next() != NULL) v = v->Next();
    00414     return v;
    00415   }
    00416
    00421   inline const Vehicle *Last() const
    00422   {
    00423     const Vehicle *v = this;
    00424     while (v->Next() != NULL) v = v->Next();
    00425     return v;
    00426   }
    00427
    00432   inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
    00433
    00439   void AddToShared(Vehicle *shared_chain);
    00440
    00444   void RemoveFromShared();
    00445
    00450   inline Vehicle *NextShared() const { return this->next_shared; }
    00451
    00456   inline Vehicle *PreviousShared() const { return this->previous_shared; }
    00457
    00462   inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
    00463
    00468   inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
    00469
    00474   inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
    00475
    00482   inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
    00483   {
    00484     this->unitnumber = src->unitnumber;
    00485
    00486     this->cur_order_index = src->cur_order_index;
    00487     this->current_order = src->current_order;
    00488     this->dest_tile  = src->dest_tile;
    00489
    00490     this->profit_this_year = src->profit_this_year;
    00491     this->profit_last_year = src->profit_last_year;
    00492
    00493     this->current_order_time = src->current_order_time;
    00494     this->lateness_counter = src->lateness_counter;
    00495     this->timetable_start = src->timetable_start;
    00496
    00497     this->service_interval = src->service_interval;
    00498   }
    00499
    00500   bool NeedsAutorenewing(const Company *c) const;
    00501
    00508   bool NeedsServicing() const;
    00509
    00515   bool NeedsAutomaticServicing() const;
    00516
    00524   virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
    00525
    00534   virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
    00535
    00542   CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
    00543
    00548   void IncrementOrderIndex()
    00549   {
    00550     this->cur_order_index++;
    00551     if (this->cur_order_index >= this->GetNumOrders()) this->cur_order_index = 0;
    00552     InvalidateVehicleOrder(this, 0);
    00553   }
    00554
    00560   inline Order *GetOrder(int index) const
    00561   {
    00562     return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
    00563   }
    00564
    00569   inline Order *GetLastOrder() const
    00570   {
    00571     return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
    00572   }
    00573
    00574   bool IsEngineCountable() const;
    00575 };
    00576
    00577 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
    00578 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
    00579
    00584 template <class T, VehicleType Type>
    00585 struct SpecializedVehicle : public Vehicle {
    00586   static const VehicleType EXPECTED_TYPE = Type;
    00587
    00591   FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
    00592
    00597   FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
    00598
    00603   FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
    00604
    00609   FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
    00610
    00615   FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
    00616
    00621   FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
    00622
    00623
    00629   static FORCEINLINE bool IsValidID(size_t index)
    00630   {
    00631     return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
    00632   }
    00633
    00638   static FORCEINLINE T *Get(size_t index)
    00639   {
    00640     return (T *)Vehicle::Get(index);
    00641   }
    00642
    00647   static FORCEINLINE T *GetIfValid(size_t index)
    00648   {
    00649     return IsValidID(index) ? Get(index) : NULL;
    00650   }
    00651
    00657   static FORCEINLINE T *From(Vehicle *v)
    00658   {
    00659     assert(v->type == Type);
    00660     return (T *)v;
    00661   }
    00662
    00668   static FORCEINLINE const T *From(const Vehicle *v)
    00669   {
    00670     assert(v->type == Type);
    00671     return (const T *)v;
    00672   }
    00673 };
    00674
    00675 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
    00676
    00680 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
    00681   uint16 image_override;
    00682   VehicleID big_ufo_destroyer_target;
    00683
    00685   DisasterVehicle() : SpecializedVehicle<DisasterVehicle, VEH_DISASTER>() {}
    00687   virtual ~DisasterVehicle() {}
    00688
    00689   const char *GetTypeString() const { return "disaster vehicle"; }
    00690   void UpdateDeltaXY(Direction direction);
    00691   bool Tick();
    00692 };
    00693
    00694 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
    00695
    00697 struct FreeUnitIDGenerator {
    00698   bool *cache;
    00699   UnitID maxid;
    00700   UnitID curid;
    00701
    00708   FreeUnitIDGenerator(VehicleType type, CompanyID owner);
    00709
    00711   UnitID NextID();
    00712
    00714   ~FreeUnitIDGenerator() { free(this->cache); }
    00715 };
    00716
    00717 static const int32 INVALID_COORD = 0x7fffffff;
    00718
    00719 #endif /* VEHICLE_BASE_H */