changeset 12085:067bb705b7bc draft

(svn r16494) -Codechange: cache train's speed limit caused by curves
author smatz <smatz@openttd.org>
date Mon, 01 Jun 2009 13:14:56 +0000
parents e1051929e7b8
children c271d53c9872
files src/settings.cpp src/train.h src/train_cmd.cpp
diffstat 3 files changed, 47 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -735,7 +735,10 @@
 {
 	Train *t;
 	FOR_ALL_TRAINS(t) {
-		if (IsFrontEngine(t)) UpdateTrainAcceleration(t);
+		if (IsFrontEngine(t)) {
+			t->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(t);
+			UpdateTrainAcceleration(t);
+		}
 	}
 
 	return true;
--- a/src/train.h
+++ b/src/train.h
@@ -257,6 +257,7 @@
 
 void TrainConsistChanged(Train *v, bool same_length);
 void TrainPowerChanged(Train *v);
+int GetTrainCurveSpeedLimit(Train *v);
 Money GetTrainRunningCost(const Train *v);
 
 /** Variables that are cached to improve performance and such */
@@ -268,7 +269,6 @@
 
 	/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
 	uint32 cached_power;        ///< total power of the consist.
-	uint16 cached_max_speed;    ///< max speed of the consist. (minimum of the max speed of all vehicles in the consist)
 	uint16 cached_total_length; ///< Length of the whole train, valid only for first engine.
 	uint8 cached_veh_length;    ///< length of this vehicle in units of 1/8 of normal length, cached because this can be set by a callback
 	bool cached_tilt;           ///< train can tilt; feature provides a bonus in curves
@@ -278,6 +278,10 @@
 	uint32 cached_veh_weight; ///< weight of the vehicle.
 	uint32 cached_max_te;     ///< max tractive effort of consist
 
+	/* cached max. speed / acceleration data */
+	uint16 cached_max_speed;    ///< max speed of the consist. (minimum of the max speed of all vehicles in the consist)
+	int cached_max_curve_speed; ///< max consist speed limited by curves
+
 	/**
 	 * Position/type of visual effect.
 	 * bit 0 - 3 = position of effect relative to vehicle. (0 = front, 8 = centre, 15 = rear)
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -342,6 +342,7 @@
 	/* store consist weight/max speed in cache */
 	v->tcache.cached_max_speed = max_speed;
 	v->tcache.cached_tilt = train_can_tilt;
+	v->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(v);
 
 	/* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
 	TrainCargoChanged(v);
@@ -406,12 +407,19 @@
 	return stop - (v->tcache.cached_veh_length + 1) / 2;
 }
 
-/** new acceleration*/
-static int GetTrainAcceleration(Train *v, bool mode)
+
+/**
+ * Computes train speed limit caused by curves
+ * @param v first vehicle of consist
+ * @return imposed speed limit
+ */
+int GetTrainCurveSpeedLimit(Train *v)
 {
 	static const int absolute_max_speed = UINT16_MAX;
 	int max_speed = absolute_max_speed;
-	int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
+
+	if (_settings_game.vehicle.train_acceleration_model == TAM_ORIGINAL) return max_speed;
+
 	int curvecount[2] = {0, 0};
 
 	/* first find the curve speed limit */
@@ -445,13 +453,11 @@
 		}
 	}
 
-	if ((curvecount[0] != 0 || curvecount[1] != 0) && max_speed > 88) {
-		int total = curvecount[0] + curvecount[1];
-
+	if (numcurve > 0 && max_speed > 88) {
 		if (curvecount[0] == 1 && curvecount[1] == 1) {
 			max_speed = absolute_max_speed;
-		} else if (total > 1) {
-			if (numcurve > 0) sum /= numcurve;
+		} else {
+			sum /= numcurve;
 			max_speed = 232 - (13 - Clamp(sum, 1, 12)) * (13 - Clamp(sum, 1, 12));
 		}
 	}
@@ -467,6 +473,16 @@
 		}
 	}
 
+	return max_speed;
+}
+
+/** new acceleration*/
+static int GetTrainAcceleration(Train *v, bool mode)
+{
+	int max_speed = v->tcache.cached_max_curve_speed;
+	assert(max_speed == GetTrainCurveSpeedLimit(v)); // safety check, will be removed later
+	int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
+
 	if (IsTileType(v->tile, MP_STATION) && IsFrontEngine(v)) {
 		StationID sid = GetStationIndex(v->tile);
 		if (v->current_order.ShouldStopAtStation(v, sid)) {
@@ -3425,18 +3441,6 @@
 	{0,       256 / 2, 256 / 4, 2}, ///< maglev
 };
 
-/** Modify the speed of the vehicle due to a turn */
-static inline void AffectSpeedByDirChange(Train *v, Direction new_dir)
-{
-	if (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL) return;
-
-	DirDiff diff = DirDifference(v->direction, new_dir);
-	if (diff == DIRDIFF_SAME) return;
-
-	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->railtype];
-	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
-}
-
 /** Modify the speed of the vehicle due to a change in altitude */
 static inline void AffectSpeedByZChange(Train *v, byte old_z)
 {
@@ -3637,7 +3641,9 @@
 
 static void TrainController(Train *v, Vehicle *nomove)
 {
+	Train *first = v->First();
 	Train *prev;
+	bool direction_changed = false; // has direction of any part changed?
 
 	/* For every vehicle after and including the given vehicle */
 	for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) {
@@ -3817,9 +3823,15 @@
 				 * has been updated by AfterSetTrainPos() */
 				update_signals_crossing = true;
 
-				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
-
-				v->direction = chosen_dir;
+				if (chosen_dir != v->direction) {
+					if (prev == NULL && _settings_game.vehicle.train_acceleration_model == TAM_ORIGINAL) {
+						const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->railtype];
+						DirDiff diff = DirDifference(v->direction, chosen_dir);
+						v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
+					}
+					direction_changed = true;
+					v->direction = chosen_dir;
+				}
 
 				if (IsFrontEngine(v)) {
 					v->load_unload_time_rem = 0;
@@ -3904,6 +3916,9 @@
 		/* Do not check on every tick to save some computing time. */
 		if (IsFrontEngine(v) && v->tick_counter % _settings_game.pf.path_backoff_interval == 0) CheckNextTrainTile(v);
 	}
+
+	if (direction_changed) first->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(first);
+
 	return;
 
 invalid_rail: