00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef VEHICLE_BASE_H
00013 #define VEHICLE_BASE_H
00014
00015 #include "track_type.h"
00016 #include "command_type.h"
00017 #include "order_base.h"
00018 #include "cargopacket.h"
00019 #include "texteff.hpp"
00020 #include "engine_type.h"
00021 #include "order_func.h"
00022 #include "transport_type.h"
00023 #include "group_type.h"
00024 #include "base_consist.h"
00025
00027 enum VehStatus {
00028 VS_HIDDEN = 0x01,
00029 VS_STOPPED = 0x02,
00030 VS_UNCLICKABLE = 0x04,
00031 VS_DEFPAL = 0x08,
00032 VS_TRAIN_SLOWING = 0x10,
00033 VS_SHADOW = 0x20,
00034 VS_AIRCRAFT_BROKEN = 0x40,
00035 VS_CRASHED = 0x80,
00036 };
00037
00039 enum VehicleFlags {
00040 VF_LOADING_FINISHED,
00041 VF_CARGO_UNLOADING,
00042 VF_BUILT_AS_PROTOTYPE,
00043 VF_TIMETABLE_STARTED,
00044 VF_AUTOFILL_TIMETABLE,
00045 VF_AUTOFILL_PRES_WAIT_TIME,
00046 VF_STOP_LOADING,
00047 VF_PATHFINDER_LOST,
00048 VF_SERVINT_IS_CUSTOM,
00049 VF_SERVINT_IS_PERCENT,
00050 };
00051
00053 enum NewGRFCacheValidValues {
00054 NCVV_POSITION_CONSIST_LENGTH = 0,
00055 NCVV_POSITION_SAME_ID_LENGTH = 1,
00056 NCVV_CONSIST_CARGO_INFORMATION = 2,
00057 NCVV_COMPANY_INFORMATION = 3,
00058 NCVV_END,
00059 };
00060
00062 struct NewGRFCache {
00063
00064 uint32 position_consist_length;
00065 uint32 position_same_id_length;
00066 uint32 consist_cargo_information;
00067 uint32 company_information;
00068 uint8 cache_valid;
00069 };
00070
00072 enum VisualEffect {
00073 VE_OFFSET_START = 0,
00074 VE_OFFSET_COUNT = 4,
00075 VE_OFFSET_CENTRE = 8,
00076
00077 VE_TYPE_START = 4,
00078 VE_TYPE_COUNT = 2,
00079 VE_TYPE_DEFAULT = 0,
00080 VE_TYPE_STEAM = 1,
00081 VE_TYPE_DIESEL = 2,
00082 VE_TYPE_ELECTRIC = 3,
00083
00084 VE_DISABLE_EFFECT = 6,
00085 VE_DISABLE_WAGON_POWER = 7,
00086
00087 VE_DEFAULT = 0xFF,
00088 };
00089
00095 enum GroundVehicleSubtypeFlags {
00096 GVSF_FRONT = 0,
00097 GVSF_ARTICULATED_PART = 1,
00098 GVSF_WAGON = 2,
00099 GVSF_ENGINE = 3,
00100 GVSF_FREE_WAGON = 4,
00101 GVSF_MULTIHEADED = 5,
00102 };
00103
00105 struct VehicleCache {
00106 uint16 cached_max_speed;
00107 uint16 cached_cargo_age_period;
00108
00109 byte cached_vis_effect;
00110 };
00111
00113 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
00114 extern VehiclePool _vehicle_pool;
00115
00116
00117 struct SaveLoad;
00118 struct GroundVehicleCache;
00119 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00120 struct LoadgameState;
00121 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00122 extern void FixOldVehicles();
00123
00124 struct GRFFile;
00125
00127 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle, BaseConsist {
00128 private:
00129 Vehicle *next;
00130 Vehicle *previous;
00131 Vehicle *first;
00132
00133 Vehicle *next_shared;
00134 Vehicle *previous_shared;
00135 public:
00136 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00137 friend void FixOldVehicles();
00138 friend void AfterLoadVehicles(bool part_of_load);
00139 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00140
00141 TileIndex tile;
00142
00148 TileIndex dest_tile;
00149
00150 Money profit_this_year;
00151 Money profit_last_year;
00152 Money value;
00153
00154 CargoPayment *cargo_payment;
00155
00156 Rect coord;
00157
00158 Vehicle *hash_viewport_next;
00159 Vehicle **hash_viewport_prev;
00160
00161 Vehicle *hash_tile_next;
00162 Vehicle **hash_tile_prev;
00163 Vehicle **hash_tile_current;
00164
00165 SpriteID colourmap;
00166
00167
00168 Year build_year;
00169 Date age;
00170 Date max_age;
00171 Date date_of_last_service;
00172 uint16 reliability;
00173 uint16 reliability_spd_dec;
00174 byte breakdown_ctr;
00175 byte breakdown_delay;
00176 byte breakdowns_since_last_service;
00177 byte breakdown_chance;
00178
00179 int32 x_pos;
00180 int32 y_pos;
00181 int32 z_pos;
00182 DirectionByte direction;
00183
00184 OwnerByte owner;
00185
00190 byte spritenum;
00191 SpriteID cur_image;
00192 byte x_extent;
00193 byte y_extent;
00194 byte z_extent;
00195 int8 x_bb_offs;
00196 int8 y_bb_offs;
00197 int8 x_offs;
00198 int8 y_offs;
00199 EngineID engine_type;
00200
00201 TextEffectID fill_percent_te_id;
00202 UnitID unitnumber;
00203
00204 uint16 cur_speed;
00205 byte subspeed;
00206 byte acceleration;
00207 uint32 motion_counter;
00208 byte progress;
00209
00210 byte random_bits;
00211 byte waiting_triggers;
00212
00213 StationID last_station_visited;
00214
00215 CargoID cargo_type;
00216 byte cargo_subtype;
00217 uint16 cargo_cap;
00218 VehicleCargoList cargo;
00219 uint16 cargo_age_counter;
00220
00221 byte day_counter;
00222 byte tick_counter;
00223 byte running_ticks;
00224
00225 byte vehstatus;
00226 Order current_order;
00227
00228 union {
00229 OrderList *list;
00230 Order *old;
00231 } orders;
00232
00233 uint16 load_unload_ticks;
00234 GroupID group_id;
00235 byte subtype;
00236
00237 NewGRFCache grf_cache;
00238 VehicleCache vcache;
00239
00240 Vehicle(VehicleType type = VEH_INVALID);
00241
00242 void PreDestructor();
00244 virtual ~Vehicle();
00245
00246 void BeginLoading();
00247 void LeaveStation();
00248
00249 GroundVehicleCache *GetGroundVehicleCache();
00250 const GroundVehicleCache *GetGroundVehicleCache() const;
00251
00252 uint16 &GetGroundVehicleFlags();
00253 const uint16 &GetGroundVehicleFlags() const;
00254
00255 void DeleteUnreachedImplicitOrders();
00256
00257 void HandleLoading(bool mode = false);
00258
00267 virtual void MarkDirty() {}
00268
00274 virtual void UpdateDeltaXY(Direction direction) {}
00275
00289 inline uint GetOldAdvanceSpeed(uint speed)
00290 {
00291 return (this->direction & 1) ? speed : speed * 3 / 4;
00292 }
00293
00306 static inline uint GetAdvanceSpeed(uint speed)
00307 {
00308 return speed * 3 / 4;
00309 }
00310
00318 inline uint GetAdvanceDistance()
00319 {
00320 return (this->direction & 1) ? 192 : 256;
00321 }
00322
00327 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00328
00332 virtual void PlayLeaveStationSound() const {}
00333
00337 virtual bool IsPrimaryVehicle() const { return false; }
00338
00339 const Engine *GetEngine() const;
00340
00346 virtual SpriteID GetImage(Direction direction, EngineImageType image_type) const { return 0; }
00347
00348 const GRFFile *GetGRF() const;
00349 uint32 GetGRFID() const;
00350
00355 inline void InvalidateNewGRFCache()
00356 {
00357 this->grf_cache.cache_valid = 0;
00358 }
00359
00364 inline void InvalidateNewGRFCacheOfChain()
00365 {
00366 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00367 u->InvalidateNewGRFCache();
00368 }
00369 }
00370
00375 inline bool IsGroundVehicle() const
00376 {
00377 return this->type == VEH_TRAIN || this->type == VEH_ROAD;
00378 }
00379
00384 virtual int GetDisplaySpeed() const { return 0; }
00385
00390 virtual int GetDisplayMaxSpeed() const { return 0; }
00391
00396 virtual int GetCurrentMaxSpeed() const { return 0; }
00397
00402 virtual Money GetRunningCost() const { return 0; }
00403
00408 virtual bool IsInDepot() const { return false; }
00409
00414 virtual bool IsChainInDepot() const { return this->IsInDepot(); }
00415
00420 bool IsStoppedInDepot() const
00421 {
00422 assert(this == this->First());
00423
00424 if (this->IsPrimaryVehicle() && !(this->vehstatus & VS_STOPPED)) return false;
00425 return this->IsChainInDepot();
00426 }
00427
00432 virtual bool Tick() { return true; };
00433
00437 virtual void OnNewDay() {};
00438
00444 virtual uint Crash(bool flooded = false);
00445
00458 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00459
00464 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00465
00470 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00471
00476 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00477
00478 void SetNext(Vehicle *next);
00479
00485 inline Vehicle *Next() const { return this->next; }
00486
00492 inline Vehicle *Previous() const { return this->previous; }
00493
00498 inline Vehicle *First() const { return this->first; }
00499
00504 inline Vehicle *Last()
00505 {
00506 Vehicle *v = this;
00507 while (v->Next() != NULL) v = v->Next();
00508 return v;
00509 }
00510
00515 inline const Vehicle *Last() const
00516 {
00517 const Vehicle *v = this;
00518 while (v->Next() != NULL) v = v->Next();
00519 return v;
00520 }
00521
00527 inline Vehicle *Move(int n)
00528 {
00529 Vehicle *v = this;
00530 if (n < 0) {
00531 for (int i = 0; i != n && v != NULL; i--) v = v->Previous();
00532 } else {
00533 for (int i = 0; i != n && v != NULL; i++) v = v->Next();
00534 }
00535 return v;
00536 }
00537
00543 inline const Vehicle *Move(int n) const
00544 {
00545 const Vehicle *v = this;
00546 if (n < 0) {
00547 for (int i = 0; i != n && v != NULL; i--) v = v->Previous();
00548 } else {
00549 for (int i = 0; i != n && v != NULL; i++) v = v->Next();
00550 }
00551 return v;
00552 }
00553
00558 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00559
00560 void AddToShared(Vehicle *shared_chain);
00561 void RemoveFromShared();
00562
00567 inline Vehicle *NextShared() const { return this->next_shared; }
00568
00573 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00574
00579 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00580
00585 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00586
00591 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00592
00597 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00598
00605 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00606 {
00607 this->CopyConsistPropertiesFrom(src);
00608
00609 this->unitnumber = src->unitnumber;
00610
00611 this->current_order = src->current_order;
00612 this->dest_tile = src->dest_tile;
00613
00614 this->profit_this_year = src->profit_this_year;
00615 this->profit_last_year = src->profit_last_year;
00616 }
00617
00618
00619 bool HandleBreakdown();
00620
00621 bool NeedsAutorenewing(const Company *c, bool use_renew_setting = true) const;
00622
00623 bool NeedsServicing() const;
00624 bool NeedsAutomaticServicing() const;
00625
00633 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00634
00643 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00644
00645 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00646
00647 void UpdateVisualEffect(bool allow_power_change = true);
00648 void ShowVisualEffect() const;
00649
00650 inline uint16 GetServiceInterval() const { return this->service_interval; }
00651
00652 inline void SetServiceInterval(uint16 interval) { this->service_interval = interval; }
00653
00654 inline bool ServiceIntervalIsCustom() const { return HasBit(this->vehicle_flags, VF_SERVINT_IS_CUSTOM); }
00655
00656 inline bool ServiceIntervalIsPercent() const { return HasBit(this->vehicle_flags, VF_SERVINT_IS_PERCENT); }
00657
00658 inline void SetServiceIntervalIsCustom(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_CUSTOM, 1, on); }
00659
00660 inline void SetServiceIntervalIsPercent(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_PERCENT, 1, on); }
00661
00662 private:
00667 void SkipToNextRealOrderIndex()
00668 {
00669 if (this->GetNumManualOrders() > 0) {
00670
00671 do {
00672 this->cur_real_order_index++;
00673 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00674 } while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT));
00675 } else {
00676 this->cur_real_order_index = 0;
00677 }
00678 }
00679
00680 public:
00686 void IncrementImplicitOrderIndex()
00687 {
00688 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00689
00690 this->SkipToNextRealOrderIndex();
00691 }
00692
00693 assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders());
00694
00695
00696 do {
00697 this->cur_implicit_order_index++;
00698 if (this->cur_implicit_order_index >= this->GetNumOrders()) this->cur_implicit_order_index = 0;
00699 } while (this->cur_implicit_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_implicit_order_index)->IsType(OT_IMPLICIT));
00700
00701 InvalidateVehicleOrder(this, 0);
00702 }
00703
00710 void IncrementRealOrderIndex()
00711 {
00712 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00713
00714 this->IncrementImplicitOrderIndex();
00715 } else {
00716
00717 this->SkipToNextRealOrderIndex();
00718 InvalidateVehicleOrder(this, 0);
00719 }
00720 }
00721
00725 void UpdateRealOrderIndex()
00726 {
00727
00728 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00729
00730 if (this->GetNumManualOrders() > 0) {
00731
00732 while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)) {
00733 this->cur_real_order_index++;
00734 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00735 }
00736 } else {
00737 this->cur_real_order_index = 0;
00738 }
00739 }
00740
00746 inline Order *GetOrder(int index) const
00747 {
00748 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00749 }
00750
00755 inline Order *GetLastOrder() const
00756 {
00757 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00758 }
00759
00760 bool IsEngineCountable() const;
00761 bool HasEngineType() const;
00762 bool HasDepotOrder() const;
00763 void HandlePathfindingResult(bool path_found);
00764
00769 inline bool IsFrontEngine() const
00770 {
00771 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT);
00772 }
00773
00778 inline bool IsArticulatedPart() const
00779 {
00780 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_ARTICULATED_PART);
00781 }
00782
00787 inline bool HasArticulatedPart() const
00788 {
00789 return this->Next() != NULL && this->Next()->IsArticulatedPart();
00790 }
00791
00797 inline Vehicle *GetNextArticulatedPart() const
00798 {
00799 assert(this->HasArticulatedPart());
00800 return this->Next();
00801 }
00802
00807 inline Vehicle *GetFirstEnginePart()
00808 {
00809 Vehicle *v = this;
00810 while (v->IsArticulatedPart()) v = v->Previous();
00811 return v;
00812 }
00813
00818 inline const Vehicle *GetFirstEnginePart() const
00819 {
00820 const Vehicle *v = this;
00821 while (v->IsArticulatedPart()) v = v->Previous();
00822 return v;
00823 }
00824
00829 inline Vehicle *GetLastEnginePart()
00830 {
00831 Vehicle *v = this;
00832 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00833 return v;
00834 }
00835
00840 inline Vehicle *GetNextVehicle() const
00841 {
00842 const Vehicle *v = this;
00843 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00844
00845
00846 return v->Next();
00847 }
00848
00853 inline Vehicle *GetPrevVehicle() const
00854 {
00855 Vehicle *v = this->Previous();
00856 while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00857
00858 return v;
00859 }
00860 };
00861
00867 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00868
00873 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00874
00879 template <class T, VehicleType Type>
00880 struct SpecializedVehicle : public Vehicle {
00881 static const VehicleType EXPECTED_TYPE = Type;
00882
00883 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase;
00884
00888 inline SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00889
00894 inline T *First() const { return (T *)this->Vehicle::First(); }
00895
00900 inline T *Last() { return (T *)this->Vehicle::Last(); }
00901
00906 inline const T *Last() const { return (const T *)this->Vehicle::Last(); }
00907
00912 inline T *Next() const { return (T *)this->Vehicle::Next(); }
00913
00918 inline T *Previous() const { return (T *)this->Vehicle::Previous(); }
00919
00925 inline T *GetNextArticulatedPart() { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00926
00932 inline T *GetNextArticulatedPart() const { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00933
00938 inline T *GetFirstEnginePart() { return (T *)this->Vehicle::GetFirstEnginePart(); }
00939
00944 inline const T *GetFirstEnginePart() const { return (const T *)this->Vehicle::GetFirstEnginePart(); }
00945
00950 inline T *GetLastEnginePart() { return (T *)this->Vehicle::GetLastEnginePart(); }
00951
00956 inline T *GetNextVehicle() const { return (T *)this->Vehicle::GetNextVehicle(); }
00957
00962 inline T *GetPrevVehicle() const { return (T *)this->Vehicle::GetPrevVehicle(); }
00963
00969 static inline bool IsValidID(size_t index)
00970 {
00971 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00972 }
00973
00978 static inline T *Get(size_t index)
00979 {
00980 return (T *)Vehicle::Get(index);
00981 }
00982
00987 static inline T *GetIfValid(size_t index)
00988 {
00989 return IsValidID(index) ? Get(index) : NULL;
00990 }
00991
00997 static inline T *From(Vehicle *v)
00998 {
00999 assert(v->type == Type);
01000 return (T *)v;
01001 }
01002
01008 static inline const T *From(const Vehicle *v)
01009 {
01010 assert(v->type == Type);
01011 return (const T *)v;
01012 }
01013
01019 inline void UpdateViewport(bool force_update, bool update_delta)
01020 {
01021 extern void VehicleUpdateViewport(Vehicle *v, bool dirty);
01022
01023
01024
01025 if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
01026 SpriteID old_image = this->cur_image;
01027 this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
01028 if (force_update || this->cur_image != old_image) VehicleUpdateViewport(this, true);
01029 }
01030 };
01031
01037 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
01038
01042 struct DisasterVehicle FINAL : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
01043 SpriteID image_override;
01044 VehicleID big_ufo_destroyer_target;
01045
01047 DisasterVehicle() : SpecializedVehicleBase() {}
01049 virtual ~DisasterVehicle() {}
01050
01051 void UpdateDeltaXY(Direction direction);
01052 bool Tick();
01053 };
01054
01059 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
01060
01062 struct FreeUnitIDGenerator {
01063 bool *cache;
01064 UnitID maxid;
01065 UnitID curid;
01066
01067 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
01068 UnitID NextID();
01069
01071 ~FreeUnitIDGenerator() { free(this->cache); }
01072 };
01073
01075 static const int32 INVALID_COORD = 0x7fffffff;
01076
01077 #endif