--- a/src/train_cmd.cpp Sun Aug 19 14:04:13 2007 +0000
+++ b/src/train_cmd.cpp Sun Sep 02 11:17:33 2007 +0000
@@ -71,7 +71,7 @@
uint32 total_power = 0;
uint32 max_te = 0;
- for (const Vehicle *u = v; u != NULL; u = u->next) {
+ for (const Vehicle *u = v; u != NULL; u = u->Next()) {
/* Power is not added for articulated parts */
if (IsArticulatedPart(u)) continue;
@@ -113,7 +113,7 @@
{
uint32 weight = 0;
- for (Vehicle *u = v; u != NULL; u = u->next) {
+ for (Vehicle *u = v; u != NULL; u = u->Next()) {
uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo.Count() * FreightWagonMult(u->cargo_type) / 16;
/* Vehicle weight is not added for articulated parts. */
@@ -159,11 +159,11 @@
v->u.rail.cached_total_length = 0;
v->u.rail.compatible_railtypes = 0;
- for (Vehicle *u = v; u != NULL; u = u->next) {
+ 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;
@@ -236,7 +236,7 @@
veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
}
if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
- veh_len = clamp(veh_len, 0, u->next == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
+ veh_len = clamp(veh_len, 0, u->Next() == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
u->u.rail.cached_veh_length = 8 - veh_len;
v->u.rail.cached_total_length += u->u.rail.cached_veh_length;
}
@@ -302,7 +302,7 @@
static int GetTrainAcceleration(Vehicle *v, bool mode)
{
int max_speed = 2000;
- int speed = v->cur_speed * 10 / 16; //[mph]
+ int speed = v->GetDisplaySpeed(); //[mph]
int curvecount[2] = {0, 0};
/*first find the curve speed limit */
@@ -310,9 +310,9 @@
int sum = 0;
int pos = 0;
int lastpos = -1;
- for (const Vehicle *u = v; u->next != NULL; u = u->next, pos++) {
+ for (const Vehicle *u = v; u->Next() != NULL; u = u->Next(), pos++) {
Direction dir = u->direction;
- Direction ndir = u->next->direction;
+ Direction ndir = u->Next()->direction;
int i;
for (i = 0; i < 2; i++) {
@@ -372,7 +372,7 @@
int num = 0; //number of vehicles, change this into the number of axles later
int incl = 0;
int drag_coeff = 20; //[1e-4]
- for (const Vehicle *u = v; u != NULL; u = u->next) {
+ for (const Vehicle *u = v; u != NULL; u = u->Next()) {
num++;
drag_coeff += 3;
@@ -559,7 +559,7 @@
SetTrainWagon(v);
if (u != NULL) {
- u->next = v;
+ u->SetNext(v);
} else {
SetFreeWagon(v);
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
@@ -584,12 +584,12 @@
_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()) {
- InvalidateAutoreplaceWindow(VEH_TRAIN, v->group_id); // updates the replace Train window
+ InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
}
GetPlayer(_current_player)->num_engines[engine]++;
}
@@ -621,6 +621,7 @@
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;
@@ -629,7 +630,6 @@
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;
@@ -637,7 +637,7 @@
u->cargo_subtype = v->cargo_subtype;
u->cargo_cap = v->cargo_cap;
u->u.rail.railtype = v->u.rail.railtype;
- if (building) v->next = u;
+ if (building) v->SetNext(u);
u->engine_type = v->engine_type;
u->build_year = v->build_year;
if (building) v->value >>= 1;
@@ -773,7 +773,7 @@
RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
if (IsLocalPlayer())
- InvalidateAutoreplaceWindow(VEH_TRAIN, v->group_id); // updates the replace Train window
+ InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
GetPlayer(_current_player)->num_engines[p1]++;
}
@@ -793,7 +793,7 @@
if (!IsTileDepotType(tile, TRANSPORT_RAIL) || v->cur_speed != 0) return -1;
int count = 0;
- for (; v != NULL; v = v->next) {
+ for (; v != NULL; v = v->Next()) {
/* This count is used by the depot code to determine the number of engines
* in the consist. Exclude articulated parts so that autoreplacing to
* engines with more articulated parts than before works correctly.
@@ -841,8 +841,7 @@
Vehicle *u;
for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {}
- GetLastEnginePart(u)->next = GetNextVehicle(v);
- v->first = NULL; // we shouldn't point to the old first, since the vehicle isn't in that chain anymore
+ GetLastEnginePart(u)->SetNext(GetNextVehicle(v));
return first;
}
@@ -858,7 +857,7 @@
Vehicle *v = dst;
while (v->engine_type == eng) {
- v = v->next;
+ v = v->Next();
if (v == NULL) return dst;
}
}
@@ -873,11 +872,12 @@
*/
static void AddWagonToConsist(Vehicle *v, Vehicle *dest)
{
- UnlinkWagon(v, GetFirstVehicleInChain(v));
+ UnlinkWagon(v, v->First());
if (dest == NULL) return;
- v->next = dest->next;
- dest->next = v;
+ Vehicle *next = dest->Next();
+ dest->SetNext(v);
+ v->SetNext(next);
ClearFreeWagon(v);
ClearFrontEngine(v);
}
@@ -897,7 +897,7 @@
/* make sure that there are no free cars before next engine */
Vehicle *u;
- for (u = v; u->next != NULL && !IsTrainEngine(u->next); u = u->next) {}
+ for (u = v; u->Next() != NULL && !IsTrainEngine(u->Next()); u = u->Next()) {}
if (u == v->u.rail.other_multiheaded_part) continue;
AddWagonToConsist(v->u.rail.other_multiheaded_part, u);
@@ -934,19 +934,19 @@
}
/* 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);
@@ -1023,10 +1023,6 @@
/* 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)) {
@@ -1042,7 +1038,7 @@
if (src != src_head) {
Vehicle *v = src_head;
while (GetNextVehicle(v) != src) v = GetNextVehicle(v);
- GetLastEnginePart(v)->next = NULL;
+ GetLastEnginePart(v)->SetNext(NULL);
} else {
InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile); // We removed a line
src_head = NULL;
@@ -1052,7 +1048,7 @@
if (src_head == dst_head) dst_head = NULL;
/* unlink single wagon from linked list */
src_head = UnlinkWagon(src, src_head);
- GetLastEnginePart(src)->next = NULL;
+ GetLastEnginePart(src)->SetNext(NULL);
}
if (dst == NULL) {
@@ -1098,17 +1094,16 @@
Vehicle *v;
for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v));
- GetLastEnginePart(v)->next = dst->next;
+ GetLastEnginePart(v)->SetNext(dst->Next());
}
- dst->next = src;
+ 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;
+ 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
@@ -1219,8 +1214,8 @@
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) {
@@ -1263,9 +1258,6 @@
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 */
@@ -1300,7 +1292,7 @@
first->next_shared = NULL;
/* If we deleted a window then open a new one for the 'new' train */
- if (IsLocalPlayer() && w != NULL) ShowTrainViewWindow(new_f);
+ if (IsLocalPlayer() && w != NULL) ShowVehicleViewWindow(new_f);
}
}
@@ -1471,8 +1463,8 @@
Vehicle *a, *b;
/* locate vehicles to swap */
- for (a = v; l != 0; l--) a = a->next;
- for (b = v; r != 0; r--) b = b->next;
+ for (a = v; l != 0; l--) a = a->Next();
+ for (b = v; r != 0; r--) b = b->Next();
if (a != b) {
/* swap the hidden bits */
@@ -1540,30 +1532,30 @@
static void AdvanceWagons(Vehicle *v, bool before)
{
Vehicle *base = v;
- Vehicle *first = base->next;
+ Vehicle *first = base->Next();
uint length = CountVehiclesInChain(v);
while (length > 2) {
/* find pairwise matching wagon
* start<>end, start+1<>end-1, ... */
Vehicle *last = first;
- for (uint i = length - 3; i > 0; i--) last = last->next;
+ for (uint i = length - 3; i > 0; i--) last = last->Next();
int differential = last->u.rail.cached_veh_length - base->u.rail.cached_veh_length;
if (before) differential *= -1;
if (differential > 0) {
/* disconnect last car to make sure only this subset moves */
- Vehicle *tempnext = last->next;
- last->next = NULL;
+ Vehicle *tempnext = last->Next();
+ last->SetNext(NULL);
for (int i = 0; i < differential; i++) TrainController(first, false);
- last->next = tempnext;
+ last->SetNext(tempnext);
}
base = first;
- first = first->next;
+ first = first->Next();
length -= 2;
}
}
@@ -1594,7 +1586,7 @@
/* count number of vehicles */
int r = -1;
const Vehicle *u = v;
- do r++; while ( (u = u->next) != NULL );
+ do r++; while ((u = u->Next()) != NULL);
AdvanceWagons(v, true);
@@ -1634,7 +1626,7 @@
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);
@@ -1646,8 +1638,8 @@
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
} else {
- /*turn the whole train around */
- if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) return CMD_ERROR;
+ /* turn the whole train around */
+ if (v->vehstatus & VS_CRASHED || v->breakdown_ctr != 0) return CMD_ERROR;
if (flags & DC_EXEC) {
if (_patches.realistic_acceleration && v->cur_speed != 0) {
@@ -1773,12 +1765,12 @@
}
}
}
- } while ((v = v->next) != NULL && !only_this);
+ } while ((v = v->Next()) != NULL && !only_this);
_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;
}
@@ -2018,7 +2010,7 @@
}
break;
}
- } while ((v = v->next) != NULL);
+ } while ((v = v->Next()) != NULL);
if (sound) PlayVehicleSound(u, VSE_TRAIN_EFFECT);
}
@@ -2047,7 +2039,7 @@
static bool CheckTrainStayInDepot(Vehicle *v)
{
/* bail out if not all wagons are in the same depot or not in a depot at all */
- for (const Vehicle *u = v; u != NULL; u = u->next) {
+ for (const Vehicle *u = v; u != NULL; u = u->Next()) {
if (u->u.rail.track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
}
@@ -2471,7 +2463,7 @@
do {
v->cur_image = v->GetImage(v->direction);
MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
- } while ((v = v->next) != NULL);
+ } while ((v = v->Next()) != NULL);
/* need to update acceleration and cached values since the goods on the train changed. */
TrainCargoChanged(this);
@@ -2719,7 +2711,7 @@
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 ||
@@ -2757,7 +2749,7 @@
TrainCollideChecker tcc;
tcc.v = v;
- tcc.v_skip = v->next;
+ tcc.v_skip = v->Next();
tcc.num = 0;
/* find colliding vehicles */
@@ -2809,7 +2801,7 @@
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);
@@ -2936,7 +2928,7 @@
goto invalid_rail;
}
- if (IsLevelCrossingTile(v->tile) && v->next == NULL) {
+ if (IsLevelCrossingTile(v->tile) && v->Next() == NULL) {
UnbarCrossing(v->tile);
MarkTileDirtyByTile(v->tile);
}
@@ -2947,7 +2939,7 @@
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;
@@ -2999,7 +2991,7 @@
/* Signals can only change when the first
* (above) or the last vehicle moves. */
- if (v->next == NULL) TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
+ if (v->Next() == NULL) TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
}
}
return;
@@ -3030,8 +3022,8 @@
* *u is then the one-before-last wagon, and *v the last
* one which will physicially be removed */
Vehicle *u = v;
- for (; v->next != NULL; v = v->next) u = v;
- u->next = NULL;
+ for (; v->Next() != NULL; v = v->Next()) u = v;
+ u->SetNext(NULL);
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
@@ -3092,7 +3084,7 @@
the bridge in that case */
if (v->u.rail.track != TRACK_BIT_WORMHOLE) AfterSetTrainPos(v, false);
}
- } while ((v = v->next) != NULL);
+ } while ((v = v->Next()) != NULL);
}
static void HandleCrashedTrain(Vehicle *v)
@@ -3119,7 +3111,7 @@
EV_EXPLOSION_SMALL);
break;
}
- } while ((u = u->next) != NULL);
+ } while ((u = u->Next()) != NULL);
}
if (state <= 240 && !(v->tick_counter & 3)) ChangeTrainDirRandomly(v);
@@ -3257,7 +3249,7 @@
static void TrainLocoHandler(Vehicle *v, bool mode)
{
/* train has crashed? */
- if (v->u.rail.crash_anim_pos != 0) {
+ if (v->vehstatus & VS_CRASHED) {
if (!mode) HandleCrashedTrain(v);
return;
}
@@ -3315,6 +3307,25 @@
}
+
+Money Train::GetRunningCost() const
+{
+ Money cost = 0;
+ const Vehicle *v = this;
+
+ do {
+ const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
+
+ byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
+ if (cost_factor == 0) continue;
+
+ cost += cost_factor * _price.running_rail[rvi->running_cost_class];
+ } while ((v = GetNextVehicle(v)) != NULL);
+
+ return cost;
+}
+
+
void Train::Tick()
{
if (_age_cargo_skip_counter == 0) this->cargo.AgeCargo();
@@ -3339,18 +3350,8 @@
static void CheckIfTrainNeedsService(Vehicle *v)
{
- if (_patches.servint_trains == 0) return;
- if (!VehicleNeedsService(v)) return;
- if (v->vehstatus & VS_STOPPED) return;
- if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
-
- /* Don't interfere with a depot visit scheduled by the user, or a
- * depot visit by the order list. */
- if (v->current_order.type == OT_GOTO_DEPOT &&
- (v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0)
- return;
-
- if (CheckTrainIsInsideDepot(v)) {
+ if (_patches.servint_trains == 0 || !VehicleNeedsService(v)) return;
+ if (v->IsInDepot()) {
VehicleServiceInDepot(v);
return;
}
@@ -3377,8 +3378,6 @@
return;
}
- if (v->current_order.type == OT_LOADING) v->LeaveStation();
-
v->current_order.type = OT_GOTO_DEPOT;
v->current_order.flags = OF_NON_STOP;
v->current_order.dest = depot->index;
@@ -3386,22 +3385,6 @@
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
}
-Money GetTrainRunningCost(const Vehicle *v)
-{
- Money cost = 0;
-
- do {
- const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
-
- byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
- if (cost_factor == 0) continue;
-
- cost += cost_factor * _price.running_rail[rvi->running_cost_class];
- } while ((v = GetNextVehicle(v)) != NULL);
-
- return cost;
-}
-
void OnNewDay_Train(Vehicle *v)
{
if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v);
@@ -3422,7 +3405,7 @@
if ((v->vehstatus & VS_STOPPED) == 0) {
/* running costs */
- CommandCost cost(GetTrainRunningCost(v) / 364);
+ CommandCost cost(v->GetRunningCost() / 364);
v->profit_this_year -= cost.GetCost() >> 8;
@@ -3497,7 +3480,7 @@
}
Vehicle *w;
- for (w = u->next; w != NULL && (w->engine_type != u->engine_type || w->u.rail.other_multiheaded_part != NULL); w = GetNextVehicle(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)) {