author | celestar |
Sat, 13 Nov 2004 18:01:33 +0000 | |
changeset 378 | 9f170b63d48e |
parent 374 | 85a6d56129dd |
child 445 | 0e3fa3da3899 |
permissions | -rw-r--r-- |
0 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
3 |
#include "vehicle.h" |
|
4 |
#include "engine.h" |
|
5 |
#include "command.h" |
|
6 |
#include "station.h" |
|
7 |
#include "news.h" |
|
8 |
#include "gfx.h" |
|
9 |
#include "pathfind.h" |
|
10 |
#include "player.h" |
|
337
66647f97e7c0
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
241
diff
changeset
|
11 |
#include "sound.h" |
0 | 12 |
|
13 |
void ShowRoadVehViewWindow(Vehicle *v); |
|
14 |
||
15 |
static const uint16 _roadveh_images[63] = { |
|
16 |
0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14, |
|
17 |
0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74, |
|
18 |
0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C, |
|
19 |
0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC, |
|
20 |
0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC, |
|
21 |
0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4, |
|
22 |
0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C, |
|
23 |
0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4 |
|
24 |
}; |
|
25 |
||
26 |
static const uint16 _roadveh_full_adder[63] = { |
|
27 |
0, 88, 0, 0, 0, 0, 48, 48, |
|
28 |
48, 48, 0, 0, 64, 64, 0, 16, |
|
29 |
16, 0, 88, 0, 0, 0, 0, 48, |
|
30 |
48, 48, 48, 0, 0, 64, 64, 0, |
|
31 |
16, 16, 0, 88, 0, 0, 0, 0, |
|
32 |
48, 48, 48, 48, 0, 0, 64, 64, |
|
33 |
0, 16, 16, 0, 8, 8, 8, 8, |
|
34 |
0, 0, 0, 8, 8, 8, 8 |
|
35 |
}; |
|
36 |
||
37 |
||
38 |
static const uint16 _road_veh_fp_ax_or[4] = { |
|
39 |
0x100,0x200,1,2, |
|
40 |
}; |
|
41 |
||
42 |
static const uint16 _road_veh_fp_ax_and[4] = { |
|
43 |
0x1009, 0x16, 0x520, 0x2A00 |
|
44 |
}; |
|
45 |
||
46 |
static const byte _road_reverse_table[4] = { |
|
47 |
6, 7, 14, 15 |
|
48 |
}; |
|
49 |
||
50 |
static const uint16 _road_pf_table_3[4] = { |
|
51 |
0x910, 0x1600, 0x2005, 0x2A |
|
52 |
}; |
|
53 |
||
54 |
int GetRoadVehImage(Vehicle *v, byte direction) |
|
55 |
{ |
|
56 |
int img = v->spritenum; |
|
57 |
int image; |
|
58 |
||
59 |
if (is_custom_sprite(img)) { |
|
60 |
image = GetCustomVehicleSprite(v, direction); |
|
61 |
if (image) return image; |
|
62 |
img = _engine_original_sprites[v->engine_type]; |
|
63 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
64 |
|
0 | 65 |
image = direction + _roadveh_images[img]; |
66 |
if (v->cargo_count >= (v->cargo_cap >> 1)) |
|
67 |
image += _roadveh_full_adder[img]; |
|
68 |
return image; |
|
69 |
} |
|
70 |
||
71 |
void DrawRoadVehEngine(int x, int y, int engine, uint32 image_ormod) |
|
72 |
{ |
|
378
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
73 |
int spritenum = road_vehicle_info(engine)->image_index; |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
74 |
|
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
75 |
if (is_custom_sprite(spritenum)) { |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
76 |
int sprite = GetCustomVehicleIcon(engine, 6); |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
77 |
|
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
78 |
if (sprite) { |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
79 |
DrawSprite(sprite | image_ormod, x, y); |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
80 |
return; |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
81 |
} |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
82 |
spritenum = _engine_original_sprites[engine]; |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
83 |
} |
9f170b63d48e
(svn r567) -newgrf: Support for road vehicles customization (seems to work at
celestar
parents:
374
diff
changeset
|
84 |
DrawSprite((6 + _roadveh_images[spritenum]) | image_ormod, x, y); |
0 | 85 |
} |
86 |
||
87 |
void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw) |
|
88 |
{ |
|
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
89 |
SET_DPARAM32(0, ((_price.roadveh_base >> 3) * road_vehicle_info(engine)->base_cost) >> 5); |
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
90 |
SET_DPARAM16(1, road_vehicle_info(engine)->max_speed * 10 >> 5); |
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
91 |
SET_DPARAM32(2, road_vehicle_info(engine)->running_cost * _price.roadveh_running >> 8); |
0 | 92 |
|
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
93 |
SET_DPARAM16(4, road_vehicle_info(engine)->capacity); |
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
94 |
SET_DPARAM16(3, _cargoc.names_long_p[road_vehicle_info(engine)->cargo_type]); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
95 |
|
0 | 96 |
DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw); |
97 |
} |
|
98 |
||
99 |
static int32 EstimateRoadVehCost(byte engine_type) |
|
100 |
{ |
|
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
101 |
return ((_price.roadveh_base >> 3) * road_vehicle_info(engine_type)->base_cost) >> 5; |
0 | 102 |
} |
103 |
||
104 |
int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
105 |
{ |
|
106 |
int32 cost; |
|
107 |
Vehicle *v; |
|
108 |
byte unit_num; |
|
109 |
uint tile = TILE_FROM_XY(x,y); |
|
110 |
Engine *e; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
111 |
|
0 | 112 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
113 |
||
114 |
cost = EstimateRoadVehCost(p1); |
|
115 |
if (flags & DC_QUERY_COST) |
|
116 |
return cost; |
|
117 |
||
118 |
v = AllocateVehicle(); |
|
119 |
if (v == NULL || _ptr_to_next_order >= endof(_order_array)) |
|
120 |
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
121 |
||
122 |
/* find the first free roadveh id */ |
|
123 |
unit_num = GetFreeUnitNumber(VEH_Road); |
|
124 |
if (unit_num > _patches.max_roadveh) |
|
125 |
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
126 |
||
127 |
if (flags & DC_EXEC) { |
|
128 |
v->unitnumber = unit_num; |
|
129 |
v->direction = 0; |
|
130 |
v->owner = _current_player; |
|
131 |
||
132 |
v->tile = tile; |
|
133 |
x = GET_TILE_X(tile)*16 + 8; |
|
134 |
y = GET_TILE_Y(tile)*16 + 8; |
|
135 |
v->x_pos = x; |
|
136 |
v->y_pos = y; |
|
137 |
v->z_pos = GetSlopeZ(x,y); |
|
138 |
v->z_height = 6; |
|
139 |
||
140 |
v->u.road.state = 254; |
|
141 |
v->vehstatus = VS_HIDDEN|VS_STOPPED|VS_DEFPAL; |
|
142 |
||
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
143 |
v->spritenum = road_vehicle_info(p1)->image_index; |
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
144 |
v->cargo_type = road_vehicle_info(p1)->cargo_type; |
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
145 |
v->cargo_cap = road_vehicle_info(p1)->capacity; |
0 | 146 |
// v->cargo_count = 0; |
147 |
v->value = cost; |
|
148 |
// v->day_counter = 0; |
|
149 |
// v->next_order_param = v->next_order = 0; |
|
150 |
// v->load_unload_time_rem = 0; |
|
151 |
// v->progress = 0; |
|
152 |
||
153 |
// v->u.road.unk2 = 0; |
|
154 |
// v->u.road.overtaking = 0; |
|
155 |
||
156 |
v->last_station_visited = 0xFF; |
|
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
157 |
v->max_speed = road_vehicle_info(p1)->max_speed; |
0 | 158 |
v->engine_type = (byte)p1; |
159 |
||
160 |
e = &_engines[p1]; |
|
161 |
v->reliability = e->reliability; |
|
162 |
v->reliability_spd_dec = e->reliability_spd_dec; |
|
163 |
v->max_age = e->lifelength * 366; |
|
164 |
_new_roadveh_id = v->index; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
165 |
|
0 | 166 |
v->string_id = STR_SV_ROADVEH_NAME; |
167 |
*(v->schedule_ptr = _ptr_to_next_order++) = 0; |
|
168 |
||
169 |
v->service_interval = _patches.servint_roadveh; |
|
170 |
||
171 |
v->date_of_last_service = _date; |
|
172 |
v->build_year = _cur_year; |
|
173 |
||
174 |
v->type = VEH_Road; |
|
175 |
v->cur_image = 0xC15; |
|
176 |
||
177 |
VehiclePositionChanged(v); |
|
178 |
||
179 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->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
|
180 |
_vehicle_sort_dirty[VEHROAD] = true; // build a new bus/truck |
0 | 181 |
InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
182 |
InvalidateWindow(WC_COMPANY, v->owner); |
|
183 |
} |
|
184 |
||
185 |
return cost; |
|
186 |
} |
|
187 |
||
188 |
// p1 = vehicle |
|
189 |
int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
190 |
{ |
|
191 |
Vehicle *v; |
|
192 |
||
193 |
v = &_vehicles[p1]; |
|
194 |
||
195 |
if (v->type != VEH_Road || !CheckOwnership(v->owner)) |
|
196 |
return CMD_ERROR; |
|
197 |
||
198 |
if (flags & DC_EXEC) { |
|
199 |
v->vehstatus ^= VS_STOPPED; |
|
200 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
201 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
202 |
} |
|
203 |
||
204 |
return 0; |
|
205 |
} |
|
206 |
||
207 |
int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
208 |
{ |
|
209 |
Vehicle *v; |
|
210 |
||
211 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
212 |
|
0 | 213 |
v = &_vehicles[p1]; |
214 |
||
215 |
if (v->type != VEH_Road || !CheckOwnership(v->owner)) |
|
216 |
return CMD_ERROR; |
|
217 |
||
218 |
if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) |
|
219 |
return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
220 |
|
0 | 221 |
if (flags & DC_EXEC) { |
222 |
// Invalidate depot |
|
223 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->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
|
224 |
_vehicle_sort_dirty[VEHROAD] = true; // sell a bus/truck |
0 | 225 |
InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
226 |
InvalidateWindow(WC_COMPANY, v->owner); |
|
227 |
DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
|
228 |
DeleteVehicle(v); |
|
229 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
230 |
|
0 | 231 |
return -(int32)v->value; |
232 |
} |
|
233 |
||
234 |
typedef struct RoadFindDepotData { |
|
235 |
uint best_length; |
|
236 |
uint tile; |
|
237 |
byte owner; |
|
238 |
} RoadFindDepotData; |
|
239 |
||
240 |
||
241 |
static const TileIndexDiff _road_find_sig_dir_mod[4] = { |
|
242 |
TILE_XY(-1,0), |
|
243 |
TILE_XY(0,1), |
|
244 |
TILE_XY(1,0), |
|
245 |
TILE_XY(0,-1), |
|
246 |
}; |
|
247 |
||
248 |
static const byte _road_pf_directions[16] = { |
|
249 |
0, 1, 0, 1, 2, 1, 255, 255, |
|
250 |
2, 3, 3, 2, 3, 0, 255, 255, |
|
251 |
}; |
|
252 |
||
253 |
static bool EnumRoadSignalFindDepot(uint tile, RoadFindDepotData *rfdd, int track, uint length, byte *state) |
|
254 |
{ |
|
255 |
tile += _road_find_sig_dir_mod[_road_pf_directions[track]]; |
|
256 |
||
257 |
if (IS_TILETYPE(tile, MP_STREET) && |
|
258 |
(_map5[tile] & 0xF0) == 0x20 && |
|
259 |
_map_owner[tile] == rfdd->owner) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
260 |
|
0 | 261 |
if (length < rfdd->best_length) { |
262 |
rfdd->best_length = length; |
|
263 |
rfdd->tile = tile; |
|
264 |
} |
|
265 |
} |
|
266 |
return false; |
|
267 |
} |
|
268 |
||
269 |
static int FindClosestRoadDepot(Vehicle *v) |
|
270 |
{ |
|
271 |
uint tile = v->tile; |
|
272 |
int i; |
|
273 |
RoadFindDepotData rfdd; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
274 |
|
0 | 275 |
if (v->u.road.state == 255) { tile = GetVehicleOutOfTunnelTile(v); } |
276 |
||
277 |
rfdd.owner = v->owner; |
|
278 |
rfdd.best_length = (uint)-1; |
|
279 |
||
280 |
/* search in all directions */ |
|
281 |
for(i=0; i!=4; i++) |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
282 |
FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, i, (TPFEnumProc*)EnumRoadSignalFindDepot, NULL, &rfdd); |
0 | 283 |
|
284 |
if (rfdd.best_length == (uint)-1) |
|
285 |
return -1; |
|
286 |
||
287 |
return GetDepotByTile(rfdd.tile); |
|
288 |
} |
|
289 |
||
290 |
int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
291 |
{ |
|
292 |
Vehicle *v = &_vehicles[p1]; |
|
293 |
int depot; |
|
294 |
||
295 |
if (v->type != VEH_Road || !CheckOwnership(v->owner)) |
|
296 |
return CMD_ERROR; |
|
297 |
||
298 |
if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { |
|
299 |
if (flags & DC_EXEC) { |
|
300 |
if (v->next_order & OF_UNLOAD) |
|
301 |
v->cur_order_index++; |
|
302 |
v->next_order = OT_DUMMY; |
|
303 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
304 |
} |
|
305 |
return 0; |
|
306 |
} |
|
307 |
||
308 |
depot = FindClosestRoadDepot(v); |
|
309 |
if (depot < 0) |
|
310 |
return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); |
|
311 |
||
312 |
if (flags & DC_EXEC) { |
|
313 |
v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; |
|
314 |
v->next_order_param = (byte)depot; |
|
315 |
v->dest_tile = _depots[depot].xy; |
|
316 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
317 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
318 |
|
0 | 319 |
return 0; |
320 |
} |
|
321 |
||
322 |
int32 CmdTurnRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
323 |
{ |
|
324 |
Vehicle *v; |
|
325 |
||
326 |
v = &_vehicles[p1]; |
|
327 |
||
328 |
if (v->type != VEH_Road || !CheckOwnership(v->owner)) |
|
329 |
return CMD_ERROR; |
|
330 |
||
331 |
if (v->vehstatus & (VS_HIDDEN|VS_STOPPED) || |
|
332 |
v->u.road.crashed_ctr != 0 || |
|
333 |
v->breakdown_ctr != 0 || |
|
334 |
v->u.road.overtaking != 0 || |
|
335 |
v->cur_speed < 5) { |
|
336 |
_error_message = STR_EMPTY; |
|
337 |
return CMD_ERROR; |
|
338 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
339 |
|
0 | 340 |
if (flags & DC_EXEC) { |
341 |
v->u.road.reverse_ctr = 180; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
342 |
} |
0 | 343 |
|
344 |
return 0; |
|
345 |
} |
|
346 |
||
347 |
int32 CmdChangeRoadVehServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
348 |
{ |
|
349 |
Vehicle *v; |
|
350 |
||
351 |
v = &_vehicles[p1]; |
|
352 |
||
353 |
if (v->type != VEH_Road || !CheckOwnership(v->owner)) |
|
354 |
return CMD_ERROR; |
|
355 |
||
356 |
if (flags & DC_EXEC) { |
|
357 |
v->service_interval = (uint16)p2; |
|
358 |
InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 7); |
|
359 |
} |
|
360 |
||
361 |
return 0; |
|
362 |
} |
|
363 |
||
364 |
||
365 |
static void MarkRoadVehDirty(Vehicle *v) |
|
366 |
{ |
|
367 |
v->cur_image = GetRoadVehImage(v, v->direction); |
|
368 |
MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
|
369 |
} |
|
370 |
||
371 |
static void UpdateRoadVehDeltaXY(Vehicle *v) |
|
372 |
{ |
|
373 |
#define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) |
|
374 |
static const uint32 _delta_xy_table[8] = { |
|
375 |
MKIT(3, 3, -1, -1), |
|
376 |
MKIT(3, 7, -1, -3), |
|
377 |
MKIT(3, 3, -1, -1), |
|
378 |
MKIT(7, 3, -3, -1), |
|
379 |
MKIT(3, 3, -1, -1), |
|
380 |
MKIT(3, 7, -1, -3), |
|
381 |
MKIT(3, 3, -1, -1), |
|
382 |
MKIT(7, 3, -3, -1), |
|
383 |
}; |
|
384 |
#undef MKIT |
|
385 |
uint32 x = _delta_xy_table[v->direction]; |
|
386 |
v->x_offs = (byte)x; |
|
387 |
v->y_offs = (byte)(x>>=8); |
|
388 |
v->sprite_width = (byte)(x>>=8); |
|
389 |
v->sprite_height = (byte)(x>>=8); |
|
390 |
} |
|
391 |
||
392 |
static void ClearCrashedStation(Vehicle *v) |
|
393 |
{ |
|
394 |
uint tile = v->tile; |
|
395 |
Station *st = DEREF_STATION(_map2[tile]); |
|
396 |
byte *b, bb; |
|
397 |
||
398 |
b = (_map5[tile] >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status; |
|
399 |
||
400 |
bb = *b; |
|
401 |
||
402 |
// mark station as not busy |
|
403 |
bb &= ~0x80; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
404 |
|
0 | 405 |
// free parking bay |
406 |
bb |= (v->u.road.state&0x02)?2:1; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
407 |
|
0 | 408 |
*b = bb; |
409 |
} |
|
410 |
||
411 |
static void RoadVehDelete(Vehicle *v) |
|
412 |
{ |
|
413 |
DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
|
414 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
415 |
|
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
|
416 |
_vehicle_sort_dirty[VEHROAD] = true; // delete bus/truck (eg. crash for example) |
0 | 417 |
InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
418 |
InvalidateWindow(WC_COMPANY, v->owner); |
|
419 |
||
420 |
if(IS_TILETYPE(v->tile, MP_STATION)) |
|
421 |
ClearCrashedStation(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
422 |
|
0 | 423 |
BeginVehicleMove(v); |
424 |
EndVehicleMove(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
425 |
|
0 | 426 |
DeleteVehicle(v); |
427 |
} |
|
428 |
||
429 |
static byte SetRoadVehPosition(Vehicle *v, int x, int y) |
|
430 |
{ |
|
431 |
byte new_z, old_z; |
|
432 |
||
433 |
// need this hint so it returns the right z coordinate on bridges. |
|
434 |
_get_z_hint = v->z_pos; |
|
435 |
new_z = GetSlopeZ(v->x_pos=x, v->y_pos=y); |
|
436 |
_get_z_hint = 0; |
|
437 |
||
438 |
old_z = v->z_pos; |
|
439 |
v->z_pos = new_z; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
440 |
|
0 | 441 |
VehiclePositionChanged(v); |
442 |
EndVehicleMove(v); |
|
443 |
return old_z; |
|
444 |
} |
|
445 |
||
446 |
static void RoadVehSetRandomDirection(Vehicle *v) |
|
447 |
{ |
|
448 |
static const int8 _turn_prob[4] = { -1, 0, 0, 1 }; |
|
449 |
uint32 r = Random(); |
|
450 |
v->direction = (v->direction+_turn_prob[r&3])&7; |
|
451 |
BeginVehicleMove(v); |
|
452 |
UpdateRoadVehDeltaXY(v); |
|
453 |
v->cur_image = GetRoadVehImage(v, v->direction); |
|
454 |
SetRoadVehPosition(v, v->x_pos, v->y_pos); |
|
455 |
} |
|
456 |
||
457 |
static void RoadVehIsCrashed(Vehicle *v) |
|
458 |
{ |
|
459 |
v->u.road.crashed_ctr++; |
|
460 |
if (v->u.road.crashed_ctr == 2) { |
|
461 |
CreateEffectVehicleRel(v,4,4,8,EV_CRASHED_SMOKE); |
|
462 |
} else if (v->u.road.crashed_ctr <= 45) { |
|
463 |
if ((v->tick_counter&7)==0) |
|
464 |
RoadVehSetRandomDirection(v); |
|
465 |
} else if (v->u.road.crashed_ctr >= 2220) { |
|
466 |
RoadVehDelete(v); |
|
467 |
} |
|
468 |
} |
|
469 |
||
470 |
static void *EnumCheckRoadVehCrashTrain(Vehicle *v, Vehicle *u) |
|
471 |
{ |
|
472 |
if (v->type != VEH_Train || |
|
473 |
myabs(v->z_pos - u->z_pos) > 6 || |
|
474 |
myabs(v->x_pos - u->x_pos) > 4 || |
|
475 |
myabs(v->y_pos - u->y_pos) > 4) |
|
476 |
return NULL; |
|
477 |
return v; |
|
478 |
} |
|
479 |
||
480 |
static void RoadVehCrash(Vehicle *v) |
|
481 |
{ |
|
482 |
uint16 pass; |
|
483 |
||
484 |
v->u.road.crashed_ctr++; |
|
485 |
v->vehstatus |= VS_CRASHED; |
|
486 |
||
487 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
488 |
||
489 |
pass = 1; |
|
490 |
if (v->cargo_type == 0) |
|
491 |
pass += v->cargo_count; |
|
492 |
v->cargo_count = 0; |
|
493 |
SET_DPARAM16(0, pass); |
|
494 |
||
495 |
AddNewsItem(STR_9031_ROAD_VEHICLE_CRASH_DRIVER+(pass!=1), |
|
496 |
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), |
|
497 |
v->index, |
|
498 |
0); |
|
499 |
||
500 |
ModifyStationRatingAround(v->tile, v->owner, -160, 22); |
|
501 |
SndPlayVehicleFx(16, v); |
|
502 |
} |
|
503 |
||
504 |
static void RoadVehCheckTrainCrash(Vehicle *v) |
|
505 |
{ |
|
506 |
uint tile; |
|
507 |
||
508 |
if (v->u.road.state == 255) |
|
509 |
return; |
|
510 |
||
511 |
tile = v->tile; |
|
512 |
||
513 |
// Make sure it's a road/rail crossing |
|
514 |
if (!IS_TILETYPE(tile, MP_STREET) || |
|
515 |
(_map5[tile] & 0xF0) != 0x10) |
|
516 |
return; |
|
517 |
||
518 |
if (VehicleFromPos(tile, v, (VehicleFromPosProc*)EnumCheckRoadVehCrashTrain) != NULL) |
|
519 |
RoadVehCrash(v); |
|
520 |
} |
|
521 |
||
522 |
static void HandleBrokenRoadVeh(Vehicle *v) |
|
523 |
{ |
|
524 |
if (v->breakdown_ctr != 1) { |
|
525 |
v->breakdown_ctr = 1; |
|
526 |
v->cur_speed = 0; |
|
527 |
||
528 |
if (v->breakdowns_since_last_service != 255) |
|
529 |
v->breakdowns_since_last_service++; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
530 |
|
0 | 531 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
532 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
533 |
|
0 | 534 |
SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? 0xD : 0x34, v); |
535 |
||
536 |
if (!(v->vehstatus & VS_HIDDEN)) { |
|
537 |
Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); |
|
538 |
if (u) |
|
539 |
u->u.special.unk0 = v->breakdown_delay * 2; |
|
540 |
} |
|
541 |
} |
|
542 |
||
543 |
if (!(v->tick_counter & 1)) { |
|
544 |
if (!--v->breakdown_delay) { |
|
545 |
v->breakdown_ctr = 0; |
|
546 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
|
547 |
} |
|
548 |
} |
|
549 |
} |
|
550 |
||
551 |
static void ProcessRoadVehOrder(Vehicle *v) |
|
552 |
{ |
|
553 |
uint order; |
|
554 |
Station *st; |
|
555 |
||
556 |
if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { |
|
557 |
// Let a depot order in the schedule interrupt. |
|
558 |
if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) |
|
559 |
return; |
|
560 |
} |
|
561 |
||
562 |
if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && |
|
156
8fef5e5752d6
(svn r157) -Feature: [1009708] Percent-based service intervals. Send a vehicle to depot after it has lost X% of its reliability (mivlad)
darkvater
parents:
76
diff
changeset
|
563 |
SERVICE_INTERVAL ) { |
0 | 564 |
v->cur_order_index++; |
565 |
} |
|
566 |
||
567 |
if (v->cur_order_index >= v->num_orders) |
|
568 |
v->cur_order_index = 0; |
|
569 |
||
570 |
order = v->schedule_ptr[v->cur_order_index]; |
|
571 |
||
572 |
if (order == 0) { |
|
573 |
v->next_order = OT_NOTHING; |
|
574 |
v->dest_tile = 0; |
|
575 |
return; |
|
576 |
} |
|
577 |
||
578 |
if (order == (uint)((v->next_order | (v->next_order_param<<8)))) |
|
579 |
return; |
|
580 |
||
581 |
v->next_order = (byte)order; |
|
582 |
v->next_order_param = (byte)(order >> 8); |
|
583 |
||
584 |
v->dest_tile = 0; |
|
585 |
||
586 |
if ((order & OT_MASK) == OT_GOTO_STATION) { |
|
587 |
if ( (byte)(order >> 8) == v->last_station_visited) |
|
588 |
v->last_station_visited = 0xFF; |
|
589 |
st = DEREF_STATION(order >> 8); |
|
590 |
v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile; |
|
591 |
} else if ((order & OT_MASK) == OT_GOTO_DEPOT) { |
|
592 |
v->dest_tile = _depots[order >> 8].xy; |
|
593 |
} |
|
594 |
||
595 |
InvalidateVehicleOrderWidget(v); |
|
596 |
} |
|
597 |
||
598 |
static void HandleRoadVehLoading(Vehicle *v) |
|
599 |
{ |
|
600 |
if (v->next_order == OT_NOTHING) |
|
601 |
return; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
602 |
|
0 | 603 |
if (v->next_order != OT_DUMMY) { |
604 |
if ((v->next_order&OT_MASK) != OT_LOADING) |
|
605 |
return; |
|
606 |
||
607 |
if (--v->load_unload_time_rem) |
|
608 |
return; |
|
609 |
||
610 |
if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { |
|
611 |
SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); |
|
612 |
if (LoadUnloadVehicle(v)) { |
|
613 |
InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
614 |
MarkRoadVehDirty(v); |
|
615 |
} |
|
616 |
return; |
|
617 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
618 |
|
0 | 619 |
{ |
620 |
byte b = v->next_order; |
|
621 |
v->next_order = OT_LEAVESTATION; |
|
622 |
if (!(b & OF_NON_STOP)) |
|
623 |
return; |
|
624 |
} |
|
625 |
} |
|
626 |
||
627 |
v->cur_order_index++; |
|
628 |
InvalidateVehicleOrderWidget(v); |
|
629 |
} |
|
630 |
||
631 |
static void StartRoadVehSound(Vehicle *v) |
|
632 |
{ |
|
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
633 |
int s = road_vehicle_info(v->engine_type)->sfx; |
0 | 634 |
if (s == 23 && (v->tick_counter&3) == 0) s++; |
635 |
SndPlayVehicleFx(s, v); |
|
636 |
} |
|
637 |
||
638 |
typedef struct RoadVehFindData { |
|
639 |
int x,y; |
|
640 |
Vehicle *veh; |
|
641 |
byte dir; |
|
642 |
} RoadVehFindData; |
|
643 |
||
644 |
void *EnumCheckRoadVehClose(Vehicle *v, RoadVehFindData *rvf) |
|
645 |
{ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
646 |
static const short _dists[] = { |
63
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
647 |
-4, -8, -4, -1, 4, 8, 4, 1, |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
648 |
-4, -1, 4, 8, 4, 1, -4, -8, |
0 | 649 |
}; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
650 |
|
63
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
651 |
short x_diff = v->x_pos - rvf->x; |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
652 |
short y_diff = v->y_pos - rvf->y; |
0 | 653 |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
654 |
if (rvf->veh == v || |
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
655 |
v->type != VEH_Road || |
0 | 656 |
v->u.road.state == 254 || |
657 |
myabs(v->z_pos - rvf->veh->z_pos) > 6 || |
|
658 |
v->direction != rvf->dir || |
|
63
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
659 |
(_dists[v->direction] < 0 && (x_diff <= _dists[v->direction] || x_diff > 0)) || |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
660 |
(_dists[v->direction] > 0 && (x_diff >= _dists[v->direction] || x_diff < 0)) || |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
661 |
(_dists[v->direction+8] < 0 && (y_diff <= _dists[v->direction+8] || y_diff > 0)) || |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
662 |
(_dists[v->direction+8] > 0 && (y_diff >= _dists[v->direction+8] || y_diff < 0))) |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
663 |
return NULL; |
0 | 664 |
|
665 |
return v; |
|
666 |
} |
|
667 |
||
668 |
static Vehicle *RoadVehFindCloseTo(Vehicle *v, int x, int y, byte dir) |
|
669 |
{ |
|
670 |
RoadVehFindData rvf; |
|
671 |
Vehicle *u; |
|
672 |
||
673 |
if (v->u.road.reverse_ctr != 0) |
|
674 |
return NULL; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
675 |
|
0 | 676 |
rvf.x = x; |
677 |
rvf.y = y; |
|
678 |
rvf.dir = dir; |
|
679 |
rvf.veh = v; |
|
680 |
u = VehicleFromPos(TILE_FROM_XY(x,y), &rvf, (VehicleFromPosProc*)EnumCheckRoadVehClose); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
681 |
|
63
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
682 |
// This code protects a roadvehicle from being blocked for ever |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
683 |
// If more then 1480 / 74 days a road vehicle is blocked, it will |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
684 |
// drive just through it. The ultimate backup-code of TTD. |
53cc59601b3c
(svn r64) Fix: Road vehicles don't get stuck any more (Truelight + Celestar
dominik
parents:
19
diff
changeset
|
685 |
// It can be disabled. |
0 | 686 |
if (u == NULL) { |
687 |
v->u.road.unk2 = 0; |
|
688 |
return NULL; |
|
689 |
} |
|
690 |
||
691 |
if (++v->u.road.unk2 > 1480) |
|
692 |
return NULL; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
693 |
|
0 | 694 |
return u; |
695 |
} |
|
696 |
||
697 |
static void RoadVehArrivesAt(Vehicle *v, Station *st) |
|
698 |
{ |
|
699 |
if (v->engine_type < 123) { |
|
700 |
/* Check if station was ever visited before */ |
|
701 |
if (!(st->had_vehicle_of_type & HVOT_BUS)) { |
|
702 |
uint32 flags; |
|
703 |
||
704 |
st->had_vehicle_of_type |= HVOT_BUS; |
|
705 |
SET_DPARAM16(0, st->index); |
|
706 |
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); |
|
707 |
AddNewsItem( |
|
708 |
STR_902F_CITIZENS_CELEBRATE_FIRST, |
|
709 |
flags, |
|
710 |
v->index, |
|
711 |
0); |
|
712 |
} |
|
713 |
} else { |
|
714 |
/* Check if station was ever visited before */ |
|
715 |
if (!(st->had_vehicle_of_type & HVOT_TRUCK)) { |
|
716 |
uint32 flags; |
|
717 |
||
718 |
st->had_vehicle_of_type |= HVOT_TRUCK; |
|
719 |
SET_DPARAM16(0, st->index); |
|
720 |
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); |
|
721 |
AddNewsItem( |
|
722 |
STR_9030_CITIZENS_CELEBRATE_FIRST, |
|
723 |
flags, |
|
724 |
v->index, |
|
725 |
0); |
|
726 |
} |
|
727 |
} |
|
728 |
} |
|
729 |
||
730 |
static bool RoadVehAccelerate(Vehicle *v) |
|
731 |
{ |
|
732 |
uint spd = v->cur_speed + 1 + ((v->u.road.overtaking != 0)?1:0); |
|
733 |
byte t; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
734 |
|
0 | 735 |
// Clamp |
736 |
spd = min(spd, v->max_speed); |
|
737 |
||
738 |
//updates statusbar only if speed have changed to save CPU time |
|
739 |
if (spd != v->cur_speed) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
740 |
v->cur_speed = spd; |
0 | 741 |
if (_patches.vehicle_speed) |
742 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
743 |
} |
|
744 |
||
745 |
// Decrease somewhat when turning |
|
746 |
if (!(v->direction&1)) |
|
747 |
spd = spd * 3 >> 2; |
|
748 |
||
749 |
if (spd == 0) |
|
750 |
return false; |
|
751 |
||
752 |
if ((byte)++spd == 0) |
|
753 |
return true; |
|
754 |
||
755 |
v->progress = (t = v->progress) - (byte)spd; |
|
756 |
||
757 |
return (t < v->progress); |
|
758 |
} |
|
759 |
||
760 |
static byte RoadVehGetNewDirection(Vehicle *v, int x, int y) |
|
761 |
{ |
|
762 |
static const byte _roadveh_new_dir[11] = { |
|
763 |
0, 7, 6, 0, |
|
764 |
1, 0, 5, 0, |
|
765 |
2, 3, 4 |
|
766 |
}; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
767 |
|
0 | 768 |
x = x - v->x_pos + 1; |
769 |
y = y - v->y_pos + 1; |
|
770 |
||
771 |
if ((uint)x > 2 || (uint)y > 2) |
|
772 |
return v->direction; |
|
773 |
return _roadveh_new_dir[y*4+x]; |
|
774 |
} |
|
775 |
||
776 |
static byte RoadVehGetSlidingDirection(Vehicle *v, int x, int y) |
|
777 |
{ |
|
778 |
byte b = RoadVehGetNewDirection(v,x,y); |
|
779 |
byte d = v->direction; |
|
780 |
if (b == d) return d; |
|
781 |
d = (d+1)&7; |
|
782 |
if (b==d) return d; |
|
783 |
d = (d-2)&7; |
|
784 |
if (b==d) return d; |
|
785 |
if (b==((d-1)&7)) return d; |
|
786 |
if (b==((d-2)&7)) return d; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
787 |
return (d+2)&7; |
0 | 788 |
} |
789 |
||
790 |
typedef struct OvertakeData { |
|
791 |
Vehicle *u, *v; |
|
792 |
uint tile; |
|
793 |
byte tilebits; |
|
794 |
} OvertakeData; |
|
795 |
||
796 |
void *EnumFindVehToOvertake(Vehicle *v, OvertakeData *od) |
|
797 |
{ |
|
798 |
if (v->tile != (TileIndex)od->tile || |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
799 |
v->type != VEH_Road || |
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
800 |
v == od->u || |
0 | 801 |
v == od->v) |
802 |
return NULL; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
803 |
return v; |
0 | 804 |
} |
805 |
||
806 |
static bool FindRoadVehToOvertake(OvertakeData *od) |
|
807 |
{ |
|
808 |
uint32 bits; |
|
809 |
||
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
810 |
bits = GetTileTrackStatus(od->tile, TRANSPORT_ROAD)&0x3F; |
0 | 811 |
|
812 |
if (!(od->tilebits & bits) || (bits&0x3C) || (bits & 0x3F3F0000)) |
|
813 |
return true; |
|
814 |
return VehicleFromPos(od->tile, od, (VehicleFromPosProc*)EnumFindVehToOvertake) != NULL; |
|
815 |
} |
|
816 |
||
817 |
static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u) |
|
818 |
{ |
|
819 |
OvertakeData od; |
|
820 |
byte tt; |
|
821 |
||
822 |
od.v = v; |
|
823 |
od.u = u; |
|
824 |
||
825 |
if (u->max_speed >= v->max_speed && |
|
826 |
!(u->vehstatus&VS_STOPPED) && |
|
827 |
u->cur_speed != 0) |
|
828 |
return; |
|
829 |
||
830 |
if (v->direction != u->direction || !(v->direction&1)) |
|
831 |
return; |
|
832 |
||
833 |
if (v->u.road.state >= 32 || (v->u.road.state&7) > 1 ) |
|
834 |
return; |
|
835 |
||
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
836 |
tt = (byte)(GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F); |
0 | 837 |
if ((tt & 3) == 0) |
838 |
return; |
|
839 |
if ((tt & 0x3C) != 0) |
|
840 |
return; |
|
841 |
||
842 |
if (tt == 3) { |
|
843 |
tt = (v->direction&2)?2:1; |
|
844 |
} |
|
845 |
od.tilebits = tt; |
|
846 |
||
847 |
od.tile = v->tile; |
|
848 |
if (FindRoadVehToOvertake(&od)) |
|
849 |
return; |
|
850 |
||
851 |
od.tile = v->tile + _tileoffs_by_dir[v->direction>>1]; |
|
852 |
if (FindRoadVehToOvertake(&od)) |
|
853 |
return; |
|
854 |
||
855 |
if (od.u->cur_speed == 0 || od.u->vehstatus&VS_STOPPED) { |
|
856 |
v->u.road.overtaking_ctr = 0x11; |
|
857 |
v->u.road.overtaking = 0x10; |
|
858 |
} else { |
|
859 |
// if (FindRoadVehToOvertake(&od)) |
|
860 |
// return; |
|
861 |
v->u.road.overtaking_ctr = 0; |
|
862 |
v->u.road.overtaking = 0x10; |
|
863 |
} |
|
864 |
} |
|
865 |
||
866 |
static void RoadZPosAffectSpeed(Vehicle *v, byte old_z) |
|
867 |
{ |
|
868 |
if (old_z == v->z_pos) |
|
869 |
return; |
|
870 |
||
871 |
if (old_z < v->z_pos) { |
|
872 |
v->cur_speed = v->cur_speed * 232 >> 8; |
|
873 |
} else { |
|
874 |
uint16 spd = v->cur_speed + 2; |
|
875 |
if (spd <= v->max_speed) |
|
876 |
v->cur_speed = spd; |
|
877 |
} |
|
878 |
} |
|
879 |
||
880 |
static int PickRandomBit(uint bits) |
|
881 |
{ |
|
882 |
uint num = 0; |
|
883 |
uint b = bits; |
|
884 |
uint i; |
|
885 |
||
886 |
do { |
|
887 |
if (b & 1) |
|
888 |
num++; |
|
889 |
} while (b >>= 1); |
|
890 |
||
891 |
num = ((uint16)Random() * num >> 16); |
|
892 |
||
893 |
for(i=0; !((bits & 1) && ((int)--num) < 0); bits>>=1,i++); |
|
894 |
return i; |
|
895 |
} |
|
896 |
||
897 |
typedef struct { |
|
898 |
TileIndex dest; |
|
899 |
uint maxtracklen; |
|
900 |
uint mindist; |
|
901 |
} FindRoadToChooseData; |
|
902 |
||
903 |
static bool EnumRoadTrackFindDist(uint tile, FindRoadToChooseData *frd, int track, uint length, byte *state) |
|
904 |
{ |
|
905 |
uint dist = GetTileDist(tile, frd->dest); |
|
906 |
if (dist <= frd->mindist) { |
|
907 |
if (dist != frd->mindist || length < frd->maxtracklen) { |
|
908 |
frd->maxtracklen = length; |
|
909 |
} |
|
910 |
frd->mindist = dist; |
|
911 |
} |
|
912 |
return false; |
|
913 |
} |
|
914 |
||
915 |
// Returns direction to choose |
|
916 |
// or -1 if the direction is currently blocked |
|
917 |
static int RoadFindPathToDest(Vehicle *v, uint tile, int direction) |
|
918 |
{ |
|
919 |
#define return_track(x) {best_track = x; goto found_best_track; } |
|
920 |
||
921 |
uint16 signal; |
|
922 |
uint bitmask; |
|
923 |
uint desttile; |
|
924 |
FindRoadToChooseData frd; |
|
925 |
int best_track; |
|
926 |
uint best_dist, best_maxlen; |
|
927 |
uint i; |
|
928 |
byte m5; |
|
929 |
||
930 |
{ |
|
931 |
uint32 r; |
|
241
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
932 |
r = GetTileTrackStatus(tile, TRANSPORT_ROAD); |
0 | 933 |
signal = (uint16)(r >> 16); |
934 |
bitmask = (uint16)r; |
|
935 |
} |
|
936 |
||
241
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
937 |
if (IS_TILETYPE(tile, MP_STREET)) { |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
938 |
if ((_map5[tile]&0xF0) == 0x20 && v->owner == _map_owner[tile]) |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
939 |
/* Road crossing */ |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
940 |
bitmask |= _road_veh_fp_ax_or[_map5[tile]&3]; |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
941 |
} else if (IS_TILETYPE(tile, MP_STATION)) { |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
942 |
if (_map_owner[tile] == OWNER_NONE || _map_owner[tile] == v->owner) { |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
943 |
/* Our station */ |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
944 |
Station *st = DEREF_STATION(_map2[tile]); |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
945 |
byte val = _map5[tile]; |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
946 |
if (v->cargo_type != CT_PASSENGERS) { |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
947 |
if (IS_BYTE_INSIDE(val, 0x43, 0x47) && (_patches.roadveh_queue || st->truck_stop_status&3)) |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
948 |
bitmask |= _road_veh_fp_ax_or[(val-0x43)&3]; |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
949 |
} else { |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
950 |
if (IS_BYTE_INSIDE(val, 0x47, 0x4B) && (_patches.roadveh_queue || st->bus_stop_status&3)) |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
951 |
bitmask |= _road_veh_fp_ax_or[(val-0x47)&3]; |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
952 |
} |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
953 |
} |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
954 |
} |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
955 |
/* The above lookups should be moved to GetTileTrackStatus in the |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
956 |
* future, but that requires more changes to the pathfinder and other |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
957 |
* stuff, probably even more arguments to GTTS. |
e6e62a5e7f52
(svn r242) -Fix: Pathfinding bug for road vehicles introduced in r160 fixed (blathijs)
darkvater
parents:
193
diff
changeset
|
958 |
*/ |
0 | 959 |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
960 |
/* remove unreachable tracks */ |
0 | 961 |
bitmask &= _road_veh_fp_ax_and[direction]; |
962 |
if (bitmask == 0) { |
|
963 |
// reverse |
|
964 |
return_track(_road_reverse_table[direction]); |
|
965 |
} |
|
966 |
||
967 |
if (v->u.road.reverse_ctr != 0) { |
|
968 |
v->u.road.reverse_ctr = 0; |
|
969 |
if (v->tile != (TileIndex)tile) { |
|
970 |
return_track(_road_reverse_table[direction]); |
|
971 |
} |
|
972 |
} |
|
973 |
||
974 |
desttile = v->dest_tile; |
|
975 |
if (desttile == 0) { |
|
976 |
// Pick a random direction |
|
977 |
return_track(PickRandomBit(bitmask)); |
|
978 |
} |
|
979 |
||
980 |
// Only one direction to choose between? |
|
981 |
if (!(bitmask & (bitmask - 1))) { |
|
982 |
return_track(FindFirstBit2x64(bitmask)); |
|
983 |
} |
|
984 |
||
985 |
if (IS_TILETYPE(desttile, MP_STREET)) { |
|
986 |
m5 = _map5[desttile]; |
|
987 |
if ((m5&0xF0) == 0x20) |
|
988 |
goto do_it; |
|
989 |
} else if (IS_TILETYPE(desttile, MP_STATION)) { |
|
990 |
m5 = _map5[desttile]; |
|
991 |
if (IS_BYTE_INSIDE(m5, 0x43, 0x4B)) { |
|
992 |
m5 -= 0x43; |
|
993 |
do_it:; |
|
994 |
desttile += _tileoffs_by_dir[m5&3]; |
|
995 |
if (desttile == tile && bitmask&_road_pf_table_3[m5&3]) { |
|
996 |
return_track(FindFirstBit2x64(bitmask&_road_pf_table_3[m5&3])); |
|
997 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
998 |
} |
0 | 999 |
} |
1000 |
// do pathfind |
|
1001 |
frd.dest = desttile; |
|
1002 |
||
1003 |
best_track = -1; |
|
1004 |
best_dist = (uint)-1; |
|
1005 |
best_maxlen = (uint)-1; |
|
1006 |
i = 0; |
|
1007 |
do { |
|
1008 |
if (bitmask & 1) { |
|
1009 |
if (best_track == -1) best_track = i; // in case we don't find the path, just pick a direction |
|
1010 |
frd.maxtracklen = (uint)-1; |
|
1011 |
frd.mindist = (uint)-1; |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
1012 |
FollowTrack(tile, 0x3000 | TRANSPORT_ROAD, _road_pf_directions[i], (TPFEnumProc*)EnumRoadTrackFindDist, NULL, &frd); |
0 | 1013 |
|
1014 |
if (frd.mindist < best_dist || (frd.mindist==best_dist && frd.maxtracklen < best_maxlen)) { |
|
1015 |
best_dist = frd.mindist; |
|
1016 |
best_maxlen = frd.maxtracklen; |
|
1017 |
best_track = i; |
|
1018 |
} |
|
1019 |
} |
|
1020 |
} while (++i,(bitmask>>=1) != 0); |
|
1021 |
||
1022 |
found_best_track:; |
|
1023 |
||
1024 |
if (HASBIT(signal, best_track)) |
|
1025 |
return -1; |
|
1026 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1027 |
return best_track; |
0 | 1028 |
} |
1029 |
||
1030 |
typedef struct RoadDriveEntry { |
|
1031 |
byte x,y; |
|
1032 |
} RoadDriveEntry; |
|
1033 |
||
1034 |
#include "table/roadveh.h" |
|
1035 |
||
1036 |
static const byte _road_veh_data_1[] = { |
|
1037 |
20, 20, 16, 16, 0, 0, 0, 0, |
|
1038 |
19, 19, 15, 15, 0, 0, 0, 0, |
|
1039 |
16, 16, 12, 12, 0, 0, 0, 0, |
|
1040 |
15, 15, 11, 11 |
|
1041 |
}; |
|
1042 |
||
1043 |
static const byte _roadveh_data_2[4] = { 0,1,8,9 }; |
|
1044 |
||
1045 |
static void RoadVehEventHandler(Vehicle *v) |
|
1046 |
{ |
|
1047 |
GetNewVehiclePosResult gp; |
|
1048 |
byte new_dir,old_dir,old_order; |
|
1049 |
RoadDriveEntry rd; |
|
1050 |
int x,y; |
|
1051 |
Station *st; |
|
1052 |
uint32 r; |
|
1053 |
Vehicle *u; |
|
1054 |
||
1055 |
// decrease counters |
|
1056 |
v->tick_counter++; |
|
1057 |
if (v->u.road.reverse_ctr != 0) |
|
1058 |
v->u.road.reverse_ctr--; |
|
1059 |
||
1060 |
// handle crashed |
|
1061 |
if (v->u.road.crashed_ctr != 0) { |
|
1062 |
RoadVehIsCrashed(v); |
|
1063 |
return; |
|
1064 |
} |
|
1065 |
||
1066 |
RoadVehCheckTrainCrash(v); |
|
1067 |
||
1068 |
// road vehicle has broken down? |
|
1069 |
if (v->breakdown_ctr != 0) { |
|
1070 |
if (v->breakdown_ctr <= 2) { |
|
1071 |
HandleBrokenRoadVeh(v); |
|
1072 |
return; |
|
1073 |
} |
|
1074 |
v->breakdown_ctr--; |
|
1075 |
} |
|
1076 |
||
1077 |
// exit if vehicle is stopped |
|
1078 |
if (v->vehstatus & VS_STOPPED) |
|
1079 |
return; |
|
1080 |
||
1081 |
ProcessRoadVehOrder(v); |
|
1082 |
HandleRoadVehLoading(v); |
|
1083 |
||
1084 |
if ((v->next_order & OT_MASK) == OT_LOADING) |
|
1085 |
return; |
|
1086 |
||
1087 |
if (v->u.road.state == 254) { |
|
1088 |
int dir; |
|
1089 |
const RoadDriveEntry*rdp; |
|
1090 |
byte rd2; |
|
1091 |
||
1092 |
v->cur_speed = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1093 |
|
0 | 1094 |
dir = _map5[v->tile]&3; |
1095 |
v->direction = dir*2+1; |
|
1096 |
||
1097 |
rd2 = _roadveh_data_2[dir]; |
|
1098 |
rdp = _road_drive_data[(_opt.road_side<<4) + rd2]; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1099 |
|
0 | 1100 |
x = GET_TILE_X(v->tile)*16 + (rdp[6].x&0xF); |
1101 |
y = GET_TILE_Y(v->tile)*16 + (rdp[6].y&0xF); |
|
1102 |
||
1103 |
if (RoadVehFindCloseTo(v,x,y,v->direction)) |
|
1104 |
return; |
|
1105 |
||
1106 |
StartRoadVehSound(v); |
|
1107 |
||
1108 |
BeginVehicleMove(v); |
|
1109 |
||
1110 |
v->vehstatus &= ~VS_HIDDEN; |
|
1111 |
v->u.road.state = rd2; |
|
1112 |
v->u.road.frame = 6; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1113 |
|
0 | 1114 |
v->cur_image = GetRoadVehImage(v, v->direction); |
1115 |
UpdateRoadVehDeltaXY(v); |
|
1116 |
SetRoadVehPosition(v,x,y); |
|
1117 |
||
1118 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
1119 |
return; |
|
1120 |
} |
|
1121 |
||
1122 |
if (!RoadVehAccelerate(v)) |
|
1123 |
return; |
|
1124 |
||
1125 |
if (v->u.road.overtaking != 0) { |
|
1126 |
if (++v->u.road.overtaking_ctr >= 35) |
|
1127 |
v->u.road.overtaking = 0; |
|
1128 |
} |
|
1129 |
||
1130 |
BeginVehicleMove(v); |
|
1131 |
||
1132 |
if (v->u.road.state == 255) { |
|
1133 |
GetNewVehiclePos(v, &gp); |
|
1134 |
||
1135 |
if (RoadVehFindCloseTo(v, gp.x, gp.y, v->direction)) { |
|
1136 |
v->cur_speed = 0; |
|
1137 |
return; |
|
1138 |
} |
|
1139 |
||
1140 |
if (IS_TILETYPE(gp.new_tile, MP_TUNNELBRIDGE) && |
|
1141 |
(_map5[gp.new_tile]&0xF0) == 0 && |
|
1142 |
(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)&4)) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1143 |
|
0 | 1144 |
//new_dir = RoadGetNewDirection(v, gp.x, gp.y) |
1145 |
v->cur_image = GetRoadVehImage(v, v->direction); |
|
1146 |
UpdateRoadVehDeltaXY(v); |
|
1147 |
SetRoadVehPosition(v,gp.x,gp.y); |
|
1148 |
return; |
|
1149 |
} |
|
1150 |
||
1151 |
v->x_pos = gp.x; |
|
1152 |
v->y_pos = gp.y; |
|
1153 |
VehiclePositionChanged(v); |
|
1154 |
return; |
|
1155 |
} |
|
1156 |
||
1157 |
rd = _road_drive_data[(v->u.road.state + (_opt.road_side<<4)) ^ v->u.road.overtaking][v->u.road.frame+1]; |
|
1158 |
||
1159 |
// switch to another tile |
|
1160 |
if (rd.x & 0x80) { |
|
1161 |
uint tile = v->tile + _tileoffs_by_dir[rd.x&3]; |
|
1162 |
int dir = RoadFindPathToDest(v, tile, rd.x&3); |
|
1163 |
int tmp; |
|
1164 |
uint32 r; |
|
1165 |
byte newdir; |
|
1166 |
const RoadDriveEntry *rdp; |
|
1167 |
||
1168 |
if (dir == -1) { |
|
1169 |
v->cur_speed = 0; |
|
1170 |
return; |
|
1171 |
} |
|
1172 |
||
1173 |
again: |
|
1174 |
if ((dir & 7) >= 6) { |
|
1175 |
tile = v->tile; |
|
1176 |
} |
|
1177 |
||
1178 |
tmp = (dir+(_opt.road_side<<4))^v->u.road.overtaking; |
|
1179 |
rdp = _road_drive_data[tmp]; |
|
1180 |
||
1181 |
tmp &= ~0x10; |
|
1182 |
||
1183 |
x = GET_TILE_X(tile)*16 + rdp[0].x; |
|
1184 |
y = GET_TILE_Y(tile)*16 + rdp[0].y; |
|
1185 |
||
1186 |
if (RoadVehFindCloseTo(v, x, y, newdir=RoadVehGetSlidingDirection(v, x, y))) |
|
1187 |
return; |
|
1188 |
||
1189 |
r = VehicleEnterTile(v, tile, x, y); |
|
1190 |
if (r & 8) { |
|
1191 |
if (!IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { |
|
1192 |
v->cur_speed = 0; |
|
1193 |
return; |
|
1194 |
} |
|
1195 |
dir = _road_reverse_table[rd.x&3]; |
|
1196 |
goto again; |
|
1197 |
} |
|
1198 |
||
1199 |
if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IS_TILETYPE(v->tile, MP_STATION)) { |
|
1200 |
if ((tmp&7) >= 6) { v->cur_speed = 0; return; } |
|
1201 |
if (IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x4B)) { |
|
1202 |
Station *st = DEREF_STATION(_map2[v->tile]); |
|
1203 |
byte *b; |
|
1204 |
||
1205 |
if (_map5[v->tile] >= 0x47) { |
|
1206 |
b = &st->bus_stop_status; |
|
1207 |
} else { |
|
1208 |
b = &st->truck_stop_status; |
|
1209 |
} |
|
1210 |
*b = (*b | ((v->u.road.state&2)?2:1)) & 0x7F; |
|
1211 |
} |
|
1212 |
} |
|
1213 |
||
1214 |
if (!(r & 4)) { |
|
1215 |
v->tile = tile; |
|
1216 |
v->u.road.state = (byte)tmp; |
|
1217 |
v->u.road.frame = 0; |
|
1218 |
} |
|
1219 |
if (newdir != v->direction) { |
|
1220 |
v->direction = newdir; |
|
1221 |
v->cur_speed -= v->cur_speed >> 2; |
|
1222 |
} |
|
1223 |
||
1224 |
v->cur_image = GetRoadVehImage(v, newdir); |
|
1225 |
UpdateRoadVehDeltaXY(v); |
|
1226 |
RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
|
1227 |
return; |
|
1228 |
} |
|
1229 |
||
1230 |
if (rd.x & 0x40) { |
|
1231 |
int dir = RoadFindPathToDest(v, v->tile, rd.x&3); |
|
1232 |
uint32 r; |
|
1233 |
int tmp; |
|
1234 |
byte newdir; |
|
1235 |
const RoadDriveEntry *rdp; |
|
1236 |
||
1237 |
if (dir == -1) { |
|
1238 |
v->cur_speed = 0; |
|
1239 |
return; |
|
1240 |
} |
|
1241 |
||
1242 |
tmp = (_opt.road_side<<4) + dir; |
|
1243 |
rdp = _road_drive_data[tmp]; |
|
1244 |
||
1245 |
x = GET_TILE_X(v->tile)*16 + rdp[1].x; |
|
1246 |
y = GET_TILE_Y(v->tile)*16 + rdp[1].y; |
|
1247 |
||
1248 |
if (RoadVehFindCloseTo(v, x, y, newdir=RoadVehGetSlidingDirection(v, x, y))) |
|
1249 |
return; |
|
1250 |
||
1251 |
r = VehicleEnterTile(v, v->tile, x, y); |
|
1252 |
if (r & 8) { |
|
1253 |
v->cur_speed = 0; |
|
1254 |
return; |
|
1255 |
} |
|
1256 |
||
1257 |
v->u.road.state = tmp & ~16; |
|
1258 |
v->u.road.frame = 1; |
|
1259 |
||
1260 |
if (newdir != v->direction) { |
|
1261 |
v->direction = newdir; |
|
1262 |
v->cur_speed -= v->cur_speed >> 2; |
|
1263 |
} |
|
1264 |
||
1265 |
v->cur_image = GetRoadVehImage(v, newdir); |
|
1266 |
UpdateRoadVehDeltaXY(v); |
|
1267 |
RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
|
1268 |
return; |
|
1269 |
} |
|
1270 |
||
1271 |
x = (v->x_pos&~15)+(rd.x&15); |
|
1272 |
y = (v->y_pos&~15)+(rd.y&15); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1273 |
|
0 | 1274 |
new_dir = RoadVehGetSlidingDirection(v, x, y); |
1275 |
||
1276 |
if (!IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && (u=RoadVehFindCloseTo(v, x, y, new_dir)) != NULL) { |
|
1277 |
if (v->u.road.overtaking == 0) |
|
1278 |
RoadVehCheckOvertake(v, u); |
|
1279 |
return; |
|
1280 |
} |
|
1281 |
||
1282 |
old_dir = v->direction; |
|
1283 |
if (new_dir != old_dir) { |
|
1284 |
v->direction = new_dir; |
|
1285 |
v->cur_speed -= (v->cur_speed >> 2); |
|
1286 |
if (old_dir != v->u.road.state) { |
|
1287 |
v->cur_image = GetRoadVehImage(v, new_dir); |
|
1288 |
UpdateRoadVehDeltaXY(v); |
|
1289 |
SetRoadVehPosition(v, v->x_pos, v->y_pos); |
|
1290 |
return; |
|
1291 |
} |
|
1292 |
} |
|
1293 |
||
1294 |
if (v->u.road.state >= 0x20 && |
|
1295 |
_road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) { |
|
1296 |
byte *b; |
|
1297 |
||
1298 |
st = DEREF_STATION(_map2[v->tile]); |
|
1299 |
b = IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x47) ? &st->truck_stop_status : &st->bus_stop_status; |
|
1300 |
||
1301 |
if ( (v->next_order&OT_MASK) != OT_LEAVESTATION && |
|
1302 |
(v->next_order&OT_MASK) != OT_GOTO_DEPOT) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1303 |
|
0 | 1304 |
*b &= ~0x80; |
1305 |
||
1306 |
v->last_station_visited = _map2[v->tile]; |
|
1307 |
||
1308 |
RoadVehArrivesAt(v, st); |
|
1309 |
||
1310 |
old_order = v->next_order; |
|
1311 |
v->next_order = OT_LOADING; |
|
1312 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1313 |
if ((old_order & OT_MASK) == OT_GOTO_STATION && |
0 | 1314 |
v->next_order_param == v->last_station_visited) { |
1315 |
v->next_order = OT_LOADING | OF_NON_STOP | (old_order & (OF_FULL_LOAD|OF_UNLOAD)); |
|
1316 |
} |
|
1317 |
||
1318 |
SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); |
|
1319 |
if (LoadUnloadVehicle(v)) { |
|
1320 |
InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
1321 |
MarkRoadVehDirty(v); |
|
1322 |
} |
|
1323 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
1324 |
return; |
|
1325 |
} |
|
1326 |
||
1327 |
if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) { |
|
1328 |
if (*b&0x80) { |
|
1329 |
v->cur_speed = 0; |
|
1330 |
return; |
|
1331 |
} |
|
1332 |
v->next_order = 0; |
|
1333 |
} |
|
1334 |
*b |= 0x80; |
|
1335 |
||
1336 |
StartRoadVehSound(v); |
|
1337 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
1338 |
} |
|
1339 |
||
1340 |
r = VehicleEnterTile(v, v->tile, x, y); |
|
1341 |
if (r & 8) { |
|
1342 |
v->cur_speed = 0; |
|
1343 |
return; |
|
1344 |
} |
|
1345 |
||
1346 |
if ((r & 4) == 0) { |
|
1347 |
v->u.road.frame++; |
|
1348 |
} |
|
1349 |
||
1350 |
v->cur_image = GetRoadVehImage(v, v->direction); |
|
1351 |
UpdateRoadVehDeltaXY(v); |
|
1352 |
RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
|
1353 |
} |
|
1354 |
||
1355 |
void RoadVehEnterDepot(Vehicle *v) |
|
1356 |
{ |
|
1357 |
byte t; |
|
1358 |
||
1359 |
v->u.road.state = 254; |
|
1360 |
v->vehstatus |= VS_HIDDEN; |
|
1361 |
||
1362 |
v->date_of_last_service = _date; |
|
1363 |
v->breakdowns_since_last_service = 0; |
|
1364 |
v->reliability = _engines[v->engine_type].reliability; |
|
1365 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
1366 |
||
1367 |
MaybeRenewVehicle(v, EstimateRoadVehCost(v->engine_type)); |
|
1368 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1369 |
|
0 | 1370 |
if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { |
1371 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1372 |
|
0 | 1373 |
t = v->next_order; |
1374 |
v->next_order = OT_DUMMY; |
|
1375 |
||
1376 |
// Part of the schedule? |
|
1377 |
if (t & OF_UNLOAD) { v->cur_order_index++; } |
|
1378 |
||
1379 |
else if (t & OF_FULL_LOAD) { |
|
1380 |
v->vehstatus |= VS_STOPPED; |
|
1381 |
if (v->owner == _local_player) { |
|
1382 |
SET_DPARAM16(0, v->unitnumber); |
|
1383 |
AddNewsItem( |
|
1384 |
STR_9016_ROAD_VEHICLE_IS_WAITING, |
|
1385 |
NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), |
|
1386 |
v->index, |
|
1387 |
0); |
|
1388 |
} |
|
1389 |
} |
|
1390 |
} |
|
1391 |
||
1392 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
1393 |
} |
|
1394 |
||
1395 |
static void AgeRoadVehCargo(Vehicle *v) |
|
1396 |
{ |
|
1397 |
if (_age_cargo_skip_counter != 0) |
|
1398 |
return; |
|
1399 |
if (v->cargo_days != 255) |
|
1400 |
v->cargo_days++; |
|
1401 |
} |
|
1402 |
||
1403 |
void RoadVeh_Tick(Vehicle *v) |
|
1404 |
{ |
|
1405 |
AgeRoadVehCargo(v); |
|
1406 |
RoadVehEventHandler(v); |
|
1407 |
} |
|
1408 |
||
1409 |
static void CheckIfRoadVehNeedsService(Vehicle *v) |
|
1410 |
{ |
|
1411 |
int i; |
|
1412 |
||
76
30511cbc5188
(svn r77) -Fix: [1010788] AI service interval bug (tnx truesatan)
truelight
parents:
63
diff
changeset
|
1413 |
if (_patches.servint_roadveh == 0) |
11
836bc4b37b5b
(svn r12) Change: removed patch no_train_service. Instead you can set the default service interval for any vehicle type to 'disabled'.
dominik
parents:
0
diff
changeset
|
1414 |
return; |
836bc4b37b5b
(svn r12) Change: removed patch no_train_service. Instead you can set the default service interval for any vehicle type to 'disabled'.
dominik
parents:
0
diff
changeset
|
1415 |
|
156
8fef5e5752d6
(svn r157) -Feature: [1009708] Percent-based service intervals. Send a vehicle to depot after it has lost X% of its reliability (mivlad)
darkvater
parents:
76
diff
changeset
|
1416 |
if (SERVICE_INTERVAL) |
0 | 1417 |
return; |
1418 |
||
1419 |
if (v->vehstatus & VS_STOPPED) |
|
1420 |
return; |
|
1421 |
||
76
30511cbc5188
(svn r77) -Fix: [1010788] AI service interval bug (tnx truesatan)
truelight
parents:
63
diff
changeset
|
1422 |
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) |
0 | 1423 |
return; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1424 |
|
0 | 1425 |
// Don't interfere with a depot visit scheduled by the user, or a |
1426 |
// depot visit by the order list. |
|
1427 |
if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && |
|
1428 |
(v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) != 0) |
|
1429 |
return; |
|
1430 |
||
1431 |
i = FindClosestRoadDepot(v); |
|
1432 |
||
1433 |
if (i < 0 || GetTileDist(v->tile, (&_depots[i])->xy) > 12) { |
|
1434 |
if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { |
|
1435 |
v->next_order = OT_DUMMY; |
|
1436 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
1437 |
} |
|
1438 |
return; |
|
1439 |
} |
|
1440 |
||
1441 |
if (v->next_order == (OT_GOTO_DEPOT | OF_NON_STOP) && !CHANCE16(1,20)) |
|
1442 |
return; |
|
1443 |
||
1444 |
v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; |
|
1445 |
v->next_order_param = (byte)i; |
|
1446 |
v->dest_tile = (&_depots[i])->xy; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1447 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
0 | 1448 |
} |
1449 |
||
1450 |
void OnNewDay_RoadVeh(Vehicle *v) |
|
1451 |
{ |
|
1452 |
int32 cost; |
|
1453 |
Station *st; |
|
1454 |
uint tile; |
|
1455 |
||
1456 |
if ((++v->day_counter & 7) == 0) |
|
1457 |
DecreaseVehicleValue(v); |
|
1458 |
||
1459 |
if (v->u.road.unk2 == 0) |
|
1460 |
CheckVehicleBreakdown(v); |
|
1461 |
||
1462 |
AgeVehicle(v); |
|
1463 |
CheckIfRoadVehNeedsService(v); |
|
1464 |
||
19
6080d2b6a959
(svn r20) Feature: warning when a vehicle has invalid orders (celestar)
dominik
parents:
11
diff
changeset
|
1465 |
CheckOrders(v); |
6080d2b6a959
(svn r20) Feature: warning when a vehicle has invalid orders (celestar)
dominik
parents:
11
diff
changeset
|
1466 |
|
0 | 1467 |
/* update destination */ |
1468 |
if ((v->next_order & OT_MASK) == OT_GOTO_STATION) { |
|
1469 |
st = DEREF_STATION(v->next_order_param); |
|
1470 |
if ((tile=(v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile)) != 0) |
|
1471 |
v->dest_tile = tile; |
|
1472 |
} |
|
1473 |
||
1474 |
if (v->vehstatus & VS_STOPPED) |
|
1475 |
return; |
|
1476 |
||
374
85a6d56129dd
(svn r562) newgrf: Merge most of the road vehicle info to a single
celestar
parents:
337
diff
changeset
|
1477 |
cost = road_vehicle_info(v->engine_type)->running_cost * _price.roadveh_running / 364; |
0 | 1478 |
|
1479 |
v->profit_this_year -= cost >> 8; |
|
1480 |
||
1481 |
SET_EXPENSES_TYPE(EXPENSES_ROADVEH_RUN); |
|
1482 |
SubtractMoneyFromPlayerFract(v->owner, cost); |
|
1483 |
||
1484 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
1485 |
InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
1486 |
} |
|
1487 |
||
1488 |
void HandleClickOnRoadVeh(Vehicle *v) |
|
1489 |
{ |
|
1490 |
ShowRoadVehViewWindow(v); |
|
1491 |
} |
|
1492 |
||
1493 |
void RoadVehiclesYearlyLoop() |
|
1494 |
{ |
|
1495 |
Vehicle *v; |
|
1496 |
||
1497 |
FOR_ALL_VEHICLES(v) { |
|
1498 |
if (v->type == VEH_Road) { |
|
1499 |
v->profit_last_year = v->profit_this_year; |
|
1500 |
v->profit_this_year = 0; |
|
1501 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
1502 |
} |
|
1503 |
} |
|
1504 |
} |
|
1505 |