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 "direction_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
00089 struct VehicleCache {
00090 uint16 cached_max_speed;
00091
00092 byte cached_vis_effect;
00093 };
00094
00096 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
00097 extern VehiclePool _vehicle_pool;
00098
00099
00100 struct SaveLoad;
00101 struct GroundVehicleCache;
00102 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00103 struct LoadgameState;
00104 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00105 extern bool AfterLoadGame();
00106 extern void FixOldVehicles();
00107
00109 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
00110 private:
00111 Vehicle *next;
00112 Vehicle *previous;
00113 Vehicle *first;
00114
00115 Vehicle *next_shared;
00116 Vehicle *previous_shared;
00117 public:
00118 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00119 friend bool AfterLoadGame();
00120 friend void FixOldVehicles();
00121 friend void AfterLoadVehicles(bool part_of_load);
00122 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00123
00124 char *name;
00125
00126 TileIndex tile;
00127
00133 TileIndex dest_tile;
00134
00135 Money profit_this_year;
00136 Money profit_last_year;
00137 Money value;
00138
00139 CargoPayment *cargo_payment;
00140
00141
00142 uint32 current_order_time;
00143 int32 lateness_counter;
00144 Date timetable_start;
00145
00146
00147
00148 Rect coord;
00149 Vehicle *next_hash, **prev_hash;
00150 Vehicle *next_new_hash, **prev_new_hash;
00151 Vehicle **old_new_hash;
00152
00153 SpriteID colourmap;
00154
00155
00156 Year build_year;
00157 Date age;
00158 Date max_age;
00159 Date date_of_last_service;
00160 Date service_interval;
00161 uint16 reliability;
00162 uint16 reliability_spd_dec;
00163 byte breakdown_ctr;
00164 byte breakdown_delay;
00165 byte breakdowns_since_last_service;
00166 byte breakdown_chance;
00167
00168 int32 x_pos;
00169 int32 y_pos;
00170 byte z_pos;
00171 DirectionByte direction;
00172
00173 OwnerByte owner;
00174 byte spritenum;
00175
00176
00177 uint16 cur_image;
00178 byte x_extent;
00179 byte y_extent;
00180 byte z_extent;
00181 int8 x_offs;
00182 int8 y_offs;
00183 EngineID engine_type;
00184
00185 TextEffectID fill_percent_te_id;
00186 UnitID unitnumber;
00187
00188 uint16 cur_speed;
00189 byte subspeed;
00190 byte acceleration;
00191 uint32 motion_counter;
00192 byte progress;
00193
00194
00195
00196
00197 byte random_bits;
00198 byte waiting_triggers;
00199
00200 StationID last_station_visited;
00201
00202 CargoID cargo_type;
00203 byte cargo_subtype;
00204 uint16 cargo_cap;
00205 VehicleCargoList cargo;
00206
00207 byte day_counter;
00208 byte tick_counter;
00209 byte running_ticks;
00210
00211 byte vehstatus;
00212 Order current_order;
00213 VehicleOrderID cur_order_index;
00214
00215 union {
00216 OrderList *list;
00217 Order *old;
00218 } orders;
00219
00220 byte vehicle_flags;
00221
00223 uint16 load_unload_ticks;
00224
00225 GroupID group_id;
00226
00227 byte subtype;
00228
00229 NewGRFCache grf_cache;
00230 VehicleCache vcache;
00231
00233 Vehicle(VehicleType type = VEH_INVALID);
00234
00236 void PreDestructor();
00238 virtual ~Vehicle();
00239
00240 void BeginLoading();
00241 void LeaveStation();
00242
00243 GroundVehicleCache *GetGroundVehicleCache();
00244 const GroundVehicleCache *GetGroundVehicleCache() const;
00245
00251 void HandleLoading(bool mode = false);
00252
00257 virtual const char *GetTypeString() const { return "base vehicle"; }
00258
00267 virtual void MarkDirty() {}
00268
00274 virtual void UpdateDeltaXY(Direction direction) {}
00275
00289 FORCEINLINE uint GetOldAdvanceSpeed(uint speed)
00290 {
00291 return (this->direction & 1) ? speed : speed * 3 / 4;
00292 }
00293
00306 static FORCEINLINE uint GetAdvanceSpeed(uint speed)
00307 {
00308 return speed * 3 / 4;
00309 }
00310
00318 FORCEINLINE uint GetAdvanceDistance()
00319 {
00320 return (this->direction & 1) ? 192 : 256;
00321 }
00322
00327 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00328
00332 virtual void PlayLeaveStationSound() const {}
00333
00337 virtual bool IsPrimaryVehicle() const { return false; }
00338
00344 virtual SpriteID GetImage(Direction direction) const { return 0; }
00345
00350 FORCEINLINE void InvalidateNewGRFCache()
00351 {
00352 this->grf_cache.cache_valid = 0;
00353 }
00354
00359 FORCEINLINE void InvalidateNewGRFCacheOfChain()
00360 {
00361 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00362 u->InvalidateNewGRFCache();
00363 }
00364 }
00365
00370 FORCEINLINE bool IsGroundVehicle() const
00371 {
00372 return this->type == VEH_TRAIN || this->type == VEH_ROAD;
00373 }
00374
00379 virtual int GetDisplaySpeed() const { return 0; }
00380
00385 virtual int GetDisplayMaxSpeed() const { return 0; }
00386
00391 virtual Money GetRunningCost() const { return 0; }
00392
00397 virtual bool IsInDepot() const { return false; }
00398
00403 virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
00404
00409 virtual bool Tick() { return true; };
00410
00414 virtual void OnNewDay() {};
00415
00421 virtual uint Crash(bool flooded = false);
00422
00435 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00436
00441 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00442
00447 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00448
00453 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00454
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
00514 void AddToShared(Vehicle *shared_chain);
00515
00519 void RemoveFromShared();
00520
00525 inline Vehicle *NextShared() const { return this->next_shared; }
00526
00531 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00532
00537 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00538
00543 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00544
00549 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00550
00555 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
00556
00563 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00564 {
00565 this->unitnumber = src->unitnumber;
00566
00567 this->cur_order_index = src->cur_order_index;
00568 this->current_order = src->current_order;
00569 this->dest_tile = src->dest_tile;
00570
00571 this->profit_this_year = src->profit_this_year;
00572 this->profit_last_year = src->profit_last_year;
00573
00574 this->current_order_time = src->current_order_time;
00575 this->lateness_counter = src->lateness_counter;
00576 this->timetable_start = src->timetable_start;
00577
00578 if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
00579 if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00580 if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00581
00582 this->service_interval = src->service_interval;
00583 }
00584
00585
00592 bool HandleBreakdown();
00593
00594 bool NeedsAutorenewing(const Company *c) const;
00595
00602 bool NeedsServicing() const;
00603
00609 bool NeedsAutomaticServicing() const;
00610
00618 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00619
00628 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00629
00636 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00637
00642 void UpdateVisualEffect(bool allow_power_change = true);
00643
00644
00645
00646
00647
00648 void ShowVisualEffect() const;
00649
00654 void IncrementOrderIndex()
00655 {
00656 this->cur_order_index++;
00657 if (this->cur_order_index >= this->GetNumOrders()) this->cur_order_index = 0;
00658 InvalidateVehicleOrder(this, 0);
00659 }
00660
00666 inline Order *GetOrder(int index) const
00667 {
00668 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00669 }
00670
00671 Order *GetNextManualOrder(int index) const;
00672
00677 inline Order *GetLastOrder() const
00678 {
00679 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00680 }
00681
00682 bool IsEngineCountable() const;
00683 bool HasDepotOrder() const;
00684 void HandlePathfindingResult(bool path_found);
00685 };
00686
00687 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00688 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00689
00694 template <class T, VehicleType Type>
00695 struct SpecializedVehicle : public Vehicle {
00696 static const VehicleType EXPECTED_TYPE = Type;
00697
00701 FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00702
00707 FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
00708
00713 FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
00714
00719 FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
00720
00725 FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
00726
00731 FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
00732
00733
00739 static FORCEINLINE bool IsValidID(size_t index)
00740 {
00741 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00742 }
00743
00748 static FORCEINLINE T *Get(size_t index)
00749 {
00750 return (T *)Vehicle::Get(index);
00751 }
00752
00757 static FORCEINLINE T *GetIfValid(size_t index)
00758 {
00759 return IsValidID(index) ? Get(index) : NULL;
00760 }
00761
00767 static FORCEINLINE T *From(Vehicle *v)
00768 {
00769 assert(v->type == Type);
00770 return (T *)v;
00771 }
00772
00778 static FORCEINLINE const T *From(const Vehicle *v)
00779 {
00780 assert(v->type == Type);
00781 return (const T *)v;
00782 }
00783
00789 FORCEINLINE void UpdateViewport(bool moved, bool turned)
00790 {
00791 extern void VehicleMove(Vehicle *v, bool update_viewport);
00792
00793
00794
00795 if (turned) ((T *)this)->T::UpdateDeltaXY(this->direction);
00796 SpriteID old_image = this->cur_image;
00797 this->cur_image = ((T *)this)->T::GetImage(this->direction);
00798 if (moved || this->cur_image != old_image) VehicleMove(this, true);
00799 }
00800 };
00801
00802 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
00803
00807 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
00808 uint16 image_override;
00809 VehicleID big_ufo_destroyer_target;
00810
00812 DisasterVehicle() : SpecializedVehicle<DisasterVehicle, VEH_DISASTER>() {}
00814 virtual ~DisasterVehicle() {}
00815
00816 const char *GetTypeString() const { return "disaster vehicle"; }
00817 void UpdateDeltaXY(Direction direction);
00818 bool Tick();
00819 };
00820
00821 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
00822
00824 struct FreeUnitIDGenerator {
00825 bool *cache;
00826 UnitID maxid;
00827 UnitID curid;
00828
00836 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
00837
00839 UnitID NextID();
00840
00842 ~FreeUnitIDGenerator() { free(this->cache); }
00843 };
00844
00845 static const int32 INVALID_COORD = 0x7fffffff;
00846
00847 #endif