mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-23 14:39:08 +00:00
(svn r10280) [0.5] -Backport from trunk (r10109, r10219, r10222, r10230, r10246, r10258):
- Fix: Do not look in every direction for tunnels when building one, one direction is enough (r10258) - Fix: Take the age of the front vehicle for station rating (r10246) - Fix: Terraforming wipes out canals. Now you always have to remove the canal before terraforming, instead of "just" removing the canal [FS#594] (r10240) - Fix: Only 2 trains could crash at one time as collision checking stopped on the first hit. This could technically cause desyncs in network games as the collision hash order is not guaranteed [FS#892] (r10222) - Fix: Land under foundations was terraform when it shouldn't be terraformed [FS#882, FS#890] (r10219) - Fix: Some NewGRFs use the same (unused in the "current" climate) sprite IDs. Normally this gives some artefacts, but when one NewGRF expects it to be a sprite and another NewGRF overwrites it with a non-sprite nasty things happen (drawing a non-sprite crashes OTTD) [FS#838] (r10109)
This commit is contained in:
91
train_cmd.c
91
train_cmd.c
@@ -2915,28 +2915,6 @@ static void TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
|
||||
}
|
||||
|
||||
|
||||
typedef struct TrainCollideChecker {
|
||||
const Vehicle *v;
|
||||
const Vehicle *v_skip;
|
||||
} TrainCollideChecker;
|
||||
|
||||
static void *FindTrainCollideEnum(Vehicle *v, void *data)
|
||||
{
|
||||
const TrainCollideChecker* tcc = data;
|
||||
|
||||
if (v != tcc->v &&
|
||||
v != tcc->v_skip &&
|
||||
v->type == VEH_Train &&
|
||||
v->u.rail.track != 0x80 &&
|
||||
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)
|
||||
{
|
||||
Vehicle *u;
|
||||
@@ -2962,6 +2940,47 @@ static uint CountPassengersInTrain(const Vehicle* v)
|
||||
return num;
|
||||
}
|
||||
|
||||
typedef struct TrainCollideChecker {
|
||||
Vehicle *v;
|
||||
const Vehicle *v_skip;
|
||||
uint num;
|
||||
} TrainCollideChecker;
|
||||
|
||||
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 != 0x80 &&
|
||||
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 == 0x40 && (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.
|
||||
@@ -2971,9 +2990,6 @@ static uint CountPassengersInTrain(const Vehicle* v)
|
||||
static void CheckTrainCollision(Vehicle *v)
|
||||
{
|
||||
TrainCollideChecker tcc;
|
||||
Vehicle *coll;
|
||||
Vehicle *realcoll;
|
||||
uint num;
|
||||
|
||||
/* can't collide in depot */
|
||||
if (v->u.rail.track == 0x80) return;
|
||||
@@ -2982,28 +2998,15 @@ static void CheckTrainCollision(Vehicle *v)
|
||||
|
||||
tcc.v = v;
|
||||
tcc.v_skip = v->next;
|
||||
tcc.num = 0;
|
||||
|
||||
/* find colliding vehicle */
|
||||
realcoll = VehicleFromPos(TileVirtXY(v->x_pos, v->y_pos), &tcc, FindTrainCollideEnum);
|
||||
if (realcoll == NULL) return;
|
||||
/* find colliding vehicles */
|
||||
VehicleFromPos(v->tile, &tcc, FindTrainCollideEnum);
|
||||
|
||||
coll = GetFirstVehicleInChain(realcoll);
|
||||
/* any dead -> no crash */
|
||||
if (tcc.num == 0) return;
|
||||
|
||||
/* it can't collide with its own wagons */
|
||||
if (v == coll ||
|
||||
(v->u.rail.track & 0x40 && (v->direction & 2) != (realcoll->direction & 2)))
|
||||
return;
|
||||
|
||||
//two drivers + passangers killed in train v
|
||||
num = 2 + CountPassengersInTrain(v);
|
||||
if (!(coll->vehstatus & VS_CRASHED))
|
||||
//two drivers + passangers killed in train coll (if it was not crashed already)
|
||||
num += 2 + CountPassengersInTrain(coll);
|
||||
|
||||
SetVehicleCrashed(v);
|
||||
if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
|
||||
|
||||
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,
|
||||
|
Reference in New Issue
Block a user