mirror of https://github.com/OpenTTD/OpenTTD
(svn r3403) -Codechange: [multiheaded engines] the references between the front and rear engines are no longer saved
instead the pointers are generated on loadrelease/0.4.5
parent
b87b5f1187
commit
e35a131153
|
@ -40,6 +40,7 @@
|
||||||
#include "depot.h"
|
#include "depot.h"
|
||||||
#include "waypoint.h"
|
#include "waypoint.h"
|
||||||
#include "ai/ai.h"
|
#include "ai/ai.h"
|
||||||
|
#include "train.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -1144,6 +1145,10 @@ bool AfterLoadGame(void)
|
||||||
* subtype to the new format */
|
* subtype to the new format */
|
||||||
if (CheckSavegameVersionOldStyle(17, 1)) ConvertOldMultiheadToNew();
|
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
|
// Update current year
|
||||||
SetDate(_date);
|
SetDate(_date);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SAVEGAME_VERSION = 19,
|
SAVEGAME_VERSION = 20,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
3
train.h
3
train.h
|
@ -205,4 +205,7 @@ static inline Vehicle *GetLastEnginePart(Vehicle *v)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConvertOldMultiheadToNew(void);
|
||||||
|
void ConnectMultiheadedTrains(void);
|
||||||
|
|
||||||
#endif /* TRAIN_H */
|
#endif /* TRAIN_H */
|
||||||
|
|
152
train_cmd.c
152
train_cmd.c
|
@ -3700,3 +3700,155 @@ void InitializeTrains(void)
|
||||||
{
|
{
|
||||||
_age_cargo_skip_counter = 1;
|
_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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
101
vehicle.c
101
vehicle.c
|
@ -2128,7 +2128,7 @@ static const SaveLoad _train_desc[] = {
|
||||||
|
|
||||||
SLE_CONDARR(NullStruct, null, SLE_FILE_U8 | SLE_VAR_NULL, 2, 2, 255),
|
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)
|
// reserve extra space in savegame here. (currently 3 bytes)
|
||||||
SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 3, 2, 255),
|
SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 3, 2, 255),
|
||||||
|
|
||||||
|
@ -2282,105 +2282,6 @@ static void Save_VEHS(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
// Will be called when vehicles need to be loaded.
|
||||||
static void Load_VEHS(void)
|
static void Load_VEHS(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -313,7 +313,6 @@ int32 GetTrainRunningCost(const Vehicle *v);
|
||||||
int CheckTrainStoppedInDepot(const Vehicle *v);
|
int CheckTrainStoppedInDepot(const Vehicle *v);
|
||||||
|
|
||||||
bool VehicleNeedsService(const Vehicle *v);
|
bool VehicleNeedsService(const Vehicle *v);
|
||||||
void ConvertOldMultiheadToNew(void);
|
|
||||||
|
|
||||||
typedef struct GetNewVehiclePosResult {
|
typedef struct GetNewVehiclePosResult {
|
||||||
int x,y;
|
int x,y;
|
||||||
|
|
Loading…
Reference in New Issue