Changeset - r1917:37ea487ce1c2
[Not reviewed]
master
0 2 0
hackykid - 19 years ago 2005-06-06 14:26:15
hackykid@openttd.org
(svn r2423) - CodeChange: Include first_engine in the train cache, instead of calculating it all over the place.
- Fix: Also recalculate the train cache values for 'wagon chains' (in the depot without an engine), to avoid possible desyncs later.
- Fix: Make CmdMoveRailVehicle update the caches of the correct trains in all cases.
2 files changed with 55 insertions and 70 deletions:
0 comments (0 inline, 0 general)
train_cmd.c
Show inline comments
 
@@ -60,19 +60,31 @@ void TrainCargoChanged(Vehicle *v) {
 
}
 

	
 
/**
 
 * 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.
 
 * Recalculates the cached stuff of a train. Should be called each time a vehicle is added
 
 * to/removed from the chain, and when the game is loaded.
 
 * Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
 
 * @param v First vehicle of the chain.
 
 */
 
void TrainConsistChanged(Vehicle *v) {
 
	const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
 
	const RailVehicleInfo *rvi_v;
 
	Vehicle *u;
 
	uint16 max_speed = 0xFFFF;
 
	uint32 power = 0;
 
	EngineID first_engine;
 

	
 
	assert(v->type == VEH_Train);
 

	
 
	assert(v->subtype == TS_Front_Engine || v->subtype == TS_Free_Car);
 

	
 
	rvi_v = RailVehInfo(v->engine_type);
 
	first_engine = (v->subtype == TS_Front_Engine) ? v->engine_type : INVALID_VEHICLE;
 

	
 
	for (u = v; u != NULL; u = u->next) {
 
		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
 

	
 
		// update the 'first engine'
 
		u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine;
 

	
 
		// power is the sum of the powers of all engines and powered wagons in the consist
 
		power += rvi_u->power;
 

	
 
@@ -449,11 +461,6 @@ static int32 CmdBuildRailWagon(uint engi
 
			if (u != NULL) {
 
				u->next = v;
 
				v->subtype = TS_Not_First;
 
				v->u.rail.first_engine = u->u.rail.first_engine;
 
				if (v->u.rail.first_engine == 0xffff && u->subtype == TS_Front_Engine)
 
					v->u.rail.first_engine = u->engine_type;
 
			} else {
 
				v->u.rail.first_engine = 0xffff;
 
			}
 

	
 
			v->cargo_type = rvi->cargo_type;
 
@@ -471,6 +478,7 @@ static int32 CmdBuildRailWagon(uint engi
 
			_new_wagon_id = v->index;
 

	
 
			VehiclePositionChanged(v);
 
			TrainConsistChanged(GetFirstVehicleInChain(v));
 

	
 
			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		}
 
@@ -547,7 +555,6 @@ void AddRearEngineToMultiheadedTrain(Veh
 
	u->z_pos = v->z_pos;
 
	u->z_height = 6;
 
	u->u.rail.track = 0x80;
 
	v->u.rail.first_engine = 0xffff;
 
	u->vehstatus = v->vehstatus & ~VS_STOPPED;
 
	u->subtype = TS_Not_First;
 
	u->spritenum = v->spritenum + 1;
 
@@ -620,7 +627,6 @@ int32 CmdBuildRailVehicle(int x, int y, 
 
			v->z_pos = GetSlopeZ(x,y);
 
			v->z_height = 6;
 
			v->u.rail.track = 0x80;
 
			v->u.rail.first_engine = 0xffff;
 
			v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
 
			v->spritenum = rvi->image_index;
 
			v->cargo_type = rvi->cargo_type;
 
@@ -705,14 +711,11 @@ static Vehicle *UnlinkWagon(Vehicle *v, 
 
{
 
	Vehicle *u;
 

	
 
	v->u.rail.first_engine = INVALID_VEHICLE;
 

	
 
	// unlinking the first vehicle of the chain?
 
	if (v == first) {
 
		v = v->next;
 
		if (v == NULL) return NULL;
 

	
 
		for (u = v; u != NULL; u = u->next) u->u.rail.first_engine = v->engine_type;
 
		v->subtype = TS_Free_Car;
 
		return v;
 
	}
 
@@ -838,10 +841,12 @@ int32 CmdMoveRailVehicle(int x, int y, u
 
				Vehicle *v = src_head;
 
				while (v->next != src) v=v->next;
 
				v->next = NULL;
 
			} else {
 
				src_head = NULL;
 
			}
 
		} else {
 
			// unlink single wagon from linked list
 
			UnlinkWagon(src, src_head);
 
			src_head = UnlinkWagon(src, src_head);
 
			src->next = NULL;
 
		}
 

	
 
@@ -854,11 +859,10 @@ int32 CmdMoveRailVehicle(int x, int y, u
 
					assert(src->orders == NULL);
 
					src->num_orders = 0;
 
				}
 
				dst_head = src;
 
			} else {
 
				src->subtype = TS_Free_Car;
 
			}
 
			src->u.rail.first_engine = 0xffff;
 
			dst_head = src;
 
		} else {
 
			if (src->subtype == TS_Front_Engine) {
 
				// the vehicle was previously a loco. need to free the order list and delete vehicle windows etc.
 
@@ -869,44 +873,42 @@ int32 CmdMoveRailVehicle(int x, int y, u
 
			src->subtype = TS_Not_First;
 
			src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
 

	
 
			// setup first_engine
 
			src->u.rail.first_engine = dst->u.rail.first_engine;
 
			if (src->u.rail.first_engine == 0xffff && dst->subtype == TS_Front_Engine)
 
				src->u.rail.first_engine = dst->engine_type;
 

	
 
			// link in the wagon(s) in the chain.
 
			{
 
				Vehicle *v;
 

	
 
				for (v = src; v->next != NULL; v = v->next) {
 
					v->next->u.rail.first_engine = v->u.rail.first_engine;
 
				}
 
				for (v = src; v->next != NULL; v = v->next) {};
 
				v->next = dst->next;
 
			}
 
			dst->next = src;
 
		}
 

	
 
		if (src_head->subtype == TS_Front_Engine) {
 
		if (src_head) {
 
			TrainConsistChanged(src_head);
 
			UpdateTrainAcceleration(src_head);
 
		}
 
		InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index);
 
		InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
 
			if (src_head->subtype == TS_Front_Engine) {
 
				UpdateTrainAcceleration(src_head);
 
				InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index);
 
				/* Update the refit button and window */
 
				InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
 
				InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, 12);
 
			}
 
			/* Update the depot window */
 
			InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile);
 
		};
 

	
 
		if (dst_head) {
 
			TrainConsistChanged(dst_head);
 
			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);
 
				InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index);
 
			}
 
			InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index);
 
			/* Update the refit button and window */
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, 12);
 
			InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index);
 
			/* Update the depot window */
 
			InvalidateWindow(WC_VEHICLE_DEPOT, dst_head->tile);
 
		}
 

	
 
		/* I added this to so that the refit buttons get updated */
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, 12);
 
		InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile);
 
		RebuildVehicleLists();
 
	}
 

	
 
