(svn r2411) - Codechange: Have trains cache stuff like consist power/weight/max speed instead of recalculating it each time.
authorhackykid
Sun, 05 Jun 2005 15:37:00 +0000
changeset 1905 f43d9e821deb
parent 1904 cf8a8adc33c9
child 1906 f5ae1d8ad052
(svn r2411) - Codechange: Have trains cache stuff like consist power/weight/max speed instead of recalculating it each time.
- Fix: Station ratings now depends on the max speed of a consist, without being affected by other speed limits from realistic acceleration.
economy.c
train_cmd.c
train_gui.c
vehicle.c
vehicle.h
--- a/economy.c	Sun Jun 05 05:35:12 2005 +0000
+++ b/economy.c	Sun Jun 05 15:37:00 2005 +0000
@@ -1405,6 +1405,7 @@
 		ge->days_since_pickup = 0;
 		t = u->max_speed;
 		if (u->type == VEH_Road) t >>=1;
+		if (u->type == VEH_Train) t = u->u.rail.cached_max_speed;
 
 		// if last speed is 0, we treat that as if no vehicle has ever visited the station.
 		ge->last_speed = t < 255 ? t : 255;
--- a/train_cmd.c	Sun Jun 05 05:35:12 2005 +0000
+++ b/train_cmd.c	Sun Jun 05 15:37:00 2005 +0000
@@ -28,6 +28,62 @@
 static const byte _vehicle_initial_y_fract[4] = {8,4,8,10};
 static const byte _state_dir_table[4] = { 0x20, 8, 0x10, 4 };
 
+/**
+ * Recalculates the cached weight of a train and its vehicles. Should be called each time the cargo on
+ * the consist changes.
+ * @param v First vehicle of the consist.
+ */
+void TrainCargoChanged(Vehicle *v) {
+	Vehicle *u;
+	uint16 weight = 0;
+
+	for (u = v; u != NULL; u = u->next) {
+		const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
+		uint16 vweight = 0;
+
+		// vehicle weight is the sum of the weight of the vehicle and the wait of its cargo
+		vweight += rvi->weight;
+		vweight += (_cargoc.weights[u->cargo_type] * u->cargo_count) / 16;
+
+		// consist weight is the sum of the weight of all vehicles in the consist
+		weight += vweight;
+
+		// store vehicle weight in cache
+		u->u.rail.cached_veh_weight = vweight;
+	};
+
+	// store consist weight in cache
+	v->u.rail.cached_weight = weight;
+}
+
+/**
+ * Recalculates the cached stuff of a train. Should be called each time a vehicle is added to/removed from
+ * the consist, and when the game is loaded.
+ * @param v First vehicle of the consist.
+ */
+void TrainConsistChanged(Vehicle *v) {
+	Vehicle *u;
+	uint16 max_speed = 0xFFFF;
+	uint32 power = 0;
+
+	// recalculate cached weights too
+	TrainCargoChanged(v);
+
+	for (u = v; u != NULL; u = u->next) {
+		const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
+
+		// power is the sum of the powers of all engines in the consist
+		power += rvi->power;
+
+		// max speed is the minimun of the speed limits of all vehicles in the consist
+		if (rvi->max_speed != 0)
+			max_speed = min(rvi->max_speed, max_speed);
+	};
+
+	// store consist weight/max speed in cache
+	v->u.rail.cached_max_speed = max_speed;
+	v->u.rail.cached_power = power;
+}
 
 /* These two arrays are used for realistic acceleration. XXX: How should they
  * be interpreted? */
@@ -164,38 +220,26 @@
 		}
 	}
 
