From 350c2bb24fe459caffd181c7030a230a4120b00e Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 6 Jun 2017 20:20:33 +0100 Subject: [PATCH] Make trains break down after collision with road vehicle. --- src/lang/english.txt | 1 + src/roadveh_cmd.cpp | 33 ++++++++++++++++++++++++-------- src/saveload/extended_ver_sl.cpp | 2 +- src/train.h | 2 +- src/train_cmd.cpp | 14 ++++++++++++++ src/vehicle.cpp | 8 ++++++-- src/vehicle_type.h | 1 + 7 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index e0ee963d2c..2857e87b20 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3646,6 +3646,7 @@ STR_BREAKDOWN_TYPE_CRITICAL :Mechanical fail STR_BREAKDOWN_TYPE_EM_STOP :Emergency stop STR_BREAKDOWN_TYPE_LOW_SPEED :Limited to {VELOCITY} STR_BREAKDOWN_TYPE_LOW_POWER :{COMMA}% Power +STR_BREAKDOWN_TYPE_HIT_RV :Collided with road vehicle STR_BREAKDOWN_TYPE_DEPOT :Heading to {STATION} Hangar for repairs STR_BREAKDOWN_TYPE_LANDING :Heading to {STATION} for emergency landing STR_ERROR_TRAIN_TOO_HEAVY :{WHITE}{VEHICLE} is too heavy diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index d5401269be..ab10c43922 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -511,20 +511,35 @@ static bool RoadVehIsCrashed(RoadVehicle *v) return true; } +struct CheckRoadVehCrashTrainInfo { + const Vehicle *u; + bool found = false; + + CheckRoadVehCrashTrainInfo(const Vehicle *u_) + : u(u_) { } +}; + /** * Check routine whether a road and a train vehicle have collided. * @param v %Train vehicle to test. - * @param data Road vehicle to test. + * @param data Info including road vehicle to test. * @return %Train vehicle if the vehicles collided, else \c NULL. */ static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data) { - const Vehicle *u = (Vehicle*)data; - - return (v->type == VEH_TRAIN && - abs(v->z_pos - u->z_pos) <= 6 && - abs(v->x_pos - u->x_pos) <= 4 && - abs(v->y_pos - u->y_pos) <= 4) ? v : NULL; + CheckRoadVehCrashTrainInfo *info = (CheckRoadVehCrashTrainInfo*) data; + + if (v->type == VEH_TRAIN && + abs(v->z_pos - info->u->z_pos) <= 6 && + abs(v->x_pos - info->u->x_pos) <= 4 && + abs(v->y_pos - info->u->y_pos) <= 4) { + info->found = true; + extern void TrainRoadVehicleCrashBreakdown(Vehicle *v); + TrainRoadVehicleCrashBreakdown(v); + return v; + } else { + return NULL; + } } uint RoadVehicle::Crash(bool flooded) @@ -570,7 +585,9 @@ static bool RoadVehCheckTrainCrash(RoadVehicle *v) if (!IsLevelCrossingTile(tile)) continue; - if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) { + CheckRoadVehCrashTrainInfo info(u); + FindVehicleOnPosXY(v->x_pos, v->y_pos, &info, EnumCheckRoadVehCrashTrain); + if (info.found) { RoadVehCrash(v); return true; } diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 0ddd32fed0..cd9d4ee47c 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,7 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 4, 4, "improved_breakdowns", NULL, NULL, NULL }, + { XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 5, 5, "improved_breakdowns", NULL, NULL, NULL }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/train.h b/src/train.h index 8139050c12..3a07d624a8 100644 --- a/src/train.h +++ b/src/train.h @@ -28,7 +28,7 @@ enum VehicleRailFlags { VRF_REVERSING = 0, VRF_POWEREDWAGON = 3, ///< Wagon is powered. VRF_REVERSE_DIRECTION = 4, ///< Reverse the visible direction of the vehicle. - + VRF_HAS_HIT_RV = 5, ///< Train has hit road vehicle VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6, ///< Electric train engine is allowed to run on normal rail. */ VRF_TOGGLE_REVERSE = 7, ///< Used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle only). VRF_TRAIN_STUCK = 8, ///< Train can't get a path reservation. diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 236898d669..352050b110 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -139,6 +139,7 @@ void CheckBreakdownFlags(Train *v) } else if (w->breakdown_ctr == 1) { switch (w->breakdown_type) { case BREAKDOWN_CRITICAL: + case BREAKDOWN_RV_CRASH: case BREAKDOWN_EM_STOP: SetBit(v->flags, VRF_BREAKDOWN_STOPPED); break; case BREAKDOWN_LOW_SPEED: SetBit(v->flags, VRF_BREAKDOWN_SPEED); break; case BREAKDOWN_LOW_POWER: SetBit(v->flags, VRF_BREAKDOWN_POWER); break; @@ -156,6 +157,9 @@ uint16 GetTrainVehicleMaxSpeed(const Train *u, const RailVehicleInfo *rvi_u, con speed = min(speed - (speed / (front->tcache.cached_num_engines + 2)) + 1, speed); } } + if (HasBit(u->flags, VRF_HAS_HIT_RV) && front->IsFrontEngine()) { + speed = min(speed, 30); + } return speed; } @@ -4118,3 +4122,13 @@ Trackdir Train::GetVehicleTrackdir() const return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction); } + +void TrainRoadVehicleCrashBreakdown(Vehicle *v) +{ + Train *t = Train::From(v)->First(); + t->breakdown_ctr = 2; + t->breakdown_delay = 255; + t->breakdown_type = BREAKDOWN_RV_CRASH; + t->breakdown_severity = 0; + t->reliability = 0; +} diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 4c0a663474..da77edc15d 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -144,7 +144,8 @@ void VehicleServiceInDepot(Vehicle *v) if (v->type == VEH_TRAIN) { if (v->Next() != NULL) VehicleServiceInDepot(v->Next()); if (!(Train::From(v)->IsEngine()) && !(Train::From(v)->IsRearDualheaded())) return; - ClrBit(Train::From(v)->flags,VRF_NEED_REPAIR); + ClrBit(Train::From(v)->flags, VRF_NEED_REPAIR); + ClrBit(Train::From(v)->flags, VRF_HAS_HIT_RV); Train::From(v)->critical_breakdown_count = 0; const RailVehicleInfo *rvi = &e->u.rail; v->vcache.cached_max_speed = rvi->max_speed; @@ -1395,6 +1396,9 @@ bool Vehicle::HandleBreakdown() if (this->breakdown_type == BREAKDOWN_LOW_POWER || this->First()->cur_speed <= ((this->breakdown_type == BREAKDOWN_LOW_SPEED) ? this->breakdown_severity : 0)) { switch (this->breakdown_type) { + case BREAKDOWN_RV_CRASH: + if (_settings_game.vehicle.improved_breakdowns) SetBit(Train::From(this)->flags, VRF_HAS_HIT_RV); + /* FALL THROUGH */ case BREAKDOWN_CRITICAL: if (!PlayVehicleSound(this, VSE_BREAKDOWN)) { bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP; @@ -1495,7 +1499,7 @@ bool Vehicle::HandleBreakdown() } } } - return (this->breakdown_type == BREAKDOWN_CRITICAL || this->breakdown_type == BREAKDOWN_EM_STOP); + return (this->breakdown_type == BREAKDOWN_CRITICAL || this->breakdown_type == BREAKDOWN_EM_STOP || this->breakdown_type == BREAKDOWN_RV_CRASH); default: if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--; diff --git a/src/vehicle_type.h b/src/vehicle_type.h index 312ebb598d..2c75acdc80 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -87,6 +87,7 @@ enum BreakdownType { BREAKDOWN_EM_STOP = 1, ///< Emergency stop BREAKDOWN_LOW_SPEED = 2, ///< Lower max speed BREAKDOWN_LOW_POWER = 3, ///< Power reduction + BREAKDOWN_RV_CRASH = 4, ///< Train hit road vehicle BREAKDOWN_AIRCRAFT_SPEED = BREAKDOWN_CRITICAL, ///< Lower speed until the next airport BREAKDOWN_AIRCRAFT_DEPOT = BREAKDOWN_EM_STOP, ///< We have to visit a depot at the next airport