1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* $Id$ */
/** @file articulated_vehicles.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "functions.h"
#include "command.h"
#include "vehicle.h"
#include "articulated_vehicles.h"
#include "engine.h"
#include "train.h"
#include "roadveh.h"
#include "newgrf_callbacks.h"
#include "newgrf_engine.h"
uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
{
if (!HASBIT(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return 0;
Vehicle *v = NULL;;
if (!purchase_window) {
v = new InvalidVehicle();
v->engine_type = engine_type;
}
uint i;
for (i = 1; i < MAX_UVALUE(EngineID); i++) {
uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, v);
if (callback == CALLBACK_FAILED || callback == 0xFF) break;
}
delete v;
return i - 1;
}
void AddArticulatedParts(Vehicle **vl, VehicleType type)
{
const Vehicle *v = vl[0];
Vehicle *u = vl[0];
if (!HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) return;
for (uint i = 1; i < MAX_UVALUE(EngineID); i++) {
uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, v->engine_type, v);
if (callback == CALLBACK_FAILED || callback == 0xFF) return;
/* Attempt to use pre-allocated vehicles until they run out. This can happen
* if the callback returns different values depending on the cargo type. */
u->SetNext(vl[i]);
if (u->Next() == NULL) return;
Vehicle *previous = u;
u = u->Next();
EngineID engine_type = GetFirstEngineOfType(type) + GB(callback, 0, 7);
bool flip_image = HASBIT(callback, 7);
/* 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();
switch (type) {
default: NOT_REACHED();
case VEH_TRAIN: {
const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
u = new (u) Train();
previous->SetNext(u);
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();
previous->SetNext(u);
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++;
VehiclePositionChanged(u);
}
}
|