@@ -209,6 +209,9 @@ void AfterLoadVehicles()
Vehicle *v;

FOR_ALL_VEHICLES(v) {
/* Reinstate the previous pointer */
if (v->Next() != NULL) v->Next()->previous = v;

v->UpdateDeltaXY(v->direction);

v->fill_percent_te_id = INVALID_TE_ID;
@@ -220,6 +223,17 @@ void AfterLoadVehicles()
}

FOR_ALL_VEHICLES(v) {
/* Fill the first pointers */
if (v->Previous() == NULL) {
for (Vehicle *u = v; u != NULL; u = u->Next()) {
u->first = v;
}
}
}

FOR_ALL_VEHICLES(v) {
assert(v->first != NULL);

if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
TrainConsistChanged(v);
} else if (v->type == VEH_ROAD && IsRoadVehFront(v)) {
@@ -269,6 +283,7 @@ Vehicle::Vehicle()
this->left_coord = INVALID_COORD;
this->group_id = DEFAULT_GROUP;
this->fill_percent_te_id = INVALID_TE_ID;
this->first = this;
}

/**
@@ -466,78 +481,6 @@ Vehicle *GetLastVehicleInChain(Vehicle *v)
return v;
}

/** Finds the previous vehicle in a chain, by a brute force search.
* This old function is REALLY slow because it searches through all vehicles to
* find the previous vehicle, but if v->first has not been set, then this function
* will need to be used to find the previous one. This function should never be
* called by anything but GetFirstVehicleInChain
*/
static Vehicle *GetPrevVehicleInChain_bruteforce(const Vehicle *v)
{
Vehicle *u;

FOR_ALL_VEHICLES(u) if (u->type == v->type && u->Next() == v) return u;

return NULL;
}

/** Find the previous vehicle in a chain, by using the v->first cache.
* While this function is fast, it cannot be used in the GetFirstVehicleInChain
* function, otherwise you'll end up in an infinite loop call
*/
Vehicle *GetPrevVehicleInChain(const Vehicle *v)
{
Vehicle *u;
assert(v != NULL);

u = GetFirstVehicleInChain(v);

/* Check to see if this is the first */
if (v == u) return NULL;

for (; u->Next() != v; u = u->Next()) assert(u->Next() != NULL);

return u;
}

/** Finds the first vehicle in a chain.
* This function reads out the v->first cache. Should the cache be dirty,
* it determines the first vehicle in a chain, and updates the cache.
*/
Vehicle *GetFirstVehicleInChain(const Vehicle *v)
{
Vehicle* u;

assert(v != NULL);
assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);

if (v->first != NULL) {
if (v->type == VEH_TRAIN) {
if (IsFrontEngine(v->first) || IsFreeWagon(v->first)) return v->first;
} else {
if (IsRoadVehFront(v->first)) return v->first;
}

DEBUG(misc, 0, "v->first cache faulty. We shouldn't be here, rebuilding cache!");
}

/* It is the fact (currently) that newly built vehicles do not have
* their ->first pointer set. When this is the case, go up to the
* first engine and set the pointers correctly. Also the first pointer
* is not saved in a savegame, so this has to be fixed up after loading */

/* Find the 'locomotive' or the first wagon in a chain */
while ((u = GetPrevVehicleInChain_bruteforce(v)) != NULL) v = u;

/* Set the first pointer of all vehicles in that chain to the first wagon */
if ((v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) ||
(v->type == VEH_ROAD && IsRoadVehFront(v))) {
for (u = (Vehicle *)v; u != NULL; u = u->Next()) u->first = (Vehicle *)v;
}

return (Vehicle*)v;
}

uint CountVehiclesInChain(const Vehicle* v)
{
uint count = 0;
@@ -2179,14 +2122,14 @@ void VehicleEnterDepot(Vehicle *v)
switch (v->type) {
case VEH_TRAIN:
InvalidateWindowClasses(WC_TRAINS_LIST);
if (!IsFrontEngine(v)) v = GetFirstVehicleInChain(v);
if (!IsFrontEngine(v)) v = v->First();
UpdateSignalsOnSegment(v->tile, GetRailDepotDirection(v->tile));
v->load_unload_time_rem = 0;
break;

case VEH_ROAD:
InvalidateWindowClasses(WC_ROADVEH_LIST);
if (!IsRoadVehFront(v)) v = GetFirstVehicleInChain(v);
if (!IsRoadVehFront(v)) v = v->First();
break;

case VEH_SHIP:
@@ -3168,6 +3111,28 @@ void Vehicle::HandleLoading(bool mode)
InvalidateVehicleOrder(this);
}

void Vehicle::SetNext(Vehicle *next)
{
if (this->next != NULL) {
/* We had an old next vehicle. Update the first and previous pointers */
for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
v->first = this->next;
}
this->next->previous = NULL;
}

this->next = next;

if (this->next != NULL) {
/* A new next vehicle. Update the first and previous pointers */
if (this->next->previous != NULL) this->next->previous->next = NULL;
this->next->previous = this;
for (Vehicle *v = this->next; v != NULL; v = v->Next()) {
v->first = this->first;
}
}
}

