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
00088 struct VehicleCache {
00089 uint16 cached_max_speed;
00090
00091 byte cached_vis_effect;
00092 };
00093
00095 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
00096 extern VehiclePool _vehicle_pool;
00097
00098
00099 struct SaveLoad;
00100 struct GroundVehicleCache;
00101 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00102 struct LoadgameState;
00103 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00104 extern bool AfterLoadGame();
00105 extern void FixOldVehicles();
00106
00108 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
00109 private:
00110 Vehicle *next;
00111 Vehicle *previous;
00112 Vehicle *first;
00113
00114 Vehicle *next_shared;
00115 Vehicle *previous_shared;
00116 public:
00117 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00118 friend bool AfterLoadGame();
00119 friend void FixOldVehicles();
00120 friend void AfterLoadVehicles(bool part_of_load);
00121 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00122
00123 char *name;
00124
00125 TileIndex tile;
00126
00132 TileIndex dest_tile;
00133
00134 Money profit_this_year;
00135 Money profit_last_year;
00136 Money value;
00137
00138 CargoPayment *cargo_payment;
00139
00140
00141 uint32 current_order_time;
00142 int32 lateness_counter;
00143 Date timetable_start;
00144
00145
00146
00147 Rect coord;
00148 Vehicle *next_hash, **prev_hash;
00149 Vehicle *next_new_hash, **prev_new_hash;
00150 Vehicle **old_new_hash;
00151
00152 SpriteID colourmap;
00153
00154
00155 Year build_year;
00156 Date age;
00157 Date max_age;
00158 Date date_of_last_service;
00159 Date service_interval;
00160 uint16 reliability;
00161 uint16 reliability_spd_dec;
00162 byte breakdown_ctr;
00163 byte breakdown_delay;
00164 byte breakdowns_since_last_service;
00165 byte breakdown_chance;
00166
00167 int32 x_pos;
00168 int32 y_pos;
00169 byte z_pos;
00170 DirectionByte direction;
00171
00172 OwnerByte owner;
00173 byte spritenum;
00174
00175
00176 SpriteID cur_image;
00177 byte x_extent;
00178 byte y_extent;
00179 byte z_extent;
00180 int8 x_offs;
00181 int8 y_offs;
00182 EngineID engine_type;
00183
00184 TextEffectID fill_percent_te_id;
00185 UnitID unitnumber;
00186
00187 uint16 cur_speed;
00188 byte subspeed;
00189 byte acceleration;
00190 uint32 motion_counter;
00191 byte progress;
00192
00193
00194
00195
00196 byte random_bits;
00197 byte waiting_triggers;
00198
00199 StationID last_station_visited;
00200
00201 CargoID cargo_type;
00202 byte cargo_subtype;
00203 uint16 cargo_cap;
00204 VehicleCargoList cargo;
00205
00206 byte day_counter;
00207 byte tick_counter;
00208 byte running_ticks;
00209
00210 byte vehstatus;
00211 Order current_order;
00212 VehicleOrderID cur_order_index;
00213
00214 union {
00215 OrderList *list;
00216 Order *old;
00217 } orders;
00218
00219 byte vehicle_flags;
00220
00222 uint16 load_unload_ticks;
00223
00224 GroupID group_id;
00225
00226 byte subtype;
00227
00228 NewGRFCache grf_cache;
00229 VehicleCache vcache;
00230
00231 Vehicle(VehicleType type = VEH_INVALID);
00232
00233 void PreDestructor();
00235 virtual ~Vehicle();
00236
00237 void BeginLoading();
00238 void LeaveStation();
00239
00240 GroundVehicleCache *GetGroundVehicleCache();
00241 const GroundVehicleCache *GetGroundVehicleCache() const;
00242
00243 void DeleteUnreachedAutoOrders();
00244
00245 void HandleLoading(bool mode = false);
00246
00251 virtual const char *GetTypeString() const { return "base vehicle"; }
00252
00261 virtual void MarkDirty() {}
00262
00268 virtual void UpdateDeltaXY(Direction direction) {}
00269
00283 FORCEINLINE uint GetOldAdvanceSpeed(uint speed)
00284 {
00285 return (this->direction & 1) ? speed : speed * 3 / 4;
00286 }
00287
00300 static FORCEINLINE uint GetAdvanceSpeed(uint speed)
00301 {
00302 return speed * 3 / 4;
00303 }
00304
00312 FORCEINLINE uint GetAdvanceDistance()
00313 {
00314 return (this->direction & 1) ? 192 : 256;
00315 }
00316
00321 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00322
00326 virtual void PlayLeaveStationSound() const {}
00327
00331 virtual bool IsPrimaryVehicle() const { return false; }
00332
00338 virtual SpriteID GetImage(Direction direction) const { return 0; }
00339
00344 FORCEINLINE void InvalidateNewGRFCache()
00345 {
00346 this->grf_cache.cache_valid = 0;
00347 }
00348
00353 FORCEINLINE void InvalidateNewGRFCacheOfChain()
00354 {
00355 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00356 u->InvalidateNewGRFCache();
00357 }
00358 }
00359
00364 FORCEINLINE bool IsGroundVehicle() const
00365 {
00366 return this->type == VEH_TRAIN || this->type == VEH_ROAD;
00367 }
00368
00373 virtual int GetDisplaySpeed() const { return 0; }
00374
00379 virtual int GetDisplayMaxSpeed() const { return 0; }
00380
00385 virtual Money GetRunningCost() const { return 0; }
00386
00391 virtual bool IsInDepot() const { return false; }
00392
00397 virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
00398
00403 virtual bool Tick() { return true; };
00404
00408 virtual void OnNewDay() {};
00409
00415 virtual uint Crash(bool flooded = false);
00416
00429 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00430
00435 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00436
00441 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00442
00447 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00448
00449 void SetNext(Vehicle *next);
00450
00456 inline Vehicle *Next() const { return this->next; }
00457
00463 inline Vehicle *Previous() const { return this->previous; }
00464
00469 inline Vehicle *First() const { return this->first; }
00470
00475 inline Vehicle *Last()
00476 {
00477 Vehicle *v = this;
00478 while (v->Next() != NULL) v = v->Next();
00479 return v;
00480 }
00481
00486 inline const Vehicle *Last() const
00487 {
00488 const Vehicle *v = this;
00489 while (v->Next() != NULL) v = v->Next();
00490 return v;
00491 }
00492
00497 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00498
00499 void AddToShared(Vehicle *shared_chain);
00500 void RemoveFromShared();
00501
00506 inline Vehicle *NextShared() const { return this->next_shared; }
00507
00512 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00513
00518 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00519
00524 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00525
00530 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00531
00536 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00537
00544 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00545 {
00546 this->unitnumber = src->unitnumber;
00547
00548 this->cur_order_index = src->cur_order_index;
00549 this->current_order = src->current_order;
00550 this->dest_tile = src->dest_tile;
00551
00552 this->profit_this_year = src->profit_this_year;
00553 this->profit_last_year = src->profit_last_year;
00554
00555 this->current_order_time = src->current_order_time;
00556 this->lateness_counter = src->lateness_counter;
00557 this->timetable_start = src->timetable_start;
00558
00559 if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
00560 if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00561 if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00562
00563 this->service_interval = src->service_interval;
00564 }
00565
00566
00567 bool HandleBreakdown();
00568
00569 bool NeedsAutorenewing(const Company *c) const;
00570
00571 bool NeedsServicing() const;
00572 bool NeedsAutomaticServicing() const;
00573
00581 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00582
00591 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00592
00593 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00594
00595 void UpdateVisualEffect(bool allow_power_change = true);
00596 void ShowVisualEffect() const;
00597
00602 void IncrementOrderIndex()
00603 {
00604 this->cur_order_index++;
00605 if (this->cur_order_index >= this->GetNumOrders()) this->cur_order_index = 0;
00606 InvalidateVehicleOrder(this, 0);
00607 }
00608
00614 inline Order *GetOrder(int index) const
00615 {
00616 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00617 }
00618
00619 Order *GetNextManualOrder(int index) const;
00620
00625 inline Order *GetLastOrder() const
00626 {
00627 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00628 }
00629
00630 bool IsEngineCountable() const;
00631 bool HasDepotOrder() const;
00632 void HandlePathfindingResult(bool path_found);
00633 };
00634
00635 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00636 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00637
00642 template <class T, VehicleType Type>
00643 struct SpecializedVehicle : public Vehicle {
00644 static const VehicleType EXPECTED_TYPE = Type;
00645
00646 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase;
00647
00651 FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00652
00657 FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
00658
00663 FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
00664
00669 FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
00670
00675 FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
00676
00681 FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
00682
00683
00689 static FORCEINLINE bool IsValidID(size_t index)
00690 {
00691 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00692 }
00693
00698 static FORCEINLINE T *Get(size_t index)
00699 {
00700 return (T *)Vehicle::Get(index);
00701 }
00702
00707 static FORCEINLINE T *GetIfValid(size_t index)
00708 {
00709 return IsValidID(index) ? Get(index) : NULL;
00710 }
00711
00717 static FORCEINLINE T *From(Vehicle *v)
00718 {
00719 assert(v->type == Type);
00720 return (T *)v;
00721 }
00722
00728 static FORCEINLINE const T *From(const Vehicle *v)
00729 {
00730 assert(v->type == Type);
00731 return (const T *)v;
00732 }
00733
00739 FORCEINLINE void UpdateViewport(bool moved, bool turned)
00740 {
00741 extern void VehicleMove(Vehicle *v, bool update_viewport);
00742
00743
00744
00745 if (turned) ((T *)this)->T::UpdateDeltaXY(this->direction);
00746 SpriteID old_image = this->cur_image;
00747 this->cur_image = ((T *)this)->T::GetImage(this->direction);
00748 if (moved || this->cur_image != old_image) VehicleMove(this, true);
00749 }
00750 };
00751
00752 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
00753
00757 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
00758 uint16 image_override;
00759 VehicleID big_ufo_destroyer_target;
00760
00762 DisasterVehicle() : SpecializedVehicleBase() {}
00764 virtual ~DisasterVehicle() {}
00765
00766 const char *GetTypeString() const { return "disaster vehicle"; }
00767 void UpdateDeltaXY(Direction direction);
00768 bool Tick();
00769 };
00770
00771 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
00772
00774 struct FreeUnitIDGenerator {
00775 bool *cache;
00776 UnitID maxid;
00777 UnitID curid;
00778
00779 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
00780 UnitID NextID();
00781
00783 ~FreeUnitIDGenerator() { free(this->cache); }
00784 };
00785
00786 static const int32 INVALID_COORD = 0x7fffffff;
00787
00788 #endif