articulated_vehicles.cpp

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

Generated on Fri Nov 21 19:01:31 2008 for openttd by  doxygen 1.5.6