articulated_vehicles.cpp

Go to the documentation of this file.
00001 /* $Id: articulated_vehicles.cpp 15299 2009-01-31 20:16:06Z smatz $ */
00002 
00005 #include "stdafx.h"
00006 #include "train.h"
00007 #include "roadveh.h"
00008 #include "newgrf_engine.h"
00009 #include "vehicle_func.h"
00010 
00011 static const uint MAX_ARTICULATED_PARTS = 100; 
00012 
00013 uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
00014 {
00015   if (!HasBit(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return 0;
00016 
00017   /* If we can't allocate a vehicle now, we can't allocate it in the command
00018    * either, so it doesn't matter how many articulated parts there are. */
00019   if (!Vehicle::CanAllocateItem()) return 0;
00020 
00021   Vehicle *v = NULL;;
00022   if (!purchase_window) {
00023     v = new InvalidVehicle();
00024     v->engine_type = engine_type;
00025   }
00026 
00027   uint i;
00028   for (i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00029     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, v);
00030     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00031   }
00032 
00033   delete v;
00034 
00035   return i - 1;
00036 }
00037 
00038 
00046 static inline uint16 GetVehicleDefaultCapacity(EngineID engine, VehicleType type, CargoID *cargo_type)
00047 {
00048   switch (type) {
00049     case VEH_TRAIN: {
00050       const RailVehicleInfo *rvi = RailVehInfo(engine);
00051       if (cargo_type != NULL) *cargo_type = rvi->cargo_type;
00052       return GetEngineProperty(engine, 0x14, rvi->capacity) + (rvi->railveh_type == RAILVEH_MULTIHEAD ? rvi->capacity : 0);
00053     }
00054 
00055     case VEH_ROAD: {
00056       const RoadVehicleInfo *rvi = RoadVehInfo(engine);
00057       if (cargo_type != NULL) *cargo_type = rvi->cargo_type;
00058       return GetEngineProperty(engine, 0x0F, rvi->capacity);
00059     }
00060 
00061     case VEH_SHIP: {
00062       const ShipVehicleInfo *svi = ShipVehInfo(engine);
00063       if (cargo_type != NULL) *cargo_type = svi->cargo_type;
00064       return GetEngineProperty(engine, 0x0D, svi->capacity);
00065     }
00066 
00067     case VEH_AIRCRAFT: {
00068       const AircraftVehicleInfo *avi = AircraftVehInfo(engine);
00069       if (cargo_type != NULL) *cargo_type = CT_PASSENGERS;
00070       return avi->passenger_capacity;
00071     }
00072 
00073     default: NOT_REACHED();
00074   }
00075 
00076 }
00077 
00085 static inline uint32 GetAvailableVehicleCargoTypes(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00086 {
00087   uint32 cargos = 0;
00088   CargoID initial_cargo_type;
00089 
00090   if (GetVehicleDefaultCapacity(engine, type, &initial_cargo_type) > 0) {
00091     if (type != VEH_SHIP || ShipVehInfo(engine)->refittable) {
00092       const EngineInfo *ei = EngInfo(engine);
00093       cargos = ei->refit_mask;
00094     }
00095     if (include_initial_cargo_type && initial_cargo_type < NUM_CARGO) SetBit(cargos, initial_cargo_type);
00096   }
00097 
00098   return cargos;
00099 }
00100 
00101 uint16 *GetCapacityOfArticulatedParts(EngineID engine, VehicleType type)
00102 {
00103   static uint16 capacity[NUM_CARGO];
00104   memset(capacity, 0, sizeof(capacity));
00105 
00106   CargoID cargo_type;
00107   uint16 cargo_capacity = GetVehicleDefaultCapacity(engine, type, &cargo_type);
00108   if (cargo_type < NUM_CARGO) capacity[cargo_type] = cargo_capacity;
00109 
00110   if (type != VEH_TRAIN && type != VEH_ROAD) return capacity;
00111 
00112   if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return capacity;
00113 
00114   for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00115     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00116     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00117 
00118     EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00119 
00120     cargo_capacity = GetVehicleDefaultCapacity(artic_engine, type, &cargo_type);
00121     if (cargo_type < NUM_CARGO) capacity[cargo_type] += cargo_capacity;
00122   }
00123 
00124   return capacity;
00125 }
00126 
00135 uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00136 {
00137   uint32 cargos = GetAvailableVehicleCargoTypes(engine, type, include_initial_cargo_type);
00138 
00139   if (type != VEH_TRAIN && type != VEH_ROAD) return cargos;
00140 
00141   if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return cargos;
00142 
00143   for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00144     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00145     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00146 
00147     EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00148     cargos |= GetAvailableVehicleCargoTypes(artic_engine, type, include_initial_cargo_type);
00149   }
00150 
00151   return cargos;
00152 }
00153 
00162 uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00163 {
00164   uint32 cargos = UINT32_MAX;
00165 
00166   uint32 veh_cargos = GetAvailableVehicleCargoTypes(engine, type, include_initial_cargo_type);
00167   if (veh_cargos != 0) cargos &= veh_cargos;
00168 
00169   if (type != VEH_TRAIN && type != VEH_ROAD) return cargos;
00170 
00171   if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return cargos;
00172 
00173   for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00174     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00175     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00176 
00177     EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00178     veh_cargos = GetAvailableVehicleCargoTypes(artic_engine, type, include_initial_cargo_type);
00179     if (veh_cargos != 0) cargos &= veh_cargos;
00180   }
00181 
00182   return cargos;
00183 }
00184 
00185 
00193 bool IsArticulatedVehicleCarryingDifferentCargos(const Vehicle *v, CargoID *cargo_type)
00194 {
00195   CargoID first_cargo = CT_INVALID;
00196 
00197   do {
00198     if (v->cargo_cap > 0 && v->cargo_type != CT_INVALID) {
00199       if (first_cargo == CT_INVALID) first_cargo = v->cargo_type;
00200       if (first_cargo != v->cargo_type) {
00201         if (cargo_type != NULL) *cargo_type = CT_INVALID;
00202         return true;
00203       }
00204     }
00205 
00206     switch (v->type) {
00207       case VEH_TRAIN:
00208         v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
00209         break;
00210 
00211       case VEH_ROAD:
00212         v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
00213         break;
00214 
00215       default:
00216         v = NULL;
00217         break;
00218     }
00219   } while (v != NULL);
00220 
00221   if (cargo_type != NULL) *cargo_type = first_cargo;
00222   return false;
00223 }
00224 
00225 
00226 void AddArticulatedParts(Vehicle **vl, VehicleType type)
00227 {
00228   const Vehicle *v = vl[0];
00229   Vehicle *u = vl[0];
00230 
00231   if (!HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return;
00232 
00233   for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00234     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v);
00235     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) return;
00236 
00237     /* Attempt to use pre-allocated vehicles until they run out. This can happen
00238      * if the callback returns different values depending on the cargo type. */
00239     u->SetNext(vl[i]);
00240     if (u->Next() == NULL) return;
00241 
00242     Vehicle *previous = u;
00243     u = u->Next();
00244 
00245     EngineID engine_type = GetNewEngineID(GetEngineGRF(v->engine_type), type, GB(callback, 0, 7));
00246     bool flip_image = HasBit(callback, 7);
00247 
00248     /* get common values from first engine */
00249     u->direction = v->direction;
00250     u->owner = v->owner;
00251     u->tile = v->tile;
00252     u->x_pos = v->x_pos;
00253     u->y_pos = v->y_pos;
00254     u->z_pos = v->z_pos;
00255     u->build_year = v->build_year;
00256     u->vehstatus = v->vehstatus & ~VS_STOPPED;
00257 
00258     u->cargo_subtype = 0;
00259     u->max_speed = 0;
00260     u->max_age = 0;
00261     u->engine_type = engine_type;
00262     u->value = 0;
00263     u->subtype = 0;
00264     u->cur_image = 0xAC2;
00265     u->random_bits = VehicleRandomBits();
00266 
00267     switch (type) {
00268       default: NOT_REACHED();
00269 
00270       case VEH_TRAIN: {
00271         const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
00272 
00273         u = new (u) Train();
00274         previous->SetNext(u);
00275         u->u.rail.track = v->u.rail.track;
00276         u->u.rail.railtype = v->u.rail.railtype;
00277         u->u.rail.first_engine = v->engine_type;
00278 
00279         u->spritenum = rvi_artic->image_index;
00280         u->cargo_type = rvi_artic->cargo_type;
00281         u->cargo_cap = rvi_artic->capacity;  // Callback 36 is called when the consist is finished
00282 
00283         SetArticulatedPart(u);
00284       } break;
00285 
00286       case VEH_ROAD: {
00287         const RoadVehicleInfo *rvi_artic = RoadVehInfo(engine_type);
00288 
00289         u = new (u) RoadVehicle();
00290         previous->SetNext(u);
00291         u->u.road.first_engine = v->engine_type;
00292         u->u.road.cached_veh_length = GetRoadVehLength(u);
00293         u->u.road.state = RVSB_IN_DEPOT;
00294 
00295         u->u.road.roadtype = v->u.road.roadtype;
00296         u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes;
00297 
00298         u->spritenum = rvi_artic->image_index;
00299         u->cargo_type = rvi_artic->cargo_type;
00300         u->cargo_cap = rvi_artic->capacity;  // Callback 36 is called when the consist is finished
00301 
00302         SetRoadVehArticPart(u);
00303       } break;
00304     }
00305 
00306     if (flip_image) u->spritenum++;
00307 
00308     VehiclePositionChanged(u);
00309   }
00310 }

Generated on Mon Feb 16 23:12:05 2009 for openttd by  doxygen 1.5.6