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
00025 enum VehStatus {
00026 VS_HIDDEN = 0x01,
00027 VS_STOPPED = 0x02,
00028 VS_UNCLICKABLE = 0x04,
00029 VS_DEFPAL = 0x08,
00030 VS_TRAIN_SLOWING = 0x10,
00031 VS_SHADOW = 0x20,
00032 VS_AIRCRAFT_BROKEN = 0x40,
00033 VS_CRASHED = 0x80,
00034 };
00035
00036 enum VehicleFlags {
00037 VF_LOADING_FINISHED,
00038 VF_CARGO_UNLOADING,
00039 VF_BUILT_AS_PROTOTYPE,
00040 VF_TIMETABLE_STARTED,
00041 VF_AUTOFILL_TIMETABLE,
00042 VF_AUTOFILL_PRES_WAIT_TIME,
00043 };
00044
00046 struct VehicleCache {
00047 uint8 cache_valid;
00048 uint32 cached_var40;
00049 uint32 cached_var41;
00050 uint32 cached_var42;
00051 uint32 cached_var43;
00052 };
00053
00054 typedef Pool<Vehicle, VehicleID, 512, 64000> VehiclePool;
00055 extern VehiclePool _vehicle_pool;
00056
00057
00058 struct SaveLoad;
00059 extern const SaveLoad *GetVehicleDescription(VehicleType vt);
00060 struct LoadgameState;
00061 extern bool LoadOldVehicle(LoadgameState *ls, int num);
00062 extern bool AfterLoadGame();
00063 extern void FixOldVehicles();
00064
00065 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle {
00066 private:
00067 Vehicle *next;
00068 Vehicle *previous;
00069 Vehicle *first;
00070
00071 Vehicle *next_shared;
00072 Vehicle *previous_shared;
00073 public:
00074 friend const SaveLoad *GetVehicleDescription(VehicleType vt);
00075 friend bool AfterLoadGame();
00076 friend void FixOldVehicles();
00077 friend void AfterLoadVehicles(bool part_of_load);
00078 friend bool LoadOldVehicle(LoadgameState *ls, int num);
00079
00080 char *name;
00081
00082 TileIndex tile;
00083
00089 TileIndex dest_tile;
00090
00091 Money profit_this_year;
00092 Money profit_last_year;
00093 Money value;
00094
00095 CargoPayment *cargo_payment;
00096
00097
00098 uint32 current_order_time;
00099 int32 lateness_counter;
00100 Date timetable_start;
00101
00102
00103
00104 Rect coord;
00105 Vehicle *next_hash, **prev_hash;
00106 Vehicle *next_new_hash, **prev_new_hash;
00107 Vehicle **old_new_hash;
00108
00109 SpriteID colourmap;
00110
00111
00112 Year build_year;
00113 Date age;
00114 Date max_age;
00115 Date date_of_last_service;
00116 Date service_interval;
00117 uint16 reliability;
00118 uint16 reliability_spd_dec;
00119 byte breakdown_ctr;
00120 byte breakdown_delay;
00121 byte breakdowns_since_last_service;
00122 byte breakdown_chance;
00123
00124 int32 x_pos;
00125 int32 y_pos;
00126 byte z_pos;
00127 DirectionByte direction;
00128
00129 OwnerByte owner;
00130 byte spritenum;
00131
00132
00133 uint16 cur_image;
00134 byte x_extent;
00135 byte y_extent;
00136 byte z_extent;
00137 int8 x_offs;
00138 int8 y_offs;
00139 EngineID engine_type;
00140
00141 TextEffectID fill_percent_te_id;
00142 UnitID unitnumber;
00143
00144 uint16 max_speed;
00145 uint16 cur_speed;
00146 byte subspeed;
00147 byte acceleration;
00148 uint32 motion_counter;
00149 byte progress;
00150
00151
00152
00153
00154 byte random_bits;
00155 byte waiting_triggers;
00156
00157 StationID last_station_visited;
00158
00159 CargoID cargo_type;
00160 byte cargo_subtype;
00161 uint16 cargo_cap;
00162 VehicleCargoList cargo;
00163
00164 byte day_counter;
00165 byte tick_counter;
00166 byte running_ticks;
00167
00168 byte vehstatus;
00169 Order current_order;
00170 VehicleOrderID cur_order_index;
00171
00172 union {
00173 OrderList *list;
00174 Order *old;
00175 } orders;
00176
00177 byte vehicle_flags;
00178
00180 uint16 load_unload_ticks;
00181
00182 GroupID group_id;
00183
00184 byte subtype;
00185
00186 VehicleCache vcache;
00187
00189 Vehicle(VehicleType type = VEH_INVALID);
00190
00192 void PreDestructor();
00194 virtual ~Vehicle();
00195
00196 void BeginLoading();
00197 void LeaveStation();
00198
00204 void HandleLoading(bool mode = false);
00205
00210 virtual const char *GetTypeString() const { return "base vehicle"; }
00211
00220 virtual void MarkDirty() {}
00221
00227 virtual void UpdateDeltaXY(Direction direction) {}
00228
00233 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; }
00234
00238 virtual void PlayLeaveStationSound() const {}
00239
00243 virtual bool IsPrimaryVehicle() const { return false; }
00244
00250 virtual SpriteID GetImage(Direction direction) const { return 0; }
00251
00256 FORCEINLINE void InvalidateNewGRFCache()
00257 {
00258 this->vcache.cache_valid = 0;
00259 }
00260
00265 FORCEINLINE void InvalidateNewGRFCacheOfChain()
00266 {
00267 for (Vehicle *u = this; u != NULL; u = u->Next()) {
00268 u->InvalidateNewGRFCache();
00269 }
00270 }
00271
00276 virtual int GetDisplaySpeed() const { return 0; }
00277
00282 virtual int GetDisplayMaxSpeed() const { return 0; }
00283
00288 virtual Money GetRunningCost() const { return 0; }
00289
00294 virtual bool IsInDepot() const { return false; }
00295
00300 virtual bool IsStoppedInDepot() const { return this->IsInDepot() && (this->vehstatus & VS_STOPPED) != 0; }
00301
00306 virtual bool Tick() { return true; };
00307
00311 virtual void OnNewDay() {};
00312
00318 virtual uint Crash(bool flooded = false);
00319
00325 inline void UpdateViewport(bool moved, bool turned)
00326 {
00327 extern void VehicleMove(Vehicle *v, bool update_viewport);
00328
00329 if (turned) this->UpdateDeltaXY(this->direction);
00330 SpriteID old_image = this->cur_image;
00331 this->cur_image = this->GetImage(this->direction);
00332 if (moved || this->cur_image != old_image) VehicleMove(this, true);
00333 }
00334
00347 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
00348
00353 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
00354
00359 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); }
00360
00365 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); }
00366
00371 void SetNext(Vehicle *next);
00372
00378 inline Vehicle *Next() const { return this->next; }
00379
00385 inline Vehicle *Previous() const { return this->previous; }
00386
00391 inline Vehicle *First() const { return this->first; }
00392
00397 inline Vehicle *Last()
00398 {
00399 Vehicle *v = this;
00400 while (v->Next() != NULL) v = v->Next();
00401 return v;
00402 }
00403
00408 inline const Vehicle *Last() const
00409 {
00410 const Vehicle *v = this;
00411 while (v->Next() != NULL) v = v->Next();
00412 return v;
00413 }
00414
00419 inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
00420
00426 void AddToShared(Vehicle *shared_chain);
00427
00431 void RemoveFromShared();
00432
00437 inline Vehicle *NextShared() const { return this->next_shared; }
00438
00443 inline Vehicle *PreviousShared() const { return this->previous_shared; }
00444
00449 inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
00450
00455 inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
00456
00461 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
00462
00469 inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
00470 {
00471 this->unitnumber = src->unitnumber;
00472
00473 this->cur_order_index = src->cur_order_index;
00474 this->current_order = src->current_order;
00475 this->dest_tile = src->dest_tile;
00476
00477 this->profit_this_year = src->profit_this_year;
00478 this->profit_last_year = src->profit_last_year;
00479
00480 this->current_order_time = src->current_order_time;
00481 this->lateness_counter = src->lateness_counter;
00482 this->timetable_start = src->timetable_start;
00483
00484 if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
00485 if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00486 if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00487
00488 this->service_interval = src->service_interval;
00489 }
00490
00491 bool NeedsAutorenewing(const Company *c) const;
00492
00499 bool NeedsServicing() const;
00500
00506 bool NeedsAutomaticServicing() const;
00507
00515 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
00516
00525 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
00526
00533 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
00534
00539 void IncrementOrderIndex()
00540 {
00541 this->cur_order_index++;
00542 if (this->cur_order_index >= this->GetNumOrders()) this->cur_order_index = 0;
00543 InvalidateVehicleOrder(this, 0);
00544 }
00545
00551 inline Order *GetOrder(int index) const
00552 {
00553 return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
00554 }
00555
00560 inline Order *GetLastOrder() const
00561 {
00562 return (this->orders.list == NULL) ? NULL : this->orders.list->GetLastOrder();
00563 }
00564
00565 bool IsEngineCountable() const;
00566 };
00567
00568 #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)
00569 #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0)
00570
00575 template <class T, VehicleType Type>
00576 struct SpecializedVehicle : public Vehicle {
00577 static const VehicleType EXPECTED_TYPE = Type;
00578
00582 FORCEINLINE SpecializedVehicle<T, Type>() : Vehicle(Type) { }
00583
00588 FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
00589
00594 FORCEINLINE T *Last() { return (T *)this->Vehicle::Last(); }
00595
00600 FORCEINLINE const T *Last() const { return (const T *)this->Vehicle::Last(); }
00601
00606 FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
00607
00612 FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
00613
00614
00620 static FORCEINLINE bool IsValidID(size_t index)
00621 {
00622 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
00623 }
00624
00629 static FORCEINLINE T *Get(size_t index)
00630 {
00631 return (T *)Vehicle::Get(index);
00632 }
00633
00638 static FORCEINLINE T *GetIfValid(size_t index)
00639 {
00640 return IsValidID(index) ? Get(index) : NULL;
00641 }
00642
00648 static FORCEINLINE T *From(Vehicle *v)
00649 {
00650 assert(v->type == Type);
00651 return (T *)v;
00652 }
00653
00659 static FORCEINLINE const T *From(const Vehicle *v)
00660 {
00661 assert(v->type == Type);
00662 return (const T *)v;
00663 }
00664 };
00665
00666 #define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
00667
00671 struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
00672 uint16 image_override;
00673 VehicleID big_ufo_destroyer_target;
00674
00676 DisasterVehicle() : SpecializedVehicle<DisasterVehicle, VEH_DISASTER>() {}
00678 virtual ~DisasterVehicle() {}
00679
00680 const char *GetTypeString() const { return "disaster vehicle"; }
00681 void UpdateDeltaXY(Direction direction);
00682 bool Tick();
00683 };
00684
00685 #define FOR_ALL_DISASTERVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(DisasterVehicle, var)
00686
00688 struct FreeUnitIDGenerator {
00689 bool *cache;
00690 UnitID maxid;
00691 UnitID curid;
00692
00699 FreeUnitIDGenerator(VehicleType type, CompanyID owner);
00700
00702 UnitID NextID();
00703
00705 ~FreeUnitIDGenerator() { free(this->cache); }
00706 };
00707
00708 static const int32 INVALID_COORD = 0x7fffffff;
00709
00710 #endif