+	mass = v->u.rail.cached_weight;
+	power = v->u.rail.cached_power * 746;
+	max_speed = min(max_speed, v->u.rail.cached_max_speed);
+
 	for (u = v; u != NULL; u = u->next) {
-		const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
-		int vmass;
-
 		num++;
-		power += rvi->power * 746;	//[W]
 		drag_coeff += 3;
 
-		if (rvi->max_speed != 0)
-			max_speed = min(rvi->max_speed, max_speed);
-
 		if (u->u.rail.track == 0x80)
 			max_speed = min(61, max_speed);
 
-		vmass = rvi->weight;  //[t]
-		vmass += (_cargoc.weights[u->cargo_type] * u->cargo_count) / 16;
-		mass += vmass; //[t]
-
 		if (HASBIT(u->u.rail.flags, VRF_GOINGUP)) {
-			incl += vmass * 60;		//3% slope, quite a bit actually
+			incl += u->u.rail.cached_veh_weight * 60;		//3% slope, quite a bit actually
 		} else if (HASBIT(u->u.rail.flags, VRF_GOINGDOWN)) {
-			incl -= vmass * 60;
+			incl -= u->u.rail.cached_veh_weight * 60;
 		}
 	}
 
-
-	// these are shown in the UI
-	v->u.rail.cached_weight = mass;
-	v->u.rail.cached_power = power / 746;
 	v->max_speed = max_speed;
 
-
 	if (v->u.rail.railtype != 2) {
 		resistance = 13 * mass / 10;
 		resistance += 60 * num;
@@ -238,32 +282,13 @@
 void UpdateTrainAcceleration(Vehicle *v)
 {
 	uint power = 0;
-	uint max_speed = 5000;
 	uint weight = 0;
-	Vehicle *u = v;
 
 	assert(v->subtype == TS_Front_Engine);
 
-	// compute stuff like max speed, power, and weight.
-	for (; u != NULL; u = u->next) {
-		const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
-
-		// power is sum of the power for all engines
-		power += rvi->power;
-
-		// limit the max speed to the speed of the slowest vehicle.
-		if (rvi->max_speed != 0 && rvi->max_speed <= max_speed)
-			max_speed = rvi->max_speed;
-
-		// weight is the sum of the weight of the wagon and the weight of the cargo.
-		weight += rvi->weight;
-		weight += (_cargoc.weights[u->cargo_type] * u->cargo_count) / 16;
-	}
-
-	// these are shown in the UI
-	v->u.rail.cached_weight = weight;
-	v->u.rail.cached_power = power;
-	v->max_speed = max_speed;
+	weight = v->u.rail.cached_weight;
+	power = v->u.rail.cached_power;
+	v->max_speed = v->u.rail.cached_max_speed;
 
 	assert(weight != 0);
 
@@ -605,6 +630,7 @@
 			if (rvi->flags&RVI_MULTIHEAD && (u = AllocateVehicle()) != NULL)
 				AddRearEngineToMultiheadedTrain(v, u, true);
 
+			TrainConsistChanged(v);
 			UpdateTrainAcceleration(v);
 			NormalizeTrainVehInDepot(v);
 
@@ -838,14 +864,18 @@
 			dst->next = src;
 		}
 
-		if (src_head->subtype == TS_Front_Engine)
+		if (src_head->subtype == TS_Front_Engine) {
+			TrainConsistChanged(src_head);
 			UpdateTrainAcceleration(src_head);
+		}
 		InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index);
 		InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
 
 		if (dst_head) {
-			if (dst_head->subtype == TS_Front_Engine)
+			if (dst_head->subtype == TS_Front_Engine) {
+				TrainConsistChanged(dst_head);
 				UpdateTrainAcceleration(dst_head);
+			}
 			InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index);
 			/* Update the refit button and window */
 			InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, 12);
@@ -999,6 +1029,7 @@
 				if (first != NULL && first->subtype == TS_Front_Engine) {
 					InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
 					InvalidateWindow(WC_VEHICLE_REFIT, first->index);
+					TrainConsistChanged(first);
 					UpdateTrainAcceleration(first);
 				}
 
@@ -1049,8 +1080,11 @@
 				}
 			}
 
-			/* 3. If it is still a valid train after selling, update its acceleration */
-			if ((flags & DC_EXEC) && first != NULL && first->subtype == TS_Front_Engine) UpdateTrainAcceleration(first);
+			/* 3. If it is still a valid train after selling, update its acceleration and cached values */
+			if ((flags & DC_EXEC) && first != NULL && first->subtype == TS_Front_Engine) {
+				TrainConsistChanged(first);
+				UpdateTrainAcceleration(first);
+			}
 		} break;
 	}
 	return cost;
