branch | NewGRF_ports |
changeset 6720 | 35756db7e577 |
parent 6719 | 4cc327ad39d5 |
child 6725 | 23339968083f |
6719:4cc327ad39d5 | 6720:35756db7e577 |
---|---|
12 #include "station_map.h" |
12 #include "station_map.h" |
13 #include "table/strings.h" |
13 #include "table/strings.h" |
14 #include "map.h" |
14 #include "map.h" |
15 #include "tile.h" |
15 #include "tile.h" |
16 #include "vehicle.h" |
16 #include "vehicle.h" |
17 #include "timetable.h" |
|
17 #include "engine.h" |
18 #include "engine.h" |
18 #include "command.h" |
19 #include "command.h" |
19 #include "station.h" |
20 #include "station.h" |
20 #include "news.h" |
21 #include "news.h" |
21 #include "pathfind.h" |
22 #include "pathfind.h" |
25 #include "depot.h" |
26 #include "depot.h" |
26 #include "bridge.h" |
27 #include "bridge.h" |
27 #include "tunnel_map.h" |
28 #include "tunnel_map.h" |
28 #include "bridge_map.h" |
29 #include "bridge_map.h" |
29 #include "vehicle_gui.h" |
30 #include "vehicle_gui.h" |
31 #include "articulated_vehicles.h" |
|
30 #include "newgrf_callbacks.h" |
32 #include "newgrf_callbacks.h" |
31 #include "newgrf_engine.h" |
33 #include "newgrf_engine.h" |
32 #include "newgrf_text.h" |
34 #include "newgrf_text.h" |
33 #include "newgrf_sound.h" |
35 #include "newgrf_sound.h" |
34 #include "yapf/yapf.h" |
36 #include "yapf/yapf.h" |
81 /** Converts the exit direction of a depot to trackdir the vehicle is going to drive to */ |
83 /** Converts the exit direction of a depot to trackdir the vehicle is going to drive to */ |
82 static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = { |
84 static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = { |
83 TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW |
85 TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW |
84 }; |
86 }; |
85 |
87 |
86 int GetRoadVehImage(const Vehicle* v, Direction direction) |
88 int RoadVehicle::GetImage(Direction direction) const |
87 { |
89 { |
88 int img = v->spritenum; |
90 int img = this->spritenum; |
89 int image; |
91 int image; |
90 |
92 |
91 if (is_custom_sprite(img)) { |
93 if (is_custom_sprite(img)) { |
92 image = GetCustomVehicleSprite(v, direction); |
94 image = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(img))); |
93 if (image != 0) return image; |
95 if (image != 0) return image; |
94 img = orig_road_vehicle_info[v->engine_type - ROAD_ENGINES_INDEX].image_index; |
96 img = orig_road_vehicle_info[this->engine_type - ROAD_ENGINES_INDEX].image_index; |
95 } |
97 } |
96 |
98 |
97 image = direction + _roadveh_images[img]; |
99 image = direction + _roadveh_images[img]; |
98 if (v->cargo_count >= v->cargo_cap / 2) image += _roadveh_full_adder[img]; |
100 if (this->cargo.Count() >= this->cargo_cap / 2U) image += _roadveh_full_adder[img]; |
99 return image; |
101 return image; |
100 } |
102 } |
101 |
103 |
102 void DrawRoadVehEngine(int x, int y, EngineID engine, SpriteID pal) |
104 void DrawRoadVehEngine(int x, int y, EngineID engine, SpriteID pal) |
103 { |
105 { |
113 spritenum = orig_road_vehicle_info[engine - ROAD_ENGINES_INDEX].image_index; |
115 spritenum = orig_road_vehicle_info[engine - ROAD_ENGINES_INDEX].image_index; |
114 } |
116 } |
115 DrawSprite(6 + _roadveh_images[spritenum], pal, x, y); |
117 DrawSprite(6 + _roadveh_images[spritenum], pal, x, y); |
116 } |
118 } |
117 |
119 |
118 static int32 EstimateRoadVehCost(EngineID engine_type) |
120 static CommandCost EstimateRoadVehCost(EngineID engine_type) |
119 { |
121 { |
120 return ((_price.roadveh_base >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5; |
122 return CommandCost(((_price.roadveh_base >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5); |
123 } |
|
124 |
|
125 byte GetRoadVehLength(const Vehicle *v) |
|
126 { |
|
127 byte length = 8; |
|
128 |
|
129 uint16 veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v); |
|
130 if (veh_len != CALLBACK_FAILED) { |
|
131 length -= clamp(veh_len, 0, 7); |
|
132 } |
|
133 |
|
134 return length; |
|
135 } |
|
136 |
|
137 void RoadVehUpdateCache(Vehicle *v) |
|
138 { |
|
139 assert(v->type == VEH_ROAD); |
|
140 assert(IsRoadVehFront(v)); |
|
141 |
|
142 for (Vehicle *u = v; u != NULL; u = u->next) { |
|
143 /* Update the v->first cache. */ |
|
144 if (u->first == NULL) u->first = v; |
|
145 |
|
146 /* Update the 'first engine' */ |
|
147 u->u.road.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type; |
|
148 |
|
149 /* Update the length of the vehicle. */ |
|
150 u->u.road.cached_veh_length = GetRoadVehLength(u); |
|
151 } |
|
121 } |
152 } |
122 |
153 |
123 /** Build a road vehicle. |
154 /** Build a road vehicle. |
124 * @param tile tile of depot where road vehicle is built |
155 * @param tile tile of depot where road vehicle is built |
125 * @param flags operation to perform |
156 * @param flags operation to perform |
126 * @param p1 bus/truck type being built (engine) |
157 * @param p1 bus/truck type being built (engine) |
127 * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number |
158 * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number |
128 */ |
159 */ |
129 int32 CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
160 CommandCost CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
130 { |
161 { |
131 int32 cost; |
162 CommandCost cost; |
132 Vehicle *v; |
163 Vehicle *v; |
133 UnitID unit_num; |
164 UnitID unit_num; |
134 Engine *e; |
165 Engine *e; |
135 |
166 |
136 if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE); |
167 if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE); |
145 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
176 if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; |
146 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
177 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
147 |
178 |
148 if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE); |
179 if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE); |
149 |
180 |
150 v = AllocateVehicle(); |
181 uint num_vehicles = 1 + CountArticulatedParts(p1); |
151 if (v == NULL) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
182 |
183 /* Allow for the front and up to 10 articulated parts. */ |
|
184 Vehicle *vl[11]; |
|
185 memset(&vl, 0, sizeof(vl)); |
|
186 |
|
187 if (!AllocateVehicles(vl, num_vehicles)) { |
|
188 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
189 } |
|
190 |
|
191 v = vl[0]; |
|
152 |
192 |
153 /* find the first free roadveh id */ |
193 /* find the first free roadveh id */ |
154 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); |
194 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); |
155 if (unit_num > _patches.max_roadveh) |
195 if (unit_num > _patches.max_roadveh) |
156 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
196 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
160 int y; |
200 int y; |
161 |
201 |
162 const RoadVehicleInfo *rvi = RoadVehInfo(p1); |
202 const RoadVehicleInfo *rvi = RoadVehInfo(p1); |
163 |
203 |
164 v->unitnumber = unit_num; |
204 v->unitnumber = unit_num; |
165 v->direction = INVALID_DIR; |
205 v->direction = DiagDirToDir(GetRoadDepotDirection(tile)); |
166 v->owner = _current_player; |
206 v->owner = _current_player; |
167 |
207 |
168 v->tile = tile; |
208 v->tile = tile; |
169 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2; |
209 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2; |
170 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2; |
210 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2; |
178 v->spritenum = rvi->image_index; |
218 v->spritenum = rvi->image_index; |
179 v->cargo_type = rvi->cargo_type; |
219 v->cargo_type = rvi->cargo_type; |
180 v->cargo_subtype = 0; |
220 v->cargo_subtype = 0; |
181 v->cargo_cap = rvi->capacity; |
221 v->cargo_cap = rvi->capacity; |
182 // v->cargo_count = 0; |
222 // v->cargo_count = 0; |
183 v->value = cost; |
223 v->value = cost.GetCost(); |
184 // v->day_counter = 0; |
224 // v->day_counter = 0; |
185 // v->next_order_param = v->next_order = 0; |
225 // v->next_order_param = v->next_order = 0; |
186 // v->load_unload_time_rem = 0; |
226 // v->load_unload_time_rem = 0; |
187 // v->progress = 0; |
227 // v->progress = 0; |
188 |
228 |
190 // v->u.road.overtaking = 0; |
230 // v->u.road.overtaking = 0; |
191 |
231 |
192 v->last_station_visited = INVALID_STATION; |
232 v->last_station_visited = INVALID_STATION; |
193 v->max_speed = rvi->max_speed; |
233 v->max_speed = rvi->max_speed; |
194 v->engine_type = (byte)p1; |
234 v->engine_type = (byte)p1; |
195 |
|
196 v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; |
|
197 v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype); |
|
198 |
235 |
199 e = GetEngine(p1); |
236 e = GetEngine(p1); |
200 v->reliability = e->reliability; |
237 v->reliability = e->reliability; |
201 v->reliability_spd_dec = e->reliability_spd_dec; |
238 v->reliability_spd_dec = e->reliability_spd_dec; |
202 v->max_age = e->lifelength * 366; |
239 v->max_age = e->lifelength * 366; |
210 v->build_year = _cur_year; |
247 v->build_year = _cur_year; |
211 |
248 |
212 v = new (v) RoadVehicle(); |
249 v = new (v) RoadVehicle(); |
213 v->cur_image = 0xC15; |
250 v->cur_image = 0xC15; |
214 v->random_bits = VehicleRandomBits(); |
251 v->random_bits = VehicleRandomBits(); |
252 SetRoadVehFront(v); |
|
253 |
|
254 v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; |
|
255 v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype); |
|
256 v->u.road.cached_veh_length = GetRoadVehLength(v); |
|
215 |
257 |
216 v->vehicle_flags = 0; |
258 v->vehicle_flags = 0; |
217 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
259 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
218 |
260 |
261 v->first = NULL; |
|
219 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
262 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
263 |
|
264 AddArticulatedParts(vl, VEH_ROAD); |
|
220 |
265 |
221 VehiclePositionChanged(v); |
266 VehiclePositionChanged(v); |
222 |
267 |
223 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
268 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
224 RebuildVehicleLists(); |
269 RebuildVehicleLists(); |
225 InvalidateWindow(WC_COMPANY, v->owner); |
270 InvalidateWindow(WC_COMPANY, v->owner); |
226 if (IsLocalPlayer()) |
271 if (IsLocalPlayer()) |
227 InvalidateAutoreplaceWindow(VEH_ROAD); // updates the replace Road window |
272 InvalidateAutoreplaceWindow(VEH_ROAD, v->group_id); // updates the replace Road window |
228 |
273 |
229 GetPlayer(_current_player)->num_engines[p1]++; |
274 GetPlayer(_current_player)->num_engines[p1]++; |
230 } |
275 } |
231 |
276 |
232 return cost; |
277 return CommandCost(cost); |
233 } |
278 } |
234 |
279 |
235 /** Start/Stop a road vehicle. |
280 /** Start/Stop a road vehicle. |
236 * @param tile unused |
281 * @param tile unused |
237 * @param flags operation to perform |
282 * @param flags operation to perform |
238 * @param p1 road vehicle ID to start/stop |
283 * @param p1 road vehicle ID to start/stop |
239 * @param p2 unused |
284 * @param p2 unused |
240 */ |
285 */ |
241 int32 CmdStartStopRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
286 CommandCost CmdStartStopRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
242 { |
287 { |
243 Vehicle *v; |
288 Vehicle *v; |
244 uint16 callback; |
289 uint16 callback; |
245 |
290 |
246 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
291 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
266 v->cur_speed = 0; |
311 v->cur_speed = 0; |
267 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
312 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
268 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
313 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
269 } |
314 } |
270 |
315 |
271 return 0; |
316 return CommandCost(); |
272 } |
317 } |
273 |
318 |
274 void ClearSlot(Vehicle *v) |
319 void ClearSlot(Vehicle *v) |
275 { |
320 { |
276 RoadStop *rs = v->u.road.slot; |
321 RoadStop *rs = v->u.road.slot; |
281 |
326 |
282 assert(rs->num_vehicles != 0); |
327 assert(rs->num_vehicles != 0); |
283 rs->num_vehicles--; |
328 rs->num_vehicles--; |
284 |
329 |
285 DEBUG(ms, 3, "Clearing slot at 0x%X", rs->xy); |
330 DEBUG(ms, 3, "Clearing slot at 0x%X", rs->xy); |
331 } |
|
332 |
|
333 static bool CheckRoadVehInDepotStopped(const Vehicle *v) |
|
334 { |
|
335 TileIndex tile = v->tile; |
|
336 |
|
337 if (!IsTileDepotType(tile, TRANSPORT_ROAD) || !(v->vehstatus & VS_STOPPED)) return false; |
|
338 |
|
339 for (; v != NULL; v = v->next) { |
|
340 if (v->u.road.state != RVSB_IN_DEPOT || v->tile != tile) return false; |
|
341 } |
|
342 return true; |
|
286 } |
343 } |
287 |
344 |
288 /** Sell a road vehicle. |
345 /** Sell a road vehicle. |
289 * @param tile unused |
346 * @param tile unused |
290 * @param flags operation to perform |
347 * @param flags operation to perform |
291 * @param p1 vehicle ID to be sold |
348 * @param p1 vehicle ID to be sold |
292 * @param p2 unused |
349 * @param p2 unused |
293 */ |
350 */ |
294 int32 CmdSellRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
351 CommandCost CmdSellRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
295 { |
352 { |
296 Vehicle *v; |
353 Vehicle *v; |
297 |
354 |
298 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
355 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
299 |
356 |
301 |
358 |
302 if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR; |
359 if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR; |
303 |
360 |
304 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
361 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
305 |
362 |
306 if (!IsRoadVehInDepotStopped(v)) { |
363 if (!CheckRoadVehInDepotStopped(v)) { |
307 return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); |
364 return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); |
308 } |
365 } |
309 |
366 |
310 if (flags & DC_EXEC) { |
367 if (flags & DC_EXEC) { |
311 // Invalidate depot |
368 // Invalidate depot |
315 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
372 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
316 DeleteDepotHighlightOfVehicle(v); |
373 DeleteDepotHighlightOfVehicle(v); |
317 DeleteVehicle(v); |
374 DeleteVehicle(v); |
318 } |
375 } |
319 |
376 |
320 return -(int32)v->value; |
377 return CommandCost(-v->value); |
321 } |
378 } |
322 |
379 |
323 struct RoadFindDepotData { |
380 struct RoadFindDepotData { |
324 uint best_length; |
381 uint best_length; |
325 TileIndex tile; |
382 TileIndex tile; |
357 } else if (_patches.new_pathfinding_all) { |
414 } else if (_patches.new_pathfinding_all) { |
358 NPFFoundTargetData ftd; |
415 NPFFoundTargetData ftd; |
359 /* See where we are now */ |
416 /* See where we are now */ |
360 Trackdir trackdir = GetVehicleTrackdir(v); |
417 Trackdir trackdir = GetVehicleTrackdir(v); |
361 |
418 |
362 ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE); |
419 ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, v->tile, ReverseTrackdir(trackdir), TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE, 0); |
363 if (ftd.best_bird_dist == 0) { |
420 if (ftd.best_bird_dist == 0) { |
364 return GetDepotByTile(ftd.node.tile); /* Target found */ |
421 return GetDepotByTile(ftd.node.tile); /* Target found */ |
365 } else { |
422 } else { |
366 return NULL; /* Target not found */ |
423 return NULL; /* Target not found */ |
367 } |
424 } |
389 * @param p1 vehicle ID to send to the depot |
446 * @param p1 vehicle ID to send to the depot |
390 * @param p2 various bitmasked elements |
447 * @param p2 various bitmasked elements |
391 * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h) |
448 * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h) |
392 * - p2 bit 8-10 - VLW flag (for mass goto depot) |
449 * - p2 bit 8-10 - VLW flag (for mass goto depot) |
393 */ |
450 */ |
394 int32 CmdSendRoadVehToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
451 CommandCost CmdSendRoadVehToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
395 { |
452 { |
396 Vehicle *v; |
453 Vehicle *v; |
397 const Depot *dep; |
454 const Depot *dep; |
398 |
455 |
399 if (p2 & DEPOT_MASS_SEND) { |
456 if (p2 & DEPOT_MASS_SEND) { |
420 * Note: the if is (true for requesting service == true for ordered to stop in depot) */ |
477 * Note: the if is (true for requesting service == true for ordered to stop in depot) */ |
421 if (flags & DC_EXEC) { |
478 if (flags & DC_EXEC) { |
422 TOGGLEBIT(v->current_order.flags, OFB_HALT_IN_DEPOT); |
479 TOGGLEBIT(v->current_order.flags, OFB_HALT_IN_DEPOT); |
423 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
480 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
424 } |
481 } |
425 return 0; |
482 return CommandCost(); |
426 } |
483 } |
427 |
484 |
428 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
485 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
429 if (flags & DC_EXEC) { |
486 if (flags & DC_EXEC) { |
430 /* If the orders to 'goto depot' are in the orders list (forced servicing), |
487 /* If the orders to 'goto depot' are in the orders list (forced servicing), |
434 |
491 |
435 v->current_order.type = OT_DUMMY; |
492 v->current_order.type = OT_DUMMY; |
436 v->current_order.flags = 0; |
493 v->current_order.flags = 0; |
437 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
494 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
438 } |
495 } |
439 return 0; |
496 return CommandCost(); |
440 } |
497 } |
441 |
498 |
442 dep = FindClosestRoadDepot(v); |
499 dep = FindClosestRoadDepot(v); |
443 if (dep == NULL) return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); |
500 if (dep == NULL) return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); |
444 |
501 |
453 v->current_order.dest = dep->index; |
510 v->current_order.dest = dep->index; |
454 v->dest_tile = dep->xy; |
511 v->dest_tile = dep->xy; |
455 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
512 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
456 } |
513 } |
457 |
514 |
458 return 0; |
515 return CommandCost(); |
459 } |
516 } |
460 |
517 |
461 /** Turn a roadvehicle around. |
518 /** Turn a roadvehicle around. |
462 * @param tile unused |
519 * @param tile unused |
463 * @param flags operation to perform |
520 * @param flags operation to perform |
464 * @param p1 vehicle ID to turn |
521 * @param p1 vehicle ID to turn |
465 * @param p2 unused |
522 * @param p2 unused |
466 */ |
523 */ |
467 int32 CmdTurnRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
524 CommandCost CmdTurnRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
468 { |
525 { |
469 Vehicle *v; |
526 Vehicle *v; |
470 |
527 |
471 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
528 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
472 |
529 |
490 if (IsTunnelTile(v->tile) && DirToDiagDir(v->direction) == GetTunnelDirection(v->tile)) return CMD_ERROR; |
547 if (IsTunnelTile(v->tile) && DirToDiagDir(v->direction) == GetTunnelDirection(v->tile)) return CMD_ERROR; |
491 if (IsBridgeTile(v->tile) && DirToDiagDir(v->direction) == GetBridgeRampDirection(v->tile)) return CMD_ERROR; |
548 if (IsBridgeTile(v->tile) && DirToDiagDir(v->direction) == GetBridgeRampDirection(v->tile)) return CMD_ERROR; |
492 |
549 |
493 if (flags & DC_EXEC) v->u.road.reverse_ctr = 180; |
550 if (flags & DC_EXEC) v->u.road.reverse_ctr = 180; |
494 |
551 |
495 return 0; |
552 return CommandCost(); |
496 } |
553 } |
497 |
554 |
498 |
555 |
499 void RoadVehicle::MarkDirty() |
556 void RoadVehicle::MarkDirty() |
500 { |
557 { |
501 this->cur_image = GetRoadVehImage(this, this->direction); |
558 this->cur_image = this->GetImage(this->direction); |
502 MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1); |
559 MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1); |
503 } |
560 } |
504 |
561 |
505 void RoadVehicle::UpdateDeltaXY(Direction direction) |
562 void RoadVehicle::UpdateDeltaXY(Direction direction) |
506 { |
563 { |
534 |
591 |
535 /* Free the parking bay */ |
592 /* Free the parking bay */ |
536 rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY)); |
593 rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY)); |
537 } |
594 } |
538 |
595 |
539 static void RoadVehDelete(Vehicle *v) |
596 static void DeleteLastRoadVeh(Vehicle *v) |
540 { |
597 { |
598 Vehicle *u = v; |
|
599 for (; v->next != NULL; v = v->next) u = v; |
|
600 u->next = NULL; |
|
601 |
|
541 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
602 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
542 |
603 |
543 RebuildVehicleLists(); |
604 RebuildVehicleLists(); |
544 InvalidateWindow(WC_COMPANY, v->owner); |
605 InvalidateWindow(WC_COMPANY, v->owner); |
545 |
606 |
572 { |
633 { |
573 static const DirDiff delta[] = { |
634 static const DirDiff delta[] = { |
574 DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT |
635 DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT |
575 }; |
636 }; |
576 |
637 |
577 uint32 r = Random(); |
638 do { |
578 |
639 uint32 r = Random(); |
579 v->direction = ChangeDir(v->direction, delta[r & 3]); |
640 |
580 BeginVehicleMove(v); |
641 v->direction = ChangeDir(v->direction, delta[r & 3]); |
581 v->UpdateDeltaXY(v->direction); |
642 BeginVehicleMove(v); |
582 v->cur_image = GetRoadVehImage(v, v->direction); |
643 v->UpdateDeltaXY(v->direction); |
583 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
644 v->cur_image = v->GetImage(v->direction); |
645 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
|
646 } while ((v = v->next) != NULL); |
|
584 } |
647 } |
585 |
648 |
586 static void RoadVehIsCrashed(Vehicle *v) |
649 static void RoadVehIsCrashed(Vehicle *v) |
587 { |
650 { |
588 v->u.road.crashed_ctr++; |
651 v->u.road.crashed_ctr++; |
589 if (v->u.road.crashed_ctr == 2) { |
652 if (v->u.road.crashed_ctr == 2) { |
590 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); |
653 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); |
591 } else if (v->u.road.crashed_ctr <= 45) { |
654 } else if (v->u.road.crashed_ctr <= 45) { |
592 if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v); |
655 if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v); |
593 } else if (v->u.road.crashed_ctr >= 2220) { |
656 } else if (v->u.road.crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) { |
594 RoadVehDelete(v); |
657 DeleteLastRoadVeh(v); |
595 } |
658 } |
596 } |
659 } |
597 |
660 |
598 static void* EnumCheckRoadVehCrashTrain(Vehicle* v, void* data) |
661 static void* EnumCheckRoadVehCrashTrain(Vehicle* v, void* data) |
599 { |
662 { |
607 v : NULL; |
670 v : NULL; |
608 } |
671 } |
609 |
672 |
610 static void RoadVehCrash(Vehicle *v) |
673 static void RoadVehCrash(Vehicle *v) |
611 { |
674 { |
612 uint16 pass; |
675 uint16 pass = 1; |
613 |
676 |
614 v->u.road.crashed_ctr++; |
677 v->u.road.crashed_ctr++; |
615 v->vehstatus |= VS_CRASHED; |
678 |
679 for (Vehicle *u = v; u != NULL; u = u->next) { |
|
680 if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count(); |
|
681 |
|
682 u->vehstatus |= VS_CRASHED; |
|
683 |
|
684 MarkAllViewportsDirty(u->left_coord, u->top_coord, u->right_coord + 1, u->bottom_coord + 1); |
|
685 } |
|
686 |
|
616 ClearSlot(v); |
687 ClearSlot(v); |
617 |
688 |
618 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
689 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
619 |
|
620 pass = 1; |
|
621 if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count; |
|
622 v->cargo_count = 0; |
|
623 |
690 |
624 SetDParam(0, pass); |
691 SetDParam(0, pass); |
625 AddNewsItem( |
692 AddNewsItem( |
626 (pass == 1) ? |
693 (pass == 1) ? |
627 STR_9031_ROAD_VEHICLE_CRASH_DRIVER : STR_9032_ROAD_VEHICLE_CRASH_DIE, |
694 STR_9031_ROAD_VEHICLE_CRASH_DRIVER : STR_9032_ROAD_VEHICLE_CRASH_DIE, |
634 SndPlayVehicleFx(SND_12_EXPLOSION, v); |
701 SndPlayVehicleFx(SND_12_EXPLOSION, v); |
635 } |
702 } |
636 |
703 |
637 static void RoadVehCheckTrainCrash(Vehicle *v) |
704 static void RoadVehCheckTrainCrash(Vehicle *v) |
638 { |
705 { |
639 TileIndex tile; |
706 for (Vehicle *u = v; u != NULL; u = u->next) { |
640 |
707 if (u->u.road.state == RVSB_WORMHOLE) continue; |
641 if (v->u.road.state == RVSB_WORMHOLE) return; |
708 |
642 |
709 TileIndex tile = u->tile; |
643 tile = v->tile; |
710 |
644 |
711 if (!IsLevelCrossingTile(tile)) continue; |
645 if (!IsLevelCrossingTile(tile)) return; |
712 |
646 |
713 if (VehicleFromPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain) != NULL) { |
647 if (VehicleFromPos(tile, v, EnumCheckRoadVehCrashTrain) != NULL) |
714 RoadVehCrash(v); |
648 RoadVehCrash(v); |
715 return; |
716 } |
|
717 } |
|
649 } |
718 } |
650 |
719 |
651 static void HandleBrokenRoadVeh(Vehicle *v) |
720 static void HandleBrokenRoadVeh(Vehicle *v) |
652 { |
721 { |
653 if (v->breakdown_ctr != 1) { |
722 if (v->breakdown_ctr != 1) { |
687 case OT_GOTO_DEPOT: |
756 case OT_GOTO_DEPOT: |
688 /* Let a depot order in the orderlist interrupt. */ |
757 /* Let a depot order in the orderlist interrupt. */ |
689 if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return; |
758 if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return; |
690 if (v->current_order.flags & OF_SERVICE_IF_NEEDED && |
759 if (v->current_order.flags & OF_SERVICE_IF_NEEDED && |
691 !VehicleNeedsService(v)) { |
760 !VehicleNeedsService(v)) { |
761 UpdateVehicleTimetable(v, true); |
|
692 v->cur_order_index++; |
762 v->cur_order_index++; |
693 } |
763 } |
694 break; |
764 break; |
695 |
765 |
696 case OT_LOADING: |
766 case OT_LOADING: |
796 |
866 |
797 short x_diff = v->x_pos - rvf->x; |
867 short x_diff = v->x_pos - rvf->x; |
798 short y_diff = v->y_pos - rvf->y; |
868 short y_diff = v->y_pos - rvf->y; |
799 |
869 |
800 return |
870 return |
801 rvf->veh != v && |
|
802 v->type == VEH_ROAD && |
871 v->type == VEH_ROAD && |
803 !IsRoadVehInDepot(v) && |
872 !IsRoadVehInDepot(v) && |
804 myabs(v->z_pos - rvf->veh->z_pos) < 6 && |
873 myabs(v->z_pos - rvf->veh->z_pos) < 6 && |
805 v->direction == rvf->dir && |
874 v->direction == rvf->dir && |
875 GetFirstVehicleInChain(rvf->veh) != GetFirstVehicleInChain(v) && |
|
806 (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) && |
876 (dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) && |
807 (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) && |
877 (dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) && |
808 (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) && |
878 (dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) && |
809 (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0)) ? |
879 (dist_y[v->direction] <= 0 || (y_diff < dist_y[v->direction] && y_diff >= 0)) ? |
810 v : NULL; |
880 v : NULL; |
819 |
889 |
820 rvf.x = x; |
890 rvf.x = x; |
821 rvf.y = y; |
891 rvf.y = y; |
822 rvf.dir = dir; |
892 rvf.dir = dir; |
823 rvf.veh = v; |
893 rvf.veh = v; |
824 u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose); |
894 u = (Vehicle*)VehicleFromPosXY(x, y, &rvf, EnumCheckRoadVehClose); |
825 |
895 |
826 /* This code protects a roadvehicle from being blocked for ever |
896 /* This code protects a roadvehicle from being blocked for ever |
827 * If more than 1480 / 74 days a road vehicle is blocked, it will |
897 * If more than 1480 / 74 days a road vehicle is blocked, it will |
828 * drive just through it. The ultimate backup-code of TTD. |
898 * drive just through it. The ultimate backup-code of TTD. |
829 * It can be disabled. */ |
899 * It can be disabled. */ |
970 } |
1040 } |
971 |
1041 |
972 /* Trams can't overtake other trams */ |
1042 /* Trams can't overtake other trams */ |
973 if (v->u.road.roadtype == ROADTYPE_TRAM) return; |
1043 if (v->u.road.roadtype == ROADTYPE_TRAM) return; |
974 |
1044 |
1045 /* For now, articulated road vehicles can't overtake anything. */ |
|
1046 if (RoadVehHasArticPart(v)) return; |
|
1047 |
|
975 if (v->direction != u->direction || !(v->direction & 1)) return; |
1048 if (v->direction != u->direction || !(v->direction & 1)) return; |
976 |
1049 |
977 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
1050 /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ |
978 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
1051 if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; |
979 |
1052 |
1012 } |
1085 } |
1013 } |
1086 } |
1014 |
1087 |
1015 static int PickRandomBit(uint bits) |
1088 static int PickRandomBit(uint bits) |
1016 { |
1089 { |
1017 uint num = 0; |
|
1018 uint b = bits; |
|
1019 uint i; |
1090 uint i; |
1020 |
1091 uint num = RandomRange(CountBitsSet(bits)); |
1021 do { |
|
1022 if (b & 1) num++; |
|
1023 } while (b >>= 1); |
|
1024 |
|
1025 num = RandomRange(num); |
|
1026 |
1092 |
1027 for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {} |
1093 for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {} |
1028 return i; |
1094 return i; |
1029 } |
1095 } |
1030 |
1096 |
1265 19, 19, 15, 15, 0, 0, 0, 0, |
1331 19, 19, 15, 15, 0, 0, 0, 0, |
1266 16, 16, 12, 12, 0, 0, 0, 0, |
1332 16, 16, 12, 12, 0, 0, 0, 0, |
1267 15, 15, 11, 11 |
1333 15, 15, 11, 11 |
1268 }; |
1334 }; |
1269 |
1335 |
1270 static void RoadVehController(Vehicle *v) |
1336 static bool RoadVehLeaveDepot(Vehicle *v, bool first) |
1337 { |
|
1338 /* Don't leave if not all the wagons are in the depot. */ |
|
1339 for (const Vehicle *u = v; u != NULL; u = u->next) { |
|
1340 if (u->u.road.state != RVSB_IN_DEPOT || u->tile != v->tile) return false; |
|
1341 } |
|
1342 |
|
1343 DiagDirection dir = GetRoadDepotDirection(v->tile); |
|
1344 v->direction = DiagDirToDir(dir); |
|
1345 |
|
1346 Trackdir tdir = _roadveh_depot_exit_trackdir[dir]; |
|
1347 const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; |
|
1348 |
|
1349 int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); |
|
1350 int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); |
|
1351 |
|
1352 if (first) { |
|
1353 if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return true; |
|
1354 |
|
1355 VehicleServiceInDepot(v); |
|
1356 |
|
1357 StartRoadVehSound(v); |
|
1358 |
|
1359 /* Vehicle is about to leave a depot */ |
|
1360 v->cur_speed = 0; |
|
1361 } |
|
1362 |
|
1363 BeginVehicleMove(v); |
|
1364 |
|
1365 v->vehstatus &= ~VS_HIDDEN; |
|
1366 v->u.road.state = tdir; |
|
1367 v->u.road.frame = RVC_DEPOT_START_FRAME; |
|
1368 |
|
1369 v->cur_image = v->GetImage(v->direction); |
|
1370 v->UpdateDeltaXY(v->direction); |
|
1371 SetRoadVehPosition(v,x,y); |
|
1372 |
|
1373 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
|
1374 |
|
1375 return true; |
|
1376 } |
|
1377 |
|
1378 static Trackdir FollowPreviousRoadVehicle(const Vehicle *v, const Vehicle *prev, TileIndex tile, DiagDirection entry_dir) |
|
1379 { |
|
1380 if (prev->tile == v->tile) { |
|
1381 /* If the previous vehicle is on the same tile as this vehicle is |
|
1382 * then it must have reversed. */ |
|
1383 return _road_reverse_table[entry_dir]; |
|
1384 } |
|
1385 |
|
1386 byte prev_state = prev->u.road.state; |
|
1387 Trackdir dir; |
|
1388 |
|
1389 if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) { |
|
1390 DiagDirection diag_dir = INVALID_DIAGDIR; |
|
1391 |
|
1392 if (IsTunnelTile(tile)) { |
|
1393 diag_dir = GetTunnelDirection(tile); |
|
1394 } else if (IsBridgeTile(tile)) { |
|
1395 diag_dir = GetBridgeRampDirection(tile); |
|
1396 } else if (IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_DEPOT) { |
|
1397 diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile)); |
|
1398 } |
|
1399 |
|
1400 if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR; |
|
1401 dir = DiagdirToDiagTrackdir(diag_dir); |
|
1402 } else if (HASBIT(prev_state, RVS_IN_DT_ROAD_STOP)) { |
|
1403 dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK); |
|
1404 } else if (prev_state < TRACKDIR_END) { |
|
1405 dir = (Trackdir)prev_state; |
|
1406 } else { |
|
1407 return INVALID_TRACKDIR; |
|
1408 } |
|
1409 |
|
1410 /* Do some sanity checking. */ |
|
1411 static const RoadBits required_roadbits[] = { |
|
1412 ROAD_X, ROAD_Y, ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE, |
|
1413 ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X, ROAD_Y |
|
1414 }; |
|
1415 RoadBits required = required_roadbits[dir & 0x07]; |
|
1416 |
|
1417 if ((required & GetAnyRoadBits(tile, v->u.road.roadtype)) == ROAD_NONE) { |
|
1418 dir = INVALID_TRACKDIR; |
|
1419 } |
|
1420 |
|
1421 return dir; |
|
1422 } |
|
1423 |
|
1424 static bool IndividualRoadVehicleController(Vehicle *v, const Vehicle *prev) |
|
1271 { |
1425 { |
1272 Direction new_dir; |
1426 Direction new_dir; |
1273 Direction old_dir; |
1427 Direction old_dir; |
1274 RoadDriveEntry rd; |
1428 RoadDriveEntry rd; |
1275 int x,y; |
1429 int x,y; |
1276 uint32 r; |
1430 uint32 r; |
1277 |
|
1278 /* decrease counters */ |
|
1279 v->tick_counter++; |
|
1280 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
|
1281 |
|
1282 /* handle crashed */ |
|
1283 if (v->u.road.crashed_ctr != 0) { |
|
1284 RoadVehIsCrashed(v); |
|
1285 return; |
|
1286 } |
|
1287 |
|
1288 RoadVehCheckTrainCrash(v); |
|
1289 |
|
1290 /* road vehicle has broken down? */ |
|
1291 if (v->breakdown_ctr != 0) { |
|
1292 if (v->breakdown_ctr <= 2) { |
|
1293 HandleBrokenRoadVeh(v); |
|
1294 return; |
|
1295 } |
|
1296 v->breakdown_ctr--; |
|
1297 } |
|
1298 |
|
1299 if (v->vehstatus & VS_STOPPED) return; |
|
1300 |
|
1301 ProcessRoadVehOrder(v); |
|
1302 v->HandleLoading(); |
|
1303 |
|
1304 if (v->current_order.type == OT_LOADING) return; |
|
1305 |
|
1306 if (IsRoadVehInDepot(v)) { |
|
1307 /* Vehicle is about to leave a depot */ |
|
1308 DiagDirection dir; |
|
1309 const RoadDriveEntry* rdp; |
|
1310 Trackdir tdir; |
|
1311 |
|
1312 v->cur_speed = 0; |
|
1313 |
|
1314 dir = GetRoadDepotDirection(v->tile); |
|
1315 v->direction = DiagDirToDir(dir); |
|
1316 |
|
1317 tdir = _roadveh_depot_exit_trackdir[dir]; |
|
1318 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; |
|
1319 |
|
1320 x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); |
|
1321 y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); |
|
1322 |
|
1323 if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return; |
|
1324 |
|
1325 VehicleServiceInDepot(v); |
|
1326 |
|
1327 StartRoadVehSound(v); |
|
1328 |
|
1329 BeginVehicleMove(v); |
|
1330 |
|
1331 v->vehstatus &= ~VS_HIDDEN; |
|
1332 v->u.road.state = tdir; |
|
1333 v->u.road.frame = RVC_DEPOT_START_FRAME; |
|
1334 |
|
1335 v->cur_image = GetRoadVehImage(v, v->direction); |
|
1336 v->UpdateDeltaXY(v->direction); |
|
1337 SetRoadVehPosition(v,x,y); |
|
1338 |
|
1339 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
|
1340 return; |
|
1341 } |
|
1342 |
|
1343 /* Check if vehicle needs to proceed, return if it doesn't */ |
|
1344 if (!RoadVehAccelerate(v)) return; |
|
1345 |
1431 |
1346 if (v->u.road.overtaking != 0) { |
1432 if (v->u.road.overtaking != 0) { |
1347 if (++v->u.road.overtaking_ctr >= 35) |
1433 if (++v->u.road.overtaking_ctr >= 35) |
1348 /* If overtaking just aborts at a random moment, we can have a out-of-bound problem, |
1434 /* If overtaking just aborts at a random moment, we can have a out-of-bound problem, |
1349 * if the vehicle started a corner. To protect that, only allow an abort of |
1435 * if the vehicle started a corner. To protect that, only allow an abort of |
1351 if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) { |
1437 if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) { |
1352 v->u.road.overtaking = 0; |
1438 v->u.road.overtaking = 0; |
1353 } |
1439 } |
1354 } |
1440 } |
1355 |
1441 |
1442 /* If this vehicle is in a depot and we've reached this point it must be |
|
1443 * one of the articulated parts. It will stay in the depot until activated |
|
1444 * by the previous vehicle in the chain when it gets to the right place. */ |
|
1445 if (IsRoadVehInDepot(v)) return true; |
|
1446 |
|
1356 /* Save old vehicle position to use at end of move to set viewport area dirty */ |
1447 /* Save old vehicle position to use at end of move to set viewport area dirty */ |
1357 BeginVehicleMove(v); |
1448 BeginVehicleMove(v); |
1358 |
1449 |
1359 if (v->u.road.state == RVSB_WORMHOLE) { |
1450 if (v->u.road.state == RVSB_WORMHOLE) { |
1360 /* Vehicle is entering a depot or is on a bridge or in a tunnel */ |
1451 /* Vehicle is entering a depot or is on a bridge or in a tunnel */ |
1361 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
1452 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
1362 |
1453 |
1363 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction); |
1454 const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction); |
1364 if (u != NULL && u->cur_speed < v->cur_speed) { |
1455 if (u != NULL && u->cur_speed < v->cur_speed) { |
1365 v->cur_speed = u->cur_speed; |
1456 v->cur_speed = u->cur_speed; |
1366 return; |
1457 return false; |
1367 } |
1458 } |
1368 |
1459 |
1369 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1460 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1370 /* Vehicle has just entered a bridge or tunnel */ |
1461 /* Vehicle has just entered a bridge or tunnel */ |
1371 v->cur_image = GetRoadVehImage(v, v->direction); |
1462 v->cur_image = v->GetImage(v->direction); |
1372 v->UpdateDeltaXY(v->direction); |
1463 v->UpdateDeltaXY(v->direction); |
1373 SetRoadVehPosition(v,gp.x,gp.y); |
1464 SetRoadVehPosition(v,gp.x,gp.y); |
1374 return; |
1465 return true; |
1375 } |
1466 } |
1376 |
1467 |
1377 v->x_pos = gp.x; |
1468 v->x_pos = gp.x; |
1378 v->y_pos = gp.y; |
1469 v->y_pos = gp.y; |
1379 VehiclePositionChanged(v); |
1470 VehiclePositionChanged(v); |
1380 if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v); |
1471 if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v); |
1381 return; |
1472 return true; |
1382 } |
1473 } |
1383 |
1474 |
1384 /* Get move position data for next frame. |
1475 /* Get move position data for next frame. |
1385 * For a drive-through road stop use 'straight road' move data. |
1476 * For a drive-through road stop use 'straight road' move data. |
1386 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1477 * In this case v->u.road.state is masked to give the road stop entry direction. */ |
1388 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1479 (HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + |
1389 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1480 (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; |
1390 |
1481 |
1391 if (rd.x & RDE_NEXT_TILE) { |
1482 if (rd.x & RDE_NEXT_TILE) { |
1392 TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3); |
1483 TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3); |
1393 Trackdir dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3)); |
1484 Trackdir dir; |
1394 uint32 r; |
1485 uint32 r; |
1395 Direction newdir; |
1486 Direction newdir; |
1396 const RoadDriveEntry *rdp; |
1487 const RoadDriveEntry *rdp; |
1397 |
1488 |
1489 if (IsRoadVehFront(v)) { |
|
1490 /* If this is the front engine, look for the right path. */ |
|
1491 dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3)); |
|
1492 } else { |
|
1493 dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3)); |
|
1494 } |
|
1495 |
|
1398 if (dir == INVALID_TRACKDIR) { |
1496 if (dir == INVALID_TRACKDIR) { |
1497 if (!IsRoadVehFront(v)) error("!Disconnecting road vehicle."); |
|
1399 v->cur_speed = 0; |
1498 v->cur_speed = 0; |
1400 return; |
1499 return false; |
1401 } |
1500 } |
1402 |
1501 |
1403 again: |
1502 again: |
1404 if (IsReversingRoadTrackdir(dir)) { |
1503 if (IsReversingRoadTrackdir(dir)) { |
1405 /* Turning around */ |
1504 /* Turning around */ |
1410 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; |
1509 case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; |
1411 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; |
1510 case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; |
1412 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; |
1511 case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; |
1413 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; |
1512 case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; |
1414 } |
1513 } |
1415 if (!IsTileType(tile, MP_STREET) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) { |
1514 if (!IsTileType(tile, MP_STREET) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || HasRoadWorks(tile) || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) { |
1416 /* The tram cannot turn here */ |
1515 /* The tram cannot turn here */ |
1417 v->cur_speed = 0; |
1516 v->cur_speed = 0; |
1418 return; |
1517 return false; |
1419 } |
1518 } |
1420 } else if (IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) { |
1519 } else if (IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) { |
1421 v->cur_speed = 0; |
1520 v->cur_speed = 0; |
1422 return; |
1521 return false; |
1423 } else { |
1522 } else { |
1424 tile = v->tile; |
1523 tile = v->tile; |
1425 } |
1524 } |
1426 } |
1525 } |
1427 |
1526 |
1430 |
1529 |
1431 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1530 x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x; |
1432 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1531 y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y; |
1433 |
1532 |
1434 newdir = RoadVehGetSlidingDirection(v, x, y); |
1533 newdir = RoadVehGetSlidingDirection(v, x, y); |
1435 if (RoadVehFindCloseTo(v, x, y, newdir) != NULL) return; |
1534 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1436 |
1535 |
1437 r = VehicleEnterTile(v, tile, x, y); |
1536 r = VehicleEnterTile(v, tile, x, y); |
1438 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1537 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1439 if (!IsTileType(tile, MP_TUNNELBRIDGE)) { |
1538 if (!IsTileType(tile, MP_TUNNELBRIDGE)) { |
1440 v->cur_speed = 0; |
1539 v->cur_speed = 0; |
1441 return; |
1540 return false; |
1442 } |
1541 } |
1443 /* Try an about turn to re-enter the previous tile */ |
1542 /* Try an about turn to re-enter the previous tile */ |
1444 dir = _road_reverse_table[rd.x & 3]; |
1543 dir = _road_reverse_table[rd.x & 3]; |
1445 goto again; |
1544 goto again; |
1446 } |
1545 } |
1448 if (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) { |
1547 if (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) { |
1449 if (IsReversingRoadTrackdir(dir) && IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { |
1548 if (IsReversingRoadTrackdir(dir) && IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { |
1450 /* New direction is trying to turn vehicle around. |
1549 /* New direction is trying to turn vehicle around. |
1451 * We can't turn at the exit of a road stop so wait.*/ |
1550 * We can't turn at the exit of a road stop so wait.*/ |
1452 v->cur_speed = 0; |
1551 v->cur_speed = 0; |
1453 return; |
1552 return false; |
1454 } |
1553 } |
1455 if (IsRoadStop(v->tile)) { |
1554 if (IsRoadStop(v->tile)) { |
1456 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1555 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1457 |
1556 |
1458 /* Vehicle is leaving a road stop tile, mark bay as free |
1557 /* Vehicle is leaving a road stop tile, mark bay as free |
1473 if (newdir != v->direction) { |
1572 if (newdir != v->direction) { |
1474 v->direction = newdir; |
1573 v->direction = newdir; |
1475 v->cur_speed -= v->cur_speed >> 2; |
1574 v->cur_speed -= v->cur_speed >> 2; |
1476 } |
1575 } |
1477 |
1576 |
1478 v->cur_image = GetRoadVehImage(v, newdir); |
1577 v->cur_image = v->GetImage(newdir); |
1479 v->UpdateDeltaXY(v->direction); |
1578 v->UpdateDeltaXY(v->direction); |
1480 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1579 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1481 return; |
1580 return true; |
1482 } |
1581 } |
1483 |
1582 |
1484 if (rd.x & RDE_TURNED) { |
1583 if (rd.x & RDE_TURNED) { |
1485 /* Vehicle has finished turning around, it will now head back onto the same tile */ |
1584 /* Vehicle has finished turning around, it will now head back onto the same tile */ |
1486 Trackdir dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3)); |
1585 Trackdir dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3)); |
1488 Direction newdir; |
1587 Direction newdir; |
1489 const RoadDriveEntry *rdp; |
1588 const RoadDriveEntry *rdp; |
1490 |
1589 |
1491 if (dir == INVALID_TRACKDIR) { |
1590 if (dir == INVALID_TRACKDIR) { |
1492 v->cur_speed = 0; |
1591 v->cur_speed = 0; |
1493 return; |
1592 return false; |
1494 } |
1593 } |
1495 |
1594 |
1496 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir]; |
1595 rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir]; |
1497 |
1596 |
1498 x = TileX(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].x; |
1597 x = TileX(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].x; |
1499 y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y; |
1598 y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y; |
1500 |
1599 |
1501 newdir = RoadVehGetSlidingDirection(v, x, y); |
1600 newdir = RoadVehGetSlidingDirection(v, x, y); |
1502 if (RoadVehFindCloseTo(v, x, y, newdir) != NULL) return; |
1601 if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false; |
1503 |
1602 |
1504 r = VehicleEnterTile(v, v->tile, x, y); |
1603 r = VehicleEnterTile(v, v->tile, x, y); |
1505 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1604 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1506 v->cur_speed = 0; |
1605 v->cur_speed = 0; |
1507 return; |
1606 return false; |
1508 } |
1607 } |
1509 |
1608 |
1510 v->u.road.state = dir; |
1609 v->u.road.state = dir; |
1511 v->u.road.frame = RVC_TURN_AROUND_START_FRAME; |
1610 v->u.road.frame = RVC_TURN_AROUND_START_FRAME; |
1512 |
1611 |
1513 if (newdir != v->direction) { |
1612 if (newdir != v->direction) { |
1514 v->direction = newdir; |
1613 v->direction = newdir; |
1515 v->cur_speed -= v->cur_speed >> 2; |
1614 v->cur_speed -= v->cur_speed >> 2; |
1516 } |
1615 } |
1517 |
1616 |
1518 v->cur_image = GetRoadVehImage(v, newdir); |
1617 v->cur_image = v->GetImage(newdir); |
1519 v->UpdateDeltaXY(v->direction); |
1618 v->UpdateDeltaXY(v->direction); |
1520 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1619 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1521 return; |
1620 return true; |
1621 } |
|
1622 |
|
1623 /* This vehicle is not in a wormhole and it hasn't entered a new tile. If |
|
1624 * it's on a depot tile, check if it's time to activate the next vehicle in |
|
1625 * the chain yet. */ |
|
1626 if (v->next != NULL && |
|
1627 IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_DEPOT) { |
|
1628 |
|
1629 if (v->u.road.frame == v->u.road.cached_veh_length + RVC_DEPOT_START_FRAME) { |
|
1630 RoadVehLeaveDepot(v->next, false); |
|
1631 } |
|
1522 } |
1632 } |
1523 |
1633 |
1524 /* Calculate new position for the vehicle */ |
1634 /* Calculate new position for the vehicle */ |
1525 x = (v->x_pos & ~15) + (rd.x & 15); |
1635 x = (v->x_pos & ~15) + (rd.x & 15); |
1526 y = (v->y_pos & ~15) + (rd.y & 15); |
1636 y = (v->y_pos & ~15) + (rd.y & 15); |
1527 |
1637 |
1528 new_dir = RoadVehGetSlidingDirection(v, x, y); |
1638 new_dir = RoadVehGetSlidingDirection(v, x, y); |
1529 |
1639 |
1530 if (!IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { |
1640 if (IsRoadVehFront(v) && !IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { |
1531 /* Vehicle is not in a road stop. |
1641 /* Vehicle is not in a road stop. |
1532 * Check for another vehicle to overtake */ |
1642 * Check for another vehicle to overtake */ |
1533 Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); |
1643 Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); |
1534 |
1644 |
1535 if (u != NULL) { |
1645 if (u != NULL) { |
1536 v->cur_speed = u->cur_speed; |
1646 v->cur_speed = u->cur_speed; |
1537 /* There is a vehicle in front overtake it if possible */ |
1647 /* There is a vehicle in front overtake it if possible */ |
1538 if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); |
1648 if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u); |
1539 return; |
1649 return false; |
1540 } |
1650 } |
1541 } |
1651 } |
1542 |
1652 |
1543 old_dir = v->direction; |
1653 old_dir = v->direction; |
1544 if (new_dir != old_dir) { |
1654 if (new_dir != old_dir) { |
1545 v->direction = new_dir; |
1655 v->direction = new_dir; |
1546 v->cur_speed -= (v->cur_speed >> 2); |
1656 v->cur_speed -= (v->cur_speed >> 2); |
1547 if (old_dir != v->u.road.state) { |
1657 if (old_dir != v->u.road.state) { |
1548 /* The vehicle is in a road stop */ |
1658 /* The vehicle is in a road stop */ |
1549 v->cur_image = GetRoadVehImage(v, new_dir); |
1659 v->cur_image = v->GetImage(new_dir); |
1550 v->UpdateDeltaXY(v->direction); |
1660 v->UpdateDeltaXY(v->direction); |
1551 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1661 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1552 /* Note, return here means that the frame counter is not incremented |
1662 /* Note, return here means that the frame counter is not incremented |
1553 * for vehicles changing direction in a road stop. This causes frames to |
1663 * for vehicles changing direction in a road stop. This causes frames to |
1554 * be repeated. (XXX) Is this intended? */ |
1664 * be repeated. (XXX) Is this intended? */ |
1555 return; |
1665 return true; |
1556 } |
1666 } |
1557 } |
1667 } |
1558 |
1668 |
1559 /* If the vehicle is in a normal road stop and the frame equals the stop frame OR |
1669 /* If the vehicle is in a normal road stop and the frame equals the stop frame OR |
1560 * if the vehicle is in a drive-through road stop and this is the destination station |
1670 * if the vehicle is in a drive-through road stop and this is the destination station |
1561 * and it's the correct type of stop (bus or truck) and the frame equals the stop frame... |
1671 * and it's the correct type of stop (bus or truck) and the frame equals the stop frame... |
1562 * (the station test and stop type test ensure that other vehicles, using the road stop as |
1672 * (the station test and stop type test ensure that other vehicles, using the road stop as |
1563 * a through route, do not stop) */ |
1673 * a through route, do not stop) */ |
1564 if ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && |
1674 if (IsRoadVehFront(v) && ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && |
1565 _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) || |
1675 _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) || |
1566 (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && |
1676 (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && |
1567 v->current_order.dest == GetStationIndex(v->tile) && |
1677 v->current_order.dest == GetStationIndex(v->tile) && |
1568 GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) && |
1678 GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) && |
1569 v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME)) { |
1679 v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) { |
1570 |
1680 |
1571 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1681 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
1572 Station* st = GetStationByTile(v->tile); |
1682 Station* st = GetStationByTile(v->tile); |
1573 |
1683 |
1574 /* Vehicle is at the stop position (at a bay) in a road stop. |
1684 /* Vehicle is at the stop position (at a bay) in a road stop. |
1594 v->dest_tile = rs_n->xy; |
1704 v->dest_tile = rs_n->xy; |
1595 v->u.road.slot_age = 14; |
1705 v->u.road.slot_age = 14; |
1596 |
1706 |
1597 v->u.road.frame++; |
1707 v->u.road.frame++; |
1598 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1708 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1599 return; |
1709 return true; |
1600 } |
1710 } |
1601 } |
1711 } |
1602 } |
1712 } |
1603 |
1713 |
1604 rs->SetEntranceBusy(false); |
1714 rs->SetEntranceBusy(false); |
1606 v->last_station_visited = GetStationIndex(v->tile); |
1716 v->last_station_visited = GetStationIndex(v->tile); |
1607 |
1717 |
1608 RoadVehArrivesAt(v, st); |
1718 RoadVehArrivesAt(v, st); |
1609 v->BeginLoading(); |
1719 v->BeginLoading(); |
1610 |
1720 |
1611 return; |
1721 return false; |
1612 } |
1722 } |
1613 |
1723 |
1614 /* Vehicle is ready to leave a bay in a road stop */ |
1724 /* Vehicle is ready to leave a bay in a road stop */ |
1615 if (v->current_order.type != OT_GOTO_DEPOT) { |
1725 if (v->current_order.type != OT_GOTO_DEPOT) { |
1616 if (rs->IsEntranceBusy()) { |
1726 if (rs->IsEntranceBusy()) { |
1617 /* Road stop entrance is busy, so wait as there is nowhere else to go */ |
1727 /* Road stop entrance is busy, so wait as there is nowhere else to go */ |
1618 v->cur_speed = 0; |
1728 v->cur_speed = 0; |
1619 return; |
1729 return false; |
1620 } |
1730 } |
1621 v->current_order.Free(); |
1731 v->current_order.Free(); |
1622 ClearSlot(v); |
1732 ClearSlot(v); |
1623 } |
1733 } |
1624 |
1734 |
1657 /* Check tile position conditions - i.e. stop position in depot, |
1767 /* Check tile position conditions - i.e. stop position in depot, |
1658 * entry onto bridge or into tunnel */ |
1768 * entry onto bridge or into tunnel */ |
1659 r = VehicleEnterTile(v, v->tile, x, y); |
1769 r = VehicleEnterTile(v, v->tile, x, y); |
1660 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1770 if (HASBIT(r, VETS_CANNOT_ENTER)) { |
1661 v->cur_speed = 0; |
1771 v->cur_speed = 0; |
1662 return; |
1772 return false; |
1663 } |
1773 } |
1664 |
1774 |
1665 /* Move to next frame unless vehicle arrived at a stop position |
1775 /* Move to next frame unless vehicle arrived at a stop position |
1666 * in a depot or entered a tunnel/bridge */ |
1776 * in a depot or entered a tunnel/bridge */ |
1667 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1777 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1668 |
1778 |
1669 v->cur_image = GetRoadVehImage(v, v->direction); |
1779 v->cur_image = v->GetImage(v->direction); |
1670 v->UpdateDeltaXY(v->direction); |
1780 v->UpdateDeltaXY(v->direction); |
1671 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1781 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1782 return true; |
|
1783 } |
|
1784 |
|
1785 static void RoadVehController(Vehicle *v) |
|
1786 { |
|
1787 /* decrease counters */ |
|
1788 v->tick_counter++; |
|
1789 v->current_order_time++; |
|
1790 if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--; |
|
1791 |
|
1792 /* handle crashed */ |
|
1793 if (v->u.road.crashed_ctr != 0) { |
|
1794 RoadVehIsCrashed(v); |
|
1795 return; |
|
1796 } |
|
1797 |
|
1798 RoadVehCheckTrainCrash(v); |
|
1799 |
|
1800 /* road vehicle has broken down? */ |
|
1801 if (v->breakdown_ctr != 0) { |
|
1802 if (v->breakdown_ctr <= 2) { |
|
1803 HandleBrokenRoadVeh(v); |
|
1804 return; |
|
1805 } |
|
1806 v->breakdown_ctr--; |
|
1807 } |
|
1808 |
|
1809 if (v->vehstatus & VS_STOPPED) return; |
|
1810 |
|
1811 ProcessRoadVehOrder(v); |
|
1812 v->HandleLoading(); |
|
1813 |
|
1814 if (v->current_order.type == OT_LOADING) return; |
|
1815 |
|
1816 if (IsRoadVehInDepot(v) && RoadVehLeaveDepot(v, true)) return; |
|
1817 |
|
1818 /* Check if vehicle needs to proceed, return if it doesn't */ |
|
1819 if (!RoadVehAccelerate(v)) return; |
|
1820 |
|
1821 for (Vehicle *prev = NULL; v != NULL; prev = v, v = v->next) { |
|
1822 if (!IndividualRoadVehicleController(v, prev)) break; |
|
1823 } |
|
1672 } |
1824 } |
1673 |
1825 |
1674 static void AgeRoadVehCargo(Vehicle *v) |
1826 static void AgeRoadVehCargo(Vehicle *v) |
1675 { |
1827 { |
1676 if (_age_cargo_skip_counter != 0) return; |
1828 if (_age_cargo_skip_counter != 0) return; |
1677 if (v->cargo_days != 255) v->cargo_days++; |
1829 v->cargo.AgeCargo(); |
1678 } |
1830 } |
1679 |
1831 |
1680 void RoadVeh_Tick(Vehicle *v) |
1832 void RoadVehicle::Tick() |
1681 { |
1833 { |
1682 AgeRoadVehCargo(v); |
1834 AgeRoadVehCargo(this); |
1683 RoadVehController(v); |
1835 |
1836 if (IsRoadVehFront(this)) RoadVehController(this); |
|
1684 } |
1837 } |
1685 |
1838 |
1686 static void CheckIfRoadVehNeedsService(Vehicle *v) |
1839 static void CheckIfRoadVehNeedsService(Vehicle *v) |
1687 { |
1840 { |
1688 const Depot* depot; |
1841 const Depot* depot; |
1734 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
1887 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
1735 } |
1888 } |
1736 |
1889 |
1737 void OnNewDay_RoadVeh(Vehicle *v) |
1890 void OnNewDay_RoadVeh(Vehicle *v) |
1738 { |
1891 { |
1739 int32 cost; |
1892 CommandCost cost; |
1893 |
|
1894 if (!IsRoadVehFront(v)) return; |
|
1740 |
1895 |
1741 if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v); |
1896 if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v); |
1742 if (v->u.road.blocked_ctr == 0) CheckVehicleBreakdown(v); |
1897 if (v->u.road.blocked_ctr == 0) CheckVehicleBreakdown(v); |
1743 |
1898 |
1744 AgeVehicle(v); |
1899 AgeVehicle(v); |
1814 } |
1969 } |
1815 } |
1970 } |
1816 |
1971 |
1817 cost = RoadVehInfo(v->engine_type)->running_cost * _price.roadveh_running / 364; |
1972 cost = RoadVehInfo(v->engine_type)->running_cost * _price.roadveh_running / 364; |
1818 |
1973 |
1819 v->profit_this_year -= cost >> 8; |
1974 v->profit_this_year -= cost.GetCost() >> 8; |
1820 |
1975 |
1821 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_RUN); |
1976 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_RUN); |
1822 SubtractMoneyFromPlayerFract(v->owner, cost); |
1977 SubtractMoneyFromPlayerFract(v->owner, CommandCost(cost)); |
1823 |
1978 |
1824 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
1979 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
1825 InvalidateWindowClasses(WC_ROADVEH_LIST); |
1980 InvalidateWindowClasses(WC_ROADVEH_LIST); |
1826 } |
1981 } |
1827 |
1982 |
1847 * - p2 = (bit 0-7) - the new cargo type to refit to |
2002 * - p2 = (bit 0-7) - the new cargo type to refit to |
1848 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
2003 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
1849 * - p2 = (bit 16) - refit only this vehicle (ignored) |
2004 * - p2 = (bit 16) - refit only this vehicle (ignored) |
1850 * @return cost of refit or error |
2005 * @return cost of refit or error |
1851 */ |
2006 */ |
1852 int32 CmdRefitRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
2007 CommandCost CmdRefitRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1853 { |
2008 { |
1854 Vehicle *v; |
2009 Vehicle *v; |
1855 int32 cost; |
2010 CommandCost cost; |
1856 CargoID new_cid = GB(p2, 0, 8); |
2011 CargoID new_cid = GB(p2, 0, 8); |
1857 byte new_subtype = GB(p2, 8, 8); |
2012 byte new_subtype = GB(p2, 8, 8); |
1858 uint16 capacity = CALLBACK_FAILED; |
2013 uint16 capacity = CALLBACK_FAILED; |
1859 |
2014 |
1860 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
2015 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
1861 |
2016 |
1862 v = GetVehicle(p1); |
2017 v = GetVehicle(p1); |
1863 |
2018 |
1864 if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR; |
2019 if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR; |
1865 if (!IsRoadVehInDepotStopped(v)) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); |
2020 if (!CheckRoadVehInDepotStopped(v)) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); |
1866 |
2021 |
1867 if (new_cid >= NUM_CARGO || !CanRefitTo(v->engine_type, new_cid)) return CMD_ERROR; |
2022 if (new_cid >= NUM_CARGO || !CanRefitTo(v->engine_type, new_cid)) return CMD_ERROR; |
1868 |
2023 |
1869 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_RUN); |
2024 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_RUN); |
1870 |
2025 |
1906 default: capacity /= 4; break; |
2061 default: capacity /= 4; break; |
1907 } |
2062 } |
1908 } |
2063 } |
1909 _returned_refit_capacity = capacity; |
2064 _returned_refit_capacity = capacity; |
1910 |
2065 |
1911 cost = 0; |
|
1912 if (IsHumanPlayer(v->owner) && new_cid != v->cargo_type) { |
2066 if (IsHumanPlayer(v->owner) && new_cid != v->cargo_type) { |
1913 cost = GetRefitCost(v->engine_type); |
2067 cost = GetRefitCost(v->engine_type); |
1914 } |
2068 } |
1915 |
2069 |
1916 if (flags & DC_EXEC) { |
2070 if (flags & DC_EXEC) { |
1917 v->cargo_cap = capacity; |
2071 v->cargo_cap = capacity; |
1918 v->cargo_count = (v->cargo_type == new_cid) ? min(capacity, v->cargo_count) : 0; |
2072 v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0); |
1919 v->cargo_type = new_cid; |
2073 v->cargo_type = new_cid; |
1920 v->cargo_subtype = new_subtype; |
2074 v->cargo_subtype = new_subtype; |
1921 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
2075 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
1922 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
2076 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1923 RebuildVehicleLists(); |
2077 RebuildVehicleLists(); |