train_cmd.c
changeset 1922 797081e56d13
parent 1921 263f1bcfc038
child 1925 e4bbd7fc2353
equal deleted inserted replaced
1921:263f1bcfc038 1922:797081e56d13
     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