00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "train.h"
00014 #include "roadveh.h"
00015 #include "vehicle_func.h"
00016 #include "engine_func.h"
00017 #include "company_func.h"
00018
00019 #include "table/strings.h"
00020 #include "table/sprites.h"
00021
00022 static const uint MAX_ARTICULATED_PARTS = 100;
00023
00032 static EngineID GetNextArticulatedPart(uint index, EngineID front_type, Vehicle *front = NULL, bool *mirrored = NULL)
00033 {
00034 assert(front == NULL || front->engine_type == front_type);
00035
00036 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, index, 0, front_type, front);
00037 if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) return INVALID_ENGINE;
00038
00039 if (mirrored != NULL) *mirrored = HasBit(callback, 7);
00040 return GetNewEngineID(GetEngineGRF(front_type), Engine::Get(front_type)->type, GB(callback, 0, 7));
00041 }
00042
00049 uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
00050 {
00051 if (!HasBit(EngInfo(engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return 0;
00052
00053
00054
00055 if (!Vehicle::CanAllocateItem()) return 0;
00056
00057 Vehicle *v = NULL;
00058 if (!purchase_window) {
00059 v = new Vehicle();
00060 v->engine_type = engine_type;
00061 v->owner = _current_company;
00062 }
00063
00064 uint i;
00065 for (i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00066 if (GetNextArticulatedPart(i, engine_type, v) == INVALID_ENGINE) break;
00067 }
00068
00069 delete v;
00070
00071 return i - 1;
00072 }
00073
00074
00081 static inline uint16 GetVehicleDefaultCapacity(EngineID engine, CargoID *cargo_type)
00082 {
00083 const Engine *e = Engine::Get(engine);
00084 CargoID cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : (CargoID)CT_INVALID);
00085 if (cargo_type != NULL) *cargo_type = cargo;
00086 if (cargo == CT_INVALID) return 0;
00087 return e->GetDisplayDefaultCapacity();
00088 }
00089
00096 static inline uint32 GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type)
00097 {
00098 uint32 cargos = 0;
00099 CargoID initial_cargo_type;
00100
00101 if (GetVehicleDefaultCapacity(engine, &initial_cargo_type) > 0) {
00102 const EngineInfo *ei = EngInfo(engine);
00103 cargos = ei->refit_mask;
00104 if (include_initial_cargo_type && initial_cargo_type < NUM_CARGO) SetBit(cargos, initial_cargo_type);
00105 }
00106
00107 return cargos;
00108 }
00109
00115 CargoArray GetCapacityOfArticulatedParts(EngineID engine)
00116 {
00117 CargoArray capacity;
00118 const Engine *e = Engine::Get(engine);
00119
00120 CargoID cargo_type;
00121 uint16 cargo_capacity = GetVehicleDefaultCapacity(engine, &cargo_type);
00122 if (cargo_type < NUM_CARGO) capacity[cargo_type] = cargo_capacity;
00123
00124 if (!e->IsGroundVehicle()) return capacity;
00125
00126 if (!HasBit(e->info.callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return capacity;
00127
00128 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00129 EngineID artic_engine = GetNextArticulatedPart(i, engine);
00130 if (artic_engine == INVALID_ENGINE) break;
00131
00132 cargo_capacity = GetVehicleDefaultCapacity(artic_engine, &cargo_type);
00133 if (cargo_type < NUM_CARGO) capacity[cargo_type] += cargo_capacity;
00134 }
00135
00136 return capacity;
00137 }
00138
00144 bool IsArticulatedVehicleRefittable(EngineID engine)
00145 {
00146 if (IsEngineRefittable(engine)) return true;
00147
00148 const Engine *e = Engine::Get(engine);
00149 if (!e->IsGroundVehicle()) return false;
00150
00151 if (!HasBit(e->info.callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return false;
00152
00153 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00154 EngineID artic_engine = GetNextArticulatedPart(i, engine);
00155 if (artic_engine == INVALID_ENGINE) break;
00156
00157 if (IsEngineRefittable(artic_engine)) return true;
00158 }
00159
00160 return false;
00161 }
00162
00170 void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, uint32 *union_mask, uint32 *intersection_mask)
00171 {
00172 const Engine *e = Engine::Get(engine);
00173 uint32 veh_cargos = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type);
00174 *union_mask = veh_cargos;
00175 *intersection_mask = (veh_cargos != 0) ? veh_cargos : UINT32_MAX;
00176
00177 if (!e->IsGroundVehicle()) return;
00178 if (!HasBit(e->info.callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return;
00179
00180 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00181 EngineID artic_engine = GetNextArticulatedPart(i, engine);
00182 if (artic_engine == INVALID_ENGINE) break;
00183
00184 veh_cargos = GetAvailableVehicleCargoTypes(artic_engine, include_initial_cargo_type);
00185 *union_mask |= veh_cargos;
00186 if (veh_cargos != 0) *intersection_mask &= veh_cargos;
00187 }
00188 }
00189
00196 uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
00197 {
00198 uint32 union_mask, intersection_mask;
00199 GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask);
00200 return union_mask;
00201 }
00202
00209 uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
00210 {
00211 uint32 union_mask, intersection_mask;
00212 GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask);
00213 return intersection_mask;
00214 }
00215
00216
00224 bool IsArticulatedVehicleCarryingDifferentCargos(const Vehicle *v, CargoID *cargo_type)
00225 {
00226 CargoID first_cargo = CT_INVALID;
00227
00228 do {
00229 if (v->cargo_cap > 0 && v->cargo_type != CT_INVALID) {
00230 if (first_cargo == CT_INVALID) first_cargo = v->cargo_type;
00231 if (first_cargo != v->cargo_type) {
00232 if (cargo_type != NULL) *cargo_type = CT_INVALID;
00233 return true;
00234 }
00235 }
00236
00237 v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL;
00238 } while (v != NULL);
00239
00240 if (cargo_type != NULL) *cargo_type = first_cargo;
00241 return false;
00242 }
00243
00252 void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
00253 {
00254 const Engine *engine = Engine::Get(v->engine_type);
00255
00256 uint32 purchase_refit_union, purchase_refit_intersection;
00257 GetArticulatedRefitMasks(v->engine_type, true, &purchase_refit_union, &purchase_refit_intersection);
00258 CargoArray purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type);
00259
00260 uint32 real_refit_union = 0;
00261 uint32 real_refit_intersection = UINT_MAX;
00262 CargoArray real_default_capacity;
00263
00264 do {
00265 uint32 refit_mask = GetAvailableVehicleCargoTypes(v->engine_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 v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL;
00273 } while (v != NULL);
00274
00275
00276 bool carries_more = false;
00277 for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
00278 if (real_default_capacity[cid] != 0 && purchase_default_capacity[cid] == 0) {
00279 carries_more = true;
00280 break;
00281 }
00282 }
00283
00284
00285 if (real_refit_union != purchase_refit_union || real_refit_intersection != purchase_refit_intersection || carries_more) {
00286 ShowNewGrfVehicleError(engine->index, STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ARTICULATED_CARGO, GBUG_VEH_REFIT, false);
00287 }
00288 }
00289
00294 void AddArticulatedParts(Vehicle *first)
00295 {
00296 VehicleType type = first->type;
00297 if (!HasBit(EngInfo(first->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return;
00298
00299 Vehicle *v = first;
00300 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
00301 bool flip_image;
00302 EngineID engine_type = GetNextArticulatedPart(i, first->engine_type, first, &flip_image);
00303 if (engine_type == INVALID_ENGINE) return;
00304
00305
00306
00307 if (!Vehicle::CanAllocateItem()) return;
00308
00309 GroundVehicleCache *gcache = v->GetGroundVehicleCache();
00310 gcache->first_engine = v->engine_type;
00311
00312 const Engine *e_artic = Engine::Get(engine_type);
00313 switch (type) {
00314 default: NOT_REACHED();
00315
00316 case VEH_TRAIN: {
00317 Train *front = Train::From(first);
00318 Train *t = new Train();
00319 v->SetNext(t);
00320 v = t;
00321
00322 t->subtype = 0;
00323 t->track = front->track;
00324 t->railtype = front->railtype;
00325
00326 t->spritenum = e_artic->u.rail.image_index;
00327 if (e_artic->CanCarryCargo()) {
00328 t->cargo_type = e_artic->GetDefaultCargoType();
00329 t->cargo_cap = e_artic->u.rail.capacity;
00330 } else {
00331 t->cargo_type = front->cargo_type;
00332 t->cargo_cap = 0;
00333 }
00334
00335 t->SetArticulatedPart();
00336 break;
00337 }
00338
00339 case VEH_ROAD: {
00340 RoadVehicle *front = RoadVehicle::From(first);
00341 RoadVehicle *rv = new RoadVehicle();
00342 v->SetNext(rv);
00343 v = rv;
00344
00345 rv->subtype = 0;
00346 gcache->cached_veh_length = VEHICLE_LENGTH;
00347 rv->state = RVSB_IN_DEPOT;
00348
00349 rv->roadtype = front->roadtype;
00350 rv->compatible_roadtypes = front->compatible_roadtypes;
00351
00352 rv->spritenum = e_artic->u.road.image_index;
00353 if (e_artic->CanCarryCargo()) {
00354 rv->cargo_type = e_artic->GetDefaultCargoType();
00355 rv->cargo_cap = e_artic->u.road.capacity;
00356 } else {
00357 rv->cargo_type = front->cargo_type;
00358 rv->cargo_cap = 0;
00359 }
00360
00361 rv->SetArticulatedPart();
00362 break;
00363 }
00364 }
00365
00366
00367 v->direction = first->direction;
00368 v->owner = first->owner;
00369 v->tile = first->tile;
00370 v->x_pos = first->x_pos;
00371 v->y_pos = first->y_pos;
00372 v->z_pos = first->z_pos;
00373 v->build_year = first->build_year;
00374 v->vehstatus = first->vehstatus & ~VS_STOPPED;
00375
00376 v->cargo_subtype = 0;
00377 v->max_age = 0;
00378 v->engine_type = engine_type;
00379 v->value = 0;
00380 v->cur_image = SPR_IMG_QUERY;
00381 v->random_bits = VehicleRandomBits();
00382
00383 if (flip_image) v->spritenum++;
00384
00385 VehicleMove(v, false);
00386 }
00387 }