# HG changeset patch # User bjarni # Date 1137596701 0 # Node ID 950b5a56f9d5fa5ad313817f690052f435df4c02 # Parent 6b85a5f4b65f89504cdbb4b4b9dfc13e98e378f1 (svn r3403) -Codechange: [multiheaded engines] the references between the front and rear engines are no longer saved instead the pointers are generated on load diff -r 6b85a5f4b65f -r 950b5a56f9d5 openttd.c --- a/openttd.c Wed Jan 18 14:12:26 2006 +0000 +++ b/openttd.c Wed Jan 18 15:05:01 2006 +0000 @@ -40,6 +40,7 @@ #include "depot.h" #include "waypoint.h" #include "ai/ai.h" +#include "train.h" #include @@ -1144,6 +1145,10 @@ * subtype to the new format */ if (CheckSavegameVersionOldStyle(17, 1)) ConvertOldMultiheadToNew(); + /* Connect front and rear engines of multiheaded trains + since this info were no longer saved in savegame version 20 */ + if (!CheckSavegameVersion(20)) ConnectMultiheadedTrains(); + // Update current year SetDate(_date); diff -r 6b85a5f4b65f -r 950b5a56f9d5 saveload.c --- a/saveload.c Wed Jan 18 14:12:26 2006 +0000 +++ b/saveload.c Wed Jan 18 15:05:01 2006 +0000 @@ -29,7 +29,7 @@ #include enum { - SAVEGAME_VERSION = 19, + SAVEGAME_VERSION = 20, }; diff -r 6b85a5f4b65f -r 950b5a56f9d5 train.h --- a/train.h Wed Jan 18 14:12:26 2006 +0000 +++ b/train.h Wed Jan 18 15:05:01 2006 +0000 @@ -205,4 +205,7 @@ return v; } +void ConvertOldMultiheadToNew(void); +void ConnectMultiheadedTrains(void); + #endif /* TRAIN_H */ diff -r 6b85a5f4b65f -r 950b5a56f9d5 train_cmd.c --- a/train_cmd.c Wed Jan 18 14:12:26 2006 +0000 +++ b/train_cmd.c Wed Jan 18 15:05:01 2006 +0000 @@ -3700,3 +3700,155 @@ { _age_cargo_skip_counter = 1; } + +/* + * Link front and rear multiheaded engines to each other + * This is done when loading a savegame + */ +void ConnectMultiheadedTrains(void) +{ + 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)) { + Vehicle *u = v; + + BEGIN_ENUM_WAGONS(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--; + } + + { + Vehicle *w; + + for(w = u->next; w != NULL && (w->engine_type != u->engine_type || w->u.rail.other_multiheaded_part != NULL); w = GetNextVehicle(w)); + if (w != NULL) { + /* 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++; + } + } + + 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); + } + } + } + } END_ENUM_WAGONS(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(void) +{ + 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)) { + Vehicle *u = v; + + BEGIN_ENUM_WAGONS(u) + const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); + CLRBIT(u->subtype, 7); + switch (u->subtype) { + case 0: /* TS_Front_Engine */ + if (rvi->flags & RVI_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->flags & RVI_WAGON) { + // normal wagon + SetTrainWagon(u); + break; + } + if (rvi->flags & RVI_MULTIHEAD && rvi->image_index == u->spritenum - 1) { + // rear end of a multiheaded engine + SetMultiheaded(u); + break; + } + if (rvi->flags & RVI_MULTIHEAD) { + SetMultiheaded(u); + } + SetTrainEngine(u); + break; + case 4: /* TS_Free_Car */ + u->subtype = 0; + SetTrainWagon(u); + SetFreeWagon(u); + break; + default: NOT_REACHED(); break; + } + END_ENUM_WAGONS(u) + u = v; + BEGIN_ENUM_WAGONS(u) + const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); + + if (u->u.rail.other_multiheaded_part != NULL) continue; + + if (rvi->flags & RVI_MULTIHEAD) { + if (!IsTrainEngine(u)) { + /* we got a rear car without a front car. We will convert it to a front one */ + SetTrainEngine(u); + u->spritenum--; + } + + { + Vehicle *w; + + for(w = u->next; w != NULL && (w->engine_type != u->engine_type || w->u.rail.other_multiheaded_part != NULL); w = GetNextVehicle(w)); + if (w != NULL) { + /* 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++; + } + } + + 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); + } + } + } + END_ENUM_WAGONS(u) + } + } + } +} diff -r 6b85a5f4b65f -r 950b5a56f9d5 vehicle.c --- a/vehicle.c Wed Jan 18 14:12:26 2006 +0000 +++ b/vehicle.c Wed Jan 18 15:05:01 2006 +0000 @@ -2128,7 +2128,7 @@ SLE_CONDARR(NullStruct, null, SLE_FILE_U8 | SLE_VAR_NULL, 2, 2, 255), - SLE_CONDREFX(offsetof(Vehicle,u)+offsetof(VehicleRail,other_multiheaded_part), REF_VEHICLE, 2, 255), // added with 17.1, but was blank since 2 + SLE_CONDREFX(offsetof(Vehicle,u)+offsetof(VehicleRail,other_multiheaded_part), REF_VEHICLE, 2, 19), // added with 17.1, but was blank since 2. Removed in 20 // reserve extra space in savegame here. (currently 3 bytes) SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 3, 2, 255), @@ -2282,105 +2282,6 @@ } } -/* - * 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(void) -{ - Vehicle *v; - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Train) { - v->u.rail.other_multiheaded_part = NULL; - 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)) { - Vehicle *u = v; - - BEGIN_ENUM_WAGONS(u) - const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); - CLRBIT(u->subtype, 7); - switch (u->subtype) { - case 0: /* TS_Front_Engine */ - if (rvi->flags & RVI_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->flags & RVI_WAGON) { - // normal wagon - SetTrainWagon(u); - break; - } - if (rvi->flags & RVI_MULTIHEAD && rvi->image_index == u->spritenum - 1) { - // rear end of a multiheaded engine - SetMultiheaded(u); - break; - } - if (rvi->flags & RVI_MULTIHEAD) { - SetMultiheaded(u); - } - SetTrainEngine(u); - break; - case 4: /* TS_Free_Car */ - u->subtype = 0; - SetTrainWagon(u); - SetFreeWagon(u); - break; - default: NOT_REACHED(); break; - } - END_ENUM_WAGONS(u) - u = v; - BEGIN_ENUM_WAGONS(u) - const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); - - if (u->u.rail.other_multiheaded_part != NULL) continue; - - if (rvi->flags & RVI_MULTIHEAD) { - if (!IsTrainEngine(u)) { - /* we got a rear car without a front car. We will convert it to a front one */ - SetTrainEngine(u); - u->spritenum--; - } - - { - Vehicle *w; - - for(w = u->next; w != NULL && (w->engine_type != u->engine_type || w->u.rail.other_multiheaded_part != NULL); w = GetNextVehicle(w)); - if (w != NULL) { - /* 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++; - } - } - - 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); - } - } - } - END_ENUM_WAGONS(u) - } - } - } -} - // Will be called when vehicles need to be loaded. static void Load_VEHS(void) { diff -r 6b85a5f4b65f -r 950b5a56f9d5 vehicle.h --- a/vehicle.h Wed Jan 18 14:12:26 2006 +0000 +++ b/vehicle.h Wed Jan 18 15:05:01 2006 +0000 @@ -313,7 +313,6 @@ int CheckTrainStoppedInDepot(const Vehicle *v); bool VehicleNeedsService(const Vehicle *v); -void ConvertOldMultiheadToNew(void); typedef struct GetNewVehiclePosResult { int x,y;