mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-10 08:00:05 +00:00
Feature: [NewGRF] Maximum curve speed modifier for rail vehicles (#9346)
This commit is contained in:
parent
579f393374
commit
2183fd4dab
@ -59,6 +59,7 @@ struct RailVehicleInfo {
|
|||||||
byte tractive_effort; ///< Tractive effort coefficient
|
byte tractive_effort; ///< Tractive effort coefficient
|
||||||
byte air_drag; ///< Coefficient of air drag
|
byte air_drag; ///< Coefficient of air drag
|
||||||
byte user_def_data; ///< Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles
|
byte user_def_data; ///< Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles
|
||||||
|
int16 curve_speed_mod; ///< Modifier to maximum speed in curves (fixed-point binary with 8 fractional bits)
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Information about a ship vehicle. */
|
/** Information about a ship vehicle. */
|
||||||
|
@ -1331,6 +1331,10 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PROP_TRAIN_CURVE_SPEED_MOD: // 0x2E Curve speed modifier
|
||||||
|
rvi->curve_speed_mod = buf->ReadWord();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = CommonVehicleChangeInfo(ei, prop, buf);
|
ret = CommonVehicleChangeInfo(ei, prop, buf);
|
||||||
break;
|
break;
|
||||||
|
@ -1177,16 +1177,23 @@ uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param
|
|||||||
|
|
||||||
|
|
||||||
/* Callback 36 handlers */
|
/* Callback 36 handlers */
|
||||||
uint GetVehicleProperty(const Vehicle *v, PropertyID property, uint orig_value)
|
int GetVehicleProperty(const Vehicle *v, PropertyID property, int orig_value, bool is_signed)
|
||||||
{
|
{
|
||||||
return GetEngineProperty(v->engine_type, property, orig_value, v);
|
return GetEngineProperty(v->engine_type, property, orig_value, v, is_signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint GetEngineProperty(EngineID engine, PropertyID property, uint orig_value, const Vehicle *v)
|
int GetEngineProperty(EngineID engine, PropertyID property, int orig_value, const Vehicle *v, bool is_signed)
|
||||||
{
|
{
|
||||||
uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, engine, v);
|
uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, engine, v);
|
||||||
if (callback != CALLBACK_FAILED) return callback;
|
if (callback != CALLBACK_FAILED) {
|
||||||
|
if (is_signed) {
|
||||||
|
/* Sign extend 15 bit integer */
|
||||||
|
return static_cast<int16>(callback << 1) >> 1;
|
||||||
|
} else {
|
||||||
|
return callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return orig_value;
|
return orig_value;
|
||||||
}
|
}
|
||||||
|
@ -100,8 +100,8 @@ bool UsesWagonOverride(const Vehicle *v);
|
|||||||
|
|
||||||
/* Handler to Evaluate callback 36. If the callback fails (i.e. most of the
|
/* Handler to Evaluate callback 36. If the callback fails (i.e. most of the
|
||||||
* time) orig_value is returned */
|
* time) orig_value is returned */
|
||||||
uint GetVehicleProperty(const Vehicle *v, PropertyID property, uint orig_value);
|
int GetVehicleProperty(const Vehicle *v, PropertyID property, int orig_value, bool is_signed = false);
|
||||||
uint GetEngineProperty(EngineID engine, PropertyID property, uint orig_value, const Vehicle *v = nullptr);
|
int GetEngineProperty(EngineID engine, PropertyID property, int orig_value, const Vehicle *v = nullptr, bool is_signed = false);
|
||||||
|
|
||||||
enum VehicleTrigger {
|
enum VehicleTrigger {
|
||||||
VEHICLE_TRIGGER_NEW_CARGO = 0x01,
|
VEHICLE_TRIGGER_NEW_CARGO = 0x01,
|
||||||
|
@ -28,6 +28,7 @@ enum PropertyID {
|
|||||||
PROP_TRAIN_SHORTEN_FACTOR = 0x21, ///< Shorter vehicles
|
PROP_TRAIN_SHORTEN_FACTOR = 0x21, ///< Shorter vehicles
|
||||||
PROP_TRAIN_USER_DATA = 0x25, ///< User defined data for vehicle variable 0x42
|
PROP_TRAIN_USER_DATA = 0x25, ///< User defined data for vehicle variable 0x42
|
||||||
PROP_TRAIN_CARGO_AGE_PERIOD = 0x2B, ///< Number of ticks before carried cargo is aged
|
PROP_TRAIN_CARGO_AGE_PERIOD = 0x2B, ///< Number of ticks before carried cargo is aged
|
||||||
|
PROP_TRAIN_CURVE_SPEED_MOD = 0x2E, ///< Modifier to maximum speed in curves
|
||||||
|
|
||||||
PROP_ROADVEH_RUNNING_COST_FACTOR = 0x09, ///< Yearly runningcost
|
PROP_ROADVEH_RUNNING_COST_FACTOR = 0x09, ///< Yearly runningcost
|
||||||
PROP_ROADVEH_CARGO_CAPACITY = 0x0F, ///< Capacity
|
PROP_ROADVEH_CARGO_CAPACITY = 0x0F, ///< Capacity
|
||||||
|
@ -386,7 +386,7 @@ static const EngineInfo _orig_engine_info[] = {
|
|||||||
* Tractive effort coefficient by default is the same as TTDPatch, 0.30*256=76
|
* Tractive effort coefficient by default is the same as TTDPatch, 0.30*256=76
|
||||||
* Air drag value depends on the top speed of the vehicle.
|
* Air drag value depends on the top speed of the vehicle.
|
||||||
*/
|
*/
|
||||||
#define RVI(a, b, c, d, e, f, g, h, i, j, k) { a, b, c, j, d, e, f, g, h, k, i, 0, 0, 0, VE_DEFAULT, 0, 76, 0, 0 }
|
#define RVI(a, b, c, d, e, f, g, h, i, j, k) { a, b, c, j, d, e, f, g, h, k, i, 0, 0, 0, VE_DEFAULT, 0, 76, 0, 0, 0 }
|
||||||
#define M RAILVEH_MULTIHEAD
|
#define M RAILVEH_MULTIHEAD
|
||||||
#define W RAILVEH_WAGON
|
#define W RAILVEH_WAGON
|
||||||
#define G RAILVEH_SINGLEHEAD
|
#define G RAILVEH_SINGLEHEAD
|
||||||
|
10
src/train.h
10
src/train.h
@ -72,6 +72,7 @@ struct TrainCache {
|
|||||||
|
|
||||||
/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
|
/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
|
||||||
bool cached_tilt; ///< train can tilt; feature provides a bonus in curves
|
bool cached_tilt; ///< train can tilt; feature provides a bonus in curves
|
||||||
|
int cached_curve_speed_mod; ///< curve speed modifier of the entire train
|
||||||
|
|
||||||
byte user_def_data; ///< Cached property 0x25. Can be set by Callback 0x36.
|
byte user_def_data; ///< Cached property 0x25. Can be set by Callback 0x36.
|
||||||
|
|
||||||
@ -312,6 +313,15 @@ protected: // These functions should not be called outside acceleration code.
|
|||||||
return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
|
return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the curve speed modifier of this vehicle.
|
||||||
|
* @return Current curve speed modifier, in fixed-point binary representation with 8 fractional bits.
|
||||||
|
*/
|
||||||
|
inline int GetCurveSpeedModifier() const
|
||||||
|
{
|
||||||
|
return GetVehicleProperty(this, PROP_TRAIN_CURVE_SPEED_MOD, RailVehInfo(this->engine_type)->curve_speed_mod, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the vehicle is at a tile that can be sloped.
|
* Checks if the vehicle is at a tile that can be sloped.
|
||||||
* @return True if the tile can be sloped.
|
* @return True if the tile can be sloped.
|
||||||
|
@ -115,6 +115,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
|||||||
this->compatible_railtypes = RAILTYPES_NONE;
|
this->compatible_railtypes = RAILTYPES_NONE;
|
||||||
|
|
||||||
bool train_can_tilt = true;
|
bool train_can_tilt = true;
|
||||||
|
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()) {
|
||||||
const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
|
const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
|
||||||
@ -146,6 +147,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;
|
||||||
|
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 */
|
||||||
u->tcache.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->gcache.first_engine);
|
u->tcache.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->gcache.first_engine);
|
||||||
@ -229,6 +231,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_tilt = train_can_tilt;
|
this->tcache.cached_tilt = train_can_tilt;
|
||||||
|
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();
|
||||||
|
|
||||||
/* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
|
/* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
|
||||||
@ -357,6 +360,11 @@ int Train::GetCurveSpeedLimit() const
|
|||||||
/* Apply max_speed bonus of 20% for a tilting train */
|
/* Apply max_speed bonus of 20% for a tilting train */
|
||||||
max_speed += max_speed / 5;
|
max_speed += max_speed / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Apply max_speed modifier (cached value is fixed-point binary with 8 fractional bits)
|
||||||
|
* and clamp the result to an acceptable range. */
|
||||||
|
max_speed += (max_speed * this->tcache.cached_curve_speed_mod) >> 8;
|
||||||
|
max_speed = Clamp(max_speed, 2, absolute_max_speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return max_speed;
|
return max_speed;
|
||||||
|
Loading…
Reference in New Issue
Block a user