2007-06-01 11:41:02 +00:00
|
|
|
/* $Id$ */
|
|
|
|
|
2007-06-01 12:26:14 +00:00
|
|
|
/** @file articulated_vehicles.cpp */
|
2007-06-01 11:41:02 +00:00
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "openttd.h"
|
|
|
|
#include "articulated_vehicles.h"
|
|
|
|
#include "train.h"
|
2007-06-11 14:00:16 +00:00
|
|
|
#include "roadveh.h"
|
2007-06-01 11:41:02 +00:00
|
|
|
#include "newgrf_callbacks.h"
|
|
|
|
#include "newgrf_engine.h"
|
2007-12-27 13:35:39 +00:00
|
|
|
#include "vehicle_func.h"
|
2007-06-01 11:41:02 +00:00
|
|
|
|
2007-06-11 14:00:16 +00:00
|
|
|
|
2007-09-17 04:23:03 +00:00
|
|
|
uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
|
2007-06-01 11:41:02 +00:00
|
|
|
{
|
2007-11-19 21:02:30 +00:00
|
|
|
if (!HasBit(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return 0;
|
2007-06-01 11:41:02 +00:00
|
|
|
|
2007-09-17 04:23:03 +00:00
|
|
|
Vehicle *v = NULL;;
|
|
|
|
if (!purchase_window) {
|
|
|
|
v = new InvalidVehicle();
|
|
|
|
v->engine_type = engine_type;
|
|
|
|
}
|
|
|
|
|
2007-06-01 11:41:02 +00:00
|
|
|
uint i;
|
2007-09-16 20:48:00 +00:00
|
|
|
for (i = 1; i < MAX_UVALUE(EngineID); i++) {
|
2007-09-17 04:23:03 +00:00
|
|
|
uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, v);
|
2008-04-21 14:33:33 +00:00
|
|
|
if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
|
2007-06-01 11:41:02 +00:00
|
|
|
}
|
|
|
|
|
2007-09-17 04:23:03 +00:00
|
|
|
delete v;
|
|
|
|
|
2007-06-01 11:41:02 +00:00
|
|
|
return i - 1;
|
|
|
|
}
|
|
|
|
|
2008-02-14 07:25:24 +00:00
|
|
|
|
|
|
|
uint16 *GetCapacityOfArticulatedParts(EngineID engine, VehicleType type)
|
|
|
|
{
|
|
|
|
static uint16 capacity[NUM_CARGO];
|
|
|
|
memset(capacity, 0, sizeof(capacity));
|
|
|
|
|
|
|
|
if (type == VEH_TRAIN) {
|
|
|
|
const RailVehicleInfo *rvi = RailVehInfo(engine);
|
|
|
|
capacity[rvi->cargo_type] = rvi->capacity;
|
|
|
|
if (rvi->railveh_type == RAILVEH_MULTIHEAD) capacity[rvi->cargo_type] += rvi->capacity;
|
|
|
|
} else if (type == VEH_ROAD) {
|
|
|
|
const RoadVehicleInfo *rvi = RoadVehInfo(engine);
|
|
|
|
capacity[rvi->cargo_type] = rvi->capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!HasBit(EngInfo(engine)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return capacity;
|
|
|
|
|
|
|
|
for (uint i = 1; i < MAX_UVALUE(EngineID); i++) {
|
|
|
|
uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
|
2008-04-21 14:33:33 +00:00
|
|
|
if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
|
2008-02-14 07:25:24 +00:00
|
|
|
|
|
|
|
EngineID artic_engine = GetFirstEngineOfType(type) + GB(callback, 0, 7);
|
|
|
|
|
|
|
|
if (type == VEH_TRAIN) {
|
|
|
|
const RailVehicleInfo *rvi = RailVehInfo(artic_engine);
|
|
|
|
capacity[rvi->cargo_type] += GetEngineProperty(artic_engine, 0x14, rvi->capacity);
|
|
|
|
} else if (type == VEH_ROAD) {
|
|
|
|
const RoadVehicleInfo *rvi = RoadVehInfo(artic_engine);
|
|
|
|
capacity[rvi->cargo_type] += GetEngineProperty(artic_engine, 0x0F, rvi->capacity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-11 14:00:16 +00:00
|
|
|
void AddArticulatedParts(Vehicle **vl, VehicleType type)
|
2007-06-01 11:41:02 +00:00
|
|
|
{
|
|
|
|
const Vehicle *v = vl[0];
|
|
|
|
Vehicle *u = vl[0];
|
|
|
|
|
2007-11-19 21:02:30 +00:00
|
|
|
if (!HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return;
|
2007-06-01 11:41:02 +00:00
|
|
|
|
2007-09-16 20:48:00 +00:00
|
|
|
for (uint i = 1; i < MAX_UVALUE(EngineID); i++) {
|
2007-07-09 19:38:12 +00:00
|
|
|
uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v);
|
2008-04-21 14:33:33 +00:00
|
|
|
if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) return;
|
2007-06-01 11:41:02 +00:00
|
|
|
|
|
|
|
/* Attempt to use pre-allocated vehicles until they run out. This can happen
|
|
|
|
* if the callback returns different values depending on the cargo type. */
|
2007-08-30 13:03:56 +00:00
|
|
|
u->SetNext(vl[i]);
|
|
|
|
if (u->Next() == NULL) return;
|
2007-06-01 11:41:02 +00:00
|
|
|
|
2007-09-01 20:09:26 +00:00
|
|
|
Vehicle *previous = u;
|
2007-08-30 13:03:56 +00:00
|
|
|
u = u->Next();
|
2007-06-01 11:41:02 +00:00
|
|
|
|
2007-06-11 14:00:16 +00:00
|
|
|
EngineID engine_type = GetFirstEngineOfType(type) + GB(callback, 0, 7);
|
2007-11-19 21:02:30 +00:00
|
|
|
bool flip_image = HasBit(callback, 7);
|
2007-06-01 11:41:02 +00:00
|
|
|
|
|
|
|
/* get common values from first engine */
|
|
|
|
u->direction = v->direction;
|
|
|
|
u->owner = v->owner;
|
|
|
|
u->tile = v->tile;
|
|
|
|
u->x_pos = v->x_pos;
|
|
|
|
u->y_pos = v->y_pos;
|
|
|
|
u->z_pos = v->z_pos;
|
|
|
|
u->build_year = v->build_year;
|
|
|
|
u->vehstatus = v->vehstatus & ~VS_STOPPED;
|
|
|
|
|
|
|
|
u->cargo_subtype = 0;
|
|
|
|
u->max_speed = 0;
|
|
|
|
u->max_age = 0;
|
|
|
|
u->engine_type = engine_type;
|
|
|
|
u->value = 0;
|
|
|
|
u->subtype = 0;
|
|
|
|
u->cur_image = 0xAC2;
|
|
|
|
u->random_bits = VehicleRandomBits();
|
|
|
|
|
2007-06-11 14:00:16 +00:00
|
|
|
switch (type) {
|
|
|
|
default: NOT_REACHED();
|
|
|
|
|
|
|
|
case VEH_TRAIN: {
|
|
|
|
const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
|
|
|
|
|
|
|
|
u = new (u) Train();
|
2007-09-05 17:53:14 +00:00
|
|
|
previous->SetNext(u);
|
2007-06-11 14:00:16 +00:00
|
|
|
u->u.rail.track = v->u.rail.track;
|
|
|
|
u->u.rail.railtype = v->u.rail.railtype;
|
|
|
|
u->u.rail.first_engine = v->engine_type;
|
|
|
|
|
|
|
|
u->spritenum = rvi_artic->image_index;
|
|
|
|
u->cargo_type = rvi_artic->cargo_type;
|
|
|
|
u->cargo_cap = rvi_artic->capacity;
|
|
|
|
|
|
|
|
SetArticulatedPart(u);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case VEH_ROAD: {
|
|
|
|
const RoadVehicleInfo *rvi_artic = RoadVehInfo(engine_type);
|
|
|
|
|
|
|
|
u = new (u) RoadVehicle();
|
2007-09-05 17:53:14 +00:00
|
|
|
previous->SetNext(u);
|
2007-06-11 14:00:16 +00:00
|
|
|
u->u.road.first_engine = v->engine_type;
|
|
|
|
u->u.road.cached_veh_length = GetRoadVehLength(u);
|
|
|
|
u->u.road.state = RVSB_IN_DEPOT;
|
|
|
|
|
|
|
|
u->u.road.roadtype = v->u.road.roadtype;
|
|
|
|
u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes;
|
|
|
|
|
|
|
|
u->spritenum = rvi_artic->image_index;
|
|
|
|
u->cargo_type = rvi_artic->cargo_type;
|
|
|
|
u->cargo_cap = rvi_artic->capacity;
|
|
|
|
|
|
|
|
SetRoadVehArticPart(u);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flip_image) u->spritenum++;
|
|
|
|
|
2007-06-01 11:41:02 +00:00
|
|
|
VehiclePositionChanged(u);
|
|
|
|
}
|
|
|
|
}
|