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
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 };
00049
00051 enum NewGRFCacheValidValues {
00052 NCVV_POSITION_CONSIST_LENGTH = 0,
00053 NCVV_POSITION_SAME_ID_LENGTH = 1,
00054 NCVV_CONSIST_CARGO_INFORMATION = 2,
00055 NCVV_COMPANY_INFORMATION = 3,
00056 NCVV_END,
00057 };
00058
00060 struct NewGRFCache {
00061
00062 uint32 position_consist_length;
00063 uint32 position_same_id_length;
00064 uint32 consist_cargo_information;
00065 uint32 company_information;
00066 uint8 cache_valid;
00067 };
00068
00070 enum VisualEffect {
00071 VE_OFFSET_START = 0,
00072 VE_OFFSET_COUNT = 4,
00073 VE_OFFSET_CENTRE = 8,
00074
00075 VE_TYPE_START = 4,
00076 VE_TYPE_COUNT = 2,
00077 VE_TYPE_DEFAULT = 0,
00078 VE_TYPE_STEAM = 1,
00079 VE_TYPE_DIESEL = 2,
00080 VE_TYPE_ELECTRIC = 3,
00081
00082 VE_DISABLE_EFFECT = 6,
00083 VE_DISABLE_WAGON_POWER = 7,
00084
00085 VE_DEFAULT = 0xFF,
00086 };
00087
00093 enum GroundVehicleSubtypeFlags {
00094 GVSF_FRONT = 0,
00095 GVSF_ARTICULATED_PART = 1,
00096 GVSF_WAGON = 2,
00097 GVSF_ENGINE = 3,
00098 GVSF_FREE_WAGON = 4,
00099 GVSF_MULTIHEADED = 5,
00100 };
00101
00103 struct VehicleCache {
00104 uint16 cached_max_speed;
00105 uint16 cached_cargo_age_period;
00106
00107 byte cached_vis_effect;
00108 };
00109
00111 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
00112 extern VehiclePool _vehicle_pool;
00113
00114
00115 struct SaveLoad;
00116 struct GroundVehicleCache;
00117 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00118 struct LoadgameState;
00119 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00120 extern void FixOldVehicles();
00121
00122 struct GRFFile;
00123
00125 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
00126 private:
00127 Vehicle *next;
00128 Vehicle *previous;
00129 Vehicle *first;
00130
00131 Vehicle *next_shared;
00132 Vehicle *previous_shared;
00133
00134 public:
00135 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00136 friend void FixOldVehicles();
00137 friend void AfterLoadVehicles(bool part_of_load);
00138 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00139
00140 char *name;
00141
00142 TileIndex tile;
00143
00149 TileIndex dest_tile;
00150
00151 Money profit_this_year;
00152 Money profit_last_year;
00153 Money value;
00154
00155 CargoPayment *cargo_payment;
00156
00157
00158 uint32 current_order_time;
00159 int32 lateness_counter;
00160 Date timetable_start;
00161
00162 Rect coord;
00163
00164 Vehicle *hash_viewport_next;
00165 Vehicle **hash_viewport_prev;
00166
00167 Vehicle *hash_tile_next;
00168 Vehicle **hash_tile_prev;
00169 Vehicle **hash_tile_current;
00170
00171 SpriteID colourmap;
00172
00173
00174 Year build_year;
00175 Date age;
00176 Date max_age;
00177 Date date_of_last_service;
00178 Date service_interval;
00179 uint16 reliability;
00180 uint16 reliability_spd_dec;
00181 byte breakdown_ctr;
00182 byte breakdown_delay;
00183 byte breakdowns_since_last_service;
00184 byte breakdown_chance;
00185
00186 int32 x_pos;
00187 int32 y_pos;
00188 int32 z_pos;
00189 DirectionByte direction;
00190
00191 OwnerByte owner;
00192
00197 byte spritenum;
00198 SpriteID cur_image;
00199 byte x_extent;
00200 byte y_extent;
00201 byte z_extent;
00202 int8 x_bb_offs;
00203 int8 y_bb_offs;
00204 int8 x_offs;
00205 int8 y_offs;
00206 EngineID engine_type;
00207
00208 TextEffectID fill_percent_te_id;
00209 UnitID unitnumber;
00210
00211 uint16 cur_speed;
00212 byte subspeed;
00213 byte acceleration;
00214 uint32 motion_counter;
00215 byte progress;
00216
00217 byte random_bits;
00218 byte waiting_triggers;
00219
00220 StationID last_station_visited;
00221 StationID last_loading_station;
00222
00223 CargoID cargo_type;
00224 byte cargo_subtype;
00225 uint16 cargo_cap;
00226 uint16 refit_cap;
00227 VehicleCargoList cargo;
00228 uint16 cargo_age_counter;
00229
00230 byte day_counter;
00231 byte tick_counter;
00232 byte running_ticks;
00233
00234 byte vehstatus;
00235 Order current_order;
00236 VehicleOrderID cur_real_order_index;
00237 VehicleOrderID cur_implicit_order_index;
00238
00239 union {
00240 OrderList *list;
00241 Order *old;
00242 } orders;
00243
00244 byte vehicle_flags;
00245
00246 uint16 load_unload_ticks;
00247 GroupID group_id;
00248 byte subtype;
00249
00250 NewGRFCache grf_cache;
00251 VehicleCache vcache;
00252
00253 Vehicle(VehicleType type = VEH_INVALID);
00254
00255 void PreDestructor();
00257 virtual ~Vehicle();
00258
00259 void BeginLoading();
00260 void CancelReservation(StationID next, Station *st);
00261 void LeaveStation();
00262
00263 GroundVehicleCache *GetGroundVehicleCache();
00264 const GroundVehicleCache *GetGroundVehicleCache() const;
00265
00266 uint16 &GetGroundVehicleFlags();
00267 const uint16 &GetGroundVehicleFlags() const;
00268
00269 void DeleteUnreachedImplicitOrders();
00270
00271 void HandleLoading(bool mode = false);
00272
00273 void GetConsistFreeCapacities(SmallMap<CargoID, uint> &capacities) const;
00274
00275 uint GetConsistTotalCapacity() const;
00276
00285 virtual void MarkDirty() {}
00286
00292 virtual void UpdateDeltaXY(Direction direction) {}
00293
00307 inline uint GetOldAdvanceSpeed(uint speed)
00308 {
00309 return (this->direction & 1) ? speed : speed * 3 / 4;
00310 }
00311
00324 static inline uint GetAdvanceSpeed(uint speed)
00325 {
00326 return speed * 3 / 4;
00327 }
00328
00336 inline uint GetAdvanceDistance()
00337 {
00338 return (this->direction & 1) ? 192 : 256;
00339 }
00340
00345 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00346
00350 virtual void PlayLeaveStationSound() const {}
00351
00355 virtual bool IsPrimaryVehicle() const { return false; }
00356
00357 const Engine *GetEngine() const;
00358
00364 virtual SpriteID GetImage(Direction direction, EngineImageType image_type) const { return 0; }
00365
00366 const GRFFile *GetGRF() const;
00367 uint32 GetGRFID() const;
00368
00373 inline void InvalidateNewGRFCache()
00374 {
00375 this->grf_cache.cache_valid = 0;
00376 }
00377
00382 inline void InvalidateNewGRFCacheOfChain()
00383 {
00384 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00385 u->InvalidateNewGRFCache();
00386 }
00387 }
00388
00393 inline bool IsGroundVehicle() const
00394 {
00395 return this->type == VEH_TRAIN || this->type == VEH_ROAD;
00396 }
00397
00402 virtual int GetDisplaySpeed() const { return 0; }
00403
00408 virtual int GetDisplayMaxSpeed() const { return 0; }
00409
00414 virtual int GetCurrentMaxSpeed() const { return 0; }
00415
00420 virtual Money GetRunningCost() const { return 0; }
00421
00426 virtual bool IsInDepot() const { return false; }
00427
00432 virtual bool IsChainInDepot() const { return this->IsInDepot(); }
00433
00438 bool IsStoppedInDepot() const
00439 {
00440 assert(this == this->First());
00441
00442 if (this->IsPrimaryVehicle() && !(this->vehstatus & VS_STOPPED)) return false;
00443 return this->IsChainInDepot();
00444 }
00445
00450 virtual bool Tick() { return true; };
00451
00455 virtual void OnNewDay() {};
00456
00462 virtual uint Crash(bool flooded = false);
00463
00476 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00477
00482 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00483
00488 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00489
00494 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00495
00496 void SetNext(Vehicle *next);
00497
00503 inline Vehicle *Next() const { return this->next; }
00504
00510 inline Vehicle *Previous() const { return this->previous; }
00511
00516 inline Vehicle *First() const { return this->first; }
00517
00522 inline Vehicle *Last()
00523 {
00524 Vehicle *v = this;
00525 while (v->Next() != NULL) v = v->Next();
00526 return v;
00527 }
00528
00533 inline const Vehicle *Last() const
00534 {
00535 const Vehicle *v = this;
00536 while (v->Next() != NULL) v = v->Next();
00537 return v;
00538 }
00539
00545 inline Vehicle *Move(int n)
00546 {
00547 Vehicle *v = this;
00548 if (n < 0) {
00549 for (int i = 0; i != n && v != NULL; i--) v = v->Previous();
00550 } else {
00551 for (int i = 0; i != n && v != NULL; i++) v = v->Next();
00552 }
00553 return v;
00554 }
00555
00560 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00561
00562 void AddToShared(Vehicle *shared_chain);
00563 void RemoveFromShared();
00564
00569 inline Vehicle *NextShared() const { return this->next_shared; }
00570
00575 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00576
00581 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00582
00587 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00588
00593 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00594
00599 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00600
00605 inline StationID GetNextStoppingStation() const
00606 {
00607 return (this->orders.list == NULL) ? INVALID_STATION : this->orders.list->GetNextStoppingStation(this);
00608 }
00609
00610 void RefreshNextHopsStats();
00611
00618 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00619 {
00620 this->unitnumber = src->unitnumber;
00621
00622 this->cur_real_order_index = src->cur_real_order_index;
00623 this->cur_implicit_order_index = src->cur_implicit_order_index;
00624 this->current_order = src->current_order;
00625 this->dest_tile = src->dest_tile;
00626
00627 this->profit_this_year = src->profit_this_year;
00628 this->profit_last_year = src->profit_last_year;
00629
00630 this->current_order_time = src->current_order_time;
00631 this->lateness_counter = src->lateness_counter;
00632 this->timetable_start = src->timetable_start;
00633
00634 if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
00635 if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00636 if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00637
00638 this->service_interval = src->service_interval;
00639 }
00640
00641
00642 bool HandleBreakdown();
00643
00644 bool NeedsAutorenewing(const Company *c, bool use_renew_setting = true) const;
00645
00646 bool NeedsServicing() const;
00647 bool NeedsAutomaticServicing() const;
00648
00656 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00657
00666 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00667
00668 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00669
00670 void UpdateVisualEffect(bool allow_power_change = true);
00671 void ShowVisualEffect() const;
00672
00673 private:
00678 void SkipToNextRealOrderIndex()
00679 {
00680 if (this->GetNumManualOrders() > 0) {
00681
00682 do {
00683 this->cur_real_order_index++;
00684 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00685 } while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT));
00686 } else {
00687 this->cur_real_order_index = 0;
00688 }
00689 }
00690
00691 public:
00697 void IncrementImplicitOrderIndex()
00698 {
00699 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00700
00701 this->SkipToNextRealOrderIndex();
00702 }
00703
00704 assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders());
00705
00706
00707 do {
00708 this->cur_implicit_order_index++;
00709 if (this->cur_implicit_order_index >= this->GetNumOrders()) this->cur_implicit_order_index = 0;
00710 } while (this->cur_implicit_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_implicit_order_index)->IsType(OT_IMPLICIT));
00711
00712 InvalidateVehicleOrder(this, 0);
00713 }
00714
00721 void IncrementRealOrderIndex()
00722 {
00723 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00724
00725 this->IncrementImplicitOrderIndex();
00726 } else {
00727
00728 this->SkipToNextRealOrderIndex();
00729 InvalidateVehicleOrder(this, 0);
00730 }
00731 }
00732
00736 void UpdateRealOrderIndex()
00737 {
00738
00739 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00740
00741 if (this->GetNumManualOrders() > 0) {
00742
00743 while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)) {
00744 this->cur_real_order_index++;
00745 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00746 }
00747 } else {
00748 this->cur_real_order_index = 0;
00749 }
00750 }
00751
00757 inline Order *GetOrder(int index) const
00758 {
00759 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00760 }
00761
00766 inline Order *GetLastOrder() const
00767 {
00768 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00769 }
00770
00771 bool IsEngineCountable() const;
00772 bool HasEngineType() const;
00773 bool HasDepotOrder() const;
00774 void HandlePathfindingResult(bool path_found);
00775
00780 inline bool IsFrontEngine() const
00781 {
00782 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT);
00783 }
00784
00789 inline bool IsArticulatedPart() const
00790 {
00791 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_ARTICULATED_PART);
00792 }
00793
00798 inline bool HasArticulatedPart() const
00799 {
00800 return this->Next() != NULL && this->Next()->IsArticulatedPart();
00801 }
00802
00808 inline Vehicle *GetNextArticulatedPart() const
00809 {
00810 assert(this->HasArticulatedPart());
00811 return this->Next();
00812 }
00813
00818 inline Vehicle *GetFirstEnginePart()
00819 {
00820 Vehicle *v = this;
00821 while (v->IsArticulatedPart()) v = v->Previous();
00822 return v;
00823 }
00824
00829 inline const Vehicle *GetFirstEnginePart() const
00830 {
00831 const Vehicle *v = this;
00832 while (v->IsArticulatedPart()) v = v->Previous();
00833 return v;
00834 }
00835
00840 inline Vehicle *GetLastEnginePart()
00841 {
00842 Vehicle *v = this;
00843 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00844 return v;
00845 }
00846
00851 inline Vehicle *GetNextVehicle() const
00852 {
00853 const Vehicle *v = this;
00854 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00855
00856
00857 return v->Next();
00858 }
00859
00864 inline Vehicle *GetPrevVehicle() const
00865 {
00866 Vehicle *v = this->Previous();
00867 while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00868
00869 return v;
00870 }
00871 };
00872
00878 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00879
00884 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00885
00890 template <class T, VehicleType Type>
00891 struct SpecializedVehicle : public Vehicle {
00892 static const VehicleType EXPECTED_TYPE = Type;
00893
00894 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase;
00895
00899 inline SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00900
00905 inline T *First() const { return (T *)this->Vehicle::First(); }
00906
00911 inline T *Last() { return (T *)this->Vehicle::Last(); }
00912
00917 inline const T *Last() const { return (const T *)this->Vehicle::Last(); }
00918
00923 inline T *Next() const { return (T *)this->Vehicle::Next(); }
00924
00929 inline T *Previous() const { return (T *)this->Vehicle::Previous(); }
00930
00936 inline T *GetNextArticulatedPart() { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00937
00943 inline T *GetNextArticulatedPart() const { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00944
00949 inline T *GetFirstEnginePart() { return (T *)this->Vehicle::GetFirstEnginePart(); }
00950
00955 inline const T *GetFirstEnginePart() const { return (const T *)this->Vehicle::GetFirstEnginePart(); }
00956
00961 inline T *GetLastEnginePart() { return (T *)this->Vehicle::GetLastEnginePart(); }
00962
00967 inline T *GetNextVehicle() const { return (T *)this->Vehicle::GetNextVehicle(); }
00968
00973 inline T *GetPrevVehicle() const { return (T *)this->Vehicle::GetPrevVehicle(); }
00974
00980 static inline bool IsValidID(size_t index)
00981 {
00982 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00983 }
00984
00989 static inline T *Get(size_t index)
00990 {
00991 return (T *)Vehicle::Get(index);
00992 }
00993
00998 static inline T *GetIfValid(size_t index)
00999 {
01000 return IsValidID(index) ? Get(index) : NULL;
01001 }
01002
01008 static inline T *From(Vehicle *v)
01009 {
01010 assert(v->type == Type);
01011 return (T *)v;
01012 }
01013
01019 static inline const T *From(const Vehicle *v)
01020 {
01021 assert(v->type == Type);
01022 return (const T *)v;
01023 }
01024
01030 inline void UpdateViewport(bool force_update, bool update_delta)
01031 {
01032 extern void VehicleUpdateViewport(Vehicle *v, bool dirty);
01033
01034
01035
01036 if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
01037 SpriteID old_image = this->cur_image;
01038 this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
01039 if (force_update || this->cur_image != old_image) VehicleUpdateViewport(this, true);
01040 }
01041 };
01042
01048 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
01049
01053 struct DisasterVehicle FINAL : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
01054 SpriteID image_override;
01055 VehicleID big_ufo_destroyer_target;
01056
01058 DisasterVehicle() : SpecializedVehicleBase() {}
01060 virtual ~DisasterVehicle() {}
01061
01062 void UpdateDeltaXY(Direction direction);
01063 bool Tick();
01064 };
01065
01070 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
01071
01073 struct FreeUnitIDGenerator {
01074 bool *cache;
01075 UnitID maxid;
01076 UnitID curid;
01077
01078 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
01079 UnitID NextID();
01080
01082 ~FreeUnitIDGenerator() { free(this->cache); }
01083 };
01084
01086 static const int32 INVALID_COORD = 0x7fffffff;
01087
01088 #endif