# articulated_vehicles.cpp

Go to the documentation of this file.

    00001 /* $Id: articulated_vehicles.cpp 13686 2008-07-09 19:13:21Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "articulated_vehicles.h"
    00008 #include "engine.h"
    00009 #include "train.h"
    00010 #include "roadveh.h"
    00011 #include "newgrf_callbacks.h"
    00012 #include "newgrf_engine.h"
    00013 #include "vehicle_func.h"
    00014
    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_UVALUE(EngineID); 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
    00038 uint16 *GetCapacityOfArticulatedParts(EngineID engine, VehicleType type)
    00039 {
    00040   static uint16 capacity[NUM_CARGO];
    00041   memset(capacity, 0, sizeof(capacity));
    00042
    00043   if (type == VEH_TRAIN) {
    00044     const RailVehicleInfo *rvi = RailVehInfo(engine);
    00045     capacity[rvi->cargo_type] = GetEngineProperty(engine, 0x14, rvi->capacity);
    00046     if (rvi->railveh_type == RAILVEH_MULTIHEAD) capacity[rvi->cargo_type] += rvi->capacity;
    00047   } else if (type == VEH_ROAD) {
    00048     const RoadVehicleInfo *rvi = RoadVehInfo(engine);
    00049     capacity[rvi->cargo_type] = GetEngineProperty(engine, 0x0F, rvi->capacity);
    00050   }
    00051
    00052   if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return capacity;
    00053
    00054   for (uint i = 1; i < MAX_UVALUE(EngineID); i++) {
    00055     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
    00056     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
    00057
    00058     EngineID artic_engine = GetFirstEngineOfType(type) + GB(callback, 0, 7);
    00059
    00060     if (type == VEH_TRAIN) {
    00061       const RailVehicleInfo *rvi = RailVehInfo(artic_engine);
    00062       capacity[rvi->cargo_type] += GetEngineProperty(artic_engine, 0x14, rvi->capacity);
    00063     } else if (type == VEH_ROAD) {
    00064       const RoadVehicleInfo *rvi = RoadVehInfo(artic_engine);
    00065       capacity[rvi->cargo_type] += GetEngineProperty(artic_engine, 0x0F, rvi->capacity);
    00066     }
    00067   }
    00068
    00069   return capacity;
    00070 }
    00071
    00072
    00073 void AddArticulatedParts(Vehicle **vl, VehicleType type)
    00074 {
    00075   const Vehicle *v = vl[0];
    00076   Vehicle *u = vl[0];
    00077
    00078   if (!HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return;
    00079
    00080   for (uint i = 1; i < MAX_UVALUE(EngineID); i++) {
    00081     uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v);
    00082     if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) return;
    00083
    00084     /* Attempt to use pre-allocated vehicles until they run out. This can happen
    00085      * if the callback returns different values depending on the cargo type. */
    00086     u->SetNext(vl[i]);
    00087     if (u->Next() == NULL) return;
    00088
    00089     Vehicle *previous = u;
    00090     u = u->Next();
    00091
    00092     EngineID engine_type = GetFirstEngineOfType(type) + GB(callback, 0, 7);
    00093     bool flip_image = HasBit(callback, 7);
    00094
    00095     /* get common values from first engine */
    00096     u->direction = v->direction;
    00097     u->owner = v->owner;
    00098     u->tile = v->tile;
    00099     u->x_pos = v->x_pos;
    00100     u->y_pos = v->y_pos;
    00101     u->z_pos = v->z_pos;
    00102     u->build_year = v->build_year;
    00103     u->vehstatus = v->vehstatus & ~VS_STOPPED;
    00104
    00105     u->cargo_subtype = 0;
    00106     u->max_speed = 0;
    00107     u->max_age = 0;
    00108     u->engine_type = engine_type;
    00109     u->value = 0;
    00110     u->subtype = 0;
    00111     u->cur_image = 0xAC2;
    00112     u->random_bits = VehicleRandomBits();
    00113
    00114     switch (type) {
    00115       default: NOT_REACHED();
    00116
    00117       case VEH_TRAIN: {
    00118         const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
    00119
    00120         u = new (u) Train();
    00121         previous->SetNext(u);
    00122         u->u.rail.track = v->u.rail.track;
    00123         u->u.rail.railtype = v->u.rail.railtype;
    00124         u->u.rail.first_engine = v->engine_type;
    00125
    00126         u->spritenum = rvi_artic->image_index;
    00127         u->cargo_type = rvi_artic->cargo_type;
    00128         u->cargo_cap = rvi_artic->capacity;
    00129
    00130         SetArticulatedPart(u);
    00131       } break;
    00132
    00133       case VEH_ROAD: {
    00134         const RoadVehicleInfo *rvi_artic = RoadVehInfo(engine_type);
    00135
    00136         u = new (u) RoadVehicle();
    00137         previous->SetNext(u);
    00138         u->u.road.first_engine = v->engine_type;
    00139         u->u.road.cached_veh_length = GetRoadVehLength(u);
    00140         u->u.road.state = RVSB_IN_DEPOT;
    00141
    00142         u->u.road.roadtype = v->u.road.roadtype;
    00143         u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes;
    00144
    00145         u->spritenum = rvi_artic->image_index;
    00146         u->cargo_type = rvi_artic->cargo_type;
    00147         u->cargo_cap = rvi_artic->capacity;
    00148
    00149         SetRoadVehArticPart(u);
    00150       } break;
    00151     }
    00152
    00153     if (flip_image) u->spritenum++;
    00154
    00155     VehiclePositionChanged(u);
    00156   }
    00157 }