diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -161,8 +161,8 @@ void TrainConsistChanged(Vehicle* v) for (Vehicle *u = v; u != NULL; u = u->Next()) { const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); - /* Update the v->first cache. This is faster than having to brute force it later. */ - if (u->first == NULL) u->first = v; + /* Check the v->first cache. */ + assert(u->First() == v); /* update the 'first engine' */ u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine; @@ -583,8 +583,8 @@ static CommandCost CmdBuildRailWagon(Eng _new_vehicle_id = v->index; VehiclePositionChanged(v); - TrainConsistChanged(GetFirstVehicleInChain(v)); - UpdateTrainGroupID(GetFirstVehicleInChain(v)); + TrainConsistChanged(v->First()); + UpdateTrainGroupID(v->First()); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); if (IsLocalPlayer()) { @@ -620,6 +620,7 @@ static CommandCost EstimateTrainCost(Eng static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building) { + u = new (u) Train(); u->direction = v->direction; u->owner = v->owner; u->tile = v->tile; @@ -628,7 +629,6 @@ static void AddRearEngineToMultiheadedTr u->z_pos = v->z_pos; u->u.rail.track = TRACK_BIT_DEPOT; u->vehstatus = v->vehstatus & ~VS_STOPPED; - u = new (u) Train(); u->subtype = 0; SetMultiheaded(u); u->spritenum = v->spritenum + 1; @@ -841,7 +841,6 @@ static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *u; for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {} GetLastEnginePart(u)->SetNext(GetNextVehicle(v)); - v->first = NULL; // we shouldn't point to the old first, since the vehicle isn't in that chain anymore return first; } @@ -872,11 +871,12 @@ static Vehicle *FindGoodVehiclePos(const */ static void AddWagonToConsist(Vehicle *v, Vehicle *dest) { - UnlinkWagon(v, GetFirstVehicleInChain(v)); + UnlinkWagon(v, v->First()); if (dest == NULL) return; - v->SetNext(dest->Next()); + Vehicle *next = dest->Next(); dest->SetNext(v); + v->SetNext(next); ClearFreeWagon(v); ClearFrontEngine(v); } @@ -933,19 +933,19 @@ CommandCost CmdMoveRailVehicle(TileIndex } /* if an articulated part is being handled, deal with its parent vehicle */ - while (IsArticulatedPart(src)) src = GetPrevVehicleInChain(src); + while (IsArticulatedPart(src)) src = src->Previous(); if (dst != NULL) { - while (IsArticulatedPart(dst)) dst = GetPrevVehicleInChain(dst); + while (IsArticulatedPart(dst)) dst = dst->Previous(); } /* don't move the same vehicle.. */ if (src == dst) return CommandCost(); /* locate the head of the two chains */ - Vehicle *src_head = GetFirstVehicleInChain(src); + Vehicle *src_head = src->First(); Vehicle *dst_head; if (dst != NULL) { - dst_head = GetFirstVehicleInChain(dst); + dst_head = dst->First(); if (dst_head->tile != src_head->tile) return CMD_ERROR; /* Now deal with articulated part of destination wagon */ dst = GetLastEnginePart(dst); @@ -1022,10 +1022,6 @@ CommandCost CmdMoveRailVehicle(TileIndex /* do it? */ if (flags & DC_EXEC) { - /* clear the ->first cache */ - for (Vehicle *u = src_head; u != NULL; u = u->Next()) u->first = NULL; - for (Vehicle *u = dst_head; u != NULL; u = u->Next()) u->first = NULL; - /* If we move the front Engine and if the second vehicle is not an engine add the whole vehicle to the DEFAULT_GROUP */ if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) { @@ -1101,13 +1097,12 @@ CommandCost CmdMoveRailVehicle(TileIndex } dst->SetNext(src); } + if (src->u.rail.other_multiheaded_part != NULL) { if (src->u.rail.other_multiheaded_part == src_head) { src_head = src_head->Next(); } AddWagonToConsist(src->u.rail.other_multiheaded_part, src); - /* previous line set the front engine to the old front. We need to clear that */ - src->u.rail.other_multiheaded_part->first = NULL; } /* If there is an engine behind first_engine we moved away, it should become new first_engine @@ -1218,8 +1213,8 @@ CommandCost CmdSellRailWagon(TileIndex t SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - while (IsArticulatedPart(v)) v = GetPrevVehicleInChain(v); - Vehicle *first = GetFirstVehicleInChain(v); + while (IsArticulatedPart(v)) v = v->Previous(); + Vehicle *first = v->First(); /* make sure the vehicle is stopped in the depot */ if (CheckTrainStoppedInDepot(first) < 0) { @@ -1262,9 +1257,6 @@ CommandCost CmdSellRailWagon(TileIndex t if ((flags & DC_EXEC) && v == first) { Vehicle *new_f = GetNextVehicle(first); - /* 2.1 If the first wagon is sold, update the first-> pointers to NULL */ - for (Vehicle *tmp = first; tmp != NULL; tmp = tmp->Next()) tmp->first = NULL; - /* 2.2 If there are wagons present after the deleted front engine, check * if the second wagon (which will be first) is an engine. If it is one, * promote it as a new train, retaining the unitnumber, orders */ @@ -1633,7 +1625,7 @@ CommandCost CmdReverseTrainDirection(Til return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT); } - Vehicle *front = GetFirstVehicleInChain(v); + Vehicle *front = v->First(); /* make sure the vehicle is stopped in the depot */ if (CheckTrainStoppedInDepot(front) < 0) { return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); @@ -1777,7 +1769,7 @@ CommandCost CmdRefitRailVehicle(TileInde _returned_refit_capacity = num; /* Update the train's cached variables */ - if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1))); + if (flags & DC_EXEC) TrainConsistChanged(GetVehicle(p1)->First()); return cost; } @@ -2718,7 +2710,7 @@ static void *FindTrainCollideEnum(Vehicl myabs(v->x_pos - tcc->v->x_pos) < 6 && myabs(v->y_pos - tcc->v->y_pos) < 6 ) { - Vehicle *coll = GetFirstVehicleInChain(v); + Vehicle *coll = v->First(); /* it can't collide with its own wagons */ if (tcc->v == coll || @@ -2807,7 +2799,7 @@ static void TrainController(Vehicle *v, Vehicle *prev; /* For every vehicle after and including the given vehicle */ - for (prev = GetPrevVehicleInChain(v); v != NULL; prev = v, v = v->Next()) { + for (prev = v->Previous(); v != NULL; prev = v, v = v->Next()) { DiagDirection enterdir = DIAGDIR_BEGIN; bool update_signals = false; BeginVehicleMove(v); @@ -2945,7 +2937,7 @@ static void TrainController(Vehicle *v, v->tile = gp.new_tile; if (GetTileRailType(gp.new_tile) != GetTileRailType(gp.old_tile)) { - TrainPowerChanged(GetFirstVehicleInChain(v)); + TrainPowerChanged(v->First()); } v->u.rail.track = chosen_track;