00001
00002
00005 #include "stdafx.h"
00006 #include "train.h"
00007 #include "roadveh.h"
00008 #include "aircraft.h"
00009 #include "newgrf_engine.h"
00010 #include "vehicle_func.h"
00011
00012 #include "table/strings.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
00021
00022 if (!Vehicle::CanAllocateItem()) return 0;
00023
00024 Vehicle *v = NULL;;
00025 if (!purchase_window) {
00026 v = new InvalidVehicle();
00027 v->engine_type = engine_type;
00028 }
00029
00030 uint i;
00031 for (i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00032 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, v);
00033 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00034 }
00035
00036 delete v;
00037
00038 return i - 1;
00039 }
00040
00041
00049 static inline uint16 GetVehicleDefaultCapacity(EngineID engine, VehicleType type, CargoID *cargo_type)
00050 {
00051 const Engine *e = GetEngine(engine);
00052 CargoID cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : (CargoID)CT_INVALID);
00053 if (cargo_type != NULL) *cargo_type = cargo;
00054 if (cargo == CT_INVALID) return 0;
00055 switch (type) {
00056 case VEH_TRAIN:
00057 return GetEngineProperty(engine, 0x14, e->u.rail.capacity) + (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? e->u.rail.capacity : 0);
00058
00059 case VEH_ROAD:
00060 return GetEngineProperty(engine, 0x0F, e->u.road.capacity);
00061
00062 case VEH_SHIP:
00063 return GetEngineProperty(engine, 0x0D, e->u.ship.capacity);
00064
00065 case VEH_AIRCRAFT:
00066 return AircraftDefaultCargoCapacity(cargo, &e->u.air);
00067
00068 default: NOT_REACHED();
00069 }
00070
00071 }
00072
00080 static inline uint32 GetAvailableVehicleCargoTypes(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00081 {
00082 uint32 cargos = 0;
00083 CargoID initial_cargo_type;
00084
00085 if (GetVehicleDefaultCapacity(engine, type, &initial_cargo_type) > 0) {
00086 if (type != VEH_SHIP || ShipVehInfo(engine)->refittable) {
00087 const EngineInfo *ei = EngInfo(engine);
00088 cargos = ei->refit_mask;
00089 }
00090 if (include_initial_cargo_type && initial_cargo_type < NUM_CARGO) SetBit(cargos, initial_cargo_type);
00091 }
00092
00093 return cargos;
00094 }
00095
00096 uint16 *GetCapacityOfArticulatedParts(EngineID engine, VehicleType type)
00097 {
00098 static uint16 capacity[NUM_CARGO];
00099 memset(capacity, 0, sizeof(capacity));
00100
00101 CargoID cargo_type;
00102 uint16 cargo_capacity = GetVehicleDefaultCapacity(engine, type, &cargo_type);
00103 if (cargo_type < NUM_CARGO) capacity[cargo_type] = cargo_capacity;
00104
00105 if (type != VEH_TRAIN && type != VEH_ROAD) return capacity;
00106
00107 if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return capacity;
00108
00109 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00110 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00111 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00112
00113 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00114
00115 cargo_capacity = GetVehicleDefaultCapacity(artic_engine, type, &cargo_type);
00116 if (cargo_type < NUM_CARGO) capacity[cargo_type] += cargo_capacity;
00117 }
00118
00119 return capacity;
00120 }
00121
00127 bool IsArticulatedVehicleRefittable(EngineID engine)
00128 {
00129 if (IsEngineRefittable(engine)) return true;
00130
00131 const Engine *e = GetEngine(engine);
00132 if (e->type != VEH_TRAIN && e->type != VEH_ROAD) return false;
00133
00134 if (!HasBit(e->info.callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return false;
00135
00136 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00137 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00138 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00139
00140 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), e->type, GB(callback, 0, 7));
00141 if (IsEngineRefittable(artic_engine)) return true;
00142 }
00143
00144 return false;
00145 }
00146
00154 uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00155 {
00156 uint32 cargos = GetAvailableVehicleCargoTypes(engine, type, include_initial_cargo_type);
00157
00158 if (type != VEH_TRAIN && type != VEH_ROAD) return cargos;
00159
00160 if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return cargos;
00161
00162 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00163 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00164 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00165
00166 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00167 cargos |= GetAvailableVehicleCargoTypes(artic_engine, type, include_initial_cargo_type);
00168 }
00169
00170 return cargos;
00171 }
00172
00180 uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00181 {
00182 uint32 cargos = UINT32_MAX;
00183
00184 uint32 veh_cargos = GetAvailableVehicleCargoTypes(engine, type, include_initial_cargo_type);
00185 if (veh_cargos != 0) cargos &= veh_cargos;
00186
00187 if (type != VEH_TRAIN && type != VEH_ROAD) return cargos;
00188
00189 if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return cargos;
00190
00191 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00192 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00193 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00194
00195 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00196 veh_cargos = GetAvailableVehicleCargoTypes(artic_engine, type, include_initial_cargo_type);
00197 if (veh_cargos != 0) cargos &= veh_cargos;
00198 }
00199
00200 return cargos;
00201 }
00202
00203
00211 bool IsArticulatedVehicleCarryingDifferentCargos(const Vehicle *v, CargoID *cargo_type)
00212 {
00213 CargoID first_cargo = CT_INVALID;
00214
00215 do {
00216 if (v->cargo_cap > 0 && v->cargo_type != CT_INVALID) {
00217 if (first_cargo == CT_INVALID) first_cargo = v->cargo_type;
00218 if (first_cargo != v->cargo_type) {
00219 if (cargo_type != NULL) *cargo_type = CT_INVALID;
00220 return true;
00221 }
00222 }
00223
00224 switch (v->type) {
00225 case VEH_TRAIN:
00226 v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
00227 break;
00228
00229 case VEH_ROAD:
00230 v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
00231 break;
00232
00233 default:
00234 v = NULL;
00235 break;
00236 }
00237 } while (v != NULL);
00238
00239 if (cargo_type != NULL) *cargo_type = first_cargo;
00240 return false;
00241 }
00242
00251 void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
00252 {
00253 const Engine *engine = GetEngine(v->engine_type);
00254
00255 uint32 purchase_refit_union = GetUnionOfArticulatedRefitMasks(v->engine_type, v->type, true);
00256 uint32 purchase_refit_intersection = GetIntersectionOfArticulatedRefitMasks(v->engine_type, v->type, true);
00257 uint16 *purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type, v->type);
00258
00259 uint32 real_refit_union = 0;
00260 uint32 real_refit_intersection = UINT_MAX;
00261 uint16 real_default_capacity[NUM_CARGO];
00262 memset(real_default_capacity, 0, sizeof(real_default_capacity));
00263
00264 do {
00265 uint32 refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, v->type, true);
00266 real_refit_union |= refit_mask;
00267 if (refit_mask != 0) real_refit_intersection &= refit_mask;
00268
00269 assert(v->cargo_type < NUM_CARGO);
00270 real_default_capacity[v->cargo_type] += v->cargo_cap;
00271
00272 switch (v->type) {
00273 case VEH_TRAIN:
00274 v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
00275 break;
00276
00277 case VEH_ROAD:
00278 v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
00279 break;
00280
00281 default:
00282 v = NULL;
00283 break;
00284 }
00285 } while (v != NULL);
00286
00287
00288 bool carries_more = false;
00289 for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
00290 if (real_default_capacity[cid] != 0 && purchase_default_capacity[cid] == 0) {
00291 carries_more = true;
00292 break;
00293 }
00294 }
00295
00296
00297 if (real_refit_union != purchase_refit_union || real_refit_intersection != purchase_refit_intersection || carries_more) {
00298 ShowNewGrfVehicleError(engine->index, STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ARTICULATED_CARGO, GBUG_VEH_REFIT, false);
00299 }
00300 }
00301
00302 void AddArticulatedParts(Vehicle **vl, VehicleType type)
00303 {
00304 const Vehicle *v = vl[0];
00305 Vehicle *u = vl[0];
00306
00307 if (!HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return;
00308
00309 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00310 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v);
00311 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) return;
00312
00313
00314
00315 u->SetNext(vl[i]);
00316 if (u->Next() == NULL) return;
00317
00318 Vehicle *previous = u;
00319 u = u->Next();
00320
00321 EngineID engine_type = GetNewEngineID(GetEngineGRF(v->engine_type), type, GB(callback, 0, 7));
00322 bool flip_image = HasBit(callback, 7);
00323
00324 const Engine *e_artic = GetEngine(engine_type);
00325 switch (type) {
00326 default: NOT_REACHED();
00327
00328 case VEH_TRAIN:
00329 u = new (u) Train();
00330 u->subtype = 0;
00331 previous->SetNext(u);
00332 u->u.rail.track = v->u.rail.track;
00333 u->u.rail.railtype = v->u.rail.railtype;
00334 u->u.rail.first_engine = v->engine_type;
00335
00336 u->spritenum = e_artic->u.rail.image_index;
00337 if (e_artic->CanCarryCargo()) {
00338 u->cargo_type = e_artic->GetDefaultCargoType();
00339 u->cargo_cap = e_artic->u.rail.capacity;
00340 } else {
00341 u->cargo_type = v->cargo_type;
00342 u->cargo_cap = 0;
00343 }
00344
00345 SetArticulatedPart(u);
00346 break;
00347
00348 case VEH_ROAD:
00349 u = new (u) RoadVehicle();
00350 u->subtype = 0;
00351 previous->SetNext(u);
00352 u->u.road.first_engine = v->engine_type;
00353 u->u.road.cached_veh_length = 8;
00354 u->u.road.state = RVSB_IN_DEPOT;
00355
00356 u->u.road.roadtype = v->u.road.roadtype;
00357 u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes;
00358
00359 u->spritenum = e_artic->u.road.image_index;
00360 if (e_artic->CanCarryCargo()) {
00361 u->cargo_type = e_artic->GetDefaultCargoType();
00362 u->cargo_cap = e_artic->u.road.capacity;
00363 } else {
00364 u->cargo_type = v->cargo_type;
00365 u->cargo_cap = 0;
00366 }
00367
00368 SetRoadVehArticPart(u);
00369 break;
00370 }
00371
00372
00373 u->direction = v->direction;
00374 u->owner = v->owner;
00375 u->tile = v->tile;
00376 u->x_pos = v->x_pos;
00377 u->y_pos = v->y_pos;
00378 u->z_pos = v->z_pos;
00379 u->build_year = v->build_year;
00380 u->vehstatus = v->vehstatus & ~VS_STOPPED;
00381
00382 u->cargo_subtype = 0;
00383 u->max_speed = 0;
00384 u->max_age = 0;
00385 u->engine_type = engine_type;
00386 u->value = 0;
00387 u->cur_image = 0xAC2;
00388 u->random_bits = VehicleRandomBits();
00389
00390 if (flip_image) u->spritenum++;
00391
00392 VehicleMove(u, false);
00393 }
00394 }