00001
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 #include "table/strings.h"
00012
00013 static const uint MAX_ARTICULATED_PARTS = 100;
00014
00015 uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
00016 {
00017 if (!HasBit(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return 0;
00018
00019
00020
00021 if (!Vehicle::CanAllocateItem()) return 0;
00022
00023 Vehicle *v = NULL;;
00024 if (!purchase_window) {
00025 v = new InvalidVehicle();
00026 v->engine_type = engine_type;
00027 }
00028
00029 uint i;
00030 for (i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00031 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, v);
00032 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00033 }
00034
00035 delete v;
00036
00037 return i - 1;
00038 }
00039
00040
00048 static inline uint16 GetVehicleDefaultCapacity(EngineID engine, VehicleType type, CargoID *cargo_type)
00049 {
00050 const Engine *e = GetEngine(engine);
00051 CargoID cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : (CargoID)CT_INVALID);
00052 if (cargo_type != NULL) *cargo_type = cargo;
00053 if (cargo == CT_INVALID) return 0;
00054 return e->GetDisplayDefaultCapacity();
00055 }
00056
00064 static inline uint32 GetAvailableVehicleCargoTypes(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00065 {
00066 uint32 cargos = 0;
00067 CargoID initial_cargo_type;
00068
00069 if (GetVehicleDefaultCapacity(engine, type, &initial_cargo_type) > 0) {
00070 if (type != VEH_SHIP || ShipVehInfo(engine)->refittable) {
00071 const EngineInfo *ei = EngInfo(engine);
00072 cargos = ei->refit_mask;
00073 }
00074 if (include_initial_cargo_type && initial_cargo_type < NUM_CARGO) SetBit(cargos, initial_cargo_type);
00075 }
00076
00077 return cargos;
00078 }
00079
00080 uint16 *GetCapacityOfArticulatedParts(EngineID engine, VehicleType type)
00081 {
00082 static uint16 capacity[NUM_CARGO];
00083 memset(capacity, 0, sizeof(capacity));
00084
00085 CargoID cargo_type;
00086 uint16 cargo_capacity = GetVehicleDefaultCapacity(engine, type, &cargo_type);
00087 if (cargo_type < NUM_CARGO) capacity[cargo_type] = cargo_capacity;
00088
00089 if (type != VEH_TRAIN && type != VEH_ROAD) return capacity;
00090
00091 if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return capacity;
00092
00093 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00094 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00095 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00096
00097 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00098
00099 cargo_capacity = GetVehicleDefaultCapacity(artic_engine, type, &cargo_type);
00100 if (cargo_type < NUM_CARGO) capacity[cargo_type] += cargo_capacity;
00101 }
00102
00103 return capacity;
00104 }
00105
00111 bool IsArticulatedVehicleRefittable(EngineID engine)
00112 {
00113 if (IsEngineRefittable(engine)) return true;
00114
00115 const Engine *e = GetEngine(engine);
00116 if (e->type != VEH_TRAIN && e->type != VEH_ROAD) return false;
00117
00118 if (!HasBit(e->info.callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return false;
00119
00120 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00121 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00122 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00123
00124 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), e->type, GB(callback, 0, 7));
00125 if (IsEngineRefittable(artic_engine)) return true;
00126 }
00127
00128 return false;
00129 }
00130
00138 uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00139 {
00140 uint32 cargos = GetAvailableVehicleCargoTypes(engine, type, include_initial_cargo_type);
00141
00142 if (type != VEH_TRAIN && type != VEH_ROAD) return cargos;
00143
00144 if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return cargos;
00145
00146 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00147 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00148 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00149
00150 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00151 cargos |= GetAvailableVehicleCargoTypes(artic_engine, type, include_initial_cargo_type);
00152 }
00153
00154 return cargos;
00155 }
00156
00164 uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, VehicleType type, bool include_initial_cargo_type)
00165 {
00166 uint32 cargos = UINT32_MAX;
00167
00168 uint32 veh_cargos = GetAvailableVehicleCargoTypes(engine, type, include_initial_cargo_type);
00169 if (veh_cargos != 0) cargos &= veh_cargos;
00170
00171 if (type != VEH_TRAIN && type != VEH_ROAD) return cargos;
00172
00173 if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return cargos;
00174
00175 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00176 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
00177 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
00178
00179 EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
00180 veh_cargos = GetAvailableVehicleCargoTypes(artic_engine, type, include_initial_cargo_type);
00181 if (veh_cargos != 0) cargos &= veh_cargos;
00182 }
00183
00184 return cargos;
00185 }
00186
00187
00195 bool IsArticulatedVehicleCarryingDifferentCargos(const Vehicle *v, CargoID *cargo_type)
00196 {
00197 CargoID first_cargo = CT_INVALID;
00198
00199 do {
00200 if (v->cargo_cap > 0 && v->cargo_type != CT_INVALID) {
00201 if (first_cargo == CT_INVALID) first_cargo = v->cargo_type;
00202 if (first_cargo != v->cargo_type) {
00203 if (cargo_type != NULL) *cargo_type = CT_INVALID;
00204 return true;
00205 }
00206 }
00207
00208 switch (v->type) {
00209 case VEH_TRAIN:
00210 v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
00211 break;
00212
00213 case VEH_ROAD:
00214 v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
00215 break;
00216
00217 default:
00218 v = NULL;
00219 break;
00220 }
00221 } while (v != NULL);
00222
00223 if (cargo_type != NULL) *cargo_type = first_cargo;
00224 return false;
00225 }
00226
00235 void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
00236 {
00237 const Engine *engine = GetEngine(v->engine_type);
00238
00239 uint32 purchase_refit_union = GetUnionOfArticulatedRefitMasks(v->engine_type, v->type, true);
00240 uint32 purchase_refit_intersection = GetIntersectionOfArticulatedRefitMasks(v->engine_type, v->type, true);
00241 uint16 *purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type, v->type);
00242
00243 uint32 real_refit_union = 0;
00244 uint32 real_refit_intersection = UINT_MAX;
00245 uint16 real_default_capacity[NUM_CARGO];
00246 memset(real_default_capacity, 0, sizeof(real_default_capacity));
00247
00248 do {
00249 uint32 refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, v->type, true);
00250 real_refit_union |= refit_mask;
00251 if (refit_mask != 0) real_refit_intersection &= refit_mask;
00252
00253 assert(v->cargo_type < NUM_CARGO);
00254 real_default_capacity[v->cargo_type] += v->cargo_cap;
00255
00256 switch (v->type) {
00257 case VEH_TRAIN:
00258 v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
00259 break;
00260
00261 case VEH_ROAD:
00262 v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
00263 break;
00264
00265 default:
00266 v = NULL;
00267 break;
00268 }
00269 } while (v != NULL);
00270
00271
00272 bool carries_more = false;
00273 for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
00274 if (real_default_capacity[cid] != 0 && purchase_default_capacity[cid] == 0) {
00275 carries_more = true;
00276 break;
00277 }
00278 }
00279
00280
00281 if (real_refit_union != purchase_refit_union || real_refit_intersection != purchase_refit_intersection || carries_more) {
00282 ShowNewGrfVehicleError(engine->index, STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ARTICULATED_CARGO, GBUG_VEH_REFIT, false);
00283 }
00284 }
00285
00286 void AddArticulatedParts(Vehicle **vl, VehicleType type)
00287 {
00288 const Vehicle *v = vl[0];
00289 Vehicle *u = vl[0];
00290
00291 if (!HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return;
00292
00293 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00294 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v);
00295 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) return;
00296
00297
00298
00299 u->SetNext(vl[i]);
00300 if (u->Next() == NULL) return;
00301
00302 Vehicle *previous = u;
00303 u = u->Next();
00304
00305 EngineID engine_type = GetNewEngineID(GetEngineGRF(v->engine_type), type, GB(callback, 0, 7));
00306 bool flip_image = HasBit(callback, 7);
00307
00308 const Engine *e_artic = GetEngine(engine_type);
00309 switch (type) {
00310 default: NOT_REACHED();
00311
00312 case VEH_TRAIN:
00313 u = new (u) Train();
00314 u->subtype = 0;
00315 previous->SetNext(u);
00316 u->u.rail.track = v->u.rail.track;
00317 u->u.rail.railtype = v->u.rail.railtype;
00318 u->u.rail.first_engine = v->engine_type;
00319
00320 u->spritenum = e_artic->u.rail.image_index;
00321 if (e_artic->CanCarryCargo()) {
00322 u->cargo_type = e_artic->GetDefaultCargoType();
00323 u->cargo_cap = e_artic->u.rail.capacity;
00324 } else {
00325 u->cargo_type = v->cargo_type;
00326 u->cargo_cap = 0;
00327 }
00328
00329 SetArticulatedPart(u);
00330 break;
00331
00332 case VEH_ROAD:
00333 u = new (u) RoadVehicle();
00334 u->subtype = 0;
00335 previous->SetNext(u);
00336 u->u.road.first_engine = v->engine_type;
00337 u->u.road.cached_veh_length = 8;
00338 u->u.road.state = RVSB_IN_DEPOT;
00339
00340 u->u.road.roadtype = v->u.road.roadtype;
00341 u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes;
00342
00343 u->spritenum = e_artic->u.road.image_index;
00344 if (e_artic->CanCarryCargo()) {
00345 u->cargo_type = e_artic->GetDefaultCargoType();
00346 u->cargo_cap = e_artic->u.road.capacity;
00347 } else {
00348 u->cargo_type = v->cargo_type;
00349 u->cargo_cap = 0;
00350 }
00351
00352 SetRoadVehArticPart(u);
00353 break;
00354 }
00355
00356
00357 u->direction = v->direction;
00358 u->owner = v->owner;
00359 u->tile = v->tile;
00360 u->x_pos = v->x_pos;
00361 u->y_pos = v->y_pos;
00362 u->z_pos = v->z_pos;
00363 u->build_year = v->build_year;
00364 u->vehstatus = v->vehstatus & ~VS_STOPPED;
00365
00366 u->cargo_subtype = 0;
00367 u->max_speed = 0;
00368 u->max_age = 0;
00369 u->engine_type = engine_type;
00370 u->value = 0;
00371 u->cur_image = 0xAC2;
00372 u->random_bits = VehicleRandomBits();
00373
00374 if (flip_image) u->spritenum++;
00375
00376 VehicleMove(u, false);
00377 }
00378 }