equal
deleted
inserted
replaced
1 #include "stdafx.h" |
1 #include "stdafx.h" |
2 #include "openttd.h" |
2 #include "openttd.h" |
|
3 #include "debug.h" |
3 #include "table/strings.h" |
4 #include "table/strings.h" |
4 #include "map.h" |
5 #include "map.h" |
5 #include "tile.h" |
6 #include "tile.h" |
6 #include "vehicle.h" |
7 #include "vehicle.h" |
7 #include "command.h" |
8 #include "command.h" |
20 |
21 |
21 #define IS_FIRSTHEAD_SPRITE(spritenum) \ |
22 #define IS_FIRSTHEAD_SPRITE(spritenum) \ |
22 (is_custom_sprite(spritenum) ? IS_CUSTOM_FIRSTHEAD_SPRITE(spritenum) : _engine_sprite_add[spritenum] == 0) |
23 (is_custom_sprite(spritenum) ? IS_CUSTOM_FIRSTHEAD_SPRITE(spritenum) : _engine_sprite_add[spritenum] == 0) |
23 |
24 |
24 static bool TrainCheckIfLineEnds(Vehicle *v); |
25 static bool TrainCheckIfLineEnds(Vehicle *v); |
|
26 static void TrainController(Vehicle *v); |
25 extern void ShowTrainViewWindow(Vehicle *v); |
27 extern void ShowTrainViewWindow(Vehicle *v); |
26 |
28 |
27 static const byte _vehicle_initial_x_fract[4] = {10,8,4,8}; |
29 static const byte _vehicle_initial_x_fract[4] = {10,8,4,8}; |
28 static const byte _vehicle_initial_y_fract[4] = {8,4,8,10}; |
30 static const byte _vehicle_initial_y_fract[4] = {8,4,8,10}; |
29 static const byte _state_dir_table[4] = { 0x20, 8, 0x10, 4 }; |
31 static const byte _state_dir_table[4] = { 0x20, 8, 0x10, 4 }; |
79 rvi_v = RailVehInfo(v->engine_type); |
81 rvi_v = RailVehInfo(v->engine_type); |
80 first_engine = (v->subtype == TS_Front_Engine) ? v->engine_type : INVALID_VEHICLE; |
82 first_engine = (v->subtype == TS_Front_Engine) ? v->engine_type : INVALID_VEHICLE; |
81 |
83 |
82 for (u = v; u != NULL; u = u->next) { |
84 for (u = v; u != NULL; u = u->next) { |
83 const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); |
85 const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); |
|
86 uint16 veh_len; |
84 |
87 |
85 // update the 'first engine' |
88 // update the 'first engine' |
86 u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine; |
89 u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine; |
87 |
90 |
88 // power is the sum of the powers of all engines and powered wagons in the consist |
91 // power is the sum of the powers of all engines and powered wagons in the consist |
107 } |
110 } |
108 |
111 |
109 // max speed is the minimum of the speed limits of all vehicles in the consist |
112 // max speed is the minimum of the speed limits of all vehicles in the consist |
110 if (rvi_u->max_speed != 0) |
113 if (rvi_u->max_speed != 0) |
111 max_speed = min(rvi_u->max_speed, max_speed); |
114 max_speed = min(rvi_u->max_speed, max_speed); |
|
115 |
|
116 // check the vehicle length (callback) |
|
117 veh_len = CALLBACK_FAILED; |
|
118 if (HASBIT(rvi_u->callbackmask, CBM_VEH_LENGTH)) |
|
119 veh_len = GetCallBackResult(CBID_VEH_LENGTH, u->engine_type, u); |
|
120 if (veh_len == CALLBACK_FAILED) |
|
121 veh_len = rvi_u->shorten_factor; |
|
122 assert(veh_len < 8); |
|
123 u->u.rail.cached_veh_length = 8 - veh_len; |
|
124 |
112 }; |
125 }; |
113 |
126 |
114 // store consist weight/max speed in cache |
127 // store consist weight/max speed in cache |
115 v->u.rail.cached_max_speed = max_speed; |
128 v->u.rail.cached_max_speed = max_speed; |
116 v->u.rail.cached_power = power; |
129 v->u.rail.cached_power = power; |
1255 } |
1268 } |
1256 } |
1269 } |
1257 } |
1270 } |
1258 } |
1271 } |
1259 |
1272 |
|
1273 /** |
|
1274 * Advances wagons for train reversing, needed for variable length wagons. |
|
1275 * Needs to be called once before the train is reversed, and once after it. |
|
1276 * @param v First vehicle in chain |
|
1277 * @param before Set to true for the call before reversing, false otherwise |
|
1278 */ |
|
1279 static void AdvanceWagons(Vehicle *v, bool before) |
|
1280 { |
|
1281 Vehicle *base, *first, *last, *tempnext; |
|
1282 int i, length; |
|
1283 int differential; |
|
1284 |
|
1285 base = v; |
|
1286 first = base->next; |
|
1287 length = CountVehiclesInChain(v); |
|
1288 |
|
1289 while (length > 2) { |
|
1290 // find pairwise matching wagon |
|
1291 // start<>end, start+1<>end-1, ... */ |
|
1292 last = first; |
|
1293 for (i = length - 3; i; i--) { |
|
1294 last = last->next; |
|
1295 } |
|
1296 |
|
1297 differential = last->u.rail.cached_veh_length - base->u.rail.cached_veh_length; |
|
1298 if (before) |
|
1299 differential *= -1; |
|
1300 |
|
1301 if (differential > 0) { |
|
1302 // disconnect last car to make sure only this subset moves |
|
1303 tempnext = last->next; |
|
1304 last->next = NULL; |
|
1305 |
|
1306 for (i = 0; i < differential; i++) { |
|
1307 TrainController(first); |
|
1308 } |
|
1309 |
|
1310 last->next = tempnext; |
|
1311 } |
|
1312 |
|
1313 base = first; |
|
1314 first = first->next; |
|
1315 length -= 2; |
|
1316 } |
|
1317 } |
|
1318 |
1260 static void ReverseTrainDirection(Vehicle *v) |
1319 static void ReverseTrainDirection(Vehicle *v) |
1261 { |
1320 { |
1262 int l = 0, r = -1; |
1321 int l = 0, r = -1; |
1263 Vehicle *u; |
1322 Vehicle *u; |
1264 |
1323 |
1283 |
1342 |
1284 // count number of vehicles |
1343 // count number of vehicles |
1285 u = v; |
1344 u = v; |
1286 do r++; while ( (u = u->next) != NULL ); |
1345 do r++; while ( (u = u->next) != NULL ); |
1287 |
1346 |
|
1347 AdvanceWagons(v, true); |
|
1348 |
1288 /* swap start<>end, start+1<>end-1, ... */ |
1349 /* swap start<>end, start+1<>end-1, ... */ |
1289 do { |
1350 do { |
1290 ReverseTrainSwapVeh(v, l++, r--); |
1351 ReverseTrainSwapVeh(v, l++, r--); |
1291 } while (l <= r); |
1352 } while (l <= r); |
|
1353 |
|
1354 AdvanceWagons(v, false); |
1292 |
1355 |
1293 if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) |
1356 if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) |
1294 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1357 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1295 |
1358 |
1296 CLRBIT(v->u.rail.flags, VRF_REVERSING); |
1359 CLRBIT(v->u.rail.flags, VRF_REVERSING); |
2721 } |
2784 } |
2722 |
2785 |
2723 v->x_pos = gp.x; |
2786 v->x_pos = gp.x; |
2724 v->y_pos = gp.y; |
2787 v->y_pos = gp.y; |
2725 VehiclePositionChanged(v); |
2788 VehiclePositionChanged(v); |
2726 if (prev == NULL) |
|
2727 CheckTrainCollision(v); |
|
2728 continue; |
2789 continue; |
2729 } |
2790 } |
2730 common:; |
2791 common:; |
2731 |
2792 |
2732 /* update image of train, as well as delta XY */ |
2793 /* update image of train, as well as delta XY */ |
2741 old_z = AfterSetTrainPos(v, (gp.new_tile != gp.old_tile)); |
2802 old_z = AfterSetTrainPos(v, (gp.new_tile != gp.old_tile)); |
2742 |
2803 |
2743 if (prev == NULL) { |
2804 if (prev == NULL) { |
2744 /* This is the first vehicle in the train */ |
2805 /* This is the first vehicle in the train */ |
2745 AffectSpeedByZChange(v, old_z); |
2806 AffectSpeedByZChange(v, old_z); |
2746 CheckTrainCollision(v); |
|
2747 } |
2807 } |
2748 } |
2808 } |
2749 return; |
2809 return; |
2750 |
2810 |
2751 invalid_rail: |
2811 invalid_rail: |
3104 } else { |
3164 } else { |
3105 TrainCheckIfLineEnds(v); |
3165 TrainCheckIfLineEnds(v); |
3106 |
3166 |
3107 do { |
3167 do { |
3108 TrainController(v); |
3168 TrainController(v); |
|
3169 CheckTrainCollision(v); |
3109 if (v->cur_speed <= 0x100) |
3170 if (v->cur_speed <= 0x100) |
3110 break; |
3171 break; |
3111 } while (--j != 0); |
3172 } while (--j != 0); |
3112 } |
3173 } |
3113 |
3174 |