@@ -1048,11 +1050,13 @@ int32 CmdSellRailWagon(int x, int y, uin
 
				if (switch_engine) first->subtype = TS_Front_Engine;
 

	
 
				/* 5. If the train still exists, update its acceleration, window, etc. */
 
				if (first != NULL && first->subtype == TS_Front_Engine) {
 
					InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
 
					InvalidateWindow(WC_VEHICLE_REFIT, first->index);
 
				if (first != NULL) {
 
					TrainConsistChanged(first);
 
					UpdateTrainAcceleration(first);
 
					if (first->subtype == TS_Front_Engine) {
 
						InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
 
						InvalidateWindow(WC_VEHICLE_REFIT, first->index);
 
						UpdateTrainAcceleration(first);
 
					}
 
				}
 

	
 

	
 
@@ -1103,9 +1107,10 @@ int32 CmdSellRailWagon(int x, int y, uin
 
			}
 

	
 
			/* 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) {
 
			if ((flags & DC_EXEC) && first != NULL) {
 
				TrainConsistChanged(first);
 
				UpdateTrainAcceleration(first);
 
				if (first->subtype == TS_Front_Engine)
 
					UpdateTrainAcceleration(first);
 
			}
 
		} break;
 
	}
vehicle.c
Show inline comments
 
@@ -188,7 +188,7 @@ void AfterLoadVehicles(void)
 
			v->left_coord = INVALID_COORD;
 
			VehiclePositionChanged(v);
 

	
 
			if (v->type == VEH_Train && v->subtype == TS_Front_Engine)
 
			if (v->type == VEH_Train && (v->subtype == TS_Front_Engine || v->subtype == TS_Free_Car))
 
				TrainConsistChanged(v);
 
		}
 
	}
 
@@ -1392,12 +1392,12 @@ int32 CmdReplaceVehicle(int x, int y, ui
 
		if ( old_engine_type != new_engine_type ) {
 

	
 
			// prevent that the rear engine can get replaced to something else than the front engine
 
			if ( v->u.rail.first_engine != 0xffff && RailVehInfo(old_engine_type)->flags & RVI_MULTIHEAD && RailVehInfo(old_engine_type)->flags ) {
 
			if ( v->u.rail.first_engine != INVALID_VEHICLE && RailVehInfo(old_engine_type)->flags & RVI_MULTIHEAD && RailVehInfo(old_engine_type)->flags ) {
 
				if ( first->engine_type != new_engine_type ) return CMD_ERROR;
 
			}
 

	
 
			// checks if the engine is the first one
 
			if ( v->u.rail.first_engine == 0xffff ) {
 
			if ( v->u.rail.first_engine == INVALID_VEHICLE ) {
 
				if ( RailVehInfo(new_engine_type)->flags & RVI_MULTIHEAD ) {
 
					if ( u->engine_type == old_engine_type && v->next != NULL) {
 
						rear_engine_cost = build_cost - u->value;
 
@@ -1471,7 +1471,7 @@ int32 CmdReplaceVehicle(int x, int y, ui
 
				v->spritenum = rvi->image_index + (( rvi->flags & RVI_MULTIHEAD && sprite - rvi2->image_index) ? 1 : 0);
 

	
 
				// turn the last engine in a multiheaded train if needed
 
				if ( v->next == NULL && v->u.rail.first_engine != 0xffff && rvi->flags & RVI_MULTIHEAD && v->spritenum == rvi->image_index )
 
				if ( v->next == NULL && v->u.rail.first_engine != INVALID_VEHICLE && rvi->flags & RVI_MULTIHEAD && v->spritenum == rvi->image_index )
 
					v->spritenum++;
 

	
 
				v->cargo_type = rvi->cargo_type;
 
@@ -1517,14 +1517,8 @@ int32 CmdReplaceVehicle(int x, int y, ui
 
				}
 
#endif
 

	
 
				// updates the id of the front engine in the other units, since the front engine just got a new engine_id
 
				// this is needed for wagon override
 
				if ( v->u.rail.first_engine == 0xffff && v->next != NULL ) {
 
					Vehicle *veh = v->next;
 
					do {
 
						veh->u.rail.first_engine = new_engine_type;
 
					} while ( (veh=veh->next) != NULL );
 
				}
 
				// recalculate changed train values
 
				TrainConsistChanged(first);
 
				InvalidateWindowClasses(WC_TRAINS_LIST);
 
				UpdateTrainAcceleration(first);
 
				break;
 
@@ -2089,9 +2083,6 @@ static void Load_VEHS(void)
 
		v = GetVehicle(index);
 
		SlObject(v, _veh_descs[SlReadByte()]);
 

	
 
		if (v->type == VEH_Train)
 
			v->u.rail.first_engine = 0xffff;
 

	
 
		/* Old savegames used 'last_station_visited = 0xFF', should be 0xFFFF */
 
		if (_sl.version < 5 && v->last_station_visited == 0xFF)
 
			v->last_station_visited = 0xFFFF;
 
@@ -2104,17 +2095,6 @@ static void Load_VEHS(void)
 
		}
 
	}
 

	
 
	// Iterate through trains and set first_engine appropriately.
 
	FOR_ALL_VEHICLES(v) {
 
		Vehicle *w;
 

	
 
		if (v->type != VEH_Train || v->subtype != TS_Front_Engine)
 
			continue;
 

	
 
		for (w = v->next; w; w = w->next)
 
			w->u.rail.first_engine = v->engine_type;
 
	}
 

	
 
	/* Check for shared order-lists (we now use pointers for that) */
 
	if (_sl.full_version < 0x502) {
 
		FOR_ALL_VEHICLES(v) {
0 comments (0 inline, 0 general)