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
00026 enum VehStatus {
00027 VS_HIDDEN = 0x01,
00028 VS_STOPPED = 0x02,
00029 VS_UNCLICKABLE = 0x04,
00030 VS_DEFPAL = 0x08,
00031 VS_TRAIN_SLOWING = 0x10,
00032 VS_SHADOW = 0x20,
00033 VS_AIRCRAFT_BROKEN = 0x40,
00034 VS_CRASHED = 0x80,
00035 };
00036
00038 enum VehicleFlags {
00039 VF_LOADING_FINISHED,
00040 VF_CARGO_UNLOADING,
00041 VF_BUILT_AS_PROTOTYPE,
00042 VF_TIMETABLE_STARTED,
00043 VF_AUTOFILL_TIMETABLE,
00044 VF_AUTOFILL_PRES_WAIT_TIME,
00045 VF_STOP_LOADING,
00046 VF_PATHFINDER_LOST,
00047 };
00048
00050 enum NewGRFCacheValidValues {
00051 NCVV_POSITION_CONSIST_LENGTH = 0,
00052 NCVV_POSITION_SAME_ID_LENGTH = 1,
00053 NCVV_CONSIST_CARGO_INFORMATION = 2,
00054 NCVV_COMPANY_INFORMATION = 3,
00055 NCVV_END,
00056 };
00057
00059 struct NewGRFCache {
00060
00061 uint32 position_consist_length;
00062 uint32 position_same_id_length;
00063 uint32 consist_cargo_information;
00064 uint32 company_information;
00065 uint8 cache_valid;
00066 };
00067
00069 enum VisualEffect {
00070 VE_OFFSET_START = 0,
00071 VE_OFFSET_COUNT = 4,
00072 VE_OFFSET_CENTRE = 8,
00073
00074 VE_TYPE_START = 4,
00075 VE_TYPE_COUNT = 2,
00076 VE_TYPE_DEFAULT = 0,
00077 VE_TYPE_STEAM = 1,
00078 VE_TYPE_DIESEL = 2,
00079 VE_TYPE_ELECTRIC = 3,
00080
00081 VE_DISABLE_EFFECT = 6,
00082 VE_DISABLE_WAGON_POWER = 7,
00083
00084 VE_DEFAULT = 0xFF,
00085 };
00086
00092 enum GroundVehicleSubtypeFlags {
00093 GVSF_FRONT = 0,
00094 GVSF_ARTICULATED_PART = 1,
00095 GVSF_WAGON = 2,
00096 GVSF_ENGINE = 3,
00097 GVSF_FREE_WAGON = 4,
00098 GVSF_MULTIHEADED = 5,
00099 };
00100
00102 struct VehicleCache {
00103 uint32 cached_cargo_mask;
00104 uint16 cached_max_speed;
00105
00106 byte cached_vis_effect;
00107 };
00108
00110 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
00111 extern VehiclePool _vehicle_pool;
00112
00113
00114 struct SaveLoad;
00115 struct GroundVehicleCache;
00116 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00117 struct LoadgameState;
00118 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00119 extern void FixOldVehicles();
00120
00122 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
00123 private:
00124 Vehicle *next;
00125 Vehicle *previous;
00126 Vehicle *first;
00127
00128 Vehicle *next_shared;
00129 Vehicle *previous_shared;
00130 public:
00131 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00132 friend void FixOldVehicles();
00133 friend void AfterLoadVehicles(bool part_of_load);
00134 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00135
00136 char *name;
00137
00138 TileIndex tile;
00139
00145 TileIndex dest_tile;
00146
00147 Money profit_this_year;
00148 Money profit_last_year;
00149 Money value;
00150
00151 CargoPayment *cargo_payment;
00152
00153
00154 uint32 current_order_time;
00155 int32 lateness_counter;
00156 Date timetable_start;
00157
00158 Rect coord;
00159
00160 Vehicle *next_hash;
00161 Vehicle **prev_hash;
00162
00163 Vehicle *next_new_hash;
00164 Vehicle **prev_new_hash;
00165 Vehicle **old_new_hash;
00166
00167 SpriteID colourmap;
00168
00169
00170 Year build_year;
00171 Date age;
00172 Date max_age;
00173 Date date_of_last_service;
00174 Date service_interval;
00175 uint16 reliability;
00176 uint16 reliability_spd_dec;
00177 byte breakdown_ctr;
00178 byte breakdown_delay;
00179 byte breakdowns_since_last_service;
00180 byte breakdown_chance;
00181
00182 int32 x_pos;
00183 int32 y_pos;
00184 byte z_pos;
00185 DirectionByte direction;
00186
00187 OwnerByte owner;
00188 byte spritenum;
00189
00190
00191 SpriteID cur_image;
00192 byte x_extent;
00193 byte y_extent;
00194 byte z_extent;
00195 int8 x_offs;
00196 int8 y_offs;
00197 EngineID engine_type;
00198
00199 TextEffectID fill_percent_te_id;
00200 UnitID unitnumber;
00201
00202 uint16 cur_speed;
00203 byte subspeed;
00204 byte acceleration;
00205 uint32 motion_counter;
00206 byte progress;
00207
00208 byte random_bits;
00209 byte waiting_triggers;
00210
00211 StationID last_station_visited;
00212 StationID last_station_loaded;
00213 OrderID last_order_id;
00214
00215 CargoID cargo_type;
00216 byte cargo_subtype;
00217 uint16 cargo_cap;
00218 VehicleCargoList cargo;
00219
00220 uint32 travel_time;
00221 byte day_counter;
00222 byte tick_counter;
00223 byte running_ticks;
00224
00225 byte vehstatus;
00226 Order current_order;
00227 VehicleOrderID cur_real_order_index;
00228 VehicleOrderID cur_implicit_order_index;
00229
00230 union {
00231 OrderList *list;
00232 Order *old;
00233 } orders;
00234
00235 byte vehicle_flags;
00236
00237 uint16 load_unload_ticks;
00238 GroupID group_id;
00239 byte subtype;
00240
00241 NewGRFCache grf_cache;
00242 VehicleCache vcache;
00243
00244 Vehicle(VehicleType type = VEH_INVALID);
00245
00246 void PreDestructor();
00248 virtual ~Vehicle();
00249
00250 void BeginLoading(StationID station);
00251 void LeaveStation();
00252
00253 GroundVehicleCache *GetGroundVehicleCache();
00254 const GroundVehicleCache *GetGroundVehicleCache() const;
00255
00256 uint16 &GetGroundVehicleFlags();
00257 const uint16 &GetGroundVehicleFlags() const;
00258
00259 void DeleteUnreachedImplicitOrders();
00260
00261 void HandleLoading(bool mode = false);
00262
00271 virtual void MarkDirty() {}
00272
00278 virtual void UpdateDeltaXY(Direction direction) {}
00279
00293 FORCEINLINE uint GetOldAdvanceSpeed(uint speed)
00294 {
00295 return (this->direction & 1) ? speed : speed * 3 / 4;
00296 }
00297
00310 static FORCEINLINE uint GetAdvanceSpeed(uint speed)
00311 {
00312 return speed * 3 / 4;
00313 }
00314
00322 FORCEINLINE uint GetAdvanceDistance()
00323 {
00324 return (this->direction & 1) ? 192 : 256;
00325 }
00326
00331 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00332
00336 virtual void PlayLeaveStationSound() const {}
00337
00341 virtual bool IsPrimaryVehicle() const { return false; }
00342
00348 virtual SpriteID GetImage(Direction direction) const { return 0; }
00349
00354 FORCEINLINE void InvalidateNewGRFCache()
00355 {
00356 this->grf_cache.cache_valid = 0;
00357 }
00358
00363 FORCEINLINE void InvalidateNewGRFCacheOfChain()
00364 {
00365 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00366 u->InvalidateNewGRFCache();
00367 }
00368 }
00369
00374 FORCEINLINE bool IsGroundVehicle() const
00375 {
00376 return this->type == VEH_TRAIN || this->type == VEH_ROAD;
00377 }
00378
00383 virtual int GetDisplaySpeed() const { return 0; }
00384
00389 virtual int GetDisplayMaxSpeed() const { return 0; }
00390
00395 virtual Money GetRunningCost() const { return 0; }
00396
00401 virtual bool IsInDepot() const { return false; }
00402
00407 virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
00408
00413 virtual bool Tick() { return true; };
00414
00418 virtual void OnNewDay() {};
00419
00425 virtual uint Crash(bool flooded = false);
00426
00439 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00440
00445 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00446
00451 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00452
00457 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00458
00459 void SetNext(Vehicle *next);
00460
00466 inline Vehicle *Next() const { return this->next; }
00467
00473 inline Vehicle *Previous() const { return this->previous; }
00474
00479 inline Vehicle *First() const { return this->first; }
00480
00485 inline Vehicle *Last()
00486 {
00487 Vehicle *v = this;
00488 while (v->Next() != NULL) v = v->Next();
00489 return v;
00490 }
00491
00496 inline const Vehicle *Last() const
00497 {
00498 const Vehicle *v = this;
00499 while (v->Next() != NULL) v = v->Next();
00500 return v;
00501 }
00502
00507 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00508
00509 void AddToShared(Vehicle *shared_chain);
00510 void RemoveFromShared();
00511
00516 inline Vehicle *NextShared() const { return this->next_shared; }
00517
00522 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00523
00528 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00529
00534 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00535
00540 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00541
00546 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00547
00554 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00555 {
00556 this->unitnumber = src->unitnumber;
00557
00558 this->cur_real_order_index = src->cur_real_order_index;
00559 this->cur_implicit_order_index = src->cur_implicit_order_index;
00560 this->current_order = src->current_order;
00561 this->dest_tile = src->dest_tile;
00562
00563 this->profit_this_year = src->profit_this_year;
00564 this->profit_last_year = src->profit_last_year;
00565
00566 this->current_order_time = src->current_order_time;
00567 this->lateness_counter = src->lateness_counter;
00568 this->timetable_start = src->timetable_start;
00569
00570 if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
00571 if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00572 if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00573
00574 this->service_interval = src->service_interval;
00575 }
00576
00577
00578 bool HandleBreakdown();
00579
00580 bool NeedsAutorenewing(const Company *c) const;
00581
00582 bool NeedsServicing() const;
00583 bool NeedsAutomaticServicing() const;
00584
00592 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00593
00602 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00603
00604 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00605
00606 void UpdateVisualEffect(bool allow_power_change = true);
00607 void ShowVisualEffect() const;
00608
00609 private:
00614 void SkipToNextRealOrderIndex()
00615 {
00616 if (this->GetNumManualOrders() > 0) {
00617
00618 do {
00619 this->cur_real_order_index++;
00620 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00621 } while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT));
00622 } else {
00623 this->cur_real_order_index = 0;
00624 }
00625 }
00626
00627 public:
00633 void IncrementImplicitOrderIndex()
00634 {
00635 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00636
00637 this->SkipToNextRealOrderIndex();
00638 }
00639
00640 assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders());
00641
00642
00643 do {
00644 this->cur_implicit_order_index++;
00645 if (this->cur_implicit_order_index >= this->GetNumOrders()) this->cur_implicit_order_index = 0;
00646 } while (this->cur_implicit_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_implicit_order_index)->IsType(OT_IMPLICIT));
00647
00648 InvalidateVehicleOrder(this, 0);
00649 }
00650
00657 void IncrementRealOrderIndex()
00658 {
00659 if (this->cur_implicit_order_index == this->cur_real_order_index) {
00660
00661 this->IncrementImplicitOrderIndex();
00662 } else {
00663
00664 this->SkipToNextRealOrderIndex();
00665 InvalidateVehicleOrder(this, 0);
00666 }
00667 }
00668
00672 void UpdateRealOrderIndex()
00673 {
00674
00675 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00676
00677 if (this->GetNumManualOrders() > 0) {
00678
00679 while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)) {
00680 this->cur_real_order_index++;
00681 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
00682 }
00683 } else {
00684 this->cur_real_order_index = 0;
00685 }
00686 }
00687
00693 inline Order *GetOrder(int index) const
00694 {
00695 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00696 }
00697
00702 inline Order *GetLastOrder() const
00703 {
00704 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00705 }
00706
00707 bool IsEngineCountable() const;
00708 bool HasDepotOrder() const;
00709 void HandlePathfindingResult(bool path_found);
00710
00715 FORCEINLINE bool IsFrontEngine() const
00716 {
00717 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT);
00718 }
00719
00724 FORCEINLINE bool IsArticulatedPart() const
00725 {
00726 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_ARTICULATED_PART);
00727 }
00728
00733 FORCEINLINE bool HasArticulatedPart() const
00734 {
00735 return this->Next() != NULL && this->Next()->IsArticulatedPart();
00736 }
00737
00743 FORCEINLINE Vehicle *GetNextArticulatedPart() const
00744 {
00745 assert(this->HasArticulatedPart());
00746 return this->Next();
00747 }
00748
00753 FORCEINLINE Vehicle *GetFirstEnginePart()
00754 {
00755 Vehicle *v = this;
00756 while (v->IsArticulatedPart()) v = v->Previous();
00757 return v;
00758 }
00759
00764 FORCEINLINE const Vehicle *GetFirstEnginePart() const
00765 {
00766 const Vehicle *v = this;
00767 while (v->IsArticulatedPart()) v = v->Previous();
00768 return v;
00769 }
00770
00775 FORCEINLINE Vehicle *GetLastEnginePart()
00776 {
00777 Vehicle *v = this;
00778 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00779 return v;
00780 }
00781
00786 FORCEINLINE Vehicle *GetNextVehicle() const
00787 {
00788 const Vehicle *v = this;
00789 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00790
00791
00792 return v->Next();
00793 }
00794
00799 FORCEINLINE Vehicle *GetPrevVehicle() const
00800 {
00801 Vehicle *v = this->Previous();
00802 while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00803
00804 return v;
00805 }
00806 };
00807
00813 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00814
00819 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00820
00825 template <class T, VehicleType Type>
00826 struct SpecializedVehicle : public Vehicle {
00827 static const VehicleType EXPECTED_TYPE = Type;
00828
00829 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase;
00830
00834 FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00835
00840 FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
00841
00846 FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
00847
00852 FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
00853
00858 FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
00859
00864 FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
00865
00871 FORCEINLINE T *GetNextArticulatedPart() { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00872
00878 FORCEINLINE T *GetNextArticulatedPart() const { return (T *)this->Vehicle::GetNextArticulatedPart(); }
00879
00884 FORCEINLINE T *GetFirstEnginePart() { return (T *)this->Vehicle::GetFirstEnginePart(); }
00885
00890 FORCEINLINE const T *GetFirstEnginePart() const { return (const T *)this->Vehicle::GetFirstEnginePart(); }
00891
00896 FORCEINLINE T *GetLastEnginePart() { return (T *)this->Vehicle::GetLastEnginePart(); }
00897
00902 FORCEINLINE T *GetNextVehicle() const { return (T *)this->Vehicle::GetNextVehicle(); }
00903
00908 FORCEINLINE T *GetPrevVehicle() const { return (T *)this->Vehicle::GetPrevVehicle(); }
00909
00915 static FORCEINLINE bool IsValidID(size_t index)
00916 {
00917 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00918 }
00919
00924 static FORCEINLINE T *Get(size_t index)
00925 {
00926 return (T *)Vehicle::Get(index);
00927 }
00928
00933 static FORCEINLINE T *GetIfValid(size_t index)
00934 {
00935 return IsValidID(index) ? Get(index) : NULL;
00936 }
00937
00943 static FORCEINLINE T *From(Vehicle *v)
00944 {
00945 assert(v->type == Type);
00946 return (T *)v;
00947 }
00948
00954 static FORCEINLINE const T *From(const Vehicle *v)
00955 {
00956 assert(v->type == Type);
00957 return (const T *)v;
00958 }
00959
00965 FORCEINLINE void UpdateViewport(bool moved, bool turned)
00966 {
00967 extern void VehicleMove(Vehicle *v, bool update_viewport);
00968
00969
00970
00971 if (turned) ((T *)this)->T::UpdateDeltaXY(this->direction);
00972 SpriteID old_image = this->cur_image;
00973 this->cur_image = ((T *)this)->T::GetImage(this->direction);
00974 if (moved || this->cur_image != old_image) VehicleMove(this, true);
00975 }
00976 };
00977
00983 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
00984
00988 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
00989 SpriteID image_override;
00990 VehicleID big_ufo_destroyer_target;
00991
00993 DisasterVehicle() : SpecializedVehicleBase() {}
00995 virtual ~DisasterVehicle() {}
00996
00997 void UpdateDeltaXY(Direction direction);
00998 bool Tick();
00999 };
01000
01005 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
01006
01008 struct FreeUnitIDGenerator {
01009 bool *cache;
01010 UnitID maxid;
01011 UnitID curid;
01012
01013 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
01014 UnitID NextID();
01015
01017 ~FreeUnitIDGenerator() { free(this->cache); }
01018 };
01019
01021 static const int32 INVALID_COORD = 0x7fffffff;
01022
01023 #endif