author | truelight |
Wed, 15 Dec 2004 22:06:47 +0000 | |
changeset 678 | f62cae2abc0c |
parent 593 | 4240f624bca0 |
child 679 | 04ca2cd69420 |
permissions | -rw-r--r-- |
0 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
507
04b5403aaf6b
(svn r815) Include strings.h only in the files which need it.
tron
parents:
495
diff
changeset
|
3 |
#include "table/strings.h" |
0 | 4 |
#include "vehicle.h" |
5 |
#include "command.h" |
|
6 |
#include "pathfind.h" |
|
7 |
#include "station.h" |
|
8 |
#include "table/train_cmd.h" |
|
9 |
#include "gfx.h" |
|
10 |
#include "news.h" |
|
11 |
#include "engine.h" |
|
12 |
#include "player.h" |
|
337
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
13 |
#include "sound.h" |
0 | 14 |
|
15 |
#define is_firsthead_sprite(spritenum) \ |
|
16 |
(is_custom_sprite(spritenum) \ |
|
17 |
? is_custom_firsthead_sprite(spritenum) \ |
|
18 |
: _engine_sprite_add[spritenum] == 0) |
|
19 |
||
20 |
||
21 |
static const byte _vehicle_initial_x_fract[4] = {10,8,4,8}; |
|
22 |
static const byte _vehicle_initial_y_fract[4] = {8,4,8,10}; |
|
23 |
static const byte _state_dir_table[4] = { 0x20, 8, 0x10, 4 }; |
|
24 |
||
25 |
static const byte _signal_onedir[14] = { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
26 |
0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0, |
0 | 27 |
0x40, 0x40, 0x40, 0x10, 0x80, 0x20 |
28 |
}; |
|
29 |
||
30 |
static const byte _signal_otherdir[14] = { |
|
31 |
0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0, |
|
32 |
0x80, 0x80, 0x80, 0x20, 0x40, 0x10 |
|
33 |
}; |
|
34 |
||
35 |
void UpdateTrainAcceleration(Vehicle *v) |
|
36 |
{ |
|
37 |
uint acc, power=0, max_speed=5000, weight=0; |
|
38 |
Vehicle *u = v; |
|
39 |
||
40 |
assert(v->subtype == 0); |
|
41 |
||
42 |
// compute stuff like max speed, power, and weight. |
|
43 |
do { |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
44 |
const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
45 |
|
0 | 46 |
// power is sum of the power for all engines |
47 |
power += rvi->power; |
|
48 |
||
49 |
// limit the max speed to the speed of the slowest vehicle. |
|
50 |
if (rvi->max_speed && rvi->max_speed <= max_speed) max_speed = rvi->max_speed; |
|
51 |
||
52 |
// weight is the sum of the weight of the wagon and the weight of the cargo. |
|
53 |
weight += rvi->weight; |
|
54 |
weight += (_cargoc.weights[u->cargo_type] * u->cargo_count) >> 4; |
|
55 |
||
56 |
} while ( (u=u->next) != NULL); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
57 |
|
0 | 58 |
// these are shown in the UI |
59 |
v->u.rail.cached_weight = weight; |
|
60 |
v->u.rail.cached_power = power; |
|
61 |
v->max_speed = max_speed; |
|
62 |
||
63 |
assert(weight != 0); |
|
64 |
||
65 |
// compute acceleration |
|
66 |
acc = power / weight * 4; |
|
67 |
||
68 |
if (acc >= 255) acc=255; |
|
69 |
if (acc == 0) acc++; |
|
70 |
||
71 |
v->acceleration = (byte)acc; |
|
72 |
} |
|
73 |
||
74 |
#define F_GRAV 9.82f |
|
75 |
#define F_THETA 0.05f |
|
76 |
||
77 |
#define F_HP_KW 0.74569f |
|
78 |
#define F_KPH_MS 0.27778f |
|
79 |
#define F_MU 0.3f |
|
80 |
||
81 |
#define F_COEF_FRIC 0.04f |
|
82 |
#define F_COEF_ROLL 0.18f |
|
83 |
||
84 |
#define F_CURVE_FACTOR (1/96.f) |
|
85 |
||
410 | 86 |
static bool IsTunnelTile(TileIndex tile); |
0 | 87 |
|
88 |
static int GetRealisticAcceleration(Vehicle *v) |
|
89 |
{ |
|
90 |
uint emass = 0; |
|
91 |
Vehicle *u = v; |
|
92 |
float f = 0.0f, spd; |
|
93 |
int curves = 0; |
|
94 |
||
95 |
assert(v->subtype == 0); |
|
96 |
||
97 |
// compute inclination force and number of curves. |
|
98 |
do { |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
99 |
const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); |
0 | 100 |
uint mass = rvi->weight + ((_cargoc.weights[u->cargo_type] * u->cargo_count) >> 4); |
101 |
if (rvi->power) emass += mass; |
|
102 |
||
103 |
if (u->u.rail.flags & VRF_GOINGUP) { |
|
104 |
f += (float)mass * ( -F_GRAV * F_THETA); |
|
105 |
} else if (u->u.rail.flags & VRF_GOINGDOWN) { |
|
106 |
f += (float)mass * ( F_GRAV * F_THETA); |
|
107 |
} |
|
108 |
||
109 |
// compute curve penalty.. |
|
110 |
if (u->next != NULL) { |
|
111 |
uint diff = (u->direction - u->next->direction) & 7; |
|
112 |
if (diff) { |
|
113 |
curves += (diff == 1 || diff == 7) ? 1 : 3; |
|
114 |
} |
|
115 |
} |
|
116 |
} while ((u = u->next) != NULL); |
|
117 |
||
118 |
spd = (float)(v->cur_speed ? v->cur_speed : 1); |
|
119 |
||
120 |
// compute tractive effort |
|
121 |
{ |
|
122 |
float te = (float)v->u.rail.cached_power * (F_HP_KW/F_KPH_MS) / spd; |
|
123 |
float te2 = (float)emass * (F_MU * F_GRAV); |
|
124 |
if (te > te2) te = te2; |
|
125 |
f += te; |
|
126 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
127 |
|
0 | 128 |
// add air resistance |
129 |
{ |
|
130 |
float cx = 1.0f; // NOT DONE |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
131 |
|
0 | 132 |
// air resistance is doubled in tunnels. |
133 |
if (v->vehstatus == 0x40) cx *= 2; |
|
134 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
135 |
f -= cx * spd * spd * (F_KPH_MS * F_KPH_MS * 0.001f); |
0 | 136 |
} |
137 |
||
138 |
// after this f contains the acceleration. |
|
139 |
f /= (float)v->u.rail.cached_weight; |
|
140 |
||
141 |
// add friction to sum of forces (avoid mul by weight). (0.001 because we want kN) |
|
142 |
f -= (F_COEF_FRIC * F_GRAV * 0.001f + (F_COEF_ROLL * F_KPH_MS * F_GRAV * 0.001f) * spd); |
|
143 |
||
144 |
// penalty for curves? |
|
145 |
if (curves) |
|
146 |
f -= (float)min(curves, 8) * F_CURVE_FACTOR; |
|
147 |
||
148 |
return (int)(f * (1.0/(F_KPH_MS * 0.015f)) + 0.5f); |
|
149 |
} |
|
150 |
||
151 |
||
152 |
int GetTrainImage(Vehicle *v, byte direction) |
|
153 |
{ |
|
154 |
int img = v->spritenum; |
|
155 |
int base; |
|
156 |
||
157 |
if (is_custom_sprite(img)) { |
|
158 |
base = GetCustomVehicleSprite(v, direction + 4 * is_custom_secondhead_sprite(img)); |
|
159 |
if (base) return base; |
|
160 |
img = _engine_original_sprites[v->engine_type]; |
|
161 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
162 |
|
0 | 163 |
base = _engine_sprite_base[img] + ((direction + _engine_sprite_add[img]) & _engine_sprite_and[img]); |
164 |
||
165 |
if (v->cargo_count >= (v->cargo_cap >> 1)) |
|
166 |
base += _wagon_full_adder[img]; |
|
167 |
return base; |
|
168 |
} |
|
169 |
||
170 |
void DrawTrainEngine(int x, int y, int engine, uint32 image_ormod) |
|
171 |
{ |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
172 |
const RailVehicleInfo *rvi = RailVehInfo(engine); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
173 |
|
0 | 174 |
int img = rvi->image_index; |
175 |
uint32 image = 0; |
|
176 |
||
177 |
if (is_custom_sprite(img)) { |
|
358
da81e0ef68cf
(svn r546) -newgrf: Use GetCustomVehicleIcon() for fetching sprites for vehicle selection dialogs. (Idea by octo, done by pasky).
darkvater
parents:
337
diff
changeset
|
178 |
image = GetCustomVehicleIcon(engine, 6); |
0 | 179 |
if (!image) img = _engine_original_sprites[engine]; |
180 |
} |
|
181 |
if (!image) { |
|
182 |
image = (6 & _engine_sprite_and[img]) + _engine_sprite_base[img]; |
|
183 |
} |
|
184 |
||
185 |
if (rvi->flags & RVI_MULTIHEAD) { |
|
186 |
DrawSprite(image | image_ormod, x-14, y); |
|
187 |
x += 15; |
|
188 |
image = 0; |
|
189 |
if (is_custom_sprite(img)) { |
|
358
da81e0ef68cf
(svn r546) -newgrf: Use GetCustomVehicleIcon() for fetching sprites for vehicle selection dialogs. (Idea by octo, done by pasky).
darkvater
parents:
337
diff
changeset
|
190 |
image = GetCustomVehicleIcon(engine, 2); |
0 | 191 |
if (!image) img = _engine_original_sprites[engine]; |
192 |
} |
|
193 |
if (!image) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
194 |
image = ((6 + _engine_sprite_add[img+1]) & _engine_sprite_and[img+1]) + _engine_sprite_base[img+1]; |
0 | 195 |
} |
196 |
} |
|
197 |
DrawSprite(image | image_ormod, x, y); |
|
198 |
} |
|
199 |
||
200 |
void DrawTrainEngineInfo(int engine, int x, int y, int maxw) |
|
201 |
{ |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
202 |
const RailVehicleInfo *rvi = RailVehInfo(engine); |
0 | 203 |
int cap; |
204 |
uint multihead = ((rvi->flags & RVI_MULTIHEAD) ? 1 : 0); |
|
205 |
||
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
206 |
SetDParam(0, ((_price.build_railvehicle >> 3) * rvi->base_cost) >> 5); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
207 |
SetDParam(2, rvi->max_speed * 10 >> 4); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
208 |
SetDParam(3, rvi->power << multihead); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
209 |
SetDParam(1, rvi->weight << multihead); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
210 |
|
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
211 |
SetDParam(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
212 |
|
0 | 213 |
cap = rvi->capacity; |
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
214 |
SetDParam(5, STR_8838_N_A); |
0 | 215 |
if (cap != 0) { |
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
216 |
SetDParam(6, cap << multihead); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
217 |
SetDParam(5, _cargoc.names_long_p[rvi->cargo_type]); |
0 | 218 |
} |
219 |
DrawStringMultiCenter(x, y, STR_885B_COST_WEIGHT_T_SPEED_POWER, maxw); |
|
220 |
} |
|
221 |
||
222 |
||
410 | 223 |
static int32 CmdBuildRailWagon(uint engine, uint tile, uint32 flags) |
0 | 224 |
{ |
225 |
int32 value; |
|
226 |
Vehicle *v; |
|
227 |
const RailVehicleInfo *rvi; |
|
228 |
int dir; |
|
229 |
const Engine *e; |
|
230 |
int x,y; |
|
231 |
||
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
232 |
rvi = RailVehInfo(engine); |
0 | 233 |
value = (rvi->base_cost * _price.build_railwagon) >> 8; |
234 |
||
235 |
if (!(flags & DC_QUERY_COST)) { |
|
236 |
_error_message = STR_00E1_TOO_MANY_VEHICLES_IN_GAME; |
|
237 |
||
238 |
v = AllocateVehicle(); |
|
239 |
if (v == NULL) |
|
240 |
return CMD_ERROR; |
|
241 |
||
242 |
if (flags & DC_EXEC) { |
|
243 |
byte img = rvi->image_index; |
|
244 |
Vehicle *u; |
|
245 |
||
246 |
v->spritenum = img; |
|
247 |
||
248 |
u = _vehicles; |
|
249 |
for(;;) { |
|
250 |
if (u->type == VEH_Train && u->tile == (TileIndex)tile && |
|
251 |
u->subtype == 4 && u->engine_type == engine) { |
|
252 |
u = GetLastVehicleInChain(u); |
|
253 |
break; |
|
254 |
} |
|
255 |
||
256 |
if (++u == endof(_vehicles)) { |
|
257 |
u = NULL; |
|
258 |
break; |
|
259 |
} |
|
260 |
} |
|
261 |
||
262 |
v->engine_type = engine; |
|
263 |
||
264 |
dir = _map5[tile] & 3; |
|
265 |
||
266 |
v->direction = (byte)(dir*2+1); |
|
267 |
v->tile = (TileIndex)tile; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
268 |
|
0 | 269 |
x = GET_TILE_X(tile)*16 | _vehicle_initial_x_fract[dir]; |
270 |
y = GET_TILE_Y(tile)*16 | _vehicle_initial_y_fract[dir]; |
|
271 |
||
272 |
v->x_pos = x; |
|
273 |
v->y_pos = y; |
|
274 |
v->z_pos = GetSlopeZ(x,y); |
|
275 |
v->owner = _current_player; |
|
276 |
v->z_height = 6; |
|
277 |
v->u.rail.track = 0x80; |
|
278 |
v->vehstatus = VS_HIDDEN | VS_DEFPAL; |
|
279 |
||
280 |
v->subtype = 4; |
|
281 |
if (u != NULL) { |
|
282 |
u->next = v; |
|
283 |
v->subtype = 2; |
|
284 |
v->u.rail.first_engine = u->u.rail.first_engine; |
|
285 |
if (v->u.rail.first_engine == 0xffff && u->subtype == 0) |
|
286 |
v->u.rail.first_engine = u->engine_type; |
|
287 |
} else { |
|
288 |
v->u.rail.first_engine = 0xffff; |
|
289 |
} |
|
290 |
||
291 |
v->cargo_type = rvi->cargo_type; |
|
292 |
v->cargo_cap = rvi->capacity; |
|
293 |
v->value = value; |
|
294 |
// v->day_counter = 0; |
|
295 |
||
296 |
e = &_engines[engine]; |
|
297 |
v->u.rail.railtype = e->railtype; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
298 |
|
0 | 299 |
v->build_year = _cur_year; |
300 |
v->type = VEH_Train; |
|
301 |
v->cur_image = 0xAC2; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
302 |
|
0 | 303 |
_new_wagon_id = v->index; |
304 |
||
305 |
VehiclePositionChanged(v); |
|
306 |
||
307 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
308 |
} |
|
309 |
} |
|
310 |
||
311 |
return value; |
|
312 |
} |
|
313 |
||
314 |
// Move all free vehicles in the depot to the train |
|
315 |
static void NormalizeTrainVehInDepot(Vehicle *u) |
|
316 |
{ |
|
317 |
Vehicle *v; |
|
318 |
FOR_ALL_VEHICLES(v) { |
|
319 |
if (v->type == VEH_Train && v->subtype==4 && |
|
320 |
v->tile == u->tile && |
|
321 |
v->u.rail.track == 0x80) { |
|
322 |
if (DoCommandByTile(0,v->index | (u->index<<16), 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE) == CMD_ERROR) |
|
323 |
break; |
|
324 |
} |
|
325 |
} |
|
326 |
} |
|
327 |
||
328 |
static const byte _railveh_unk1[] = { |
|
329 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
330 |
0, 0, 0, 1, 1, 0, 0, 0, |
|
331 |
0, 0, 0, 0, 1, 0, 1, 0, |
|
332 |
0, 1, 1, 0, 0, 0, 0, 0, |
|
333 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
334 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
335 |
0, 0, 0, 0, 0, 0, 0, 1, |
|
336 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
337 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
338 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
339 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
340 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
341 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
342 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
343 |
0, 0, 0, 0, |
|
344 |
}; |
|
345 |
||
346 |
static const byte _railveh_score[] = { |
|
347 |
1, 4, 7, 19, 20, 30, 31, 19, |
|
348 |
20, 21, 22, 10, 11, 30, 31, 32, |
|
349 |
33, 34, 35, 29, 45, 32, 50, 40, |
|
350 |
41, 51, 52, 0, 0, 0, 0, 0, |
|
351 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
352 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
353 |
0, 0, 0, 0, 0, 0, 60, 62, |
|
354 |
63, 0, 0, 0, 0, 0, 0, 0, |
|
355 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
356 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
357 |
0, 0, 0, 0, 70, 71, 72, 73, |
|
358 |
74, 0, 0, 0, 0, 0, 0, 0, |
|
359 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
360 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
361 |
0, 0, 0, 0, |
|
362 |
}; |
|
363 |
||
364 |
||
365 |
static int32 EstimateTrainCost(const RailVehicleInfo *rvi) |
|
366 |
{ |
|
367 |
return (rvi->base_cost * (_price.build_railvehicle >> 3)) >> 5; |
|
368 |
} |
|
369 |
||
370 |
/* Build a railroad vehicle |
|
371 |
* p1 = vehicle type id |
|
372 |
*/ |
|
373 |
||
374 |
int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
375 |
{ |
|
376 |
const RailVehicleInfo *rvi; |
|
377 |
int value,dir; |
|
378 |
Vehicle *v, *u; |
|
379 |
byte unit_num; |
|
380 |
Engine *e; |
|
381 |
uint tile; |
|
382 |
||
383 |
_cmd_build_rail_veh_var1 = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
384 |
|
0 | 385 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
386 |
||
387 |
tile = TILE_FROM_XY(x,y); |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
388 |
rvi = RailVehInfo(p1); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
389 |
|
0 | 390 |
if (rvi->flags & RVI_WAGON) { |
391 |
return CmdBuildRailWagon(p1, tile, flags); |
|
392 |
} |
|
393 |
||
394 |
value = EstimateTrainCost(rvi); |
|
395 |
||
396 |
if (!(flags & DC_QUERY_COST)) { |
|
397 |
v = AllocateVehicle(); |
|
398 |
if (v == NULL || _ptr_to_next_order >= endof(_order_array)) |
|
399 |
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
400 |
||
401 |
unit_num = GetFreeUnitNumber(VEH_Train); |
|
402 |
if (unit_num > _patches.max_trains) |
|
403 |
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
404 |
||
405 |
if (flags & DC_EXEC) { |
|
406 |
v->unitnumber = unit_num; |
|
407 |
||
408 |
dir = _map5[tile] & 3; |
|
409 |
||
410 |
v->direction = (byte)(dir*2+1); |
|
411 |
v->tile = (TileIndex)tile; |
|
412 |
v->owner = _current_player; |
|
413 |
v->x_pos = (x |= _vehicle_initial_x_fract[dir]); |
|
414 |
v->y_pos = (y |= _vehicle_initial_y_fract[dir]); |
|
415 |
v->z_pos = GetSlopeZ(x,y); |
|
416 |
v->z_height = 6; |
|
417 |
v->u.rail.track = 0x80; |
|
418 |
v->u.rail.first_engine = 0xffff; |
|
419 |
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
|
420 |
// v->subtype = 0; |
|
421 |
v->spritenum = rvi->image_index; |
|
422 |
v->cargo_type = rvi->cargo_type; |
|
423 |
v->cargo_cap = rvi->capacity; |
|
424 |
v->max_speed = rvi->max_speed; |
|
425 |
// v->cargo_count = 0; |
|
426 |
v->value = value; |
|
427 |
// v->day_counter = 0; |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
428 |
// v->current_order = 0; |
0 | 429 |
// v->next_station = 0; |
430 |
// v->load_unload_time_rem = 0; |
|
431 |
// v->progress = 0; |
|
432 |
// v->targetairport = 0; |
|
433 |
// v->crash_anim_pos = 0; |
|
434 |
v->last_station_visited = 0xff; |
|
435 |
v->dest_tile = 0; |
|
436 |
// v->profit_last_year = 0; |
|
437 |
// v->profit_this_year = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
438 |
|
0 | 439 |
v->engine_type = (byte)p1; |
440 |
e = &_engines[p1]; |
|
441 |
||
442 |
v->reliability = e->reliability; |
|
443 |
v->reliability_spd_dec = e->reliability_spd_dec; |
|
444 |
v->max_age = e->lifelength * 366; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
445 |
|
0 | 446 |
v->string_id = STR_SV_TRAIN_NAME; |
447 |
// v->cur_speed = 0; |
|
448 |
// v->subspeed = 0; |
|
449 |
v->u.rail.railtype = e->railtype; |
|
450 |
_new_train_id = v->index; |
|
451 |
// v->cur_order_index = 0; |
|
452 |
// v->num_orders = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
453 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
454 |
_ptr_to_next_order->type = OT_NOTHING; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
455 |
_ptr_to_next_order->flags = 0; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
456 |
v->schedule_ptr = _ptr_to_next_order++; |
0 | 457 |
// v->next_in_chain = 0xffff; |
458 |
// v->next = NULL; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
459 |
|
0 | 460 |
v->service_interval = _patches.servint_trains; |
461 |
// v->breakdown_ctr = 0; |
|
462 |
// v->breakdowns_since_last_service = 0; |
|
463 |
// v->unk4D = 0; |
|
464 |
v->date_of_last_service = _date; |
|
465 |
v->build_year = _cur_year; |
|
466 |
v->type = VEH_Train; |
|
467 |
v->cur_image = 0xAC2; |
|
468 |
||
469 |
VehiclePositionChanged(v); |
|
470 |
||
471 |
if (rvi->flags&RVI_MULTIHEAD && (u=AllocateVehicle()) != NULL) { |
|
472 |
u->direction = v->direction; |
|
473 |
u->owner = v->owner; |
|
474 |
u->tile = v->tile; |
|
475 |
u->x_pos = v->x_pos; |
|
476 |
u->y_pos = v->y_pos; |
|
477 |
u->z_pos = v->z_pos; |
|
478 |
u->z_height = 6; |
|
479 |
u->u.rail.track = 0x80; |
|
480 |
v->u.rail.first_engine = 0xffff; |
|
481 |
u->vehstatus = VS_HIDDEN | VS_DEFPAL; |
|
482 |
u->subtype = 2; |
|
483 |
u->spritenum = v->spritenum + 1; |
|
484 |
u->cargo_type = v->cargo_type; |
|
485 |
u->cargo_cap = v->cargo_cap; |
|
486 |
u->u.rail.railtype = v->u.rail.railtype; |
|
487 |
// u->next_in_chain = 0xffff; |
|
488 |
v->next = u; |
|
489 |
u->engine_type = v->engine_type; |
|
490 |
u->build_year = v->build_year; |
|
491 |
v->value = u->value = v->value >> 1; |
|
492 |
// u->day_counter = 0; |
|
493 |
u->type = VEH_Train; |
|
494 |
u->cur_image = 0xAC2; |
|
495 |
VehiclePositionChanged(u); |
|
496 |
} |
|
497 |
||
498 |
UpdateTrainAcceleration(v); |
|
499 |
NormalizeTrainVehInDepot(v); |
|
500 |
||
501 |
InvalidateWindow(WC_VEHICLE_DEPOT, tile); |
|
588 | 502 |
RebuildVehicleLists(); |
0 | 503 |
InvalidateWindow(WC_COMPANY, v->owner); |
504 |
} |
|
505 |
} |
|
506 |
_cmd_build_rail_veh_var1 = _railveh_unk1[p1]; |
|
507 |
_cmd_build_rail_veh_score = _railveh_score[p1]; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
508 |
return value; |
0 | 509 |
} |
510 |
||
511 |
||
512 |
bool IsTrainDepotTile(TileIndex tile) |
|
513 |
{ |
|
514 |
return IS_TILETYPE(tile, MP_RAILWAY) && |
|
515 |
(_map5[tile] & 0xFC) == 0xC0; |
|
516 |
} |
|
517 |
||
410 | 518 |
static bool IsTunnelTile(TileIndex tile) |
0 | 519 |
{ |
520 |
return IS_TILETYPE(tile, MP_TUNNELBRIDGE) && |
|
521 |
(_map5[tile]&0x80) == 0; |
|
522 |
} |
|
523 |
||
524 |
||
525 |
int CheckStoppedInDepot(Vehicle *v) |
|
526 |
{ |
|
527 |
int count; |
|
528 |
TileIndex tile = v->tile; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
529 |
|
0 | 530 |
/* check if stopped in a depot */ |
531 |
if (!IsTrainDepotTile(tile) || v->cur_speed != 0) { |
|
532 |
errmsg: |
|
533 |
_error_message = STR_881A_TRAINS_CAN_ONLY_BE_ALTERED; |
|
534 |
return -1; |
|
535 |
} |
|
536 |
||
537 |
count = 0; |
|
538 |
do { |
|
539 |
count++; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
540 |
if (v->u.rail.track != 0x80 || v->tile != (TileIndex)tile || |
0 | 541 |
(v->subtype==0 && !(v->vehstatus&VS_STOPPED))) |
542 |
goto errmsg; |
|
543 |
} while ( (v=v->next) != NULL); |
|
544 |
||
545 |
return count; |
|
546 |
} |
|
547 |
||
548 |
// unlink a rail wagon from the linked list. |
|
549 |
// returns the new value of first |
|
550 |
static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first) |
|
551 |
{ |
|
552 |
// unlinking the first vehicle of the chain? |
|
553 |
v->u.rail.first_engine = 0xffff; |
|
554 |
if (v == first) { |
|
555 |
Vehicle *u; |
|
556 |
if ((v=v->next) == NULL) return NULL; |
|
557 |
for (u=v; u; u=u->next) u->u.rail.first_engine = v->engine_type; |
|
558 |
v->subtype = 4; |
|
559 |
return v; |
|
560 |
} else { |
|
561 |
Vehicle *u; |
|
562 |
for(u=first; u->next!=v; u=u->next) {} |
|
563 |
u->next = v->next; |
|
564 |
return first; |
|
565 |
} |
|
566 |
} |
|
567 |
||
568 |
static Vehicle *FindGoodVehiclePos(Vehicle *src) |
|
569 |
{ |
|
570 |
Vehicle *dst; |
|
571 |
uint16 eng = src->engine_type; |
|
572 |
TileIndex tile = src->tile; |
|
573 |
||
574 |
FOR_ALL_VEHICLES(dst) { |
|
575 |
if (dst->type==VEH_Train && dst->subtype==4 && dst->tile==tile) { |
|
576 |
// check so all vehicles in the line have the same engine. |
|
577 |
Vehicle *v = dst; |
|
578 |
while (v->engine_type == eng) { |
|
579 |
if ((v = v->next) == NULL) return dst; |
|
580 |
} |
|
581 |
} |
|
582 |
} |
|
583 |
||
584 |
return NULL; |
|
585 |
} |
|
586 |
||
587 |
/* p1 & 0xffff= source vehicle index |
|
588 |
p1 & 0xffff0000 = what wagon to put the wagon AFTER, 0xffff0000 to make a new line |
|
589 |
p2 & 1 = move all vehicles following the vehicle.. |
|
590 |
*/ |
|
591 |
||
592 |
int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
593 |
{ |
|
594 |
Vehicle *src, *dst, *src_head, *dst_head; |
|
595 |
bool is_loco; |
|
596 |
||
597 |
src = &_vehicles[p1 & 0xffff]; |
|
598 |
if (src->type != VEH_Train) return CMD_ERROR; |
|
599 |
||
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
600 |
is_loco = !(RailVehInfo(src->engine_type)->flags & RVI_WAGON) |
0 | 601 |
&& is_firsthead_sprite(src->spritenum); |
602 |
||
603 |
// if nothing is selected as destination, try and find a matching vehicle to drag to. |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
604 |
if (((int32)p1 >> 16) == -1) { |
0 | 605 |
dst = NULL; |
606 |
if (!is_loco) dst = FindGoodVehiclePos(src); |
|
607 |
} else { |
|
608 |
dst = &_vehicles[((int32)p1 >> 16)]; |
|
609 |
} |
|
610 |
||
611 |
// don't move the same vehicle.. |
|
612 |
if (src == dst) |
|
613 |
return 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
614 |
|
0 | 615 |
/* the player must be the owner */ |
616 |
if (!CheckOwnership(src->owner) || (dst!=NULL && !CheckOwnership(dst->owner))) |
|
617 |
return CMD_ERROR; |
|
618 |
||
619 |
/* locate the head of the two chains */ |
|
620 |
src_head = GetFirstVehicleInChain(src); |
|
621 |
dst_head = NULL; |
|
622 |
if (dst != NULL) dst_head = GetFirstVehicleInChain(dst); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
623 |
|
0 | 624 |
/* check if all vehicles in the source train are stopped */ |
625 |
if (CheckStoppedInDepot(src_head) < 0) |
|
626 |
return CMD_ERROR; |
|
627 |
||
628 |
/* check if all the vehicles in the dest train are stopped, |
|
629 |
* and that the length of the dest train is no longer than XXX vehicles */ |
|
630 |
if (dst_head != NULL) { |
|
631 |
int num = CheckStoppedInDepot(dst_head); |
|
632 |
if (num < 0) |
|
633 |
return CMD_ERROR; |
|
634 |
||
635 |
if (num > (_patches.mammoth_trains ? 100 : 9) && dst_head->subtype==0) |
|
636 |
return_cmd_error(STR_8819_TRAIN_TOO_LONG); |
|
637 |
||
638 |
// if it's a multiheaded vehicle we're dragging to, drag to the vehicle before.. |
|
639 |
while (is_custom_secondhead_sprite(dst->spritenum) |
|
640 |
|| (!is_custom_sprite(dst->spritenum) && _engine_sprite_add[dst->spritenum] != 0)) { |
|
641 |
Vehicle *v = GetPrevVehicleInChain(dst); |
|
642 |
if (!v || src == v) break; |
|
643 |
dst = v; |
|
644 |
} |
|
645 |
||
646 |
assert(dst_head->tile == src_head->tile); |
|
647 |
} |
|
648 |
||
649 |
// when moving all wagons, we can't have the same src_head and dst_head |
|
650 |
if (p2 & 1 && src_head == dst_head) |
|
651 |
return 0; |
|
652 |
||
653 |
// moving a loco to a new line?, then we need to assign a unitnumber. |
|
654 |
if (dst == NULL && src->subtype != 0 && is_loco) { |
|
655 |
uint unit_num = GetFreeUnitNumber(VEH_Train); |
|
656 |
if (unit_num > _patches.max_trains) |
|
657 |
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
658 |
||
659 |
if (flags & DC_EXEC) |
|
660 |
src->unitnumber = unit_num; |
|
661 |
} |
|
662 |
||
663 |
||
664 |
/* do it? */ |
|
665 |
if (flags & DC_EXEC) { |
|
666 |
if (p2 & 1) { |
|
667 |
// unlink ALL wagons |
|
668 |
if (src != src_head) { |
|
669 |
Vehicle *v = src_head; |
|
670 |
while (v->next != src) v=v->next; |
|
671 |
v->next = NULL; |
|
672 |
} |
|
673 |
} else { |
|
674 |
// unlink single wagon from linked list |
|
675 |
UnlinkWagon(src, src_head); |
|
676 |
src->next = NULL; |
|
677 |
} |
|
678 |
||
679 |
if (dst == NULL) { |
|
680 |
// move the train to an empty line. for locomotives, we set the type to 0. for wagons, 4. |
|
681 |
if (is_loco) { |
|
682 |
if (src->subtype != 0) { |
|
683 |
// setting the type to 0 also involves setting up the schedule_ptr field. |
|
684 |
src->subtype = 0; |
|
685 |
assert(src->schedule_ptr == NULL); |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
686 |
_ptr_to_next_order->type = OT_NOTHING; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
687 |
_ptr_to_next_order->flags = 0; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
688 |
src->schedule_ptr = _ptr_to_next_order++; |
0 | 689 |
src->num_orders = 0; |
690 |
} |
|
691 |
dst_head = src; |
|
692 |
} else { |
|
693 |
src->subtype = 4; |
|
694 |
} |
|
695 |
src->u.rail.first_engine = 0xffff; |
|
696 |
} else { |
|
697 |
if (src->subtype == 0) { |
|
698 |
// the vehicle was previously a loco. need to free the schedule list and delete vehicle windows etc. |
|
699 |
DeleteWindowById(WC_VEHICLE_VIEW, src->index); |
|
700 |
DeleteVehicleSchedule(src); |
|
701 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
702 |
|
0 | 703 |
src->subtype = 2; |
704 |
src->unitnumber = 0; // doesn't occupy a unitnumber anymore. |
|
705 |
||
706 |
// setup first_engine |
|
707 |
src->u.rail.first_engine = dst->u.rail.first_engine; |
|
708 |
if (src->u.rail.first_engine == 0xffff && dst->subtype == 0) |
|
709 |
src->u.rail.first_engine = dst->engine_type; |
|
710 |
||
711 |
// link in the wagon(s) in the chain. |
|
712 |
{ |
|
713 |
Vehicle *v = src; |
|
714 |
while (v->next != NULL) { |
|
715 |
v->next->u.rail.first_engine = v->u.rail.first_engine; |
|
716 |
v = v->next; |
|
717 |
} |
|
718 |
v->next = dst->next; |
|
719 |
} |
|
720 |
dst->next = src; |
|
721 |
} |
|
722 |
||
723 |
if (src_head->subtype == 0) |
|
724 |
UpdateTrainAcceleration(src_head); |
|
725 |
InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index); |
|
726 |
||
727 |
if (dst_head) { |
|
728 |
if (dst_head->subtype == 0) |
|
729 |
UpdateTrainAcceleration(dst_head); |
|
730 |
InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index); |
|
731 |
} |
|
732 |
||
733 |
InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile); |
|
734 |
InvalidateWindow(WC_TRAINS_LIST, _current_player); |
|
735 |
} |
|
736 |
||
737 |
return 0; |
|
738 |
} |
|
739 |
||
740 |
/* p1 = train to start / stop */ |
|
741 |
int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
742 |
{ |
|
743 |
Vehicle *v; |
|
744 |
||
745 |
v = &_vehicles[p1]; |
|
746 |
||
747 |
if (!CheckOwnership(v->owner)) |
|
748 |
return CMD_ERROR; |
|
749 |
||
750 |
if (flags & DC_EXEC) { |
|
751 |
v->u.rail.days_since_order_progr = 0; |
|
752 |
v->vehstatus ^= VS_STOPPED; |
|
753 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
754 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
755 |
} |
|
756 |
return 0; |
|
757 |
} |
|
758 |
||
759 |
// p1 = wagon/loco index |
|
760 |
// p2 = mode |
|
761 |
// 0: sell just the vehicle |
|
762 |
// 1: sell the vehicle and all vehicles that follow it in the chain |
|
763 |
// 2: when selling attached locos, rearrange all vehicles after it to separate lines. |
|
764 |
int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
765 |
{ |
|
766 |
Vehicle *v, *first,*last; |
|
767 |
int32 cost; |
|
768 |
||
769 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
|
770 |
||
771 |
v = &_vehicles[p1]; |
|
772 |
||
773 |
if (!CheckOwnership(v->owner)) |
|
774 |
return CMD_ERROR; |
|
775 |
||
776 |
// get first vehicle in chain |
|
777 |
first = v; |
|
778 |
if (first->subtype != 0) { |
|
779 |
first = GetFirstVehicleInChain(first); |
|
242
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
780 |
last = GetLastVehicleInChain(first); |
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
781 |
//now if: |
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
782 |
// 1) we delete a whole a chain, and |
244
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
783 |
// 2) we don't actually try to delete the last engine |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
784 |
// 3) the first and the last vehicle of that train are of the same type, and |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
785 |
// 4) the first and the last vehicle of the chain are not identical |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
786 |
// 5) and of "engine" type (i.e. not a carriage) |
242
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
787 |
// then let the last vehicle live |
244
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
788 |
if ( (p2 == 1) && (v != last) && ( last->engine_type == first->engine_type ) && (last != first) && (first->subtype == 0) ) |
242
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
789 |
last = GetPrevVehicleInChain(last); |
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
790 |
else |
f4894a2cdfe8
(svn r243) -Fix: [1022689] When destroying a part of a train with a 2 side engine the second engine was also deleted [Celestar]
signde
parents:
193
diff
changeset
|
791 |
last = NULL; |
0 | 792 |
} else { |
793 |
if (p2 != 1) { |
|
794 |
// sell last part of multiheaded? |
|
795 |
last = GetLastVehicleInChain(v); |
|
73
34d5f66cfad7
(svn r74) -Fix: [1009631] Wrong multihead selling (Bodewes)
truelight
parents:
22
diff
changeset
|
796 |
// Check if the end-part is the same engine and check if it is the rear-end |
34d5f66cfad7
(svn r74) -Fix: [1009631] Wrong multihead selling (Bodewes)
truelight
parents:
22
diff
changeset
|
797 |
if (last->engine_type != first->engine_type || is_firsthead_sprite(last->spritenum)) |
0 | 798 |
last = NULL; |
799 |
} else { |
|
800 |
last = NULL; |
|
801 |
} |
|
802 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
803 |
|
0 | 804 |
// make sure the vehicle is stopped in the depot |
805 |
if (CheckStoppedInDepot(first) < 0) |
|
806 |
return CMD_ERROR; |
|
807 |
||
808 |
||
809 |
if (flags & DC_EXEC) { |
|
810 |
// always redraw the depot. maybe redraw train list |
|
811 |
InvalidateWindow(WC_VEHICLE_DEPOT, first->tile); |
|
164
0cbdf3c9bde1
(svn r165) -Feature: Option to sort vehicles in vehicle-list window by different criteria. Total independent sort for all types and players. Periodic resort of list every 10 TTD days. Thank you for your graphical inspiration follow and buxo (since none of you provided any code).
darkvater
parents:
159
diff
changeset
|
812 |
if (first->subtype == 0) { |
588 | 813 |
RebuildVehicleLists(); |
164
0cbdf3c9bde1
(svn r165) -Feature: Option to sort vehicles in vehicle-list window by different criteria. Total independent sort for all types and players. Periodic resort of list every 10 TTD days. Thank you for your graphical inspiration follow and buxo (since none of you provided any code).
darkvater
parents:
159
diff
changeset
|
814 |
} |
0 | 815 |
// when selling an attached locomotive. we need to delete its window. |
816 |
if (v->subtype == 0) { |
|
817 |
DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
818 |
|
0 | 819 |
// rearrange all vehicles that follow to separate lines. |
820 |
if (p2 == 2) { |
|
821 |
Vehicle *u,*tmp; |
|
822 |
u = v->next; |
|
823 |
while (u != last) { |
|
824 |
tmp = u; |
|
825 |
u = u->next; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
826 |
DoCommandByTile(tmp->tile, tmp->index | ((-1)<<16), 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); |
0 | 827 |
} |
828 |
} |
|
829 |
} |
|
830 |
||
831 |
// delete the vehicles |
|
832 |
cost = 0; |
|
833 |
for(;;) { |
|
834 |
Vehicle *tmp; |
|
835 |
||
836 |
assert(first); |
|
837 |
first = UnlinkWagon(v, first); |
|
838 |
cost -= v->value; |
|
839 |
tmp = v; |
|
840 |
DeleteVehicle(tmp); |
|
244
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
841 |
if ( v == last ) { |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
842 |
last = NULL; |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
843 |
break; |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
844 |
} |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
845 |
if ( (v=v->next) == last || p2 != 1) break; |
0 | 846 |
} |
847 |
||
848 |
// delete last vehicle of multiheaded train? |
|
849 |
if (last) { |
|
850 |
first = UnlinkWagon(last, first); |
|
851 |
cost -= last->value; |
|
852 |
DeleteVehicle(last); |
|
853 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
854 |
|
0 | 855 |
// an attached train changed? |
856 |
if (first && first->subtype == 0) { |
|
857 |
UpdateTrainAcceleration(first); |
|
858 |
InvalidateWindow(WC_VEHICLE_DETAILS, first->index); |
|
859 |
} |
|
860 |
} else { |
|
861 |
cost = 0; |
|
862 |
for(;;) { |
|
863 |
cost -= v->value; |
|
244
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
864 |
if ( v == last ) { |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
865 |
last = NULL; |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
866 |
break; |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
867 |
} |
57a3922a029c
(svn r245) -Fix: [1022689] Bug when dragging a part of a multiheaded engine to 'sell-whole-train'. The rear-head of the multiheaded train will now not be sold automatically. You have to drag it manually (Celestar)
darkvater
parents:
242
diff
changeset
|
868 |
if ( (v=v->next) == last || p2 != 1) break; |
0 | 869 |
} |
870 |
if (last) cost -= last->value; |
|
871 |
} |
|
872 |
||
873 |
return cost; |
|
874 |
} |
|
875 |
||
876 |
static void UpdateTrainDeltaXY(Vehicle *v, int direction) |
|
877 |
{ |
|
878 |
#define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) |
|
879 |
static const uint32 _delta_xy_table[8] = { |
|
880 |
MKIT(3, 3, -1, -1), |
|
881 |
MKIT(3, 7, -1, -3), |
|
882 |
MKIT(3, 3, -1, -1), |
|
883 |
MKIT(7, 3, -3, -1), |
|
884 |
MKIT(3, 3, -1, -1), |
|
885 |
MKIT(3, 7, -1, -3), |
|
886 |
MKIT(3, 3, -1, -1), |
|
887 |
MKIT(7, 3, -3, -1), |
|
888 |
}; |
|
889 |
#undef MKIT |
|
890 |
||
891 |
uint32 x = _delta_xy_table[direction]; |
|
892 |
||
893 |
v->x_offs = (byte)x; |
|
894 |
v->y_offs = (byte)(x>>=8); |
|
895 |
v->sprite_width = (byte)(x>>=8); |
|
896 |
v->sprite_height = (byte)(x>>=8); |
|
897 |
} |
|
898 |
||
899 |
static void UpdateVarsAfterSwap(Vehicle *v) |
|
900 |
{ |
|
901 |
UpdateTrainDeltaXY(v, v->direction); |
|
902 |
v->cur_image = GetTrainImage(v, v->direction); |
|
903 |
BeginVehicleMove(v); |
|
904 |
VehiclePositionChanged(v); |
|
905 |
EndVehicleMove(v); |
|
906 |
} |
|
907 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
908 |
static void SetLastSpeed(Vehicle *v, int spd) { |
0 | 909 |
int old = v->u.rail.last_speed; |
910 |
if (spd != old) { |
|
911 |
v->u.rail.last_speed = spd; |
|
912 |
if (_patches.vehicle_speed || !old != !spd) |
|
913 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
914 |
} |
|
915 |
} |
|
916 |
||
917 |
static void ReverseTrainSwapVeh(Vehicle *v, int l, int r) |
|
918 |
{ |
|
919 |
Vehicle *a, *b; |
|
920 |
||
921 |
/* locate vehicles to swap */ |
|
922 |
for(a=v; l!=0; l--) { a = a->next; } |
|
923 |
for(b=v; r!=0; r--) { b = b->next; } |
|
924 |
||
925 |
if (a != b) { |
|
926 |
/* swap the hidden bits */ |
|
927 |
{ |
|
928 |
uint16 tmp = (a->vehstatus & ~VS_HIDDEN) | (b->vehstatus&VS_HIDDEN); |
|
929 |
b->vehstatus = (b->vehstatus & ~VS_HIDDEN) | (a->vehstatus&VS_HIDDEN); |
|
930 |
a->vehstatus = tmp; |
|
931 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
932 |
|
0 | 933 |
/* swap variables */ |
934 |
swap_byte(&a->u.rail.track, &b->u.rail.track); |
|
935 |
swap_byte(&a->direction, &b->direction); |
|
936 |
||
937 |
/* toggle direction */ |
|
938 |
if (!(a->u.rail.track & 0x80)) a->direction ^= 4; |
|
939 |
if (!(b->u.rail.track & 0x80)) b->direction ^= 4; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
940 |
|
0 | 941 |
/* swap more variables */ |
942 |
swap_int16(&a->x_pos, &b->x_pos); |
|
943 |
swap_int16(&a->y_pos, &b->y_pos); |
|
944 |
swap_tile(&a->tile, &b->tile); |
|
945 |
swap_byte(&a->z_pos, &b->z_pos); |
|
946 |
||
947 |
/* update other vars */ |
|
948 |
UpdateVarsAfterSwap(a); |
|
949 |
UpdateVarsAfterSwap(b); |
|
950 |
} else { |
|
951 |
if (!(a->u.rail.track & 0x80)) a->direction ^= 4; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
952 |
UpdateVarsAfterSwap(a); |
0 | 953 |
} |
954 |
} |
|
955 |
||
956 |
static void ReverseTrainDirection(Vehicle *v) |
|
957 |
{ |
|
958 |
int l = 0, r = -1; |
|
959 |
Vehicle *u; |
|
960 |
||
961 |
if (IsTrainDepotTile(v->tile)) |
|
962 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
963 |
||
964 |
// count number of vehicles |
|
965 |
u = v; |
|
966 |
do r++; while ( (u = u->next) != NULL ); |
|
967 |
||
968 |
/* swap start<>end, start+1<>end-1, ... */ |
|
969 |
do { |
|
970 |
ReverseTrainSwapVeh(v, l++, r--); |
|
971 |
} while (l <= r); |
|
972 |
||
973 |
if (IsTrainDepotTile(v->tile)) |
|
974 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
975 |
||
976 |
v->u.rail.flags &= ~VRF_REVERSING; |
|
977 |
} |
|
978 |
||
979 |
/* p1 = vehicle */ |
|
980 |
int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
981 |
{ |
|
982 |
Vehicle *v; |
|
983 |
||
984 |
v = &_vehicles[p1]; |
|
985 |
||
986 |
if (!CheckOwnership(v->owner)) |
|
987 |
return CMD_ERROR; |
|
988 |
||
989 |
_error_message = STR_EMPTY; |
|
990 |
||
991 |
// if (v->u.rail.track & 0x80 || IsTrainDepotTile(v->tile)) |
|
992 |
// return CMD_ERROR; |
|
993 |
||
994 |
if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) |
|
995 |
return CMD_ERROR; |
|
996 |
||
997 |
if (flags & DC_EXEC) { |
|
998 |
if (_patches.realistic_acceleration && v->cur_speed != 0) { |
|
999 |
v->u.rail.flags ^= VRF_REVERSING; |
|
1000 |
} else { |
|
1001 |
v->cur_speed = 0; |
|
1002 |
SetLastSpeed(v, 0); |
|
1003 |
ReverseTrainDirection(v); |
|
1004 |
} |
|
1005 |
} |
|
1006 |
return 0; |
|
1007 |
} |
|
1008 |
||
1009 |
int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
1010 |
{ |
|
1011 |
Vehicle *v; |
|
1012 |
||
1013 |
v = &_vehicles[p1]; |
|
1014 |
||
1015 |
if (!CheckOwnership(v->owner)) |
|
1016 |
return CMD_ERROR; |
|
1017 |
||
1018 |
if (flags & DC_EXEC) |
|
1019 |
v->u.rail.force_proceed = 0x50; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1020 |
|
0 | 1021 |
return 0; |
1022 |
} |
|
1023 |
||
1024 |
// p1 = vehicle to refit |
|
1025 |
// p2 = new cargo |
|
1026 |
||
1027 |
int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
1028 |
{ |
|
1029 |
Vehicle *v; |
|
1030 |
int32 cost; |
|
1031 |
uint num; |
|
1032 |
||
1033 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
|
1034 |
||
1035 |
v = &_vehicles[p1]; |
|
1036 |
if (!CheckOwnership(v->owner) || CheckStoppedInDepot(v) < 0) |
|
1037 |
return CMD_ERROR; |
|
1038 |
||
1039 |
cost = 0; |
|
1040 |
num = 0; |
|
1041 |
||
1042 |
do { |
|
491
6527219352cd
(svn r773) When refitting a train engine, refit also all the attached wagons which can be refitted (applicable to DBSetXL, as shown in http://pasky.or.cz/~pasky/dev/openttd/screenshots/wagrefit.png). This is how TTDPatch does it, pointed out by Bjarni.
pasky
parents:
445
diff
changeset
|
1043 |
/* XXX: We also refit all the attached wagons en-masse if they |
6527219352cd
(svn r773) When refitting a train engine, refit also all the attached wagons which can be refitted (applicable to DBSetXL, as shown in http://pasky.or.cz/~pasky/dev/openttd/screenshots/wagrefit.png). This is how TTDPatch does it, pointed out by Bjarni.
pasky
parents:
445
diff
changeset
|
1044 |
* can be refitted. This is how TTDPatch does it. TODO: Have |
6527219352cd
(svn r773) When refitting a train engine, refit also all the attached wagons which can be refitted (applicable to DBSetXL, as shown in http://pasky.or.cz/~pasky/dev/openttd/screenshots/wagrefit.png). This is how TTDPatch does it, pointed out by Bjarni.
pasky
parents:
445
diff
changeset
|
1045 |
* some nice [Refit] button near each wagon. --pasky */ |
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
1046 |
if ((!(RailVehInfo(v->engine_type)->flags & RVI_WAGON) |
491
6527219352cd
(svn r773) When refitting a train engine, refit also all the attached wagons which can be refitted (applicable to DBSetXL, as shown in http://pasky.or.cz/~pasky/dev/openttd/screenshots/wagrefit.png). This is how TTDPatch does it, pointed out by Bjarni.
pasky
parents:
445
diff
changeset
|
1047 |
|| (_engine_refit_masks[v->engine_type] & (1 << p2))) |
6527219352cd
(svn r773) When refitting a train engine, refit also all the attached wagons which can be refitted (applicable to DBSetXL, as shown in http://pasky.or.cz/~pasky/dev/openttd/screenshots/wagrefit.png). This is how TTDPatch does it, pointed out by Bjarni.
pasky
parents:
445
diff
changeset
|
1048 |
&& (byte) p2 != v->cargo_type && v->cargo_cap != 0) { |
15
255d0f685325
(svn r16) Fix: Train refit cost based on _price.ship_base
dominik
parents:
11
diff
changeset
|
1049 |
cost += (_price.build_railvehicle >> 8); |
0 | 1050 |
num += v->cargo_cap; |
1051 |
if (flags & DC_EXEC) { |
|
1052 |
v->cargo_count = 0; |
|
1053 |
v->cargo_type = (byte)p2; |
|
1054 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
1055 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1056 |
} |
0 | 1057 |
} while ( (v=v->next) != NULL); |
1058 |
||
1059 |
_returned_refit_amount = num; |
|
1060 |
||
1061 |
return cost; |
|
1062 |
} |
|
1063 |
||
1064 |
int GetDepotByTile(uint tile) |
|
1065 |
{ |
|
1066 |
Depot *d; |
|
1067 |
int i=0; |
|
1068 |
for(d=_depots; d->xy != (TileIndex)tile; d++) { i++; } |
|
1069 |
return i; |
|
1070 |
} |
|
1071 |
||
1072 |
typedef struct TrainFindDepotData { |
|
1073 |
uint best_length; |
|
1074 |
uint tile; |
|
1075 |
byte owner; |
|
1076 |
} TrainFindDepotData; |
|
1077 |
||
1078 |
static bool TrainFindDepotEnumProc(uint tile, TrainFindDepotData *tfdd, int track, uint length, byte *state) |
|
1079 |
{ |
|
1080 |
if (IS_TILETYPE(tile, MP_RAILWAY) && _map_owner[tile] == tfdd->owner) { |
|
1081 |
if ((_map5[tile] & ~0x3) == 0xC0) { |
|
1082 |
if (length < tfdd->best_length) { |
|
1083 |
tfdd->best_length = length; |
|
1084 |
tfdd->tile = tile; |
|
1085 |
} |
|
1086 |
return true; |
|
1087 |
} |
|
1088 |
||
1089 |
// make sure the train doesn't run against a oneway signal |
|
1090 |
if ((_map5[tile] & 0xC0) == 0x40) { |
|
1091 |
if (!(_map3_lo[tile] & _signal_onedir[track]) && _map3_lo[tile] & _signal_otherdir[track]) |
|
1092 |
return true; |
|
1093 |
} |
|
1094 |
} |
|
1095 |
||
1096 |
// stop searching if we've found a destination that is closer already. |
|
1097 |
return length >= tfdd->best_length; |
|
1098 |
} |
|
1099 |
||
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1100 |
// returns the tile of a depot to goto to. |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1101 |
static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) |
0 | 1102 |
{ |
1103 |
int i; |
|
1104 |
TrainFindDepotData tfdd; |
|
1105 |
uint tile = v->tile; |
|
1106 |
||
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1107 |
tfdd.owner = v->owner; |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1108 |
tfdd.best_length = (uint)-1; |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1109 |
|
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1110 |
if (IsTrainDepotTile(tile)){ |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1111 |
tfdd.tile = tile; |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1112 |
tfdd.best_length = 0; |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1113 |
return tfdd; |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1114 |
} |
0 | 1115 |
|
1116 |
if (v->u.rail.track == 0x40) { tile = GetVehicleOutOfTunnelTile(v); } |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1117 |
|
0 | 1118 |
if (!_patches.new_depot_finding) { |
1119 |
// search in all directions |
|
1120 |
for(i=0; i!=4; i++) |
|
1121 |
NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL); |
|
1122 |
} else { |
|
1123 |
// search in the forward direction first. |
|
1124 |
i = v->direction >> 1; |
|
1125 |
if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; } |
|
1126 |
NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL); |
|
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1127 |
if (tfdd.best_length == (uint)-1){ |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1128 |
// search in backwards direction |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1129 |
i = (v->direction^4) >> 1; |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1130 |
if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; } |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1131 |
NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL); |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1132 |
} |
0 | 1133 |
} |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1134 |
|
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1135 |
return tfdd; |
0 | 1136 |
} |
1137 |
||
1138 |
int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
1139 |
{ |
|
1140 |
Vehicle *v = &_vehicles[p1]; |
|
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1141 |
TrainFindDepotData tfdd; |
0 | 1142 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1143 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
0 | 1144 |
if (flags & DC_EXEC) { |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1145 |
if (v->current_order.flags & OF_UNLOAD) { |
0 | 1146 |
v->u.rail.days_since_order_progr = 0; |
1147 |
v->cur_order_index++; |
|
1148 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1149 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1150 |
v->current_order.type = OT_DUMMY; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1151 |
v->current_order.flags = 0; |
0 | 1152 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
1153 |
} |
|
1154 |
return 0; |
|
1155 |
} |
|
1156 |
||
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1157 |
tfdd = FindClosestTrainDepot(v); |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1158 |
if (tfdd.best_length == (uint)-1) |
0 | 1159 |
return_cmd_error(STR_883A_UNABLE_TO_FIND_ROUTE_TO); |
1160 |
||
1161 |
if (flags & DC_EXEC) { |
|
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
1162 |
v->dest_tile = tfdd.tile; |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1163 |
v->current_order.type = OT_GOTO_DEPOT; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1164 |
v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1165 |
v->current_order.station = GetDepotByTile(tfdd.tile); |
0 | 1166 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
1167 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1168 |
|
0 | 1169 |
return 0; |
1170 |
} |
|
1171 |
||
1172 |
/* p1 = vehicle |
|
1173 |
* p2 = new service int |
|
1174 |
*/ |
|
1175 |
int32 CmdChangeTrainServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
1176 |
{ |
|
1177 |
Vehicle *v = &_vehicles[p1]; |
|
1178 |
||
1179 |
if (!CheckOwnership(v->owner)) |
|
1180 |
return CMD_ERROR; |
|
1181 |
||
1182 |
if (flags & DC_EXEC) { |
|
1183 |
v->service_interval = (uint16)p2; |
|
1184 |
InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 8); |
|
1185 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1186 |
|
0 | 1187 |
return 0; |
1188 |
} |
|
1189 |
||
1190 |
void OnTick_Train() |
|
1191 |
{ |
|
1192 |
_age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1); |
|
1193 |
} |
|
1194 |
||
1195 |
static const int8 _vehicle_smoke_pos[16] = { |
|
1196 |
-4, -4, -4, 0, 4, 4, 4, 0, |
|
1197 |
-4, 0, 4, 4, 4, 0,-4,-4, |
|
1198 |
}; |
|
1199 |
||
1200 |
static void HandleLocomotiveSmokeCloud(Vehicle *v) |
|
1201 |
{ |
|
1202 |
Vehicle *u; |
|
1203 |
||
1204 |
if (v->vehstatus & VS_TRAIN_SLOWING || v->load_unload_time_rem != 0 || v->cur_speed < 2) |
|
1205 |
return; |
|
1206 |
||
1207 |
u = v; |
|
1208 |
||
1209 |
do { |
|
1210 |
int engtype = v->engine_type; |
|
1211 |
||
1212 |
// no smoke? |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
1213 |
if (RailVehInfo(engtype)->flags & 2 |
0 | 1214 |
|| _engines[engtype].railtype > 0 |
1215 |
|| (v->vehstatus&VS_HIDDEN) || (v->u.rail.track & 0xC0) ) |
|
1216 |
continue; |
|
1217 |
||
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
1218 |
switch (RailVehInfo(engtype)->engclass) { |
0 | 1219 |
case 0: |
1220 |
// steam smoke. |
|
1221 |
if ( (v->tick_counter&0xF) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile)) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1222 |
CreateEffectVehicleRel(v, |
0 | 1223 |
(_vehicle_smoke_pos[v->direction]), |
1224 |
(_vehicle_smoke_pos[v->direction+8]), |
|
1225 |
10, |
|
1226 |
EV_STEAM_SMOKE); |
|
1227 |
} |
|
1228 |
break; |
|
1229 |
||
1230 |
case 1: |
|
1231 |
// diesel smoke |
|
1232 |
if (u->cur_speed <= 40 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x1E00) { |
|
1233 |
CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_3); |
|
1234 |
} |
|
1235 |
break; |
|
1236 |
||
1237 |
case 2: |
|
1238 |
// blue spark |
|
1239 |
if ( (v->tick_counter&0x3) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x5B0) { |
|
1240 |
CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_2); |
|
1241 |
} |
|
1242 |
break; |
|
1243 |
} |
|
1244 |
} while ( (v = v->next) != NULL ); |
|
1245 |
||
1246 |
} |
|
1247 |
||
1248 |
static void TrainPlayLeaveStationSound(Vehicle *v) |
|
1249 |
{ |
|
541 | 1250 |
static const SoundFx sfx[] = { |
1251 |
SND_04_TRAIN, |
|
1252 |
SND_0A_TRAIN_HORN, |
|
1253 |
SND_0A_TRAIN_HORN |
|
1254 |
}; |
|
1255 |
||
0 | 1256 |
int engtype = v->engine_type; |
1257 |
||
1258 |
switch (_engines[engtype].railtype) { |
|
337
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1259 |
case 0: |
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
1260 |
SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], v); |
337
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1261 |
break; |
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1262 |
case 1: |
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1263 |
SndPlayVehicleFx(SND_47_MAGLEV_2, v); |
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1264 |
break; |
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1265 |
case 2: |
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1266 |
SndPlayVehicleFx(SND_41_MAGLEV, v); |
cbe0c766c947
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
308
diff
changeset
|
1267 |
break; |
0 | 1268 |
} |
1269 |
} |
|
1270 |
||
1271 |
static bool CheckTrainStayInDepot(Vehicle *v) |
|
1272 |
{ |
|
1273 |
Vehicle *u; |
|
495
6b3e2b4fa7c9
(svn r785) -Fix: A train can leave and enter the same depot at the same time, then the trai simply got stuck
tron
parents:
491
diff
changeset
|
1274 |
|
6b3e2b4fa7c9
(svn r785) -Fix: A train can leave and enter the same depot at the same time, then the trai simply got stuck
tron
parents:
491
diff
changeset
|
1275 |
// bail out if not all wagons are in the same depot or not in a depot at all |
6b3e2b4fa7c9
(svn r785) -Fix: A train can leave and enter the same depot at the same time, then the trai simply got stuck
tron
parents:
491
diff
changeset
|
1276 |
for (u = v; u != NULL; u = u->next) |
6b3e2b4fa7c9
(svn r785) -Fix: A train can leave and enter the same depot at the same time, then the trai simply got stuck
tron
parents:
491
diff
changeset
|
1277 |
if (u->u.rail.track != 0x80 || u->tile != v->tile) |
6b3e2b4fa7c9
(svn r785) -Fix: A train can leave and enter the same depot at the same time, then the trai simply got stuck
tron
parents:
491
diff
changeset
|
1278 |
return false; |
0 | 1279 |
|
1280 |
if (v->u.rail.force_proceed == 0) { |
|
1281 |
if (++v->load_unload_time_rem < 37) |
|
1282 |
return true; |
|
1283 |
v->load_unload_time_rem = 0; |
|
1284 |
||
1285 |
if (UpdateSignalsOnSegment(v->tile, v->direction)) |
|
1286 |
return true; |
|
1287 |
} |
|
1288 |
||
578
1e66514eb621
(svn r998) now vehicles are serviced both when entering and when leaving depots to prevent that vehicles might need service when leaving after a long stay (ln--)
bjarni
parents:
555
diff
changeset
|
1289 |
VehicleServiceInDepot(v); |
0 | 1290 |
TrainPlayLeaveStationSound(v); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1291 |
|
0 | 1292 |
v->u.rail.track = 1; |
1293 |
if (v->direction & 2) |
|
1294 |
v->u.rail.track = 2; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1295 |
|
0 | 1296 |
v->vehstatus &= ~VS_HIDDEN; |
1297 |
v->cur_speed = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1298 |
|
0 | 1299 |
UpdateTrainDeltaXY(v, v->direction); |
1300 |
v->cur_image = GetTrainImage(v, v->direction); |
|
1301 |
VehiclePositionChanged(v); |
|
1302 |
UpdateSignalsOnSegment(v->tile, v->direction); |
|
1303 |
UpdateTrainAcceleration(v); |
|
1304 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
1305 |
||
1306 |
return false; |
|
1307 |
} |
|
1308 |
||
1309 |
typedef struct TrainTrackFollowerData { |
|
1310 |
TileIndex dest_coords; |
|
1311 |
int station_index; // station index we're heading for |
|
1312 |
uint best_bird_dist; |
|
1313 |
uint best_track_dist; |
|
1314 |
byte best_track; |
|
1315 |
} TrainTrackFollowerData; |
|
1316 |
||
1317 |
static bool TrainTrackFollower(uint tile, TrainTrackFollowerData *ttfd, int track, uint length, byte *state){ |
|
1318 |
if (IS_TILETYPE(tile, MP_RAILWAY) && (_map5[tile]&0xC0) == 0x40) { |
|
1319 |
// the tile has a signal |
|
1320 |
byte m3 = _map3_lo[tile]; |
|
1321 |
if (!(m3 & _signal_onedir[track])) { |
|
1322 |
// if one way signal not pointing towards us, stop going in this direction. |
|
1323 |
if (m3 & _signal_otherdir[track]) |
|
1324 |
return true; |
|
1325 |
} else if (_map2[tile] & _signal_onedir[track]) { |
|
1326 |
// green signal in our direction. either one way or two way. |
|
1327 |
*state = true; |
|
1328 |
} else if (m3 & _signal_otherdir[track]) { |
|
1329 |
// two way signal. unless we passed another green signal on the way, |
|
1330 |
// stop going in this direction. |
|
1331 |
if (!*state) return true; |
|
1332 |
} |
|
1333 |
} |
|
1334 |
||
1335 |
// heading for nowhere? |
|
1336 |
if (ttfd->dest_coords == 0) |
|
1337 |
return false; |
|
1338 |
||
1339 |
// did we reach the final station? |
|
166
683136f1e8a8
(svn r167) -Fix: [972247] bug in '[a] weird non-uniform stations handling'
truelight
parents:
164
diff
changeset
|
1340 |
if ((ttfd->station_index == -1 && tile == ttfd->dest_coords) || |
683136f1e8a8
(svn r167) -Fix: [972247] bug in '[a] weird non-uniform stations handling'
truelight
parents:
164
diff
changeset
|
1341 |
(IS_TILETYPE(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 0, 8) && _map2[tile] == ttfd->station_index)) { |
683136f1e8a8
(svn r167) -Fix: [972247] bug in '[a] weird non-uniform stations handling'
truelight
parents:
164
diff
changeset
|
1342 |
/* We do not check for dest_coords if we have a station_index, |
683136f1e8a8
(svn r167) -Fix: [972247] bug in '[a] weird non-uniform stations handling'
truelight
parents:
164
diff
changeset
|
1343 |
* because in that case the dest_coords are just an |
683136f1e8a8
(svn r167) -Fix: [972247] bug in '[a] weird non-uniform stations handling'
truelight
parents:
164
diff
changeset
|
1344 |
* approximation of where the station is */ |
0 | 1345 |
// found station |
1346 |
ttfd->best_bird_dist = 0; |
|
1347 |
if (length < ttfd->best_track_dist) { |
|
1348 |
ttfd->best_track_dist = length; |
|
1349 |
ttfd->best_track = state[1]; |
|
1350 |
} |
|
1351 |
return true; |
|
1352 |
} else { |
|
1353 |
uint dist; |
|
1354 |
||
1355 |
// we've actually found the destination already. no point searching in directions longer than this. |
|
1356 |
if (ttfd->best_track_dist != (uint)-1) |
|
1357 |
return length >= ttfd->best_track_dist; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1358 |
|
0 | 1359 |
// didn't find station |
1360 |
dist = GetTileDist(tile, ttfd->dest_coords); |
|
1361 |
if (dist < ttfd->best_bird_dist) { |
|
1362 |
ttfd->best_bird_dist = dist; |
|
1363 |
ttfd->best_track = state[1]; |
|
1364 |
} |
|
1365 |
return false; |
|
1366 |
} |
|
1367 |
} |
|
1368 |
||
1369 |
static void FillWithStationData(TrainTrackFollowerData *fd, Vehicle *v) |
|
1370 |
{ |
|
103
3af99b9373a1
(svn r104) Fix: wrong pathfinding when northern station tile is missing (blathijs)
dominik
parents:
98
diff
changeset
|
1371 |
fd->dest_coords = v->dest_tile; |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1372 |
if (v->current_order.type == OT_GOTO_STATION) |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1373 |
fd->station_index = v->current_order.station; |
103
3af99b9373a1
(svn r104) Fix: wrong pathfinding when northern station tile is missing (blathijs)
dominik
parents:
98
diff
changeset
|
1374 |
else |
3af99b9373a1
(svn r104) Fix: wrong pathfinding when northern station tile is missing (blathijs)
dominik
parents:
98
diff
changeset
|
1375 |
fd->station_index = -1; |
3af99b9373a1
(svn r104) Fix: wrong pathfinding when northern station tile is missing (blathijs)
dominik
parents:
98
diff
changeset
|
1376 |
|
0 | 1377 |
} |
1378 |
||
1379 |
static const byte _initial_tile_subcoord[6][4][3] = { |
|
1380 |
{{ 15, 8, 1 },{ 0, 0, 0 },{ 0, 8, 5 },{ 0, 0, 0 }}, |
|
1381 |
{{ 0, 0, 0 },{ 8, 0, 3 },{ 0, 0, 0 },{ 8,15, 7 }}, |
|
1382 |
{{ 0, 0, 0 },{ 7, 0, 2 },{ 0, 7, 6 },{ 0, 0, 0 }}, |
|
1383 |
{{ 15, 8, 2 },{ 0, 0, 0 },{ 0, 0, 0 },{ 8,15, 6 }}, |
|
1384 |
{{ 15, 7, 0 },{ 8, 0, 4 },{ 0, 0, 0 },{ 0, 0, 0 }}, |
|
1385 |
{{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 8, 4 },{ 7,15, 0 }}, |
|
1386 |
}; |
|
1387 |
||
1388 |
static const uint32 _reachable_tracks[4] = { |
|
1389 |
0x10091009, |
|
1390 |
0x00160016, |
|
1391 |
0x05200520, |
|
1392 |
0x2A002A00, |
|
1393 |
}; |
|
1394 |
||
1395 |
static const byte _search_directions[6][4] = { |
|
1396 |
{ 0, 9, 2, 9 }, // track 1 |
|
1397 |
{ 9, 1, 9, 3 }, // track 2 |
|
1398 |
{ 9, 0, 3, 9 }, // track upper |
|
1399 |
{ 1, 9, 9, 2 }, // track lower |
|
1400 |
{ 3, 2, 9, 9 }, // track left |
|
1401 |
{ 9, 9, 1, 0 }, // track right |
|
1402 |
}; |
|
1403 |
||
1404 |
static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0}; |
|
1405 |
||
1406 |
/* choose a track */ |
|
1407 |
static byte ChooseTrainTrack(Vehicle *v, uint tile, int direction, byte trackbits) |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1408 |
{ |
0 | 1409 |
TrainTrackFollowerData fd; |
1410 |
int bits = trackbits; |
|
1411 |
uint best_track; |
|
1412 |
#if 0 |
|
1413 |
int time = rdtsc(); |
|
1414 |
static float f; |
|
1415 |
#endif |
|
1416 |
||
1417 |
assert( (bits & ~0x3F) == 0); |
|
1418 |
||
1419 |
/* quick return in case only one possible direction is available */ |
|
1420 |
if (KILL_FIRST_BIT(bits) == 0) |
|
1421 |
return FIND_FIRST_BIT(bits); |
|
1422 |
||
1423 |
FillWithStationData(&fd, v); |
|
1424 |
||
1425 |
if (_patches.new_pathfinding) { |
|
1426 |
fd.best_bird_dist = (uint)-1; |
|
1427 |
fd.best_track_dist = (uint)-1; |
|
1428 |
fd.best_track = 0xFF; |
|
1429 |
NewTrainPathfind(tile - _tileoffs_by_dir[direction], direction, (TPFEnumProc*)TrainTrackFollower, &fd, NULL); |
|
1430 |
||
1431 |
// printf("Train %d %s\n", v->unitnumber, fd.best_track_dist == -1 ? "NOTFOUND" : "FOUND"); |
|
1432 |
||
1433 |
if (fd.best_track == 0xff) { |
|
1434 |
// blaha |
|
1435 |
best_track = FIND_FIRST_BIT(bits); |
|
1436 |
} else { |
|
1437 |
best_track = fd.best_track & 7; |
|
1438 |
} |
|
1439 |
} else { |
|
1440 |
int i, r; |
|
1441 |
uint best_bird_dist = 0; |
|
1442 |
uint best_track_dist = 0; |
|
1443 |
byte train_dir = v->direction & 3; |
|
1444 |
||
1445 |
||
1446 |
best_track = -1; |
|
1447 |
||
1448 |
do { |
|
1449 |
i = FIND_FIRST_BIT(bits); |
|
1450 |
bits = KILL_FIRST_BIT(bits); |
|
1451 |
||
1452 |
fd.best_bird_dist = (uint)-1; |
|
1453 |
fd.best_track_dist = (uint)-1; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1454 |
|
0 | 1455 |
NewTrainPathfind(tile, _search_directions[i][direction], (TPFEnumProc*)TrainTrackFollower, &fd, NULL); |
1456 |
if (best_track != -1) { |
|
1457 |
if (best_track_dist == -1) { |
|
1458 |
if (fd.best_track_dist == -1) { |
|
1459 |
/* neither reached the destination, pick the one with the smallest bird dist */ |
|
1460 |
if (fd.best_bird_dist > best_bird_dist) goto bad; |
|
1461 |
if (fd.best_bird_dist < best_bird_dist) goto good; |
|
1462 |
} else { |
|
1463 |
/* we found the destination for the first time */ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1464 |
goto good; |
0 | 1465 |
} |
1466 |
} else { |
|
1467 |
if (fd.best_track_dist == -1) { |
|
1468 |
/* didn't find destination, but we've found the destination previously */ |
|
1469 |
goto bad; |
|
1470 |
} else { |
|
1471 |
/* both old & new reached the destination, compare track length */ |
|
1472 |
if (fd.best_track_dist > best_track_dist) goto bad; |
|
1473 |
if (fd.best_track_dist < best_track_dist) goto good; |
|
1474 |
} |
|
1475 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1476 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1477 |
/* if we reach this position, there's two paths of equal value so far. |
0 | 1478 |
* pick one randomly. */ |
1479 |
r = (byte)Random(); |
|
1480 |
if (_pick_track_table[i] == train_dir) r += 80; |
|
1481 |
if (_pick_track_table[best_track] == train_dir) r -= 80; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1482 |
|
0 | 1483 |
if (r <= 127) goto bad; |
1484 |
} |
|
1485 |
good:; |
|
1486 |
best_track = i; |
|
1487 |
best_bird_dist = fd.best_bird_dist; |
|
1488 |
best_track_dist = fd.best_track_dist; |
|
1489 |
bad:; |
|
1490 |
} while (bits != 0); |
|
1491 |
// printf("Train %d %s\n", v->unitnumber, best_track_dist == -1 ? "NOTFOUND" : "FOUND"); |
|
1492 |
assert(best_track != -1); |
|
1493 |
} |
|
1494 |
||
1495 |
#if 0 |
|
1496 |
time = rdtsc() - time; |
|
1497 |
f = f * 0.99 + 0.01 * time; |
|
1498 |
printf("PF time = %d %f\n", time, f); |
|
1499 |
#endif |
|
1500 |
||
1501 |
return best_track; |
|
1502 |
} |
|
1503 |
||
1504 |
||
1505 |
static bool CheckReverseTrain(Vehicle *v) |
|
1506 |
{ |
|
1507 |
TrainTrackFollowerData fd; |
|
1508 |
int i, r; |
|
1509 |
int best_track; |
|
1510 |
uint best_bird_dist = 0; |
|
1511 |
uint best_track_dist = 0; |
|
1512 |
uint reverse, reverse_best; |
|
1513 |
||
1514 |
if (_opt.diff.line_reverse_mode != 0 || |
|
1515 |
v->u.rail.track & 0xC0 || |
|
1516 |
!(v->direction & 1)) |
|
1517 |
return false; |
|
1518 |
||
1519 |
FillWithStationData(&fd, v); |
|
1520 |
||
1521 |
best_track = -1; |
|
1522 |
reverse_best = reverse = 0; |
|
1523 |
||
1524 |
assert(v->u.rail.track); |
|
1525 |
||
1526 |
i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][v->direction>>1]; |
|
1527 |
||
1528 |
while(true) { |
|
1529 |
fd.best_bird_dist = (uint)-1; |
|
1530 |
fd.best_track_dist = (uint)-1; |
|
1531 |
||
1532 |
NewTrainPathfind(v->tile, reverse ^ i, (TPFEnumProc*)TrainTrackFollower, &fd, NULL); |
|
1533 |
||
1534 |
if (best_track != -1) { |
|
1535 |
if (best_bird_dist != 0) { |
|
1536 |
if (fd.best_bird_dist != 0) { |
|
1537 |
/* neither reached the destination, pick the one with the smallest bird dist */ |
|
1538 |
if (fd.best_bird_dist > best_bird_dist) goto bad; |
|
1539 |
if (fd.best_bird_dist < best_bird_dist) goto good; |
|
1540 |
} else { |
|
1541 |
/* we found the destination for the first time */ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1542 |
goto good; |
0 | 1543 |
} |
1544 |
} else { |
|
1545 |
if (fd.best_bird_dist != 0) { |
|
1546 |
/* didn't find destination, but we've found the destination previously */ |
|
1547 |
goto bad; |
|
1548 |
} else { |
|
1549 |
/* both old & new reached the destination, compare track length */ |
|
1550 |
if (fd.best_track_dist > best_track_dist) goto bad; |
|
1551 |
if (fd.best_track_dist < best_track_dist) goto good; |
|
1552 |
} |
|
1553 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1554 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1555 |
/* if we reach this position, there's two paths of equal value so far. |
0 | 1556 |
* pick one randomly. */ |
1557 |
r = (byte)Random(); |
|
1558 |
if (_pick_track_table[i] == (v->direction & 3)) r += 80; |
|
1559 |
if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80; |
|
1560 |
if (r <= 127) goto bad; |
|
1561 |
} |
|
1562 |
good:; |
|
1563 |
best_track = i; |
|
1564 |
best_bird_dist = fd.best_bird_dist; |
|
1565 |
best_track_dist = fd.best_track_dist; |
|
1566 |
reverse_best = reverse; |
|
1567 |
bad:; |
|
1568 |
if (reverse != 0) |
|
1569 |
break; |
|
1570 |
reverse = 2; |
|
1571 |
} |
|
1572 |
||
1573 |
return reverse_best != 0; |
|
1574 |
} |
|
1575 |
||
1576 |
static bool ProcessTrainOrder(Vehicle *v) |
|
1577 |
{ |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1578 |
Order order; |
0 | 1579 |
bool result; |
1580 |
||
1581 |
// These are un-interruptible |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1582 |
if (v->current_order.type >= OT_GOTO_DEPOT && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1583 |
v->current_order.type <= OT_LEAVESTATION) { |
0 | 1584 |
// Let a depot order in the schedule interrupt. |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1585 |
if (v->current_order.type != OT_GOTO_DEPOT || |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1586 |
!(v->current_order.flags & OF_UNLOAD)) |
0 | 1587 |
return false; |
1588 |
} |
|
1589 |
||
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1590 |
if (v->current_order.type == OT_GOTO_DEPOT && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1591 |
(v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) && |
593 | 1592 |
!VehicleNeedsService(v)) { |
0 | 1593 |
v->cur_order_index++; |
1594 |
} |
|
1595 |
||
395
788a9bba0889
(svn r587) -newgrf: Rename all /Checkpoint/i tokens to 'Waypoint's. The name actually makes some sense and is also compatible with TTDPatch (pasky).
darkvater
parents:
358
diff
changeset
|
1596 |
// check if we've reached the waypoint? |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1597 |
if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) { |
0 | 1598 |
v->cur_order_index++; |
1599 |
} |
|
1600 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1601 |
// check if we've reached a non-stop station while TTDPatch nonstop is enabled.. |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1602 |
if (_patches.new_nonstop && v->current_order.flags & OF_NON_STOP && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1603 |
v->current_order.station == _map2[v->tile]) { |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1604 |
v->cur_order_index++; |
0 | 1605 |
} |
1606 |
||
1607 |
// Get the current order |
|
1608 |
if (v->cur_order_index >= v->num_orders) |
|
1609 |
v->cur_order_index = 0; |
|
1610 |
order = v->schedule_ptr[v->cur_order_index]; |
|
1611 |
||
1612 |
// If no order, do nothing. |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1613 |
if (order.type == OT_NOTHING) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1614 |
v->current_order.type = OT_NOTHING; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1615 |
v->current_order.flags = 0; |
0 | 1616 |
v->dest_tile = 0; |
1617 |
return false; |
|
1618 |
} |
|
1619 |
||
1620 |
// If it is unchanged, keep it. |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1621 |
if (order.type == v->current_order.type && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1622 |
order.flags == v->current_order.flags && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1623 |
order.station == v->current_order.station) |
0 | 1624 |
return false; |
1625 |
||
1626 |
// Otherwise set it, and determine the destination tile. |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1627 |
v->current_order = order; |
0 | 1628 |
|
1629 |
v->dest_tile = 0; |
|
1630 |
||
1631 |
result = false; |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1632 |
if (order.type == OT_GOTO_STATION) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1633 |
if (order.station == v->last_station_visited) |
0 | 1634 |
v->last_station_visited = 0xFF; |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1635 |
v->dest_tile = DEREF_STATION(order.station)->xy; |
0 | 1636 |
result = CheckReverseTrain(v); |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1637 |
} else if (order.type == OT_GOTO_DEPOT) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1638 |
v->dest_tile = _depots[order.station].xy; |
0 | 1639 |
result = CheckReverseTrain(v); |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1640 |
} else if (order.type == OT_GOTO_WAYPOINT) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1641 |
v->dest_tile = _waypoints[order.station].xy; |
0 | 1642 |
result = CheckReverseTrain(v); |
1643 |
} |
|
1644 |
||
1645 |
InvalidateVehicleOrderWidget(v); |
|
1646 |
||
1647 |
return result; |
|
1648 |
} |
|
1649 |
||
1650 |
static void MarkTrainDirty(Vehicle *v) |
|
1651 |
{ |
|
1652 |
do { |
|
1653 |
v->cur_image = GetTrainImage(v, v->direction); |
|
1654 |
MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
|
1655 |
} while ( (v=v->next) != NULL); |
|
1656 |
} |
|
1657 |
||
1658 |
static void HandleTrainLoading(Vehicle *v, bool mode) |
|
1659 |
{ |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1660 |
if (v->current_order.type == OT_NOTHING) |
0 | 1661 |
return; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1662 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1663 |
if (v->current_order.type != OT_DUMMY) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1664 |
if (v->current_order.type != OT_LOADING) |
0 | 1665 |
return; |
1666 |
||
1667 |
if (mode) |
|
1668 |
return; |
|
1669 |
||
1670 |
// don't mark the train as lost if we're loading on the final station. |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1671 |
if (v->current_order.flags & OF_NON_STOP) |
0 | 1672 |
v->u.rail.days_since_order_progr = 0; |
1673 |
||
1674 |
if (--v->load_unload_time_rem) |
|
1675 |
return; |
|
1676 |
||
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1677 |
if (v->current_order.flags & OF_FULL_LOAD && CanFillVehicle(v)) { |
0 | 1678 |
SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); |
1679 |
if (LoadUnloadVehicle(v)) { |
|
1680 |
InvalidateWindow(WC_TRAINS_LIST, v->owner); |
|
1681 |
MarkTrainDirty(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1682 |
|
0 | 1683 |
// need to update acceleration since the goods on the train changed. |
1684 |
UpdateTrainAcceleration(v); |
|
1685 |
} |
|
1686 |
return; |
|
1687 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1688 |
|
0 | 1689 |
TrainPlayLeaveStationSound(v); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1690 |
|
0 | 1691 |
{ |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1692 |
Order b = v->current_order; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1693 |
v->current_order.type = OT_LEAVESTATION; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1694 |
v->current_order.flags = 0; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1695 |
|
0 | 1696 |
// If this was not the final order, don't remove it from the list. |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1697 |
if (!(b.flags & OF_NON_STOP)) |
0 | 1698 |
return; |
1699 |
} |
|
1700 |
} |
|
1701 |
||
1702 |
v->u.rail.days_since_order_progr = 0; |
|
1703 |
v->cur_order_index++; |
|
1704 |
InvalidateVehicleOrderWidget(v); |
|
1705 |
} |
|
1706 |
||
1707 |
static int UpdateTrainSpeed(Vehicle *v) |
|
1708 |
{ |
|
1709 |
uint spd; |
|
1710 |
uint accel; |
|
1711 |
||
1712 |
if (v->vehstatus & VS_STOPPED || v->u.rail.flags & VRF_REVERSING) { |
|
1713 |
accel = -v->acceleration * 2; |
|
1714 |
} else { |
|
1715 |
accel = v->acceleration; |
|
1716 |
if (_patches.realistic_acceleration) { |
|
1717 |
accel = GetRealisticAcceleration(v); |
|
1718 |
} |
|
1719 |
} |
|
1720 |
||
1721 |
spd = v->subspeed + accel * 2; |
|
1722 |
v->subspeed = (byte)spd; |
|
1723 |
v->cur_speed = spd = clamp(v->cur_speed + ((int)spd >> 8), 0, v->max_speed); |
|
1724 |
||
1725 |
if (!(v->direction & 1)) spd = spd * 3 >> 2; |
|
1726 |
||
1727 |
spd += v->progress; |
|
1728 |
v->progress = (byte)spd; |
|
1729 |
return (spd >> 8); |
|
1730 |
} |
|
1731 |
||
1732 |
static void TrainEnterStation(Vehicle *v, int station) |
|
1733 |
{ |
|
1734 |
Station *st; |
|
1735 |
uint32 flags; |
|
1736 |
||
1737 |
v->last_station_visited = station; |
|
1738 |
||
1739 |
/* check if a train ever visited this station before */ |
|
1740 |
st = DEREF_STATION(station); |
|
1741 |
if (!(st->had_vehicle_of_type & HVOT_TRAIN)) { |
|
1742 |
st->had_vehicle_of_type |= HVOT_TRAIN; |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
1743 |
SetDParam(0, st->index); |
0 | 1744 |
flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); |
1745 |
AddNewsItem( |
|
1746 |
STR_8801_CITIZENS_CELEBRATE_FIRST, |
|
1747 |
flags, |
|
1748 |
v->index, |
|
1749 |
0); |
|
1750 |
} |
|
1751 |
||
1752 |
// Did we reach the final destination? |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1753 |
if (v->current_order.type == OT_GOTO_STATION && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1754 |
v->current_order.station == (byte)station) { |
0 | 1755 |
// Yeah, keep the load/unload flags |
1756 |
// Non Stop now means if the order should be increased. |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1757 |
v->current_order.type = OT_LOADING; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1758 |
v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1759 |
v->current_order.flags |= OF_NON_STOP; |
0 | 1760 |
} else { |
1761 |
// No, just do a simple load |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1762 |
v->current_order.type = OT_LOADING; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1763 |
v->current_order.flags = 0; |
0 | 1764 |
} |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
1765 |
v->current_order.station = 0; |
0 | 1766 |
|
1767 |
SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); |
|
1768 |
if (LoadUnloadVehicle(v) != 0) { |
|
1769 |
InvalidateWindow(WC_TRAINS_LIST, v->owner); |
|
1770 |
MarkTrainDirty(v); |
|
1771 |
UpdateTrainAcceleration(v); |
|
1772 |
} |
|
1773 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
1774 |
} |
|
1775 |
||
1776 |
static byte AfterSetTrainPos(Vehicle *v) |
|
1777 |
{ |
|
1778 |
byte new_z, old_z; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1779 |
|
0 | 1780 |
// need this hint so it returns the right z coordinate on bridges. |
1781 |
_get_z_hint = v->z_pos; |
|
1782 |
new_z = GetSlopeZ(v->x_pos, v->y_pos); |
|
1783 |
_get_z_hint = 0; |
|
1784 |
||
1785 |
old_z = v->z_pos; |
|
1786 |
v->z_pos = new_z; |
|
1787 |
||
1788 |
v->u.rail.flags &= ~(VRF_GOINGUP | VRF_GOINGDOWN); |
|
1789 |
||
1790 |
if (new_z != old_z) { |
|
1791 |
v->u.rail.flags |= (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN; |
|
1792 |
} |
|
1793 |
||
1794 |
VehiclePositionChanged(v); |
|
1795 |
EndVehicleMove(v); |
|
1796 |
return old_z; |
|
1797 |
} |
|
1798 |
||
1799 |
static const byte _new_vehicle_direction_table[11] = { |
|
1800 |
0, 7, 6, 0, |
|
1801 |
1, 0, 5, 0, |
|
1802 |
2, 3, 4, |
|
1803 |
}; |
|
1804 |
||
1805 |
static int GetNewVehicleDirectionByTile(uint new_tile, uint old_tile) |
|
1806 |
{ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1807 |
uint offs = (GET_TILE_Y(new_tile) - GET_TILE_Y(old_tile) + 1) * 4 + |
0 | 1808 |
GET_TILE_X(new_tile) - GET_TILE_X(old_tile) + 1; |
1809 |
assert(offs < 11); |
|
1810 |
return _new_vehicle_direction_table[offs]; |
|
1811 |
} |
|
1812 |
||
1813 |
static int GetNewVehicleDirection(Vehicle *v, int x, int y) |
|
1814 |
{ |
|
1815 |
uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1); |
|
1816 |
assert(offs < 11); |
|
1817 |
return _new_vehicle_direction_table[offs]; |
|
1818 |
} |
|
1819 |
||
1820 |
static int GetDirectionToVehicle(Vehicle *v, int x, int y) |
|
1821 |
{ |
|
1822 |
byte offs; |
|
1823 |
||
1824 |
x -= v->x_pos; |
|
1825 |
if (x >= 0) { |
|
1826 |
offs = (x > 2) ? 0 : 1; |
|
1827 |
} else { |
|
1828 |
offs = (x < -2) ? 2 : 1; |
|
1829 |
} |
|
1830 |
||
1831 |
y -= v->y_pos; |
|
1832 |
if (y >= 0) { |
|
1833 |
offs += ((y > 2) ? 0 : 1) * 4; |
|
1834 |
} else { |
|
1835 |
offs += ((y < -2) ? 2 : 1) * 4; |
|
1836 |
} |
|
1837 |
||
1838 |
assert(offs < 11); |
|
1839 |
return _new_vehicle_direction_table[offs]; |
|
1840 |
} |
|
1841 |
||
1842 |
/* Check if the vehicle is compatible with the specified tile */ |
|
1843 |
static bool CheckCompatibleRail(Vehicle *v, uint tile) |
|
1844 |
{ |
|
300
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1845 |
if (IS_TILETYPE(tile, MP_RAILWAY) || IS_TILETYPE(tile, MP_STATION)) { |
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1846 |
// normal tracks, jump to owner check |
0 | 1847 |
} else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { |
1848 |
if ((_map5[tile] & 0xC0) == 0xC0) {// is bridge middle part? |
|
1849 |
TileInfo ti; |
|
1850 |
FindLandscapeHeightByTile(&ti, tile); |
|
1851 |
||
1852 |
// correct Z position of a train going under a bridge on slopes |
|
1853 |
if (CORRECT_Z(ti.tileh)) |
|
1854 |
ti.z += 8; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1855 |
|
0 | 1856 |
if(v->z_pos != ti.z) // train is going over bridge |
1857 |
return true; |
|
1858 |
} |
|
300
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1859 |
} else if (IS_TILETYPE(tile, MP_STREET)) { // train is going over a road-crossing |
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1860 |
// tracks over roads, do owner check of tracks (_map_owner[tile]) |
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1861 |
if (_map_owner[tile] != v->owner || (v->subtype == 0 && (_map3_hi[tile] & 0xF) != v->u.rail.railtype)) |
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1862 |
return false; |
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1863 |
|
824331d2a868
(svn r306) -Fix: [985439] un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
darkvater
parents:
288
diff
changeset
|
1864 |
return true; |
0 | 1865 |
} else |
1866 |
return true; |
|
1867 |
||
1868 |
if (_map_owner[tile] != v->owner || |
|
1869 |
(v->subtype == 0 && (_map3_lo[tile] & 0xF) != v->u.rail.railtype)) |
|
1870 |
return false; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1871 |
|
0 | 1872 |
return true; |
1873 |
} |
|
1874 |
||
1875 |
typedef struct { |
|
1876 |
byte small_turn, large_turn; |
|
1877 |
byte z_up; // fraction to remove when moving up |
|
1878 |
byte z_down; // fraction to remove when moving down |
|
1879 |
} RailtypeSlowdownParams; |
|
1880 |
||
1881 |
static const RailtypeSlowdownParams _railtype_slowdown[3] = { |
|
1882 |
// normal accel |
|
1883 |
{256/4, 256/2, 256/4, 2}, // normal |
|
1884 |
{256/4, 256/2, 256/4, 2}, // monorail |
|
1885 |
{0, 256/2, 256/4, 2}, // maglev |
|
1886 |
}; |
|
1887 |
||
1888 |
/* Modify the speed of the vehicle due to a turn */ |
|
1889 |
static void AffectSpeedByDirChange(Vehicle *v, byte new_dir) |
|
1890 |
{ |
|
1891 |
byte diff; |
|
1892 |
const RailtypeSlowdownParams *rsp; |
|
1893 |
||
1894 |
if (_patches.realistic_acceleration || (diff = (v->direction - new_dir) & 7) == 0) |
|
1895 |
return; |
|
1896 |
||
1897 |
rsp = &_railtype_slowdown[v->u.rail.railtype]; |
|
1898 |
v->cur_speed -= ((diff == 1 || diff == 7) ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8; |
|
1899 |
} |
|
1900 |
||
1901 |
/* Modify the speed of the vehicle due to a change in altitude */ |
|
1902 |
static void AffectSpeedByZChange(Vehicle *v, byte old_z) |
|
1903 |
{ |
|
1904 |
const RailtypeSlowdownParams *rsp; |
|
1905 |
if (old_z == v->z_pos || _patches.realistic_acceleration) |
|
1906 |
return; |
|
1907 |
||
1908 |
rsp = &_railtype_slowdown[v->u.rail.railtype]; |
|
1909 |
||
1910 |
if (old_z < v->z_pos) { |
|
1911 |
v->cur_speed -= (v->cur_speed * rsp->z_up >> 8); |
|
1912 |
} else { |
|
1913 |
uint16 spd = v->cur_speed + rsp->z_down; |
|
1914 |
if (spd <= v->max_speed) |
|
1915 |
v->cur_speed = spd; |
|
1916 |
} |
|
1917 |
} |
|
1918 |
||
1919 |
static const byte _otherside_signal_directions[14] = { |
|
1920 |
1, 3, 1, 3, 5, 3, 0, 0, |
|
1921 |
5, 7, 7, 5, 7, 1, |
|
1922 |
}; |
|
1923 |
||
1924 |
static void TrainMovedChangeSignals(uint tile, int dir) |
|
1925 |
{ |
|
1926 |
int i; |
|
1927 |
if (IS_TILETYPE(tile, MP_RAILWAY) && (_map5[tile]&0xC0)==0x40) { |
|
1928 |
i = FindFirstBit2x64((_map5[tile]+(_map5[tile]<<8)) & _reachable_tracks[dir]); |
|
1929 |
UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]); |
|
1930 |
} |
|
1931 |
} |
|
1932 |
||
1933 |
||
1934 |
typedef struct TrainCollideChecker { |
|
1935 |
Vehicle *v, *v_skip; |
|
1936 |
||
1937 |
} TrainCollideChecker; |
|
1938 |
||
1939 |
void *FindTrainCollideEnum(Vehicle *v, TrainCollideChecker *tcc) |
|
1940 |
{ |
|
1941 |
if (v == tcc->v || v == tcc->v_skip || v->type != VEH_Train || v->u.rail.track==0x80) |
|
1942 |
return 0; |
|
1943 |
||
1944 |
if ( myabs(v->z_pos - tcc->v->z_pos) > 6 || |
|
1945 |
myabs(v->x_pos - tcc->v->x_pos) >= 6 || |
|
1946 |
myabs(v->y_pos - tcc->v->y_pos) >= 6) |
|
1947 |
return NULL; |
|
1948 |
return v; |
|
1949 |
} |
|
1950 |
||
1951 |
static void SetVehicleCrashed(Vehicle *v) |
|
1952 |
{ |
|
1953 |
Vehicle *u; |
|
1954 |
||
1955 |
if (v->u.rail.crash_anim_pos != 0) |
|
1956 |
return; |
|
1957 |
||
1958 |
v->u.rail.crash_anim_pos++; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1959 |
|
0 | 1960 |
u = v; |
1961 |
BEGIN_ENUM_WAGONS(v) |
|
1962 |
v->vehstatus |= VS_CRASHED; |
|
1963 |
END_ENUM_WAGONS(v) |
|
1964 |
||
1965 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, u->index, 4); |
|
1966 |
} |
|
1967 |
||
1968 |
static int CountPassengersInTrain(Vehicle *v) |
|
1969 |
{ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1970 |
int num = 0; |
0 | 1971 |
BEGIN_ENUM_WAGONS(v) |
1972 |
if (v->cargo_type == 0) num += v->cargo_count; |
|
1973 |
END_ENUM_WAGONS(v) |
|
1974 |
return num; |
|
1975 |
} |
|
1976 |
||
22 | 1977 |
/* |
1978 |
* Checks whether the specified tried has a collision with another vehicle. If |
|
1979 |
* so, destroys this vehicle, and the other vehicle if its subtype is 0 (?). |
|
1980 |
* Reports the incident in a flashy news item, modifies station ratings and |
|
1981 |
* plays a sound. |
|
1982 |
*/ |
|
0 | 1983 |
static void CheckTrainCollision(Vehicle *v) |
1984 |
{ |
|
1985 |
TrainCollideChecker tcc; |
|
98 | 1986 |
Vehicle *coll,*realcoll; |
0 | 1987 |
int num; |
1988 |
||
1989 |
/* can't collide in depot */ |
|
1990 |
if (v->u.rail.track == 0x80) |
|
1991 |
return; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1992 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
1993 |
if ( !(v->u.rail.track == 0x40) ) |
98 | 1994 |
assert((uint)TILE_FROM_XY(v->x_pos, v->y_pos) == v->tile); |
0 | 1995 |
|
1996 |
tcc.v = v; |
|
1997 |
tcc.v_skip = v->next; |
|
1998 |
||
1999 |
/* find colliding vehicle */ |
|
98 | 2000 |
realcoll = coll = VehicleFromPos(TILE_FROM_XY(v->x_pos, v->y_pos), &tcc, (VehicleFromPosProc*)FindTrainCollideEnum); |
0 | 2001 |
if (coll == NULL) |
2002 |
return; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2003 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2004 |
|
0 | 2005 |
coll = GetFirstVehicleInChain(coll); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2006 |
|
0 | 2007 |
/* it can't collide with its own wagons */ |
98 | 2008 |
if ( (v == coll) || ( (v->u.rail.track & 0x40) && ( (v->direction & 2) != (realcoll->direction & 2) ) ) ) |
0 | 2009 |
return; |
2010 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2011 |
//two drivers + passangers killed in train v |
0 | 2012 |
num = 2 + CountPassengersInTrain(v); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2013 |
if(!(coll->vehstatus&VS_CRASHED)) |
0 | 2014 |
//two drivers + passangers killed in train coll (if it was not crashed already) |
2015 |
num += 2 + CountPassengersInTrain(coll); |
|
2016 |
||
2017 |
SetVehicleCrashed(v); |
|
2018 |
if (coll->subtype == 0) |
|
2019 |
SetVehicleCrashed(coll); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2020 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2021 |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
2022 |
SetDParam(0, num); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2023 |
|
0 | 2024 |
AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL, |
2025 |
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), |
|
2026 |
v->index, |
|
2027 |
0); |
|
2028 |
||
2029 |
ModifyStationRatingAround(v->tile, v->owner, -160, 30); |
|
541 | 2030 |
SndPlayVehicleFx(SND_13_BIG_CRASH, v); |
0 | 2031 |
} |
2032 |
||
2033 |
static void *CheckVehicleAtSignal(Vehicle *v, void *data) |
|
2034 |
{ |
|
2035 |
uint32 d = (uint32)data; |
|
2036 |
||
2037 |
if (v->type == VEH_Train && v->subtype == 0 && v->tile == (TileIndex)(d >> 8)) { |
|
2038 |
byte diff = (v->direction - (byte)d + 2) & 7; |
|
2039 |
if (diff == 2 || (v->cur_speed <= 5 && diff <= 4)) |
|
2040 |
return (void*)1; |
|
2041 |
} |
|
2042 |
return 0; |
|
2043 |
} |
|
2044 |
||
2045 |
static void TrainController(Vehicle *v) |
|
2046 |
{ |
|
2047 |
Vehicle *prev = NULL; |
|
2048 |
GetNewVehiclePosResult gp; |
|
2049 |
uint32 r, tracks,ts; |
|
2050 |
int dir, i; |
|
2051 |
byte chosen_dir; |
|
2052 |
byte chosen_track; |
|
2053 |
byte old_z; |
|
2054 |
||
22 | 2055 |
/* For every vehicle after and including the given vehicle */ |
0 | 2056 |
for(;;) { |
2057 |
BeginVehicleMove(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2058 |
|
0 | 2059 |
if (v->u.rail.track != 0x40) { |
22 | 2060 |
/* Not inside tunnel */ |
0 | 2061 |
if (GetNewVehiclePos(v, &gp)) { |
22 | 2062 |
/* Staying in the old tile */ |
0 | 2063 |
if (v->u.rail.track == 0x80) { |
2064 |
/* inside depot */ |
|
2065 |
gp.x = v->x_pos; |
|
2066 |
gp.y = v->y_pos; |
|
2067 |
} else { |
|
22 | 2068 |
/* is not inside depot */ |
0 | 2069 |
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
2070 |
if (r & 0x8) |
|
2071 |
goto invalid_rail; |
|
2072 |
if (r & 0x2) { |
|
2073 |
TrainEnterStation(v, r >> 8); |
|
2074 |
return; |
|
2075 |
} |
|
2076 |
||
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2077 |
if (v->current_order.type == OT_LEAVESTATION) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2078 |
v->current_order.type = OT_NOTHING; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2079 |
v->current_order.flags = 0; |
0 | 2080 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
2081 |
} |
|
2082 |
} |
|
2083 |
} else { |
|
2084 |
/* A new tile is about to be entered. */ |
|
2085 |
||
2086 |
/* Determine what direction we're entering the new tile from */ |
|
2087 |
dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile); |
|
2088 |
assert(dir==1 || dir==3 || dir==5 || dir==7); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2089 |
|
0 | 2090 |
/* Get the status of the tracks in the new tile and mask |
2091 |
* away the bits that aren't reachable. */ |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
2092 |
ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _reachable_tracks[dir >> 1]; |
0 | 2093 |
|
2094 |
/* Combine the from & to directions. |
|
2095 |
* Now, the lower byte contains the track status, and the byte at bit 16 contains |
|
2096 |
* the signal status. */ |
|
2097 |
tracks = ts|(ts >> 8); |
|
2098 |
if ( (byte) tracks == 0) |
|
2099 |
goto invalid_rail; |
|
2100 |
||
2101 |
/* Check if the new tile contrains tracks that are compatible |
|
2102 |
* with the current train, if not, bail out. */ |
|
2103 |
if (!CheckCompatibleRail(v, gp.new_tile)) |
|
2104 |
goto invalid_rail; |
|
2105 |
||
2106 |
if (prev == NULL) { |
|
2107 |
/* Currently the locomotive is active. Determine which one of the |
|
2108 |
* available tracks to choose */ |
|
2109 |
chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, dir>>1, (byte)tracks); |
|
2110 |
||
2111 |
/* Check if it's a red signal and that force proceed is not clicked. */ |
|
2112 |
if ( (tracks>>16)&chosen_track && v->u.rail.force_proceed == 0) goto red_light; |
|
2113 |
} else { |
|
2114 |
static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2}; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2115 |
|
0 | 2116 |
/* The wagon is active, simply follow the prev vehicle. */ |
2117 |
chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & tracks); |
|
2118 |
} |
|
2119 |
||
2120 |
/* make sure chosen track is a valid track */ |
|
2121 |
assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32); |
|
2122 |
||
2123 |
/* Update XY to reflect the entrance to the new tile, and select the direction to use */ |
|
2124 |
{ |
|
2125 |
const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][dir>>1]; |
|
2126 |
gp.x = (gp.x & ~0xF) | b[0]; |
|
2127 |
gp.y = (gp.y & ~0xF) | b[1]; |
|
2128 |
chosen_dir = b[2]; |
|
2129 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2130 |
|
0 | 2131 |
/* Call the landscape function and tell it that the vehicle entered the tile */ |
2132 |
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
2133 |
if (r&0x8) |
|
2134 |
goto invalid_rail; |
|
2135 |
||
2136 |
if (v->subtype == 0) v->load_unload_time_rem = 0; |
|
2137 |
||
2138 |
if (!(r&0x4)) { |
|
2139 |
v->tile = gp.new_tile; |
|
2140 |
v->u.rail.track = chosen_track; |
|
2141 |
} |
|
2142 |
||
2143 |
if (v->subtype == 0) |
|
2144 |
TrainMovedChangeSignals(gp.new_tile, dir>>1); |
|
2145 |
||
22 | 2146 |
/* Signals can only change when the first |
2147 |
* (above) or the last vehicle moves. */ |
|
0 | 2148 |
if (v->next == NULL) |
2149 |
TrainMovedChangeSignals(gp.old_tile, (dir>>1) ^ 2); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2150 |
|
0 | 2151 |
if (prev == NULL) { |
2152 |
AffectSpeedByDirChange(v, chosen_dir); |
|
2153 |
} |
|
2154 |
||
2155 |
v->direction = chosen_dir; |
|
2156 |
} |
|
2157 |
} else { |
|
2158 |
/* in tunnel */ |
|
2159 |
GetNewVehiclePos(v, &gp); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2160 |
|
0 | 2161 |
if (IS_TILETYPE(gp.new_tile, MP_TUNNELBRIDGE) && |
2162 |
!(_map5[gp.new_tile] & 0xF0)) { |
|
2163 |
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
2164 |
if (r & 0x4) goto common; |
|
2165 |
} |
|
2166 |
||
2167 |
v->x_pos = gp.x; |
|
2168 |
v->y_pos = gp.y; |
|
2169 |
VehiclePositionChanged(v); |
|
98 | 2170 |
if (prev == NULL) |
2171 |
CheckTrainCollision(v); |
|
0 | 2172 |
goto next_vehicle; |
2173 |
} |
|
2174 |
common:; |
|
2175 |
||
2176 |
/* update image of train, as well as delta XY */ |
|
2177 |
dir = GetNewVehicleDirection(v, gp.x, gp.y); |
|
2178 |
UpdateTrainDeltaXY(v, dir); |
|
2179 |
v->cur_image = GetTrainImage(v, dir); |
|
2180 |
||
2181 |
v->x_pos = gp.x; |
|
2182 |
v->y_pos = gp.y; |
|
2183 |
||
2184 |
/* update the Z position of the vehicle */ |
|
2185 |
old_z = AfterSetTrainPos(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2186 |
|
0 | 2187 |
if (prev == NULL) { |
22 | 2188 |
/* This is the first vehicle in the train */ |
0 | 2189 |
AffectSpeedByZChange(v, old_z); |
2190 |
CheckTrainCollision(v); |
|
2191 |
} |
|
2192 |
||
22 | 2193 |
next_vehicle:; |
0 | 2194 |
/* continue with next vehicle */ |
2195 |
prev = v; |
|
2196 |
if ((v=v->next) == NULL) |
|
2197 |
return; |
|
2198 |
} |
|
2199 |
||
2200 |
invalid_rail: |
|
22 | 2201 |
/* We've reached end of line?? */ |
0 | 2202 |
if (prev != NULL) { |
2203 |
error("!Disconnecting train"); |
|
2204 |
} |
|
2205 |
goto reverse_train_direction; |
|
2206 |
||
2207 |
red_light: { |
|
22 | 2208 |
/* We're in front of a red signal ?? */ |
0 | 2209 |
/* find the first set bit in ts. need to do it in 2 steps, since |
2210 |
* FIND_FIRST_BIT only handles 6 bits at a time. */ |
|
2211 |
i = FindFirstBit2x64(ts); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2212 |
|
0 | 2213 |
if (!(_map3_lo[gp.new_tile] & _signal_otherdir[i])) { |
2214 |
v->cur_speed = 0; |
|
2215 |
v->subspeed = 0; |
|
2216 |
v->progress = 255-100; |
|
2217 |
if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20) |
|
2218 |
return; |
|
2219 |
} else if (_map3_lo[gp.new_tile] & _signal_onedir[i]){ |
|
2220 |
v->cur_speed = 0; |
|
2221 |
v->subspeed = 0; |
|
2222 |
v->progress = 255-10; |
|
2223 |
if (++v->load_unload_time_rem < _patches.wait_twoway_signal * 73) { |
|
2224 |
uint o_tile = gp.new_tile + _tileoffs_by_dir[dir>>1]; |
|
2225 |
/* check if a train is waiting on the other side */ |
|
2226 |
if (VehicleFromPos(o_tile, (void*)( (o_tile<<8) | (dir^4)), (VehicleFromPosProc*)CheckVehicleAtSignal) == NULL) |
|
2227 |
return; |
|
2228 |
} |
|
2229 |
} |
|
2230 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2231 |
|
0 | 2232 |
reverse_train_direction: |
2233 |
v->load_unload_time_rem = 0; |
|
2234 |
v->cur_speed = 0; |
|
2235 |
v->subspeed = 0; |
|
2236 |
ReverseTrainDirection(v); |
|
2237 |
||
2238 |
} |
|
2239 |
||
98 | 2240 |
extern uint CheckTunnelBusy(uint tile, int *length); |
2241 |
||
0 | 2242 |
static void DeleteLastWagon(Vehicle *v) |
2243 |
{ |
|
2244 |
Vehicle *u = v; |
|
2245 |
int t; |
|
2246 |
||
2247 |
while (v->next != NULL) { |
|
2248 |
u = v; |
|
2249 |
v = v->next; |
|
2250 |
} |
|
2251 |
u->next = NULL; |
|
2252 |
||
2253 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
2254 |
DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
|
588 | 2255 |
RebuildVehicleLists(); |
0 | 2256 |
InvalidateWindow(WC_COMPANY, v->owner); |
2257 |
||
2258 |
BeginVehicleMove(v); |
|
2259 |
EndVehicleMove(v); |
|
2260 |
DeleteVehicle(v); |
|
2261 |
||
2262 |
if (!((t=v->u.rail.track) & 0xC0)) { |
|
2263 |
SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(t)); |
|
2264 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2265 |
|
98 | 2266 |
if (v->u.rail.track == 0x40) { |
2267 |
int length; |
|
2268 |
TileIndex endtile = CheckTunnelBusy(v->tile, &length); |
|
2269 |
if ((v->direction == 1) || (v->direction == 5) ) |
|
2270 |
SetSignalsOnBothDir(v->tile,0); |
|
2271 |
SetSignalsOnBothDir(endtile,0); |
|
2272 |
if ((v->direction == 3) || (v->direction == 7) ) |
|
2273 |
SetSignalsOnBothDir(v->tile,1); |
|
2274 |
SetSignalsOnBothDir(endtile,1); |
|
2275 |
} |
|
0 | 2276 |
} |
2277 |
||
2278 |
static void ChangeTrainDirRandomly(Vehicle *v) |
|
2279 |
{ |
|
2280 |
static int8 _random_dir_change[4] = { -1, 0, 0, 1}; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2281 |
|
0 | 2282 |
do { |
98 | 2283 |
//I need to buffer the train direction |
288
72ca19a694dd
(svn r294) -Fix: autorail always builds rail, instead of occasional rail removal (on pressing hotkey after pressing 'bulldozer')
darkvater
parents:
244
diff
changeset
|
2284 |
if (!(v->u.rail.track & 0x40)) |
72ca19a694dd
(svn r294) -Fix: autorail always builds rail, instead of occasional rail removal (on pressing hotkey after pressing 'bulldozer')
darkvater
parents:
244
diff
changeset
|
2285 |
v->direction = (v->direction + _random_dir_change[InteractiveRandom()&3]) & 7; |
0 | 2286 |
if (!(v->vehstatus & VS_HIDDEN)) { |
2287 |
BeginVehicleMove(v); |
|
2288 |
UpdateTrainDeltaXY(v, v->direction); |
|
2289 |
v->cur_image = GetTrainImage(v, v->direction); |
|
2290 |
AfterSetTrainPos(v); |
|
2291 |
} |
|
2292 |
} while ( (v=v->next) != NULL); |
|
2293 |
} |
|
2294 |
||
2295 |
static void HandleCrashedTrain(Vehicle *v) |
|
2296 |
{ |
|
2297 |
int state = ++v->u.rail.crash_anim_pos, index; |
|
2298 |
uint32 r; |
|
2299 |
Vehicle *u; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2300 |
|
98 | 2301 |
if ( (state == 4) && (v->u.rail.track != 0x40) ) { |
0 | 2302 |
CreateEffectVehicleRel(v, 4, 4, 8, EV_CRASHED_SMOKE); |
2303 |
} |
|
2304 |
||
288
72ca19a694dd
(svn r294) -Fix: autorail always builds rail, instead of occasional rail removal (on pressing hotkey after pressing 'bulldozer')
darkvater
parents:
244
diff
changeset
|
2305 |
if (state <= 200 && (uint16)(r=InteractiveRandom()) <= 0x2492) { |
0 | 2306 |
index = (r * 10 >> 16); |
2307 |
||
2308 |
u = v; |
|
2309 |
do { |
|
2310 |
if (--index < 0) { |
|
288
72ca19a694dd
(svn r294) -Fix: autorail always builds rail, instead of occasional rail removal (on pressing hotkey after pressing 'bulldozer')
darkvater
parents:
244
diff
changeset
|
2311 |
r = InteractiveRandom(); |
0 | 2312 |
|
2313 |
CreateEffectVehicleRel(u, |
|
2314 |
2 + ((r>>8)&7), |
|
2315 |
2 + ((r>>16)&7), |
|
2316 |
5 + (r&7), |
|
2317 |
EV_DEMOLISH); |
|
2318 |
break; |
|
2319 |
} |
|
2320 |
} while ( (u=u->next) != NULL); |
|
2321 |
} |
|
2322 |
||
2323 |
if (state <= 240 && !(v->tick_counter&3)) { |
|
2324 |
ChangeTrainDirRandomly(v); |
|
2325 |
} |
|
2326 |
||
2327 |
if (state >= 4440 && !(v->tick_counter&0x1F)) |
|
2328 |
DeleteLastWagon(v); |
|
2329 |
} |
|
2330 |
||
2331 |
static void HandleBrokenTrain(Vehicle *v) |
|
2332 |
{ |
|
2333 |
if (v->breakdown_ctr != 1) { |
|
2334 |
v->breakdown_ctr = 1; |
|
2335 |
v->cur_speed = 0; |
|
2336 |
||
2337 |
if (v->breakdowns_since_last_service != 255) |
|
2338 |
v->breakdowns_since_last_service++; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2339 |
|
0 | 2340 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
2341 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2342 |
|
541 | 2343 |
SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? |
2344 |
SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); |
|
0 | 2345 |
|
2346 |
if (!(v->vehstatus & VS_HIDDEN)) { |
|
2347 |
Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); |
|
2348 |
if (u) |
|
2349 |
u->u.special.unk0 = v->breakdown_delay * 2; |
|
2350 |
} |
|
2351 |
} |
|
2352 |
||
2353 |
if (!(v->tick_counter & 3)) { |
|
2354 |
if (!--v->breakdown_delay) { |
|
2355 |
v->breakdown_ctr = 0; |
|
2356 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
|
2357 |
} |
|
2358 |
} |
|
2359 |
} |
|
2360 |
||
2361 |
static const byte _breakdown_speeds[16] = { |
|
2362 |
225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15 |
|
2363 |
}; |
|
2364 |
||
2365 |
static void TrainCheckIfLineEnds(Vehicle *v) |
|
2366 |
{ |
|
2367 |
uint tile; |
|
2368 |
uint x,y; |
|
2369 |
int t; |
|
2370 |
uint32 ts; |
|
2371 |
||
2372 |
if ((uint)(t=v->breakdown_ctr) > 1) { |
|
2373 |
v->vehstatus |= VS_TRAIN_SLOWING; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2374 |
|
0 | 2375 |
t = _breakdown_speeds[ ((~t) >> 4) & 0xF]; |
2376 |
if ((uint16)t <= v->cur_speed) |
|
2377 |
v->cur_speed = t; |
|
2378 |
} else { |
|
2379 |
v->vehstatus &= ~VS_TRAIN_SLOWING; |
|
2380 |
} |
|
2381 |
||
2382 |
// exit if inside a tunnel |
|
2383 |
if (v->u.rail.track & 0x40) |
|
2384 |
return; |
|
2385 |
||
2386 |
tile = v->tile; |
|
2387 |
||
2388 |
// tunnel entrance? |
|
2389 |
if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && |
|
2390 |
(_map5[tile] & 0xF0) == 0 && (byte)((_map5[tile] & 3)*2+1) == v->direction) |
|
2391 |
return; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2392 |
|
0 | 2393 |
// depot? |
2394 |
if (IS_TILETYPE(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0) |
|
2395 |
return; |
|
2396 |
||
22 | 2397 |
/* Determine the non-diagonal direction in which we will exit this tile */ |
0 | 2398 |
t = v->direction >> 1; |
2399 |
if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[t]) { |
|
2400 |
t = (t - 1) & 3; |
|
2401 |
} |
|
22 | 2402 |
/* Calculate next tile */ |
0 | 2403 |
tile += _tileoffs_by_dir[t]; |
22 | 2404 |
// determine the track status on the next tile. |
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
2405 |
ts = GetTileTrackStatus(tile, TRANSPORT_RAIL) & _reachable_tracks[t]; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2406 |
|
22 | 2407 |
/* Calc position within the current tile ?? */ |
0 | 2408 |
x = v->x_pos & 0xF; |
2409 |
y = v->y_pos & 0xF; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2410 |
|
0 | 2411 |
switch(v->direction) { |
2412 |
case 0: |
|
2413 |
x = (~x) + (~y) + 24; |
|
2414 |
break; |
|
2415 |
case 7: |
|
2416 |
x = y; |
|
2417 |
/* fall through */ |
|
2418 |
case 1: |
|
2419 |
x = (~x) + 16; |
|
2420 |
break; |
|
2421 |
case 2: |
|
2422 |
x = (~x) + y + 8; |
|
2423 |
break; |
|
2424 |
case 3: |
|
2425 |
x = y; |
|
2426 |
break; |
|
2427 |
case 4: |
|
2428 |
x = x + y - 8; |
|
2429 |
break; |
|
2430 |
case 6: |
|
2431 |
x = (~y) + x + 8; |
|
2432 |
break; |
|
2433 |
} |
|
2434 |
||
2435 |
if ( (uint16)ts != 0) { |
|
2436 |
if ((ts &= (ts >> 16)) == 0) { |
|
2437 |
// make a rail/road crossing red |
|
2438 |
if (IS_TILETYPE(tile, MP_STREET) && (_map5[tile] & 0xF0)==0x10) { |
|
2439 |
if (!(_map5[tile] & 4)) { |
|
2440 |
_map5[tile] |= 4; |
|
541 | 2441 |
SndPlayVehicleFx(SND_0E_LEVEL_CROSSING, v); |
0 | 2442 |
MarkTileDirtyByTile(tile); |
2443 |
} |
|
2444 |
} |
|
2445 |
return; |
|
2446 |
} |
|
2447 |
} else if (x + 4 > 15) { |
|
2448 |
v->cur_speed = 0; |
|
2449 |
ReverseTrainDirection(v); |
|
2450 |
return; |
|
2451 |
} |
|
2452 |
||
2453 |
// slow down |
|
2454 |
v->vehstatus |= VS_TRAIN_SLOWING; |
|
2455 |
t = _breakdown_speeds[x & 0xF]; |
|
2456 |
if (!(v->direction&1)) t>>=1; |
|
2457 |
if ((uint16)t < v->cur_speed) |
|
2458 |
v->cur_speed = t; |
|
2459 |
} |
|
2460 |
||
2461 |
static void TrainLocoHandler(Vehicle *v, bool mode) |
|
2462 |
{ |
|
2463 |
int j; |
|
2464 |
||
2465 |
/* train has crashed? */ |
|
2466 |
if (v->u.rail.crash_anim_pos != 0) { |
|
2467 |
if (!mode) HandleCrashedTrain(v); |
|
2468 |
return; |
|
2469 |
} |
|
2470 |
||
2471 |
if (v->u.rail.force_proceed != 0) |
|
2472 |
v->u.rail.force_proceed--; |
|
2473 |
||
2474 |
/* train is broken down? */ |
|
2475 |
if (v->breakdown_ctr != 0) { |
|
2476 |
if (v->breakdown_ctr <= 2) { |
|
2477 |
HandleBrokenTrain(v); |
|
2478 |
return; |
|
2479 |
} |
|
2480 |
v->breakdown_ctr--; |
|
2481 |
} |
|
2482 |
||
2483 |
if (v->u.rail.flags & VRF_REVERSING && v->cur_speed == 0) { |
|
2484 |
ReverseTrainDirection(v); |
|
2485 |
} |
|
2486 |
||
2487 |
/* exit if train is stopped */ |
|
2488 |
if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) |
|
2489 |
return; |
|
2490 |
||
2491 |
||
2492 |
if (ProcessTrainOrder(v)) { |
|
2493 |
v->load_unload_time_rem = 0; |
|
2494 |
v->cur_speed = 0; |
|
2495 |
v->subspeed = 0; |
|
2496 |
ReverseTrainDirection(v); |
|
2497 |
return; |
|
2498 |
} |
|
2499 |
||
2500 |
HandleTrainLoading(v, mode); |
|
2501 |
||
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2502 |
if (v->current_order.type == OT_LOADING) |
0 | 2503 |
return; |
2504 |
||
2505 |
if (CheckTrainStayInDepot(v)) |
|
2506 |
return; |
|
2507 |
||
2508 |
if (!mode) HandleLocomotiveSmokeCloud(v); |
|
2509 |
||
2510 |
j = UpdateTrainSpeed(v); |
|
2511 |
if (j == 0) { |
|
2512 |
// if the vehicle has speed 0, update the last_speed field. |
|
2513 |
if (v->cur_speed != 0) |
|
2514 |
return; |
|
2515 |
} else { |
|
2516 |
TrainCheckIfLineEnds(v); |
|
2517 |
||
2518 |
do { |
|
2519 |
TrainController(v); |
|
2520 |
if (v->cur_speed <= 0x100) |
|
2521 |
break; |
|
2522 |
} while (--j != 0); |
|
2523 |
} |
|
2524 |
||
2525 |
SetLastSpeed(v, v->cur_speed); |
|
2526 |
} |
|
2527 |
||
2528 |
||
2529 |
void Train_Tick(Vehicle *v) |
|
2530 |
{ |
|
2531 |
if (_age_cargo_skip_counter == 0 && v->cargo_days != 0xff) |
|
2532 |
v->cargo_days++; |
|
2533 |
||
2534 |
v->tick_counter++; |
|
2535 |
||
2536 |
if (v->subtype == 0) { |
|
2537 |
TrainLocoHandler(v, false); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2538 |
|
0 | 2539 |
// make sure vehicle wasn't deleted. |
2540 |
if (v->type == VEH_Train && v->subtype == 0) |
|
2541 |
TrainLocoHandler(v, true); |
|
2542 |
} |
|
2543 |
} |
|
2544 |
||
2545 |
||
2546 |
static const byte _depot_track_ind[4] = {0,1,0,1}; |
|
2547 |
||
2548 |
void TrainEnterDepot(Vehicle *v, uint tile) |
|
2549 |
{ |
|
2550 |
SetSignalsOnBothDir(tile, _depot_track_ind[_map5[tile]&3]); |
|
2551 |
||
2552 |
if (v->subtype != 0) |
|
2553 |
v = GetFirstVehicleInChain(v); |
|
2554 |
||
578
1e66514eb621
(svn r998) now vehicles are serviced both when entering and when leaving depots to prevent that vehicles might need service when leaving after a long stay (ln--)
bjarni
parents:
555
diff
changeset
|
2555 |
VehicleServiceInDepot(v); |
1e66514eb621
(svn r998) now vehicles are serviced both when entering and when leaving depots to prevent that vehicles might need service when leaving after a long stay (ln--)
bjarni
parents:
555
diff
changeset
|
2556 |
|
0 | 2557 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
2558 |
||
2559 |
v->load_unload_time_rem = 0; |
|
2560 |
v->cur_speed = 0; |
|
2561 |
||
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
2562 |
MaybeRenewVehicle(v, EstimateTrainCost(RailVehInfo(v->engine_type))); |
0 | 2563 |
|
445
beafc0fb8f12
(svn r654) Hopefully complete support for randomized variational spritegroups (i.e. the cars transporter in DBSetXL gets different cars each time) (pasky)
tron
parents:
410
diff
changeset
|
2564 |
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); |
beafc0fb8f12
(svn r654) Hopefully complete support for randomized variational spritegroups (i.e. the cars transporter in DBSetXL gets different cars each time) (pasky)
tron
parents:
410
diff
changeset
|
2565 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2566 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2567 |
Order t; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2568 |
|
0 | 2569 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2570 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2571 |
t = v->current_order; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2572 |
v->current_order.type = OT_DUMMY; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2573 |
v->current_order.flags = 0; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2574 |
|
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2575 |
if (t.flags & OF_UNLOAD) { // Part of the schedule? |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2576 |
v->u.rail.days_since_order_progr = 0; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2577 |
v->cur_order_index++; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2578 |
} else if (t.flags & OF_FULL_LOAD) { // User initiated? |
0 | 2579 |
v->vehstatus |= VS_STOPPED; |
2580 |
if (v->owner == _local_player) { |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
2581 |
SetDParam(0, v->unitnumber); |
0 | 2582 |
AddNewsItem( |
2583 |
STR_8814_TRAIN_IS_WAITING_IN_DEPOT, |
|
2584 |
NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), |
|
2585 |
v->index, |
|
2586 |
0); |
|
2587 |
} |
|
2588 |
} |
|
2589 |
} |
|
2590 |
} |
|
2591 |
||
2592 |
static void CheckIfTrainNeedsService(Vehicle *v) |
|
2593 |
{ |
|
2594 |
byte depot; |
|
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2595 |
TrainFindDepotData tfdd; |
0 | 2596 |
|
76
30511cbc5188
(svn r77) -Fix: [1010788] AI service interval bug (tnx truesatan)
truelight
parents:
73
diff
changeset
|
2597 |
if (_patches.servint_trains == 0) |
0 | 2598 |
return; |
2599 |
||
593 | 2600 |
if (!VehicleNeedsService(v)) |
0 | 2601 |
return; |
2602 |
||
2603 |
if (v->vehstatus & VS_STOPPED) |
|
2604 |
return; |
|
2605 |
||
76
30511cbc5188
(svn r77) -Fix: [1010788] AI service interval bug (tnx truesatan)
truelight
parents:
73
diff
changeset
|
2606 |
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) |
0 | 2607 |
return; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2608 |
|
0 | 2609 |
// Don't interfere with a depot visit scheduled by the user, or a |
2610 |
// depot visit by the order list. |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2611 |
if (v->current_order.type == OT_GOTO_DEPOT && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2612 |
(v->current_order.flags & (OF_FULL_LOAD | OF_UNLOAD)) != 0) |
0 | 2613 |
return; |
2614 |
||
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2615 |
tfdd = FindClosestTrainDepot(v); |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2616 |
/* Only go to the depot if it is not too far out of our way. */ |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2617 |
if (tfdd.best_length == (uint)-1 || tfdd.best_length > 16 ) { |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2618 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2619 |
/* If we were already heading for a depot but it has |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2620 |
* suddenly moved farther away, we continue our normal |
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2621 |
* schedule? */ |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2622 |
v->current_order.type = OT_DUMMY; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2623 |
v->current_order.flags = 0; |
0 | 2624 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
2625 |
} |
|
2626 |
return; |
|
2627 |
} |
|
2628 |
||
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2629 |
depot = GetDepotByTile(tfdd.tile); |
0 | 2630 |
|
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2631 |
if (v->current_order.type == OT_GOTO_DEPOT && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2632 |
v->current_order.station != depot && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2633 |
!CHANCE16(3,16)) |
0 | 2634 |
return; |
2635 |
||
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2636 |
v->current_order.type = OT_GOTO_DEPOT; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2637 |
v->current_order.flags = OF_NON_STOP; |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2638 |
v->current_order.station = depot; |
308
8088f72d10f5
(svn r314) -Fix: [982611] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
darkvater
parents:
300
diff
changeset
|
2639 |
v->dest_tile = tfdd.tile; |
0 | 2640 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
2641 |
} |
|
2642 |
||
2643 |
int32 GetTrainRunningCost(Vehicle *v) |
|
2644 |
{ |
|
2645 |
int32 cost = 0; |
|
2646 |
||
2647 |
do { |
|
540
2987d7976ea2
(svn r924) Use RailVehInfo() instead of &_rail_vehicle_info[]
tron
parents:
534
diff
changeset
|
2648 |
const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); |
0 | 2649 |
if (rvi->running_cost_base) |
2650 |
cost += rvi->running_cost_base * _price.running_rail[rvi->engclass]; |
|
2651 |
} while ( (v=v->next) != NULL ); |
|
2652 |
||
2653 |
return cost; |
|
2654 |
} |
|
2655 |
||
2656 |
void OnNewDay_Train(Vehicle *v) |
|
2657 |
{ |
|
2658 |
TileIndex tile; |
|
2659 |
||
2660 |
if ((++v->day_counter & 7) == 0) |
|
2661 |
DecreaseVehicleValue(v); |
|
2662 |
||
2663 |
if (v->subtype == 0) { |
|
2664 |
CheckVehicleBreakdown(v); |
|
2665 |
AgeVehicle(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2666 |
|
0 | 2667 |
CheckIfTrainNeedsService(v); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2668 |
|
0 | 2669 |
// check if train hasn't advanced in its order list for a set number of days |
2670 |
if (_patches.lost_train_days && v->num_orders && !(v->vehstatus & VS_STOPPED) && ++v->u.rail.days_since_order_progr >= _patches.lost_train_days && v->owner == _local_player) { |
|
2671 |
v->u.rail.days_since_order_progr = 0; |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
2672 |
SetDParam(0, v->unitnumber); |
0 | 2673 |
AddNewsItem( |
2674 |
STR_TRAIN_IS_LOST, |
|
2675 |
NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), |
|
2676 |
v->index, |
|
2677 |
0); |
|
2678 |
} |
|
2679 |
||
19
6080d2b6a959
(svn r20) Feature: warning when a vehicle has invalid orders (celestar)
dominik
parents:
15
diff
changeset
|
2680 |
CheckOrders(v); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2681 |
|
0 | 2682 |
/* update destination */ |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2683 |
if (v->current_order.type == OT_GOTO_STATION && |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2684 |
(tile = DEREF_STATION(v->current_order.station)->train_tile) != 0) |
0 | 2685 |
v->dest_tile = tile; |
2686 |
||
2687 |
if ((v->vehstatus & VS_STOPPED) == 0) { |
|
2688 |
/* running costs */ |
|
2689 |
int32 cost = GetTrainRunningCost(v) / 364; |
|
2690 |
||
2691 |
v->profit_this_year -= cost >> 8; |
|
2692 |
||
2693 |
SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN); |
|
2694 |
SubtractMoneyFromPlayerFract(v->owner, cost); |
|
2695 |
||
2696 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
2697 |
InvalidateWindow(WC_TRAINS_LIST, v->owner); |
|
2698 |
} |
|
2699 |
} |
|
2700 |
} |
|
2701 |
||
2702 |
void TrainsYearlyLoop() |
|
2703 |
{ |
|
2704 |
Vehicle *v; |
|
2705 |
||
2706 |
FOR_ALL_VEHICLES(v) { |
|
2707 |
if (v->type == VEH_Train && v->subtype == 0) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
166
diff
changeset
|
2708 |
|
0 | 2709 |
// show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) |
2710 |
if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) { |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
2711 |
SetDParam(1, v->profit_this_year); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
2712 |
SetDParam(0, v->unitnumber); |
0 | 2713 |
AddNewsItem( |
2714 |
STR_TRAIN_IS_UNPROFITABLE, |
|
2715 |
NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), |
|
2716 |
v->index, |
|
2717 |
0); |
|
2718 |
} |
|
2719 |
||
2720 |
v->profit_last_year = v->profit_this_year; |
|
2721 |
v->profit_this_year = 0; |
|
2722 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
2723 |
} |
|
2724 |
} |
|
2725 |
} |
|
2726 |
||
2727 |
extern void ShowTrainViewWindow(Vehicle *v); |
|
2728 |
||
2729 |
void HandleClickOnTrain(Vehicle *v) |
|
2730 |
{ |
|
2731 |
if (v->subtype != 0) v = GetFirstVehicleInChain(v); |
|
2732 |
ShowTrainViewWindow(v); |
|
2733 |
} |
|
2734 |
||
2735 |
void InitializeTrains() |
|
2736 |
{ |
|
2737 |
_age_cargo_skip_counter = 1; |
|
2738 |
} |
|
2739 |
||
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2740 |
int ScheduleHasDepotOrders(const Order *schedule) |
0 | 2741 |
{ |
555
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2742 |
for (; schedule->type != OT_NOTHING; schedule++) |
02df8a1b7f33
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
2743 |
if (schedule->type == OT_GOTO_DEPOT) |
0 | 2744 |
return true; |
2745 |
return false; |
|
2746 |
} |