/** * Converts all trains to the new subtype format introduced in savegame 16.2 * It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found */ void ConvertOldMultiheadToNew() { Train *t; FOR_ALL_TRAINS(t) SetBit(t->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop FOR_ALL_TRAINS(t) { if (HasBit(t->subtype, 7) && ((t->subtype & ~0x80) == 0 || (t->subtype & ~0x80) == 4)) { for (Train *u = t; u != NULL; u = u->Next()) { const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); ClrBit(u->subtype, 7); switch (u->subtype) { case 0: // TS_Front_Engine if (rvi->railveh_type == RAILVEH_MULTIHEAD) u->SetMultiheaded(); u->SetFrontEngine(); u->SetEngine(); break; case 1: // TS_Artic_Part u->subtype = 0; u->SetArticulatedPart(); break; case 2: // TS_Not_First u->subtype = 0; if (rvi->railveh_type == RAILVEH_WAGON) { /* normal wagon */ u->SetWagon(); break; } if (rvi->railveh_type == RAILVEH_MULTIHEAD && rvi->image_index == u->spritenum - 1) { /* rear end of a multiheaded engine */ u->SetMultiheaded(); break; } if (rvi->railveh_type == RAILVEH_MULTIHEAD) u->SetMultiheaded(); u->SetEngine(); break; case 4: // TS_Free_Car u->subtype = 0; u->SetWagon(); u->SetFreeWagon(); break; default: NOT_REACHED(); } } } } }
void AddArticulatedParts(Vehicle *first) { VehicleType type = first->type; if (!HasBit(EngInfo(first->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return; Vehicle *v = first; for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) { bool flip_image; EngineID engine_type = GetNextArticPart(i, first->engine_type, first, &flip_image); if (engine_type == INVALID_ENGINE) return; /* In the (very rare) case the GRF reported wrong number of articulated parts * and we run out of available vehicles, bail out. */ if (!Vehicle::CanAllocateItem()) return; const Engine *e_artic = Engine::Get(engine_type); switch (type) { default: NOT_REACHED(); case VEH_TRAIN: { Train *front = Train::From(first); Train *t = new Train(); v->SetNext(t); v = t; t->subtype = 0; t->track = front->track; t->railtype = front->railtype; t->tcache.first_engine = front->engine_type; // needs to be set before first callback t->spritenum = e_artic->u.rail.image_index; if (e_artic->CanCarryCargo()) { t->cargo_type = e_artic->GetDefaultCargoType(); t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished } else { t->cargo_type = front->cargo_type; // Needed for livery selection t->cargo_cap = 0; } t->SetArticulatedPart(); } break; case VEH_ROAD: { RoadVehicle *front = RoadVehicle::From(first); RoadVehicle *rv = new RoadVehicle(); v->SetNext(rv); v = rv; rv->subtype = 0; rv->rcache.first_engine = front->engine_type; // needs to be set before first callback rv->rcache.cached_veh_length = 8; // Callback is called when the consist is finished rv->state = RVSB_IN_DEPOT; rv->roadtype = front->roadtype; rv->compatible_roadtypes = front->compatible_roadtypes; rv->spritenum = e_artic->u.road.image_index; if (e_artic->CanCarryCargo()) { rv->cargo_type = e_artic->GetDefaultCargoType(); rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished } else { rv->cargo_type = front->cargo_type; // Needed for livery selection rv->cargo_cap = 0; } rv->SetArticulatedPart(); } break; } /* get common values from first engine */ v->direction = first->direction; v->owner = first->owner; v->tile = first->tile; v->x_pos = first->x_pos; v->y_pos = first->y_pos; v->z_pos = first->z_pos; v->build_year = first->build_year; v->vehstatus = first->vehstatus & ~VS_STOPPED; v->cargo_subtype = 0; v->max_speed = 0; v->max_age = 0; v->engine_type = engine_type; v->value = 0; v->cur_image = SPR_IMG_QUERY; v->random_bits = VehicleRandomBits(); if (flip_image) v->spritenum++; VehicleMove(v, false); } }