void SpecialVehicle::UpdateDeltaXY(Direction direction)
{
this->x_offs = 0;
@@ -219,18 +219,21 @@ struct Vehicle;
DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 125)

struct SaveLoad;
extern const SaveLoad *GetVehicleDescription(VehicleType vt);
const SaveLoad *GetVehicleDescription(VehicleType vt);
void AfterLoadVehicles();

struct Vehicle : PoolItem<Vehicle, VehicleID, &_Vehicle_pool> {
VehicleTypeByte type; ///< Type of vehicle
byte subtype; // subtype (Filled with values from EffectVehicles/TrainSubTypes/AircraftSubTypes)

private:
Vehicle *next; // pointer to the next vehicle in the chain
Vehicle *previous; // NOSAVE: pointer to the previous vehicle in the chain
Vehicle *first; // NOSAVE: pointer to the first vehicle in the chain
public:
friend const SaveLoad *GetVehicleDescription(VehicleType vt); // So we can use private/protected variables in the saveload code
friend void AfterLoadVehicles();

Vehicle *first; // NOSAVE: pointer to the first vehicle in the chain
Vehicle *depot_list; // NOSAVE: linked list to tell what vehicles entered a depot during the last tick. Used by autoreplace

StringID string_id; // Displayed string
@@ -472,14 +475,27 @@ struct Vehicle : PoolItem<Vehicle, VehicleID, &_Vehicle_pool> {
* Set the next vehicle of this vehicle.
* @param next the next vehicle. NULL removes the next vehicle.
*/
void SetNext(Vehicle *next) { this->next = next; }
void SetNext(Vehicle *next);

/**
* Get the next vehicle of this vehicle.
* @note articulated parts are also counted as vehicles.
* @return the next vehicle or NULL when there isn't a next vehicle.
*/
inline Vehicle *Next() const { return this->next; }

/**
* Get the previous vehicle of this vehicle.
* @note articulated parts are also counted as vehicles.
* @return the previous vehicle or NULL when there isn't a previous vehicle.
*/
inline Vehicle *Previous() const { return this->previous; }

/**
* Get the first vehicle of this vehicle chain.
* @return the first vehicle of the chain.
*/
inline Vehicle *First() const { return this->first; }
};

/**
@@ -556,10 +572,7 @@ typedef void *VehicleFromPosProc(Vehicle *v, void *data);

void VehicleServiceInDepot(Vehicle *v);
void VehiclePositionChanged(Vehicle *v);
void AfterLoadVehicles();
Vehicle *GetLastVehicleInChain(Vehicle *v);
Vehicle *GetPrevVehicleInChain(const Vehicle *v);
Vehicle *GetFirstVehicleInChain(const Vehicle *v);
uint CountVehiclesInChain(const Vehicle *v);
bool IsEngineCountable(const Vehicle *v);
void DeleteVehicleChain(Vehicle *v);
@@ -1786,13 +1786,13 @@ static void CheckClickOnLandscape(const ViewPort *vp, int x, int y)

static void SafeShowTrainViewWindow(const Vehicle* v)
{
if (!IsFrontEngine(v)) v = GetFirstVehicleInChain(v);
if (!IsFrontEngine(v)) v = v->First();
ShowVehicleViewWindow(v);
}

static void SafeShowRoadVehViewWindow(const Vehicle *v)
{
if (!IsRoadVehFront(v)) v = GetFirstVehicleInChain(v);
if (!IsRoadVehFront(v)) v = v->First();
ShowVehicleViewWindow(v);
}

@@ -658,7 +658,7 @@ static void FloodVehicle(Vehicle *v)
}
Vehicle *u;

if (v->type != VEH_AIRCRAFT) v = GetFirstVehicleInChain(v);
if (v->type != VEH_AIRCRAFT) v = v->First();
u = v;

/* crash all wagons, and count passengers */