diff --git a/doc/angelscript/Script2Game/BeamClass.h b/doc/angelscript/Script2Game/BeamClass.h index 034ee7534d..232bc4a086 100644 --- a/doc/angelscript/Script2Game/BeamClass.h +++ b/doc/angelscript/Script2Game/BeamClass.h @@ -122,6 +122,14 @@ class BeamClass * Sets the mass of the truck. */ void setMass(float m); + + /** + * Allows advanced users to set physics settings directly, including some not accessible from rig-def file format. + * HAZARDOUS - values may not be checked; Pay attention to 'safe values' at each attribute description. + */ + void setSimAttribute(ActorSimAttr attr, float val); + + float getSimAttribute(ActorSimAttr attr); //! @} diff --git a/doc/angelscript/Script2Game/globals.h b/doc/angelscript/Script2Game/globals.h index fedf4df220..49cc17cdd4 100644 --- a/doc/angelscript/Script2Game/globals.h +++ b/doc/angelscript/Script2Game/globals.h @@ -711,6 +711,19 @@ enum ScriptRetCode SCRIPTRETCODE_FUNCTION_NOT_EXISTS = -1006, }; +/// Parameter to `Actor::setSimAttribute()` and `Actor::getSimAttribute()`; allows advanced users to tweak physics internals via script. +/// Each value represents a variable, either directly in `Actor` or a subsystem, i.e. `EngineSim`. +/// PAY ATTENTION to the 'safe value' limits below - those may not be checked when setting attribute values! +enum ActorSimAttr +{ + ACTORSIMATTR_NONE, + + // TractionControl + ACTORSIMATTR_TC_RATIO, //!< Regulating force, safe values: <1 - 20> + ACTORSIMATTR_TC_PULSE_TIME, //!< Pulse duration in seconds, safe values <0.005 - 1> + ACTORSIMATTR_TC_WHEELSLIP_CONSTANT //!< Minimum wheel slip threshold, safe value = 0.25 +}; + } // namespace Script2Game /// @} //addtogroup Script2Game diff --git a/source/main/physics/Actor.cpp b/source/main/physics/Actor.cpp index e5622db6f0..d683129b63 100644 --- a/source/main/physics/Actor.cpp +++ b/source/main/physics/Actor.cpp @@ -4740,3 +4740,29 @@ int Actor::getShockNode2(int shock_number) } return -1.f; } + +void Actor::setSimAttribute(ActorSimAttr attr, float val) +{ + LOG(fmt::format("[RoR|Actor] setSimAttribute: '{}' = {}", ActorSimAttrToString(attr), val)); + + // PLEASE maintain the same order as in `enum ActorSimAttr` + switch (attr) + { + case ACTORSIMATTR_TC_RATIO: tc_ratio = val; return; + case ACTORSIMATTR_TC_PULSE_TIME: tc_pulse_time = val; return; + case ACTORSIMATTR_TC_WHEELSLIP_CONSTANT: tc_wheelslip_constant = val; return; + default: return; + } +} + +float Actor::getSimAttribute(ActorSimAttr attr) +{ + // PLEASE maintain the same order as in `enum ActorSimAttr` + switch (attr) + { + case ACTORSIMATTR_TC_RATIO: return tc_ratio; + case ACTORSIMATTR_TC_PULSE_TIME: return tc_pulse_time; + case ACTORSIMATTR_TC_WHEELSLIP_CONSTANT: return tc_wheelslip_constant; + default: return 0.f; + } +} diff --git a/source/main/physics/Actor.h b/source/main/physics/Actor.h index f0149ccc8b..051622b597 100644 --- a/source/main/physics/Actor.h +++ b/source/main/physics/Actor.h @@ -125,6 +125,8 @@ class Actor : public RefCountingObject // PLEASE maintain the same order as in 'scripting/bindings/ActorAngelscript.cpp' and 'doc/angelscript/.../BeamClass.h' void scaleTruck(float value); void setMass(float m); + void setSimAttribute(ActorSimAttr attr, float val); //!< HAZARDOUS - values may not be checked; Pay attention to 'safe values' at each attribute description. + float getSimAttribute(ActorSimAttr attr); // not exported to scripting: void applyNodeBeamScales(); //!< For GUI::NodeBeamUtils void searchBeamDefaults(); //!< Searches for more stable beam defaults @@ -353,13 +355,6 @@ class Actor : public RefCountingObject bool alb_nodash = false; //!< Anti-lock brake attribute: Hide the dashboard indicator? bool alb_notoggle = false; //!< Anti-lock brake attribute: Disable in-game toggle? float alb_timer = 0.f; //!< Anti-lock brake state; - float tc_ratio = 0.f; //!< Traction control attribute: Regulating force - bool tc_mode = false; //!< Traction control state; Enabled? {1/0} - float tc_pulse_time = 0.f; //!< Traction control attribute; - bool tc_pulse_state = 0.f; //!< Traction control state; - bool tc_nodash = false; //!< Traction control attribute; Hide the dashboard indicator? - bool tc_notoggle = false; //!< Traction control attribute; Disable in-game toggle? - float tc_timer = 0.f; //!< Traction control state; float ar_anim_shift_timer = 0.f;//!< For 'animator' with flag 'shifter' bool cc_mode = false; //!< Cruise Control bool cc_can_brake = false; //!< Cruise Control @@ -437,6 +432,16 @@ class Actor : public RefCountingObject CollisionBoxPtrVec m_potential_eventboxes; std::vector> m_active_eventboxes; + // TractionControl + float tc_ratio = 0.f; //!< Regulating force + bool tc_mode = false; //!< Enabled? + float tc_pulse_time = 0.f; + bool tc_pulse_state = 0.f; + bool tc_nodash = false; //!< Hide the dashboard indicator? + bool tc_notoggle = false; //!< Disable in-game toggle? + float tc_timer = 0.f; + float tc_wheelslip_constant = 0.25f; //!< use `ACTORSIMATTR_TC_WHEELSLIP_CONSTANT` + // Guisettings bool ar_guisettings_use_engine_max_rpm = false; float ar_guisettings_speedo_max_kph = 0.f; diff --git a/source/main/physics/ActorForcesEuler.cpp b/source/main/physics/ActorForcesEuler.cpp index 3a28e45cce..3aadf60cce 100644 --- a/source/main/physics/ActorForcesEuler.cpp +++ b/source/main/physics/ActorForcesEuler.cpp @@ -302,7 +302,7 @@ void Actor::CalcWheels(bool doUpdate, int num_steps) float wheel_slip = fabs(ar_wheels[i].wh_speed - relspeed) / std::max(1.0f, curspeed); // traction control - if (tc_mode && fabs(ar_wheels[i].wh_torque) > 0.0f && fabs(ar_wheels[i].wh_speed) > curspeed && wheel_slip > 0.25f) + if (tc_mode && fabs(ar_wheels[i].wh_torque) > 0.0f && fabs(ar_wheels[i].wh_speed) > curspeed && wheel_slip > tc_wheelslip_constant) { if (tc_pulse_state) { diff --git a/source/main/physics/SimData.cpp b/source/main/physics/SimData.cpp index 9fdf81ad68..1a577b7281 100644 --- a/source/main/physics/SimData.cpp +++ b/source/main/physics/SimData.cpp @@ -103,3 +103,17 @@ ActorModifyRequest::~ActorModifyRequest() { // Destructs `CacheEntryPtr` which is a `RefCountingObjectPtr<>` so it doesn't compile without `#include "TuneupFileFormat.h"` and thus should not be in header. } + +const char* RoR::ActorSimAttrToString(ActorSimAttr attr) +{ + switch (attr) + { + case ACTORSIMATTR_NONE: return "NONE"; + + // TractionControl + case ACTORSIMATTR_TC_RATIO: return "TC_RATIO"; + case ACTORSIMATTR_TC_PULSE_TIME: return "TC_PULSE_TIME"; + case ACTORSIMATTR_TC_WHEELSLIP_CONSTANT: return "TC_WHEELSLIP_CONSTANT"; + default: ""; + } +} diff --git a/source/main/physics/SimData.h b/source/main/physics/SimData.h index 3e026c5412..e446c78609 100644 --- a/source/main/physics/SimData.h +++ b/source/main/physics/SimData.h @@ -913,4 +913,18 @@ struct ActorLinkingRequest int alr_rope_group = -1; }; +/// Parameter to `Actor::setSimAttribute()` and `Actor::getSimAttribute()`; allows advanced users to tweak physics internals via script. +/// Each value represents a variable, either directly in `Actor` or a subsystem, i.e. `EngineSim`. +/// PAY ATTENTION to the 'safe value' limits below - those may not be checked when setting attribute values! +enum ActorSimAttr +{ + ACTORSIMATTR_NONE, + + // TractionControl + ACTORSIMATTR_TC_RATIO, //!< Regulating force, safe values: <1 - 20> + ACTORSIMATTR_TC_PULSE_TIME, //!< Pulse duration in seconds, safe values <0.00005 - 1> + ACTORSIMATTR_TC_WHEELSLIP_CONSTANT //!< Minimum wheel slip threshold, safe value = 0.25 +}; +const char* ActorSimAttrToString(ActorSimAttr attr); + } // namespace RoR diff --git a/source/main/scripting/bindings/ActorAngelscript.cpp b/source/main/scripting/bindings/ActorAngelscript.cpp index 9ccfa86d0f..da247a2950 100644 --- a/source/main/scripting/bindings/ActorAngelscript.cpp +++ b/source/main/scripting/bindings/ActorAngelscript.cpp @@ -79,6 +79,13 @@ void RoR::RegisterActor(asIScriptEngine *engine) result = engine->RegisterEnumValue("ActorModifyRequestType", "ACTOR_MODIFY_REQUEST_RESTORE_SAVED", (int)ActorModifyRequest::Type::RESTORE_SAVED); ROR_ASSERT(result >= 0); result = engine->RegisterEnumValue("ActorModifyRequestType", "ACTOR_MODIFY_REQUEST_WAKE_UP", (int)ActorModifyRequest::Type::WAKE_UP); ROR_ASSERT(result >= 0); + // enum ActorSimAttr + result = engine->RegisterEnum("ActorSimAttr"); ROR_ASSERT(result >= 0); + result = engine->RegisterEnumValue("ActorSimAttr", "ACTORSIMATTR_NONE", (int)ACTORSIMATTR_NONE); ROR_ASSERT(result >= 0); + result = engine->RegisterEnumValue("ActorSimAttr", "ACTORSIMATTR_TC_RATIO", (int)ACTORSIMATTR_TC_RATIO); ROR_ASSERT(result >= 0); + result = engine->RegisterEnumValue("ActorSimAttr", "ACTORSIMATTR_TC_PULSE_TIME", (int)ACTORSIMATTR_TC_PULSE_TIME); ROR_ASSERT(result >= 0); + result = engine->RegisterEnumValue("ActorSimAttr", "ACTORSIMATTR_TC_WHEELSLIP_CONSTANT", (int)ACTORSIMATTR_TC_WHEELSLIP_CONSTANT); ROR_ASSERT(result >= 0); + // class Actor (historically Beam) Actor::RegisterRefCountingObject(engine, "BeamClass"); ActorPtr::RegisterRefCountingObjectPtr(engine, "BeamClassPtr", "BeamClass"); @@ -110,6 +117,8 @@ void RoR::RegisterActor(asIScriptEngine *engine) // - physics editing (PLEASE maintain the same order as 'Actor.h' and 'doc/angelscript/.../BeamClass.h') result = engine->RegisterObjectMethod("BeamClass", "void scaleTruck(float)", asMETHOD(Actor,scaleTruck), asCALL_THISCALL); ROR_ASSERT(result>=0); result = engine->RegisterObjectMethod("BeamClass", "void setMass(float)", asMETHOD(Actor,setMass), asCALL_THISCALL); ROR_ASSERT(result>=0); + result = engine->RegisterObjectMethod("BeamClass", "void setSimAttribute(ActorSimAttr, float)", asMETHOD(Actor, setSimAttribute), asCALL_THISCALL); ROR_ASSERT(result >= 0); + result = engine->RegisterObjectMethod("BeamClass", "float getSimAttribute(ActorSimAttr)", asMETHOD(Actor, getSimAttribute), asCALL_THISCALL); ROR_ASSERT(result >= 0); // - user interaction (PLEASE maintain the same order as 'Actor.h' and 'doc/angelscript/.../BeamClass.h') result = engine->RegisterObjectMethod("BeamClass", "void parkingbrakeToggle()", asMETHOD(Actor,parkingbrakeToggle), asCALL_THISCALL); ROR_ASSERT(result>=0);