diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 6863a74751..6866908cef 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -2878,6 +2878,7 @@ static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int case ROAD_TILE_CROSSING: { if (v->type != VEH_ROAD) break; SetCrossingOccupiedByRoadVehicle(tile, true); + SetBit(RoadVehicle::From(v->First())->rvflags, RVF_ON_LEVEL_CROSSING); break; } diff --git a/src/roadveh.h b/src/roadveh.h index 02b5bb339a..e86b86333a 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -132,6 +132,10 @@ struct RoadVehPathCache { } }; +enum RoadVehicleFlags { + RVF_ON_LEVEL_CROSSING = 0, ///< One or more parts of this road vehicle are on a level crossing +}; + /** * Buses, trucks and trams belong to this class. */ @@ -150,6 +154,8 @@ struct RoadVehicle FINAL : public GroundVehicle { byte critical_breakdown_count; ///< Counter for the number of critical breakdowns since last service + uint8 rvflags; ///< Road vehicle flags + /** We don't want GCC to zero our struct! It already is zeroed and has an index! */ RoadVehicle() : GroundVehicleBase() {} /** We want to 'destruct' the right class. */ diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 69e7c363c2..1a3d925d80 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -631,8 +631,11 @@ static void RoadVehCrash(RoadVehicle *v) static bool RoadVehCheckTrainCrash(RoadVehicle *v) { + if (!HasBit(v->rvflags, RVF_ON_LEVEL_CROSSING)) return false; if (HasBit(_roadtypes_non_train_colliding, v->roadtype)) return false; + bool still_on_level_crossing = false; + for (RoadVehicle *u = v; u != nullptr; u = u->Next()) { if (u->state == RVSB_WORMHOLE) continue; @@ -640,6 +643,8 @@ static bool RoadVehCheckTrainCrash(RoadVehicle *v) if (!IsLevelCrossingTile(tile)) continue; + still_on_level_crossing = true; + CheckRoadVehCrashTrainInfo info(u); FindVehicleOnPosXY(v->x_pos, v->y_pos, VEH_TRAIN, &info, EnumCheckRoadVehCrashTrain); if (info.found) { @@ -648,6 +653,10 @@ static bool RoadVehCheckTrainCrash(RoadVehicle *v) } } + if (!still_on_level_crossing) { + ClrBit(v->rvflags, RVF_ON_LEVEL_CROSSING); + } + return false; } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 990ec5822d..07d0d4c199 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -4237,6 +4237,14 @@ bool AfterLoadGame() _settings_game.economy.tick_rate = IsSavegameVersionUntil(SLV_MORE_CARGO_AGE) ? TRM_TRADITIONAL : TRM_MODERN; } + if (SlXvIsFeatureMissing(XSLFI_ROAD_VEH_FLAGS)) { + for (RoadVehicle *rv : RoadVehicle::Iterate()) { + if (IsLevelCrossingTile(rv->tile)) { + SetBit(rv->First()->rvflags, RVF_ON_LEVEL_CROSSING); + } + } + } + if (SlXvIsFeatureMissing(XSLFI_AI_START_DATE) && IsSavegameVersionBefore(SLV_AI_START_DATE)) { /* For older savegames, we don't now the actual interval; so set it to the newgame value. */ _settings_game.difficulty.competitors_interval = _settings_newgame.difficulty.competitors_interval; diff --git a/src/sl/extended_ver_sl.cpp b/src/sl/extended_ver_sl.cpp index c92ac0724e..c5ce5f7542 100644 --- a/src/sl/extended_ver_sl.cpp +++ b/src/sl/extended_ver_sl.cpp @@ -189,6 +189,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_REMAIN_NEXT_ORDER_STATION, XSCF_IGNORABLE_UNKNOWN, 1, 1, "remain_next_order_station", nullptr, nullptr, nullptr }, { XSLFI_LABEL_ORDERS, XSCF_NULL, 2, 2, "label_orders", nullptr, nullptr, nullptr }, { XSLFI_VARIABLE_TICK_RATE, XSCF_IGNORABLE_ALL, 1, 1, "variable_tick_rate", nullptr, nullptr, nullptr }, + { XSLFI_ROAD_VEH_FLAGS, XSCF_NULL, 1, 1, "road_veh_flags", nullptr, nullptr, nullptr }, { XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr }, { XSLFI_U64_TICK_COUNTER, XSCF_NULL, 1, 1, "u64_tick_counter", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_TRAVEL_TIME, XSCF_NULL, 1, 1, "linkgraph_travel_time", nullptr, nullptr, nullptr }, diff --git a/src/sl/extended_ver_sl.h b/src/sl/extended_ver_sl.h index 2aa20b8ad0..10de8f8f25 100644 --- a/src/sl/extended_ver_sl.h +++ b/src/sl/extended_ver_sl.h @@ -140,6 +140,7 @@ enum SlXvFeatureIndex { XSLFI_REMAIN_NEXT_ORDER_STATION, ///< Remain in station if next order is for same station XSLFI_LABEL_ORDERS, ///< Label orders XSLFI_VARIABLE_TICK_RATE, ///< Variable tick rate + XSLFI_ROAD_VEH_FLAGS, ///< Road vehicle flags XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64 XSLFI_U64_TICK_COUNTER, ///< See: SLV_U64_TICK_COUNTER diff --git a/src/sl/vehicle_sl.cpp b/src/sl/vehicle_sl.cpp index add26d00c5..cd3ce69399 100644 --- a/src/sl/vehicle_sl.cpp +++ b/src/sl/vehicle_sl.cpp @@ -871,6 +871,7 @@ SaveLoadTable GetVehicleDescription(VehicleType vt) SLE_CONDNULL(2, SLV_6, SLV_131), SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space SLE_CONDVAR_X(RoadVehicle, critical_breakdown_count, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_IMPROVED_BREAKDOWNS, 6)), + SLE_CONDVAR_X(RoadVehicle, rvflags, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ROAD_VEH_FLAGS)), }; static const SaveLoad _ship_desc[] = { diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 4ae7bd3efc..493da6398a 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -4279,6 +4279,11 @@ void DumpVehicleFlagsGeneric(const Vehicle *v, T dump, U dump_header) dump('X', "VRF_PENDING_SPEED_RESTRICTION", HasBit(t->flags, VRF_PENDING_SPEED_RESTRICTION)); dump('c', "VRF_SPEED_ADAPTATION_EXEMPT", HasBit(t->flags, VRF_SPEED_ADAPTATION_EXEMPT)); } + if (v->type == VEH_ROAD) { + const RoadVehicle *rv = RoadVehicle::From(v); + dump_header("rvf:", "road vehicle flags:"); + dump('L', "RVF_ON_LEVEL_CROSSING", HasBit(rv->rvflags, RVF_ON_LEVEL_CROSSING)); + } } char *Vehicle::DumpVehicleFlags(char *b, const char *last, bool include_tile) const