File diff r10570:e200b86ce378 → r10571:99cb9a95b4cf
src/train_cmd.cpp
Show inline comments
 
@@ -4500,146 +4500,3 @@ void InitializeTrains()
 
{
 
	_age_cargo_skip_counter = 1;
 
}
 

	
 
/*
 
 * Link front and rear multiheaded engines to each other
 
 * This is done when loading a savegame
 
 */
 
void ConnectMultiheadedTrains()
 
{
 
	Vehicle *v;
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type == VEH_TRAIN) {
 
			v->u.rail.other_multiheaded_part = NULL;
 
		}
 
	}
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
 
			/* Two ways to associate multiheaded parts to each other:
 
			 * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
 
			 * bracket-matching:    Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
 
			 *
 
			 * Note: Old savegames might contain chains which do not comply with these rules, e.g.
 
			 *   - the front and read parts have invalid orders
 
			 *   - different engine types might be combined
 
			 *   - there might be different amounts of front and rear parts.
 
			 *
 
			 * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
 
			 *   This is why two matching strategies are needed.
 
			 */
 

	
 
			bool sequential_matching = IsFrontEngine(v);
 

	
 
			for (Vehicle *u = v; u != NULL; u = GetNextVehicle(u)) {
 
				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
 

	
 
				if (IsMultiheaded(u)) {
 
					if (!IsTrainEngine(u)) {
 
						/* we got a rear car without a front car. We will convert it to a front one */
 
						SetTrainEngine(u);
 
						u->spritenum--;
 
					}
 

	
 
					/* Find a matching back part */
 
					EngineID eid = u->engine_type;
 
					Vehicle *w;
 
					if (sequential_matching) {
 
						for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
 
							if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
 

	
 
							/* we found a car to partner with this engine. Now we will make sure it face the right way */
 
							if (IsTrainEngine(w)) {
 
								ClearTrainEngine(w);
 
								w->spritenum++;
 
							}
 
							break;
 
						}
 
					} else {
 
						uint stack_pos = 0;
 
						for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
 
							if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
 

	
 
							if (IsTrainEngine(w)) {
 
								stack_pos++;
 
							} else {
 
								if (stack_pos == 0) break;
 
								stack_pos--;
 
							}
 
						}
 
					}
 

	
 
					if (w != NULL) {
 
						w->u.rail.other_multiheaded_part = u;
 
						u->u.rail.other_multiheaded_part = w;
 
					} else {
 
						/* we got a front car and no rear cars. We will fake this one for forget that it should have been multiheaded */
 
						ClearMultiheaded(u);
 
					}
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 *  Converts all trains to the new subtype format introduced in savegame 16.2
 
 *  It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
 
 */
 
void ConvertOldMultiheadToNew()
 
{
 
	Vehicle *v;
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type == VEH_TRAIN) {
 
			SetBit(v->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop
 
		}
 
	}
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type == VEH_TRAIN) {
 
			if (HasBit(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
 
				for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
					const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
 

	
 
					ClrBit(u->subtype, 7);
 
					switch (u->subtype) {
 
						case 0: /* TS_Front_Engine */
 
							if (rvi->railveh_type == RAILVEH_MULTIHEAD) SetMultiheaded(u);
 
							SetFrontEngine(u);
 
							SetTrainEngine(u);
 
							break;
 

	
 
						case 1: /* TS_Artic_Part */
 
							u->subtype = 0;
 
							SetArticulatedPart(u);
 
							break;
 

	
 
						case 2: /* TS_Not_First */
 
							u->subtype = 0;
 
							if (rvi->railveh_type == RAILVEH_WAGON) {
 
								// normal wagon
 
								SetTrainWagon(u);
 
								break;
 
							}
 
							if (rvi->railveh_type == RAILVEH_MULTIHEAD && rvi->image_index == u->spritenum - 1) {
 
								// rear end of a multiheaded engine
 
								SetMultiheaded(u);
 
								break;
 
							}
 
							if (rvi->railveh_type == RAILVEH_MULTIHEAD) SetMultiheaded(u);
 
							SetTrainEngine(u);
 
							break;
 

	
 
						case 4: /* TS_Free_Car */
 
							u->subtype = 0;
 
							SetTrainWagon(u);
 
							SetFreeWagon(u);
 
							break;
 
						default: NOT_REACHED(); break;
 
					}
 
				}
 
			}
 
		}
 
	}
 
}