@@ -2116,7 +2150,8 @@
 				InvalidateWindow(WC_TRAINS_LIST, v->owner);
 				MarkTrainDirty(v);
 
-				// need to update acceleration since the goods on the train changed.
+				// need to update acceleration and cached values since the goods on the train changed.
+				TrainCargoChanged(v);
 				UpdateTrainAcceleration(v);
 			}
 			return;
@@ -2212,6 +2247,7 @@
 	if (LoadUnloadVehicle(v) != 0) {
 		InvalidateWindow(WC_TRAINS_LIST, v->owner);
 		MarkTrainDirty(v);
+		TrainCargoChanged(v);
 		UpdateTrainAcceleration(v);
 	}
 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
--- a/train_gui.c	Sun Jun 05 05:35:12 2005 +0000
+++ b/train_gui.c	Sun Jun 05 15:37:00 2005 +0000
@@ -979,7 +979,6 @@
 {
 	const Vehicle *v, *u;
 	uint16 tot_cargo[NUM_CARGO][2];	// count total cargo ([0]-actual cargo, [1]-total cargo)
-	int max_speed = 0xFFFF;
 	int i,num,x,y,sel;
 	StringID str;
 	byte det_tab = WP(w, traindetails_d).tab;
@@ -999,8 +998,6 @@
 			tot_cargo[u->cargo_type][0] += u->cargo_count;
 			tot_cargo[u->cargo_type][1] += u->cargo_cap;
 		}
-		if (RailVehInfo(u->engine_type)->max_speed != 0)
-			max_speed = min(max_speed, RailVehInfo(u->engine_type)->max_speed);
 	} while ( (u = u->next) != NULL);
 
 	/*	set scroll-amount seperately from counting, as to not
@@ -1043,7 +1040,7 @@
 	SetDParam(3, GetTrainRunningCost(v) >> 8);
 	DrawString(x, 15, STR_885D_AGE_RUNNING_COST_YR, 0);
 
-	SetDParam(2, max_speed * 10 >> 4);
+	SetDParam(2, v->u.rail.cached_max_speed * 10 >> 4);
 	SetDParam(1, v->u.rail.cached_power);
 	SetDParam(0, v->u.rail.cached_weight);
 	DrawString(x, 25, STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED, 0);
--- a/vehicle.c	Sun Jun 05 05:35:12 2005 +0000
+++ b/vehicle.c	Sun Jun 05 15:37:00 2005 +0000
@@ -188,10 +188,8 @@
 			v->left_coord = INVALID_COORD;
 			VehiclePositionChanged(v);
 
-			if (!_patches.realistic_acceleration && v->type == VEH_Train) {
-				if (v->subtype == TS_Front_Engine)
-					UpdateTrainAcceleration(v);
-			}
+			if (v->type == VEH_Train && v->subtype == TS_Front_Engine)
+				TrainConsistChanged(v);
 		}
 	}
 }
--- a/vehicle.h	Sun Jun 05 05:35:12 2005 +0000
+++ b/vehicle.h	Sun Jun 05 15:37:00 2005 +0000
@@ -50,8 +50,12 @@
 	uint16 crash_anim_pos;
 	uint16 days_since_order_progr;
 
-	uint16 cached_weight; // cached power and weight for the vehicle.
-	uint32 cached_power;  // no need to save those, they are recomputed on load.
+	// cached values, recalculated on load and each time a vehicle is added to/removed from the consist.
+	uint16 cached_max_speed;  // max speed of the consist. (minimum of the max speed of all vehicles in the consist)
+	uint32 cached_power;      // total power of the consist.
+	// cached values, recalculated when the cargo on a train changes (in addition to the conditions above)
+	uint16 cached_weight;     // total weight of the consist.
+	uint16 cached_veh_weight; // weight of the vehicle.
 
 	// NOSAVE: for wagon override - id of the first engine in train
 	// 0xffff == not in train
@@ -307,6 +311,7 @@
 
 int LoadUnloadVehicle(Vehicle *v);
 
+void TrainConsistChanged(Vehicle *v);
 void UpdateTrainAcceleration(Vehicle *v);
 int32 GetTrainRunningCost(const Vehicle *v);