summaryrefslogtreecommitdiff
path: root/src/train_cmd.cpp
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2007-06-19 16:40:59 +0000
committerpeter1138 <peter1138@openttd.org>2007-06-19 16:40:59 +0000
commite7191fc57a9ef00e6495014f1da5a2ea67b839ca (patch)
tree8f7fb6917660b57f3555a30a5162243e206263ea /src/train_cmd.cpp
parente51a513eb812e61470a0f98689f43cda25971e94 (diff)
downloadopenttd-e7191fc57a9ef00e6495014f1da5a2ea67b839ca.tar.xz
(svn r10222) -Fix [FS#892]: Only 2 trains could crash at one time as collision checking stopped on the first hit. This could cause desyncs in network games as the collision hash order is not guaranteed. (patch by B. N. Smatz)
Diffstat (limited to 'src/train_cmd.cpp')
-rw-r--r--src/train_cmd.cpp88
1 files changed, 47 insertions, 41 deletions
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index f04121db6..0aca1b08d 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -2659,28 +2659,6 @@ static void TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
}
-struct TrainCollideChecker {
- const Vehicle *v;
- const Vehicle *v_skip;
-};
-
-static void *FindTrainCollideEnum(Vehicle *v, void *data)
-{
- const TrainCollideChecker* tcc = (TrainCollideChecker*)data;
-
- if (v != tcc->v &&
- v != tcc->v_skip &&
- v->type == VEH_TRAIN &&
- v->u.rail.track != TRACK_BIT_DEPOT &&
- myabs(v->z_pos - tcc->v->z_pos) < 6 &&
- myabs(v->x_pos - tcc->v->x_pos) < 6 &&
- myabs(v->y_pos - tcc->v->y_pos) < 6) {
- return v;
- } else {
- return NULL;
- }
-}
-
static void SetVehicleCrashed(Vehicle *v)
{
if (v->u.rail.crash_anim_pos != 0) return;
@@ -2704,6 +2682,47 @@ static uint CountPassengersInTrain(const Vehicle* v)
return num;
}
+struct TrainCollideChecker {
+ Vehicle *v;
+ const Vehicle *v_skip;
+ uint num;
+};
+
+static void *FindTrainCollideEnum(Vehicle *v, void *data)
+{
+ TrainCollideChecker* tcc = (TrainCollideChecker*)data;
+
+ if (v != tcc->v &&
+ v != tcc->v_skip &&
+ v->type == VEH_TRAIN &&
+ v->u.rail.track != TRACK_BIT_DEPOT &&
+ myabs(v->z_pos - tcc->v->z_pos) < 6 &&
+ myabs(v->x_pos - tcc->v->x_pos) < 6 &&
+ myabs(v->y_pos - tcc->v->y_pos) < 6 ) {
+
+ Vehicle *coll = GetFirstVehicleInChain(v);
+
+ /* it can't collide with its own wagons */
+ if (tcc->v == coll ||
+ (tcc->v->u.rail.track == TRACK_BIT_WORMHOLE && (tcc->v->direction & 2) != (v->direction & 2)))
+ return NULL;
+
+ /* two drivers + passengers killed in train tcc->v (if it was not crashed already) */
+ if (!(tcc->v->vehstatus & VS_CRASHED)) {
+ tcc->num += 2 + CountPassengersInTrain(tcc->v);
+ SetVehicleCrashed(tcc->v);
+ }
+
+ if (!(coll->vehstatus & VS_CRASHED)) {
+ /* two drivers + passengers killed in train coll (if it was not crashed already) */
+ tcc->num += 2 + CountPassengersInTrain(coll);
+ SetVehicleCrashed(coll);
+ }
+ }
+
+ return NULL;
+}
+
/**
* Checks whether the specified train has a collision with another vehicle. If
* so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
@@ -2720,28 +2739,15 @@ static void CheckTrainCollision(Vehicle *v)
TrainCollideChecker tcc;
tcc.v = v;
tcc.v_skip = v->next;
+ tcc.num = 0;
- /* find colliding vehicle */
- Vehicle *realcoll = (Vehicle*)VehicleFromPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
- if (realcoll == NULL) return;
-
- Vehicle *coll = GetFirstVehicleInChain(realcoll);
-
- /* it can't collide with its own wagons */
- if (v == coll ||
- (v->u.rail.track == TRACK_BIT_WORMHOLE && (v->direction & 2) != (realcoll->direction & 2)))
- return;
-
- /* two drivers + passengers killed in train v */
- uint num = 2 + CountPassengersInTrain(v);
- if (!(coll->vehstatus & VS_CRASHED))
- /* two drivers + passengers killed in train coll (if it was not crashed already) */
- num += 2 + CountPassengersInTrain(coll);
+ /* find colliding vehicles */
+ VehicleFromPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
- SetVehicleCrashed(v);
- if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
+ /* any dead -> no crash */
+ if (tcc.num == 0) return;
- SetDParam(0, num);
+ SetDParam(0, tcc.num);
AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
v->index,