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 "timetable.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_AUTOMATE_TIMETABLE,
00048 VF_PATHFINDER_LOST,
00049 };
00050
00052 enum NewGRFCacheValidValues {
00053 NCVV_POSITION_CONSIST_LENGTH = 0,
00054 NCVV_POSITION_SAME_ID_LENGTH = 1,
00055 NCVV_CONSIST_CARGO_INFORMATION = 2,
00056 NCVV_COMPANY_INFORMATION = 3,
00057 NCVV_END,
00058 };
00059
00061 struct NewGRFCache {
00062
00063 uint32 position_consist_length;
00064 uint32 position_same_id_length;
00065 uint32 consist_cargo_information;
00066 uint32 company_information;
00067 uint8 cache_valid;
00068 };
00069
00071 enum VisualEffect {
00072 VE_OFFSET_START = 0,
00073 VE_OFFSET_COUNT = 4,
00074 VE_OFFSET_CENTRE = 8,
00075
00076 VE_TYPE_START = 4,
00077 VE_TYPE_COUNT = 2,
00078 VE_TYPE_DEFAULT = 0,
00079 VE_TYPE_STEAM = 1,
00080 VE_TYPE_DIESEL = 2,
00081 VE_TYPE_ELECTRIC = 3,
00082
00083 VE_DISABLE_EFFECT = 6,
00084 VE_DISABLE_WAGON_POWER = 7,
00085
00086 VE_DEFAULT = 0xFF,
00087 };
00088
00094 enum GroundVehicleSubtypeFlags {
00095 GVSF_FRONT = 0,
00096 GVSF_ARTICULATED_PART = 1,
00097 GVSF_WAGON = 2,
00098 GVSF_ENGINE = 3,
00099 GVSF_FREE_WAGON = 4,
00100 GVSF_MULTIHEADED = 5,
00101 };
00102
00104 struct VehicleCache {
00105 uint16 cached_max_speed;
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
00123 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
00124 private:
00125 Vehicle *next;
00126 Vehicle *previous;
00127 Vehicle *first;
00128
00129 Vehicle *next_shared;
00130 Vehicle *previous_shared;
00131
00132 Vehicle *ahead_separation;
00133 Vehicle *behind_separation;
00134
00135 bool CanLeaveWithCargo();
00136 public:
00137 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00138 friend void FixOldVehicles();
00139 friend void AfterLoadVehicles(bool part_of_load);
00140 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00141
00142 char *name;
00143
00144 TileIndex tile;
00145
00151 TileIndex dest_tile;
00152
00153 Money profit_this_year;
00154 Money profit_last_year;
00155 Money value;
00156
00157 CargoPayment *cargo_payment;
00158
00159
00160 uint32 current_order_time;
00161 uint32 current_loading_time;
00162 int32 lateness_counter;
00163 #if WALLCLOCK_NETWORK_COMPATIBLE
00164 Date timetable_start;
00165 #else
00166 DateTicks timetable_start;
00167 #endif
00168
00169 Rect coord;
00170
00171 Vehicle *next_hash;
00172 Vehicle **prev_hash;
00173
00174 Vehicle *next_new_hash;
00175 Vehicle **prev_new_hash;
00176 Vehicle **old_new_hash;
00177
00178 byte breakdown_severity;
00179 BreakdownType breakdown_type;
00180
00181 SpriteID colourmap;
00182
00183
00184 Year build_year;
00185 Date age;
00186 Date max_age;
00187 Date date_of_last_service;
00188 Date service_interval;
00189 uint16 reliability;
00190 uint16 reliability_spd_dec;
00191 byte breakdown_ctr;
00192 byte breakdown_delay;
00193 byte breakdowns_since_last_service;
00194 byte breakdown_chance;
00195
00196 int32 x_pos;
00197 int32 y_pos;
00198 int32 z_pos;
00199 DirectionByte direction;
00200
00201 OwnerByte owner;
00202 byte spritenum;
00203
00204
00205 SpriteID cur_image;
00206 byte x_extent;
00207 byte y_extent;
00208 byte z_extent;
00209 int8 x_offs;
00210 int8 y_offs;
00211 EngineID engine_type;
00212
00213 TextEffectID fill_percent_te_id;
00214 UnitID unitnumber;
00215
00216 uint16 cur_speed;
00217 byte subspeed;
00218 byte acceleration;
00219 uint32 motion_counter;
00220 byte progress;
00221
00222 byte random_bits;
00223 byte waiting_triggers;
00224
00225 StationID last_station_visited;
00226 StationID last_loading_station;
00227
00228 CargoID cargo_type;
00229 byte cargo_subtype;
00230 uint16 cargo_cap;
00231 VehicleCargoList cargo;
00232
00233 byte day_counter;
00234 byte tick_counter;
00235 uint16 running_ticks;
00236
00237 byte vehstatus;
00238 Order current_order;
00239 VehicleOrderID cur_real_order_index;
00240 VehicleOrderID cur_implicit_order_index;
00241
00242 union {
00243 OrderList *list;
00244 Order *old;
00245 } orders;
00246
00247 byte vehicle_flags;
00248
00249 uint16 load_unload_ticks;
00250 GroupID group_id;
00251 byte subtype;
00252
00253 NewGRFCache grf_cache;
00254 VehicleCache vcache;
00255
00256 Vehicle(VehicleType type = VEH_INVALID);
00257
00258 void PreDestructor();
00260 virtual ~Vehicle();
00261
00262 void BeginLoading();
00263 void CancelReservation(StationID next, Station *st);
00264 void LeaveStation();
00265
00266 GroundVehicleCache *GetGroundVehicleCache();
00267 const GroundVehicleCache *GetGroundVehicleCache() const;
00268
00269 uint16 &GetGroundVehicleFlags();
00270 const uint16 &GetGroundVehicleFlags() const;
00271
00272 void DeleteUnreachedImplicitOrders();
00273
00274 void HandleLoading(bool mode = false);
00275
00280 bool IsDrawn() const;
00281
00290 virtual void MarkDirty() {}
00291
00297 virtual void UpdateDeltaXY(Direction direction) {}
00298
00312 FORCEINLINE uint GetOldAdvanceSpeed(uint speed)
00313 {
00314 return (this->direction & 1) ? speed : speed * 3 / 4;
00315 }
00316
00329 static FORCEINLINE uint GetAdvanceSpeed(uint speed)
00330 {
00331 return speed * 3 / 4;
00332 }
00333
00341 FORCEINLINE uint GetAdvanceDistance()
00342 {
00343 return (this->direction & 1) ? 192 : 256;
00344 }
00345
00350 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00351
00355 virtual void PlayLeaveStationSound() const {}
00356
00360 virtual bool IsPrimaryVehicle() const { return false; }
00361
00367 virtual SpriteID GetImage(Direction direction) const { return 0; }
00368
00373 FORCEINLINE void InvalidateNewGRFCache()
00374 {
00375 this->grf_cache.cache_valid = 0;
00376 }
00377
00382 FORCEINLINE void InvalidateNewGRFCacheOfChain()
00383 {
00384 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00385 u->InvalidateNewGRFCache();
00386 }
00387 }
00388
00393 FORCEINLINE 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 Money GetRunningCost() const { return 0; }
00415
00420 virtual bool IsInDepot() const { return false; }
00421
00426 virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
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
00526 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00527
00532 inline Vehicle *AheadSeparation() const { return this->ahead_separation; }
00533
00538 inline Vehicle *BehindSeparation() const { return this->behind_separation; }
00539
00540 void ClearSeparation();
00541
00542 void InitSeparation();
00543
00544 void AddToSeparationBehind(Vehicle *v_other);
00545
00546 void AddToShared(Vehicle *shared_chain);
00547 void RemoveFromShared();
00548
00553 inline Vehicle *NextShared() const { return this->next_shared; }
00554
00559 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00560
00565 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00566
00571 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00572
00577 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00578
00583 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00584
00591 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00592 {
00593 this->unitnumber = src->unitnumber;
00594
00595 this->cur_real_order_index = src->cur_real_order_index;
00596 this->cur_implicit_order_index = src->cur_implicit_order_index;
00597 this->current_order = src->current_order;
00598 this->dest_tile = src->dest_tile;
00599
00600 this->profit_this_year = src->profit_this_year;
00601 this->profit_last_year = src->profit_last_year;
00602
00603 this->current_order_time = src->current_order_time;
00604 this->current_loading_time = src->current_loading_time;
00605 this->lateness_counter = src->lateness_counter;
00606 this->timetable_start = src->timetable_start;
00607
00608 if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
00609 if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00610 if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00611
00612 this->service_interval = src->service_interval;
00613 }
00614
00615
00616 bool HandleBreakdown();
00617
00618 bool NeedsAutorenewing(const Company *c) const;
00619
00620 bool NeedsServicing() const;
00621 bool NeedsAutomaticServicing() const;
00622
00630 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00631
00640 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00641
00642 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00643
00644 void UpdateVisualEffect(bool allow_power_change = true);
00645 void ShowVisualEffect() const;
00646
00647 private:
00652 void SkipToNextRealOrderIndex()
00653 {
00654 if (this->GetNumManualOrders() > 0) {
00655
00656 do {
00657 this->cur_real_order_index++;
00658 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00659 } while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT));
00660 } else {
00661 this->cur_real_order_index = 0;
00662 }
00663 }
00664
00665 public:
00671 void IncrementImplicitOrderIndex()
00672 {
00673 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00674
00675 this->SkipToNextRealOrderIndex();
00676 }
00677
00678 assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders());
00679
00680
00681 do {
00682 this->cur_implicit_order_index++;
00683 if (this->cur_implicit_order_index >= this->GetNumOrders()) this->cur_implicit_order_index = 0;
00684 } while (this->cur_implicit_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_implicit_order_index)->IsType(OT_IMPLICIT));
00685
00686 InvalidateVehicleOrder(this, 0);
00687 }
00688
00695 void IncrementRealOrderIndex()
00696 {
00697 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00698
00699 this->IncrementImplicitOrderIndex();
00700 } else {
00701
00702 this->SkipToNextRealOrderIndex();
00703 InvalidateVehicleOrder(this, 0);
00704 }
00705 }
00706
00710 void UpdateRealOrderIndex()
00711 {
00712
00713 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00714
00715 if (this->GetNumManualOrders() > 0) {
00716
00717 while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)) {
00718 this->cur_real_order_index++;
00719 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00720 }
00721 } else {
00722 this->cur_real_order_index = 0;
00723 }
00724 }
00725
00731 inline Order *GetOrder(int index) const
00732 {
00733 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00734 }
00735
00740 inline Order *GetLastOrder() const
00741 {
00742 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00743 }
00744
00745 bool IsEngineCountable() const;
00746 bool HasDepotOrder() const;
00747 void HandlePathfindingResult(bool path_found);
00748
00753 FORCEINLINE bool IsFrontEngine() const
00754 {
00755 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT);
00756 }
00757
00762 FORCEINLINE bool IsArticulatedPart() const
00763 {
00764 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_ARTICULATED_PART);
00765 }
00766
00771 FORCEINLINE bool HasArticulatedPart() const
00772 {
00773 return this->Next() != NULL && this->Next()->IsArticulatedPart();
00774 }
00775
00781 FORCEINLINE Vehicle *GetNextArticulatedPart() const
00782 {
00783 assert(this->HasArticulatedPart());
00784 return this->Next();
00785 }
00786
00791 FORCEINLINE Vehicle *GetFirstEnginePart()
00792 {
00793 Vehicle *v = this;
00794 while (v->IsArticulatedPart()) v = v->Previous();
00795 return v;
00796 }
00797
00802 FORCEINLINE const Vehicle *GetFirstEnginePart() const
00803 {
00804 const Vehicle *v = this;
00805 while (v->IsArticulatedPart()) v = v->Previous();
00806 return v;
00807 }
00808
00813 FORCEINLINE Vehicle *GetLastEnginePart()
00814 {
00815 Vehicle *v = this;
00816 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00817 return v;
00818 }
00819
00824 FORCEINLINE Vehicle *GetNextVehicle() const
00825 {
00826 const Vehicle *v = this;
00827 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00828
00829
00830 return v->Next();
00831 }
00832
00837 FORCEINLINE Vehicle *GetPrevVehicle() const
00838 {
00839 Vehicle *v = this->Previous();
00840 while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00841
00842 return v;
00843 }
00844 };
00845
00851 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00852
00857 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00858
00863 template <class T, VehicleType Type>
00864 struct SpecializedVehicle : public Vehicle {
00865 static const VehicleType EXPECTED_TYPE = Type;
00866
00867 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase;
00868
00872 FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00873
00878 FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
00879
00884 FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
00885
00890 FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
00891
00896 FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
00897
00902 FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
00903
00909 FORCEINLINE T *GetNextArticulatedPart() { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00910
00916 FORCEINLINE T *GetNextArticulatedPart() const { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00917
00922 FORCEINLINE T *GetFirstEnginePart() { return (T *)this->Vehicle::GetFirstEnginePart(); }
00923
00928 FORCEINLINE const T *GetFirstEnginePart() const { return (const T *)this->Vehicle::GetFirstEnginePart(); }
00929
00934 FORCEINLINE T *GetLastEnginePart() { return (T *)this->Vehicle::GetLastEnginePart(); }
00935
00940 FORCEINLINE T *GetNextVehicle() const { return (T *)this->Vehicle::GetNextVehicle(); }
00941
00946 FORCEINLINE T *GetPrevVehicle() const { return (T *)this->Vehicle::GetPrevVehicle(); }
00947
00953 static FORCEINLINE bool IsValidID(size_t index)
00954 {
00955 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00956 }
00957
00962 static FORCEINLINE T *Get(size_t index)
00963 {
00964 return (T *)Vehicle::Get(index);
00965 }
00966
00971 static FORCEINLINE T *GetIfValid(size_t index)
00972 {
00973 return IsValidID(index) ? Get(index) : NULL;
00974 }
00975
00981 static FORCEINLINE T *From(Vehicle *v)
00982 {
00983 assert(v->type == Type);
00984 return (T *)v;
00985 }
00986
00992 static FORCEINLINE const T *From(const Vehicle *v)
00993 {
00994 assert(v->type == Type);
00995 return (const T *)v;
00996 }
00997
01003 FORCEINLINE void UpdateViewport(bool moved, bool turned)
01004 {
01005 extern void VehicleMove(Vehicle *v, bool update_viewport);
01006
01007
01008
01009 if (turned) ((T *)this)->T::UpdateDeltaXY(this->direction);
01010 SpriteID old_image = this->cur_image;
01011 this->cur_image = ((T *)this)->T::GetImage(this->direction);
01012 if (moved || this->cur_image != old_image) VehicleMove(this, true);
01013 }
01014 };
01015
01021 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
01022
01026 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
01027 SpriteID image_override;
01028 VehicleID big_ufo_destroyer_target;
01029
01030
01031 bool in_max_height_correction;
01032 bool in_min_height_correction;
01033
01035 DisasterVehicle() : SpecializedVehicleBase() {}
01037 virtual ~DisasterVehicle() {}
01038
01039 void UpdateDeltaXY(Direction direction);
01040 bool Tick();
01041 };
01042
01047 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
01048
01050 struct FreeUnitIDGenerator {
01051 bool *cache;
01052 UnitID maxid;
01053 UnitID curid;
01054
01055 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
01056 UnitID NextID();
01057
01059 ~FreeUnitIDGenerator() { free(this->cache); }
01060 };
01061
01063 static const int32 INVALID_COORD = 0x7fffffff;
01064
01065 #endif