Support railtype-dependant GRF train speed limits with realistic braking
See: #389
This commit is contained in:
@@ -339,6 +339,7 @@ enum SpriteGroupCallbacksUsed : uint8 {
|
|||||||
SGCU_VEHICLE_32DAY_CALLBACK = 1 << 0,
|
SGCU_VEHICLE_32DAY_CALLBACK = 1 << 0,
|
||||||
SGCU_VEHICLE_REFIT_COST = 1 << 1,
|
SGCU_VEHICLE_REFIT_COST = 1 << 1,
|
||||||
SGCU_RANDOM_TRIGGER = 1 << 2,
|
SGCU_RANDOM_TRIGGER = 1 << 2,
|
||||||
|
SGCU_CB36_SPEED_RAILTYPE = 1 << 3,
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(SpriteGroupCallbacksUsed)
|
DECLARE_ENUM_AS_BIT_SET(SpriteGroupCallbacksUsed)
|
||||||
|
|
||||||
|
@@ -354,6 +354,7 @@ void DeterministicSpriteGroup::AnalyseCallbacks(AnalyseCallbackOperation &op) co
|
|||||||
cb36_op.mode = ACOM_CB36_PROP;
|
cb36_op.mode = ACOM_CB36_PROP;
|
||||||
range.group->AnalyseCallbacks(cb36_op);
|
range.group->AnalyseCallbacks(cb36_op);
|
||||||
op.properties_used |= cb36_op.properties_used;
|
op.properties_used |= cb36_op.properties_used;
|
||||||
|
op.callbacks_used |= cb36_op.callbacks_used;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -370,7 +371,18 @@ void DeterministicSpriteGroup::AnalyseCallbacks(AnalyseCallbackOperation &op) co
|
|||||||
for (const auto &range : this->ranges) {
|
for (const auto &range : this->ranges) {
|
||||||
if (range.low == range.high) {
|
if (range.low == range.high) {
|
||||||
if (range.low < 64) {
|
if (range.low < 64) {
|
||||||
if (find_cb_result()) SetBit(op.properties_used, range.low);
|
if (find_cb_result()) {
|
||||||
|
SetBit(op.properties_used, range.low);
|
||||||
|
if (range.low == 0x9) {
|
||||||
|
/* Speed */
|
||||||
|
if (range.group != nullptr) {
|
||||||
|
AnalyseCallbackOperation cb36_speed;
|
||||||
|
cb36_speed.mode = ACOM_CB36_SPEED;
|
||||||
|
range.group->AnalyseCallbacks(cb36_speed);
|
||||||
|
op.callbacks_used |= cb36_speed.callbacks_used;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (range.group != nullptr) range.group->AnalyseCallbacks(op);
|
if (range.group != nullptr) range.group->AnalyseCallbacks(op);
|
||||||
@@ -392,6 +404,10 @@ void DeterministicSpriteGroup::AnalyseCallbacks(AnalyseCallbackOperation &op) co
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (op.mode == ACOM_CB36_SPEED && adjust.variable == 0x4A) {
|
||||||
|
op.callbacks_used |= SGCU_CB36_SPEED_RAILTYPE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const auto &adjust : this->adjusts) {
|
for (const auto &adjust : this->adjusts) {
|
||||||
if (op.mode == ACOM_CB_VAR && adjust.variable == 0xC) {
|
if (op.mode == ACOM_CB_VAR && adjust.variable == 0xC) {
|
||||||
|
@@ -53,6 +53,7 @@ enum AnalyseCallbackOperationMode {
|
|||||||
ACOM_CB_VAR,
|
ACOM_CB_VAR,
|
||||||
ACOM_CB36_PROP,
|
ACOM_CB36_PROP,
|
||||||
ACOM_FIND_CB_RESULT,
|
ACOM_FIND_CB_RESULT,
|
||||||
|
ACOM_CB36_SPEED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnalyseCallbackOperation {
|
struct AnalyseCallbackOperation {
|
||||||
|
27
src/pbs.cpp
27
src/pbs.cpp
@@ -386,6 +386,26 @@ static uint16 ApplyTunnelBridgeLookaheadSignalSpeedRestriction(TileIndex tile, T
|
|||||||
return speed_restriction;
|
return speed_restriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint16 GetTrainSpeedLimitForRailtype(const Train *v, RailType rt, TileIndex tile, Track track)
|
||||||
|
{
|
||||||
|
uint16 speed = GetRailTypeInfo(rt)->max_speed;
|
||||||
|
if (v->tcache.cached_tflags & TCF_SPD_RAILTYPE) {
|
||||||
|
for (const Train *u = v; u != nullptr; u = u->Next()) {
|
||||||
|
if (u->GetEngine()->callbacks_used & SGCU_CB36_SPEED_RAILTYPE) {
|
||||||
|
const TileIndex prev_tile = u->tile;
|
||||||
|
const TrackBits prev_track = u->track;
|
||||||
|
const_cast<Train *>(u)->tile = tile;
|
||||||
|
const_cast<Train *>(u)->track = TrackToTrackBits(track);
|
||||||
|
uint16 cb_speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, speed);
|
||||||
|
if (cb_speed != 0 && (cb_speed < speed || speed == 0)) speed = cb_speed;
|
||||||
|
const_cast<Train *>(u)->tile = prev_tile;
|
||||||
|
const_cast<Train *>(u)->track = prev_track;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
/** Follow a reservation starting from a specific tile to the end. */
|
/** Follow a reservation starting from a specific tile to the end. */
|
||||||
static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, FollowReservationFlags flags, const Train *v, TrainReservationLookAhead *lookahead)
|
static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, FollowReservationFlags flags, const Train *v, TrainReservationLookAhead *lookahead)
|
||||||
{
|
{
|
||||||
@@ -431,7 +451,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||||||
auto check_rail_type = [&](TileIndex t, Trackdir td, int offset) {
|
auto check_rail_type = [&](TileIndex t, Trackdir td, int offset) {
|
||||||
RailType new_rt = GetRailTypeByTrack(t, TrackdirToTrack(td));
|
RailType new_rt = GetRailTypeByTrack(t, TrackdirToTrack(td));
|
||||||
if (new_rt != rt) {
|
if (new_rt != rt) {
|
||||||
uint16 rail_speed = GetRailTypeInfo(new_rt)->max_speed;
|
uint16 rail_speed = GetTrainSpeedLimitForRailtype(v, new_rt, t, TrackdirToTrack(td));
|
||||||
if (rail_speed > 0) lookahead->AddTrackSpeedLimit(rail_speed, offset, 4, z);
|
if (rail_speed > 0) lookahead->AddTrackSpeedLimit(rail_speed, offset, 4, z);
|
||||||
if (GetRailTypeInfo(rt)->curve_speed != GetRailTypeInfo(new_rt)->curve_speed) {
|
if (GetRailTypeInfo(rt)->curve_speed != GetRailTypeInfo(new_rt)->curve_speed) {
|
||||||
CheckCurveLookAhead(v, lookahead, lookahead->RealEndPosition() + 4 + offset, z, new_rt);
|
CheckCurveLookAhead(v, lookahead, lookahead->RealEndPosition() + 4 + offset, z, new_rt);
|
||||||
@@ -870,9 +890,10 @@ static int ScanTrainPositionForLookAheadStation(Train *t, TileIndex start_tile)
|
|||||||
if (u == t) {
|
if (u == t) {
|
||||||
for (uint i = 1; i < forward_length; i++) {
|
for (uint i = 1; i < forward_length; i++) {
|
||||||
/* Check for mid platform rail type change */
|
/* Check for mid platform rail type change */
|
||||||
RailType new_rt = GetRailTypeByTrack(tile + (i * diff), TrackdirToTrack(trackdir));
|
TileIndex new_tile = tile + (i * diff);
|
||||||
|
RailType new_rt = GetRailTypeByTrack(new_tile, TrackdirToTrack(trackdir));
|
||||||
if (new_rt != rt) {
|
if (new_rt != rt) {
|
||||||
uint16 rail_speed = GetRailTypeInfo(new_rt)->max_speed;
|
uint16 rail_speed = GetTrainSpeedLimitForRailtype(t, new_rt, new_tile, TrackdirToTrack(trackdir));
|
||||||
if (rail_speed > 0) t->lookahead->AddTrackSpeedLimit(rail_speed, (i - 1) * TILE_SIZE, 4, z);
|
if (rail_speed > 0) t->lookahead->AddTrackSpeedLimit(rail_speed, (i - 1) * TILE_SIZE, 4, z);
|
||||||
rt = new_rt;
|
rt = new_rt;
|
||||||
}
|
}
|
||||||
|
@@ -182,8 +182,8 @@ class NIHVehicle : public NIHelper {
|
|||||||
}
|
}
|
||||||
if (v->type == VEH_TRAIN) {
|
if (v->type == VEH_TRAIN) {
|
||||||
const Train *t = Train::From(v);
|
const Train *t = Train::From(v);
|
||||||
seprintf(buffer, lastof(buffer), " T cache: tilt: %d, curve speed mod: %d, engines: %u",
|
seprintf(buffer, lastof(buffer), " T cache: tilt: %d, speed varies by railtype: %d, curve speed mod: %d, engines: %u",
|
||||||
(t->tcache.cached_tflags & TCF_TILT) ? 1 : 0, t->tcache.cached_curve_speed_mod, t->tcache.cached_num_engines);
|
(t->tcache.cached_tflags & TCF_TILT) ? 1 : 0, (t->tcache.cached_tflags & TCF_SPD_RAILTYPE) ? 1 : 0, t->tcache.cached_curve_speed_mod, t->tcache.cached_num_engines);
|
||||||
output.print(buffer);
|
output.print(buffer);
|
||||||
seprintf(buffer, lastof(buffer), " T cache: RL braking: %d, decel: %u, uncapped decel: %u, centre mass: %u",
|
seprintf(buffer, lastof(buffer), " T cache: RL braking: %d, decel: %u, uncapped decel: %u, centre mass: %u",
|
||||||
(t->UsingRealisticBraking()) ? 1 : 0, t->tcache.cached_deceleration, t->tcache.cached_uncapped_decel, t->tcache.cached_centre_mass);
|
(t->UsingRealisticBraking()) ? 1 : 0, t->tcache.cached_deceleration, t->tcache.cached_uncapped_decel, t->tcache.cached_centre_mass);
|
||||||
|
@@ -99,6 +99,7 @@ enum TrainCacheFlags : byte {
|
|||||||
TCF_NONE = 0, ///< No flags
|
TCF_NONE = 0, ///< No flags
|
||||||
TCF_TILT = 0x01, ///< Train can tilt; feature provides a bonus in curves.
|
TCF_TILT = 0x01, ///< Train can tilt; feature provides a bonus in curves.
|
||||||
TCF_RL_BRAKING = 0x02, ///< Train realistic braking (movement physics) in effect for this vehicle
|
TCF_RL_BRAKING = 0x02, ///< Train realistic braking (movement physics) in effect for this vehicle
|
||||||
|
TCF_SPD_RAILTYPE = 0x04, ///< Train speed varies depending on railtype
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(TrainCacheFlags)
|
DECLARE_ENUM_AS_BIT_SET(TrainCacheFlags)
|
||||||
|
|
||||||
|
@@ -264,6 +264,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
|||||||
this->tcache.cached_num_engines = 0;
|
this->tcache.cached_num_engines = 0;
|
||||||
|
|
||||||
bool train_can_tilt = true;
|
bool train_can_tilt = true;
|
||||||
|
bool speed_varies_by_railtype = false;
|
||||||
int min_curve_speed_mod = INT_MAX;
|
int min_curve_speed_mod = INT_MAX;
|
||||||
|
|
||||||
for (Train *u = this; u != nullptr; u = u->Next()) {
|
for (Train *u = this; u != nullptr; u = u->Next()) {
|
||||||
@@ -304,6 +305,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
|||||||
const RailVehicleInfo *rvi_u = &e_u->u.rail;
|
const RailVehicleInfo *rvi_u = &e_u->u.rail;
|
||||||
|
|
||||||
if (!HasBit(e_u->info.misc_flags, EF_RAIL_TILTS)) train_can_tilt = false;
|
if (!HasBit(e_u->info.misc_flags, EF_RAIL_TILTS)) train_can_tilt = false;
|
||||||
|
if (e_u->callbacks_used & SGCU_CB36_SPEED_RAILTYPE) speed_varies_by_railtype = true;
|
||||||
min_curve_speed_mod = std::min(min_curve_speed_mod, u->GetCurveSpeedModifier());
|
min_curve_speed_mod = std::min(min_curve_speed_mod, u->GetCurveSpeedModifier());
|
||||||
|
|
||||||
/* Cache wagon override sprite group. nullptr is returned if there is none */
|
/* Cache wagon override sprite group. nullptr is returned if there is none */
|
||||||
@@ -390,7 +392,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
|||||||
|
|
||||||
/* store consist weight/max speed in cache */
|
/* store consist weight/max speed in cache */
|
||||||
this->vcache.cached_max_speed = max_speed;
|
this->vcache.cached_max_speed = max_speed;
|
||||||
this->tcache.cached_tflags = (train_can_tilt ? TCF_TILT : TCF_NONE);
|
this->tcache.cached_tflags = (train_can_tilt ? TCF_TILT : TCF_NONE) | (speed_varies_by_railtype ? TCF_SPD_RAILTYPE : TCF_NONE);
|
||||||
this->tcache.cached_curve_speed_mod = min_curve_speed_mod;
|
this->tcache.cached_curve_speed_mod = min_curve_speed_mod;
|
||||||
this->tcache.cached_max_curve_speed = this->GetCurveSpeedLimit();
|
this->tcache.cached_max_curve_speed = this->GetCurveSpeedLimit();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user