00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef VEHICLE_BASE_H
00013 #define VEHICLE_BASE_H
00014
00015 #include "core/smallmap_type.hpp"
00016 #include "track_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 #include "group_type.h"
00025 #include "base_consist.h"
00026 #include <list>
00027 #include <map>
00028
00030 enum VehStatus {
00031 VS_HIDDEN = 0x01,
00032 VS_STOPPED = 0x02,
00033 VS_UNCLICKABLE = 0x04,
00034 VS_DEFPAL = 0x08,
00035 VS_TRAIN_SLOWING = 0x10,
00036 VS_SHADOW = 0x20,
00037 VS_AIRCRAFT_BROKEN = 0x40,
00038 VS_CRASHED = 0x80,
00039 };
00040
00042 enum VehicleFlags {
00043 VF_LOADING_FINISHED,
00044 VF_CARGO_UNLOADING,
00045 VF_BUILT_AS_PROTOTYPE,
00046 VF_TIMETABLE_STARTED,
00047 VF_AUTOFILL_TIMETABLE,
00048 VF_AUTOFILL_PRES_WAIT_TIME,
00049 VF_STOP_LOADING,
00050 VF_PATHFINDER_LOST,
00051 VF_SERVINT_IS_CUSTOM,
00052 VF_SERVINT_IS_PERCENT,
00053 };
00054
00056 enum NewGRFCacheValidValues {
00057 NCVV_POSITION_CONSIST_LENGTH = 0,
00058 NCVV_POSITION_SAME_ID_LENGTH = 1,
00059 NCVV_CONSIST_CARGO_INFORMATION = 2,
00060 NCVV_COMPANY_INFORMATION = 3,
00061 NCVV_POSITION_IN_VEHICLE = 4,
00062 NCVV_END,
00063 };
00064
00066 struct NewGRFCache {
00067
00068 uint32 position_consist_length;
00069 uint32 position_same_id_length;
00070 uint32 consist_cargo_information;
00071 uint32 company_information;
00072 uint32 position_in_vehicle;
00073 uint8 cache_valid;
00074 };
00075
00077 enum VisualEffect {
00078 VE_OFFSET_START = 0,
00079 VE_OFFSET_COUNT = 4,
00080 VE_OFFSET_CENTRE = 8,
00081
00082 VE_TYPE_START = 4,
00083 VE_TYPE_COUNT = 2,
00084 VE_TYPE_DEFAULT = 0,
00085 VE_TYPE_STEAM = 1,
00086 VE_TYPE_DIESEL = 2,
00087 VE_TYPE_ELECTRIC = 3,
00088
00089 VE_DISABLE_EFFECT = 6,
00090 VE_DISABLE_WAGON_POWER = 7,
00091
00092 VE_DEFAULT = 0xFF,
00093 };
00094
00100 enum GroundVehicleSubtypeFlags {
00101 GVSF_FRONT = 0,
00102 GVSF_ARTICULATED_PART = 1,
00103 GVSF_WAGON = 2,
00104 GVSF_ENGINE = 3,
00105 GVSF_FREE_WAGON = 4,
00106 GVSF_MULTIHEADED = 5,
00107 };
00108
00110 struct VehicleCache {
00111 uint16 cached_max_speed;
00112 uint16 cached_cargo_age_period;
00113
00114 byte cached_vis_effect;
00115 };
00116
00118 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
00119 extern VehiclePool _vehicle_pool;
00120
00121
00122 struct SaveLoad;
00123 struct GroundVehicleCache;
00124 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00125 struct LoadgameState;
00126 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00127 extern void FixOldVehicles();
00128
00129 struct GRFFile;
00130
00134 struct RefitDesc {
00135 CargoID cargo;
00136 uint16 capacity;
00137 uint16 remaining;
00138 RefitDesc(CargoID cargo, uint16 capacity, uint16 remaining) :
00139 cargo(cargo), capacity(capacity), remaining(remaining) {}
00140 };
00141
00143 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle, BaseConsist {
00144 private:
00145 typedef std::list<RefitDesc> RefitList;
00146 typedef std::map<CargoID, uint> CapacitiesMap;
00147
00148 Vehicle *next;
00149 Vehicle *previous;
00150 Vehicle *first;
00151
00152 Vehicle *next_shared;
00153 Vehicle *previous_shared;
00154
00155 public:
00156 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00157 friend void FixOldVehicles();
00158 friend void AfterLoadVehicles(bool part_of_load);
00159 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00160
00161 TileIndex tile;
00162
00168 TileIndex dest_tile;
00169
00170 Money profit_this_year;
00171 Money profit_last_year;
00172 Money value;
00173
00174 CargoPayment *cargo_payment;
00175
00176 Rect coord;
00177
00178 Vehicle *hash_viewport_next;
00179 Vehicle **hash_viewport_prev;
00180
00181 Vehicle *hash_tile_next;
00182 Vehicle **hash_tile_prev;
00183 Vehicle **hash_tile_current;
00184
00185 SpriteID colourmap;
00186
00187
00188 Year build_year;
00189 Date age;
00190 Date max_age;
00191 Date date_of_last_service;
00192 uint16 reliability;
00193 uint16 reliability_spd_dec;
00194 byte breakdown_ctr;
00195 byte breakdown_delay;
00196 byte breakdowns_since_last_service;
00197 byte breakdown_chance;
00198
00199 int32 x_pos;
00200 int32 y_pos;
00201 int32 z_pos;
00202 DirectionByte direction;
00203
00204 OwnerByte owner;
00205
00210 byte spritenum;
00211 SpriteID cur_image;
00212 byte x_extent;
00213 byte y_extent;
00214 byte z_extent;
00215 int8 x_bb_offs;
00216 int8 y_bb_offs;
00217 int8 x_offs;
00218 int8 y_offs;
00219 EngineID engine_type;
00220
00221 TextEffectID fill_percent_te_id;
00222 UnitID unitnumber;
00223
00224 uint16 cur_speed;
00225 byte subspeed;
00226 byte acceleration;
00227 uint32 motion_counter;
00228 byte progress;
00229
00230 byte random_bits;
00231 byte waiting_triggers;
00232
00233 StationID last_station_visited;
00234 StationID last_loading_station;
00235
00236 CargoID cargo_type;
00237 byte cargo_subtype;
00238 uint16 cargo_cap;
00239 uint16 refit_cap;
00240 VehicleCargoList cargo;
00241 uint16 cargo_age_counter;
00242
00243 byte day_counter;
00244 byte tick_counter;
00245 byte running_ticks;
00246
00247 byte vehstatus;
00248 Order current_order;
00249
00250 union {
00251 OrderList *list;
00252 Order *old;
00253 } orders;
00254
00255 uint16 load_unload_ticks;
00256 GroupID group_id;
00257 byte subtype;
00258
00259 NewGRFCache grf_cache;
00260 VehicleCache vcache;
00261
00262 Vehicle(VehicleType type = VEH_INVALID);
00263
00264 void PreDestructor();
00266 virtual ~Vehicle();
00267
00268 void BeginLoading();
00269 void CancelReservation(StationID next, Station *st);
00270 void LeaveStation();
00271
00272 GroundVehicleCache *GetGroundVehicleCache();
00273 const GroundVehicleCache *GetGroundVehicleCache() const;
00274
00275 uint16 &GetGroundVehicleFlags();
00276 const uint16 &GetGroundVehicleFlags() const;
00277
00278 void DeleteUnreachedImplicitOrders();
00279
00280 void HandleLoading(bool mode = false);
00281
00282 void GetConsistFreeCapacities(SmallMap<CargoID, uint> &capacities) const;
00283
00284 uint GetConsistTotalCapacity() const;
00285
00294 virtual void MarkDirty() {}
00295
00301 virtual void UpdateDeltaXY(Direction direction) {}
00302
00316 inline uint GetOldAdvanceSpeed(uint speed)
00317 {
00318 return (this->direction & 1) ? speed : speed * 3 / 4;
00319 }
00320
00333 static inline uint GetAdvanceSpeed(uint speed)
00334 {
00335 return speed * 3 / 4;
00336 }
00337
00345 inline uint GetAdvanceDistance()
00346 {
00347 return (this->direction & 1) ? 192 : 256;
00348 }
00349
00354 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00355
00359 virtual void PlayLeaveStationSound() const {}
00360
00364 virtual bool IsPrimaryVehicle() const { return false; }
00365
00366 const Engine *GetEngine() const;
00367
00373 virtual SpriteID GetImage(Direction direction, EngineImageType image_type) const { return 0; }
00374
00375 const GRFFile *GetGRF() const;
00376 uint32 GetGRFID() const;
00377
00382 inline void InvalidateNewGRFCache()
00383 {
00384 this->grf_cache.cache_valid = 0;
00385 }
00386
00391 inline void InvalidateNewGRFCacheOfChain()
00392 {
00393 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00394 u->InvalidateNewGRFCache();
00395 }
00396 }
00397
00402 inline bool IsGroundVehicle() const
00403 {
00404 return this->type == VEH_TRAIN || this->type == VEH_ROAD;
00405 }
00406
00411 virtual int GetDisplaySpeed() const { return 0; }
00412
00417 virtual int GetDisplayMaxSpeed() const { return 0; }
00418
00423 virtual int GetCurrentMaxSpeed() const { return 0; }
00424
00429 virtual Money GetRunningCost() const { return 0; }
00430
00435 virtual bool IsInDepot() const { return false; }
00436
00441 virtual bool IsChainInDepot() const { return this->IsInDepot(); }
00442
00447 bool IsStoppedInDepot() const
00448 {
00449 assert(this == this->First());
00450
00451 if (this->IsPrimaryVehicle() && !(this->vehstatus & VS_STOPPED)) return false;
00452 return this->IsChainInDepot();
00453 }
00454
00459 virtual bool Tick() { return true; };
00460
00464 virtual void OnNewDay() {};
00465
00471 virtual uint Crash(bool flooded = false);
00472
00485 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00486
00491 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00492
00497 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00498
00503 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00504
00505 void SetNext(Vehicle *next);
00506
00512 inline Vehicle *Next() const { return this->next; }
00513
00519 inline Vehicle *Previous() const { return this->previous; }
00520
00525 inline Vehicle *First() const { return this->first; }
00526
00531 inline Vehicle *Last()
00532 {
00533 Vehicle *v = this;
00534 while (v->Next() != NULL) v = v->Next();
00535 return v;
00536 }
00537
00542 inline const Vehicle *Last() const
00543 {
00544 const Vehicle *v = this;
00545 while (v->Next() != NULL) v = v->Next();
00546 return v;
00547 }
00548
00554 inline Vehicle *Move(int n)
00555 {
00556 Vehicle *v = this;
00557 if (n < 0) {
00558 for (int i = 0; i != n && v != NULL; i--) v = v->Previous();
00559 } else {
00560 for (int i = 0; i != n && v != NULL; i++) v = v->Next();
00561 }
00562 return v;
00563 }
00564
00570 inline const Vehicle *Move(int n) const
00571 {
00572 const Vehicle *v = this;
00573 if (n < 0) {
00574 for (int i = 0; i != n && v != NULL; i--) v = v->Previous();
00575 } else {
00576 for (int i = 0; i != n && v != NULL; i++) v = v->Next();
00577 }
00578 return v;
00579 }
00580
00585 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00586
00587 void AddToShared(Vehicle *shared_chain);
00588 void RemoveFromShared();
00589
00594 inline Vehicle *NextShared() const { return this->next_shared; }
00595
00600 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00601
00606 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00607
00612 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00613
00618 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00619
00624 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00625
00630 inline StationIDStack GetNextStoppingStation() const
00631 {
00632 return (this->orders.list == NULL) ? INVALID_STATION : this->orders.list->GetNextStoppingStation(this);
00633 }
00634
00635 void ResetRefitCaps();
00636
00643 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00644 {
00645 this->CopyConsistPropertiesFrom(src);
00646
00647 this->unitnumber = src->unitnumber;
00648
00649 this->current_order = src->current_order;
00650 this->dest_tile = src->dest_tile;
00651
00652 this->profit_this_year = src->profit_this_year;
00653 this->profit_last_year = src->profit_last_year;
00654 }
00655
00656
00657 bool HandleBreakdown();
00658
00659 bool NeedsAutorenewing(const Company *c, bool use_renew_setting = true) const;
00660
00661 bool NeedsServicing() const;
00662 bool NeedsAutomaticServicing() const;
00663
00671 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00672
00681 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00682
00683 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00684
00685 void UpdateVisualEffect(bool allow_power_change = true);
00686 void ShowVisualEffect() const;
00687
00688 inline uint16 GetServiceInterval() const { return this->service_interval; }
00689
00690 inline void SetServiceInterval(uint16 interval) { this->service_interval = interval; }
00691
00692 inline bool ServiceIntervalIsCustom() const { return HasBit(this->vehicle_flags, VF_SERVINT_IS_CUSTOM); }
00693
00694 inline bool ServiceIntervalIsPercent() const { return HasBit(this->vehicle_flags, VF_SERVINT_IS_PERCENT); }
00695
00696 inline void SetServiceIntervalIsCustom(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_CUSTOM, 1, on); }
00697
00698 inline void SetServiceIntervalIsPercent(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_PERCENT, 1, on); }
00699
00700 private:
00705 void SkipToNextRealOrderIndex()
00706 {
00707 if (this->GetNumManualOrders() > 0) {
00708
00709 do {
00710 this->cur_real_order_index++;
00711 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00712 } while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT));
00713 } else {
00714 this->cur_real_order_index = 0;
00715 }
00716 }
00717
00718 public:
00724 void IncrementImplicitOrderIndex()
00725 {
00726 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00727
00728 this->SkipToNextRealOrderIndex();
00729 }
00730
00731 assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders());
00732
00733
00734 do {
00735 this->cur_implicit_order_index++;
00736 if (this->cur_implicit_order_index >= this->GetNumOrders()) this->cur_implicit_order_index = 0;
00737 } while (this->cur_implicit_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_implicit_order_index)->IsType(OT_IMPLICIT));
00738
00739 InvalidateVehicleOrder(this, 0);
00740 }
00741
00748 void IncrementRealOrderIndex()
00749 {
00750 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00751
00752 this->IncrementImplicitOrderIndex();
00753 } else {
00754
00755 this->SkipToNextRealOrderIndex();
00756 InvalidateVehicleOrder(this, 0);
00757 }
00758 }
00759
00763 void UpdateRealOrderIndex()
00764 {
00765
00766 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00767
00768 if (this->GetNumManualOrders() > 0) {
00769
00770 while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)) {
00771 this->cur_real_order_index++;
00772 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00773 }
00774 } else {
00775 this->cur_real_order_index = 0;
00776 }
00777 }
00778
00784 inline Order *GetOrder(int index) const
00785 {
00786 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00787 }
00788
00793 inline Order *GetLastOrder() const
00794 {
00795 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00796 }
00797
00798 bool IsEngineCountable() const;
00799 bool HasEngineType() const;
00800 bool HasDepotOrder() const;
00801 void HandlePathfindingResult(bool path_found);
00802
00807 inline bool IsFrontEngine() const
00808 {
00809 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT);
00810 }
00811
00816 inline bool IsArticulatedPart() const
00817 {
00818 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_ARTICULATED_PART);
00819 }
00820
00825 inline bool HasArticulatedPart() const
00826 {
00827 return this->Next() != NULL && this->Next()->IsArticulatedPart();
00828 }
00829
00835 inline Vehicle *GetNextArticulatedPart() const
00836 {
00837 assert(this->HasArticulatedPart());
00838 return this->Next();
00839 }
00840
00845 inline Vehicle *GetFirstEnginePart()
00846 {
00847 Vehicle *v = this;
00848 while (v->IsArticulatedPart()) v = v->Previous();
00849 return v;
00850 }
00851
00856 inline const Vehicle *GetFirstEnginePart() const
00857 {
00858 const Vehicle *v = this;
00859 while (v->IsArticulatedPart()) v = v->Previous();
00860 return v;
00861 }
00862
00867 inline Vehicle *GetLastEnginePart()
00868 {
00869 Vehicle *v = this;
00870 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00871 return v;
00872 }
00873
00878 inline Vehicle *GetNextVehicle() const
00879 {
00880 const Vehicle *v = this;
00881 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00882
00883
00884 return v->Next();
00885 }
00886
00891 inline Vehicle *GetPrevVehicle() const
00892 {
00893 Vehicle *v = this->Previous();
00894 while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00895
00896 return v;
00897 }
00898 };
00899
00905 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00906
00911 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00912
00917 template <class T, VehicleType Type>
00918 struct SpecializedVehicle : public Vehicle {
00919 static const VehicleType EXPECTED_TYPE = Type;
00920
00921 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase;
00922
00926 inline SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00927
00932 inline T *First() const { return (T *)this->Vehicle::First(); }
00933
00938 inline T *Last() { return (T *)this->Vehicle::Last(); }
00939
00944 inline const T *Last() const { return (const T *)this->Vehicle::Last(); }
00945
00950 inline T *Next() const { return (T *)this->Vehicle::Next(); }
00951
00956 inline T *Previous() const { return (T *)this->Vehicle::Previous(); }
00957
00963 inline T *GetNextArticulatedPart() { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00964
00970 inline T *GetNextArticulatedPart() const { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00971
00976 inline T *GetFirstEnginePart() { return (T *)this->Vehicle::GetFirstEnginePart(); }
00977
00982 inline const T *GetFirstEnginePart() const { return (const T *)this->Vehicle::GetFirstEnginePart(); }
00983
00988 inline T *GetLastEnginePart() { return (T *)this->Vehicle::GetLastEnginePart(); }
00989
00994 inline T *GetNextVehicle() const { return (T *)this->Vehicle::GetNextVehicle(); }
00995
01000 inline T *GetPrevVehicle() const { return (T *)this->Vehicle::GetPrevVehicle(); }
01001
01007 static inline bool IsValidID(size_t index)
01008 {
01009 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
01010 }
01011
01016 static inline T *Get(size_t index)
01017 {
01018 return (T *)Vehicle::Get(index);
01019 }
01020
01025 static inline T *GetIfValid(size_t index)
01026 {
01027 return IsValidID(index) ? Get(index) : NULL;
01028 }
01029
01035 static inline T *From(Vehicle *v)
01036 {
01037 assert(v->type == Type);
01038 return (T *)v;
01039 }
01040
01046 static inline const T *From(const Vehicle *v)
01047 {
01048 assert(v->type == Type);
01049 return (const T *)v;
01050 }
01051
01057 inline void UpdateViewport(bool force_update, bool update_delta)
01058 {
01059 extern void VehicleUpdateViewport(Vehicle *v, bool dirty);
01060
01061
01062
01063 if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
01064 SpriteID old_image = this->cur_image;
01065 this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
01066 if (force_update || this->cur_image != old_image) VehicleUpdateViewport(this, true);
01067 }
01068 };
01069
01075 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
01076
01080 struct DisasterVehicle FINAL : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
01081 SpriteID image_override;
01082 VehicleID big_ufo_destroyer_target;
01083
01085 DisasterVehicle() : SpecializedVehicleBase() {}
01087 virtual ~DisasterVehicle() {}
01088
01089 void UpdateDeltaXY(Direction direction);
01090 bool Tick();
01091 };
01092
01097 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
01098
01100 struct FreeUnitIDGenerator {
01101 bool *cache;
01102 UnitID maxid;
01103 UnitID curid;
01104
01105 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
01106 UnitID NextID();
01107
01109 ~FreeUnitIDGenerator() { free(this->cache); }
01110 };
01111
01113 static const int32 INVALID_COORD = 0x7fffffff;
01114
01115 #endif