00001
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
00237
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
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 }