From d05b7b37f501017019caadc17b6bb779822da68b Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 1 Feb 2026 11:49:43 +0100 Subject: [PATCH 1/2] Optimize misc. ballistics funtions --- ...statTextStatement_weaponMuzzleVelocity.sqf | 8 ++- .../functions/fnc_calculateRangeCard.sqf | 2 +- addons/rangecard/script_component.hpp | 2 + .../fnc_calculateZeroAngleCorrection.sqf | 24 ++++--- .../functions/fnc_ballistics_calculator.sqf | 66 ++++++++++++------- .../functions/fnc_ballistics_getData.sqf | 55 +++++++++------- 6 files changed, 97 insertions(+), 60 deletions(-) diff --git a/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf b/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf index 49dc6776a9b..52eaa5ada42 100644 --- a/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf +++ b/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf @@ -41,11 +41,13 @@ if (_useAB) then { }; } else { private _initSpeedCoef = getNumber (_configWeapon >> "initSpeed"); - if (_initSpeedCoef < 0) then { - _muzzleVelocity = _muzzleVelocity * -_initSpeedCoef; - }; + if (_initSpeedCoef > 0) then { _muzzleVelocity = _initSpeedCoef; + } else { + if (_initSpeedCoef < 0) then { + _muzzleVelocity = _muzzleVelocity * -_initSpeedCoef; + }; }; }; diff --git a/addons/rangecard/functions/fnc_calculateRangeCard.sqf b/addons/rangecard/functions/fnc_calculateRangeCard.sqf index 4f1ea68b7d1..abf729bdc54 100644 --- a/addons/rangecard/functions/fnc_calculateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_calculateRangeCard.sqf @@ -76,7 +76,7 @@ if (_useABConfig) then { private _airFrictionCoef = if (!_useABConfig && _isABenabled) then { private _airDensity = [_temperature, _barometricPressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity); - _airDensity / 1.22498 + _airDensity / STD_AIR_DENSITY_ICAO } else { 1 }; diff --git a/addons/rangecard/script_component.hpp b/addons/rangecard/script_component.hpp index 8f64b49b549..7ea468fe95c 100644 --- a/addons/rangecard/script_component.hpp +++ b/addons/rangecard/script_component.hpp @@ -14,6 +14,8 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_RANGECARD #endif +#define STD_AIR_DENSITY_ICAO 1.22498 + #define RANGE_CARD_INCREMENT 50 #define RANGE_CARD_START_RANGE 100 #define RANGE_CARD_END_RANGE (RANGE_CARD_START_RANGE + 49 * RANGE_CARD_INCREMENT) diff --git a/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf b/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf index 56168326654..ce0b7b2a75f 100644 --- a/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf +++ b/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf @@ -1,12 +1,12 @@ #include "..\script_component.hpp" /* * Author: Ruthberg - * Calculates the zero angle correction for the new zero range based on current zero range and bore height (distance between bore- and sight axis) + * Calculates the zero angle correction for the new zero range based on current zero range and bore height (distance between bore- and sight axis). * * Arguments: * 0: Old Zero range * 1: New Zero range - * 2: Bore height + * 2: Bore height - cm * 3: Weapon * 4: Muzzle * 5: Ammo @@ -14,28 +14,32 @@ * 7: Advanced Ballistics enabled? * * Return Value: - * zeroAngleCorrection + * Zero angle correction * * Example: - * [5, 6, 7, gun, ammo, magazine, true] call ace_scopes_fnc_calculateZeroAngleCorrection + * [5, 6, 3.81, "arifle_MXM_F", "B_65x39_Caseless", "30Rnd_65x39_caseless_mag", true] call ace_scopes_fnc_calculateZeroAngleCorrection * * Public: No */ -params ["_oldZeroRange", "_newZeroRange", "_boreHeight"/*in cm*/, "_weapon", "_muzzle", "_ammo", "_magazine", "_advancedBallistics"]; +params ["_oldZeroRange", "_newZeroRange", "_boreHeight", "_weapon", "_muzzle", "_ammo", "_magazine", "_advancedBallistics"]; // When FFV from vehicles currentZeroing will report 0 so just bail if (_oldZeroRange <= 0) exitWith { 0 }; GVAR(zeroAngleCorrectionData) getOrDefaultCall [[_oldZeroRange, _newZeroRange, _boreHeight, _weapon, _ammo, _magazine, _advancedBallistics], { private _airFriction = getNumber (configFile >> "CfgAmmo" >> _ammo >> "airFriction"); - private _initSpeed = getNumber(configFile >> "CfgMagazines" >> _magazine >> "initSpeed"); - private _initSpeedCoef = getNumber(configFile >> "CfgWeapons" >> _weapon >> "initSpeed"); + private _initSpeed = 0; + private _initSpeedCoef = getNumber (configFile >> "CfgWeapons" >> _weapon >> "initSpeed"); + if (_initSpeedCoef > 0) then { _initSpeed = _initSpeedCoef; - }; - if (_initSpeedCoef < 0) then { - _initSpeed = _initSpeed * (-1 * _initSpeedCoef); + } else { + _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazine >> "initSpeed"); + + if (_initSpeedCoef < 0) then { + _initSpeed = _initSpeed * -_initSpeedCoef; + }; }; private _vanillaZero = parseNumber (("ace" callExtension ["ballistics:replicate_vanilla_zero", [_oldZeroRange, _initSpeed, _airFriction]]) select 0); diff --git a/addons/xm157/functions/fnc_ballistics_calculator.sqf b/addons/xm157/functions/fnc_ballistics_calculator.sqf index e0b0dc9524b..30c2999f889 100644 --- a/addons/xm157/functions/fnc_ballistics_calculator.sqf +++ b/addons/xm157/functions/fnc_ballistics_calculator.sqf @@ -21,48 +21,67 @@ params ["_targetRange", "_directionOfFire", "_inclinationAngle", "_bank"]; private _weaponInfo = [] call FUNC(ballistics_getData); -if (_weaponInfo isEqualTo []) exitWith { [0,0,0] }; -_weaponInfo params ["_scopeBaseAngle","_boreHeight","_airFriction","_muzzleVelocity","_bc", - "_dragModel","_atmosphereModel","_barrelTwist","_twistDirection","_caliber","_bulletLength","_bulletMass"]; + +if (_weaponInfo isEqualTo []) exitWith { + [0, 0, 0] // return +}; + +_weaponInfo params [ + "_scopeBaseAngle", + "_boreHeight", + "_airFriction", + "_muzzleVelocity", + "_bc", + "_dragModel", + "_atmosphereModel", + "_barrelTwist", + "_twistDirection", + "_caliber", + "_bulletLength", + "_bulletMass" +]; private _latitude = GVAR(data) getOrDefault ["latitude", 0]; // Get Wind private _windSpeed = GVAR(data) getOrDefault ["wind_speed", 0]; private _windDirection = 22.5 * (GVAR(data) getOrDefault ["wind_dir", 0]); -private _wind = [sin (_directionOfFire-_windDirection) * _windSpeed, -cos (_directionOfFire-_windDirection) * _windSpeed, 0]; +private _wind = [sin (_directionOfFire - _windDirection), -cos (_directionOfFire - _windDirection), 0] vectorMultiply _windSpeed; // Get atmosphere -private _altitude = (getPosASL ace_player) select 2; +private _altitude = (getPosASL ACE_player) select 2; private _relativeHumidity = EGVAR(weather,currentHumidity); private _temperature = _altitude call EFUNC(weather,calculateTemperatureAtHeight); private _barometricPressure = _altitude call EFUNC(weather,calculateBarometricPressure); -private _bulletPos = [0,0,-(_boreHeight / 100)]; +private _bulletPos = [0, 0, -_boreHeight / 100]; private _lastBulletPos = +_bulletPos; -private _bulletVelocity = [0,cos(_scopeBaseAngle) * _muzzleVelocity,sin(_scopeBaseAngle) * _muzzleVelocity]; -private _gravity = [-sin (_bank) * cos(_scopeBaseAngle + _inclinationAngle) * -GRAVITY, - sin(_scopeBaseAngle + _inclinationAngle) * -GRAVITY, - cos (_bank) * cos(_scopeBaseAngle + _inclinationAngle) * -GRAVITY]; +private _bulletVelocity = [0, cos _scopeBaseAngle, sin _scopeBaseAngle] vectorMultiply _muzzleVelocity; +private _gravity = [(-sin _bank) * cos (_scopeBaseAngle + _inclinationAngle), + sin (_scopeBaseAngle + _inclinationAngle), + (cos _bank) * cos (_scopeBaseAngle + _inclinationAngle)] vectorMultiply -GRAVITY; private _useAB = missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]; + if (_useAB) then { _bc = parseNumber (("ace" callExtension ["ballistics:atmospheric_correction", [_bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel]]) select 0); }; private _deltaT = 1 / 60; private _TOF = 0; // Limit TOF to 5 seconds! + while {(_TOF < 5) && {(_bulletPos # 1) < _targetRange}} do { private _trueVelocity = _bulletVelocity vectorDiff _wind; private _trueSpeed = vectorMagnitude _trueVelocity; private _bulletAccel = if (_useAB) then { private _drag = parseNumber (("ace" callExtension ["ballistics:retard", [_dragModel, _bc, _trueSpeed, _temperature]]) select 0); - (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag); + (vectorNormalized _trueVelocity) vectorMultiply -_drag; } else { _trueVelocity vectorMultiply (_trueSpeed * _airFriction); }; + _bulletAccel = _bulletAccel vectorAdd _gravity; _lastBulletPos = _bulletPos; _bulletPos = _bulletPos vectorAdd (_bulletVelocity vectorMultiply (_deltaT * 0.5)); @@ -74,27 +93,30 @@ while {(_TOF < 5) && {(_bulletPos # 1) < _targetRange}} do { private _tx = linearConversion [_lastBulletPos select 1, _bulletPos select 1, _targetRange, _lastBulletPos select 0, _bulletPos select 0]; private _tz = linearConversion [_lastBulletPos select 1, _bulletPos select 1, _targetRange, _lastBulletPos select 2, _bulletPos select 2]; -private _elevation = - atan(_tz / _targetRange); -private _windage = - atan(_tx / _targetRange); - +private _elevation = -atan (_tz / _targetRange); +private _windage = -atan (_tx / _targetRange); if (_useAB && {(_bulletPos select 1) > 0}) then { // Coriolis - private _horizontalDeflection = 0.0000729 * (_bulletPos select 1) * _TOF * sin(_latitude); - private _horizontalCoriolis = - atan(_horizontalDeflection / (_bulletPos select 1)); + private _horizontalDeflection = 0.0000729 * (_bulletPos select 1) * _TOF * (sin _latitude); + private _horizontalCoriolis = -atan (_horizontalDeflection / (_bulletPos select 1)); _windage = _windage + _horizontalCoriolis; + // Eoetvoes - private _eoetvoesMultiplier = 2 * (0.0000729 * _muzzleVelocity / -GRAVITY) * cos(_latitude) * sin(_directionOfFire); + private _eoetvoesMultiplier = 2 * (0.0000729 * _muzzleVelocity / -GRAVITY) * (cos _latitude) * (sin _directionOfFire); private _verticalDeflection = (_bulletPos select 2) * _eoetvoesMultiplier; - private _verticalCoriolis = - atan(_verticalDeflection / (_bulletPos select 1)); + private _verticalCoriolis = -atan (_verticalDeflection / (_bulletPos select 1)); _elevation = _elevation + _verticalCoriolis; + // Spin drift - private _stabilityFactor = 1.5; - if (_caliber * _bulletLength * _bulletMass * _barrelTwist > 0) then { - _stabilityFactor = [_caliber, _bulletLength, _bulletMass, _barrelTwist, _muzzleVelocity, _temperature, _barometricPressure] call EFUNC(advanced_ballistics,calculateStabilityFactor); + private _stabilityFactor = if (_caliber * _bulletLength * _bulletMass * _barrelTwist > 0) then { + [_caliber, _bulletLength, _bulletMass, _barrelTwist, _muzzleVelocity, _temperature, _barometricPressure] call EFUNC(advanced_ballistics,calculateStabilityFactor) + } else { + 1.5 }; + private _spinDeflection = _twistDirection * 0.0254 * 1.25 * (_stabilityFactor + 1.2) * _TOF ^ 1.83; - private _spinDrift = - atan(_spinDeflection / (_bulletPos select 1)); + private _spinDrift = -atan (_spinDeflection / (_bulletPos select 1)); _windage = _windage + _spinDrift; }; diff --git a/addons/xm157/functions/fnc_ballistics_getData.sqf b/addons/xm157/functions/fnc_ballistics_getData.sqf index 48b61bea9b0..a0454e265ac 100644 --- a/addons/xm157/functions/fnc_ballistics_getData.sqf +++ b/addons/xm157/functions/fnc_ballistics_getData.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: PabstMirror, Ruthberg (Based on ace_atragmx) - * Gets ballistic info for a weapon, mag and ammo + * Gets ballistic info for a weapon, mag and ammo. * * Arguments: * None @@ -15,24 +15,25 @@ * Public: No */ -private _unit = ace_player; -private _weaponClass = primaryWeapon _unit; +private _unit = ACE_player; private _magazineClass = (primaryWeaponMagazine _unit) param [0, ""]; -private _ammoClass = getText (configFile >> "CfgMagazines" >> _magazineClass >> "ammo"); -private _key = format ["weaponInfoCache-%1-%2-%3",_weaponClass,_magazineClass,_ammoClass]; -private _weaponInfo = GVAR(data) getOrDefault [_key, []]; -if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then { +if (_magazineClass == "") exitWith { + [] // return +}; + +private _weaponClass = primaryWeapon _unit; + +GVAR(data) getOrDefault [[_weaponClass, _magazineClass], { + private _ammoClass = getText (configFile >> "CfgMagazines" >> _magazineClass >> "ammo"); TRACE_3("new weapon/mag",_weaponClass,_magazineClass,_ammoClass); private _zeroRange = 100; private _boreHeight = [_unit, 0] call EFUNC(scopes,getBoreHeight); - private _ammoConfig = _ammoClass call EFUNC(advanced_ballistics,readAmmoDataFromConfig); - _ammoConfig params ["_airFriction","_caliber","_bulletLength","_bulletMass","","_dragModel","_ballisticCoefficients","","_atmosphereModel","","_muzzleVelocityTable","_barrelLengthTable"]; - private _weaponConfig = _weaponClass call EFUNC(advanced_ballistics,readWeaponDataFromConfig); - _weaponConfig params ["_barrelTwist", "_twistDirection", "_barrelLength"]; - private _bc = if (_ballisticCoefficients isEqualTo []) then { 0 } else { _ballisticCoefficients # 0 }; + (_ammoClass call EFUNC(advanced_ballistics,readAmmoDataFromConfig)) params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "", "_dragModel", "_ballisticCoefficients", "", "_atmosphereModel", "", "_muzzleVelocityTable", "_barrelLengthTable"]; + (_weaponClass call EFUNC(advanced_ballistics,readWeaponDataFromConfig)) params ["_barrelTwist", "_twistDirection", "_barrelLength"]; + private _bc = _ballisticCoefficients select 0; private _useAB = ( missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] && @@ -42,31 +43,37 @@ if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then { // Get Muzzle Velocity private _muzzleVelocity = 0; - if (_barrelLength > 0 && _useAB) then { + + if (_useAB && _barrelLength > 0) then { _muzzleVelocity = [_barrelLength, _muzzleVelocityTable, _barrelLengthTable, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift) }; + if (_muzzleVelocity == 0) then { - private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed"); private _initSpeedCoef = getNumber (configFile >> "CfgWeapons" >> _weaponClass >> "initSpeed"); - if (_initSpeedCoef < 0) then { - _initSpeed = _initSpeed * -_initSpeedCoef; - }; + private _initSpeed = 0; + if (_initSpeedCoef > 0) then { _initSpeed = _initSpeedCoef; + } else { + _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed"); + + if (_initSpeedCoef < 0) then { + _initSpeed = _initSpeed * -_initSpeedCoef; + }; }; - _muzzleVelocity = _initSpeed + + _muzzleVelocity = _initSpeed; }; // Scope Base Angle - private _scopeBaseAngle = if ((getText (configFile >> "CfgAmmo" >> _ammoClass >> "simulation")) != "shotshell") then { + private _scopeBaseAngle = if (getText (configFile >> "CfgAmmo" >> _ammoClass >> "simulation") != "shotshell") then { parseNumber (("ace" callExtension ["ballistics:zero_vanilla", [_zeroRange, _muzzleVelocity, _airFriction, _boreHeight]]) select 0) } else { 0 // shotshell will not have any vanilla zeroing applied, 0 is a reasonable default for now }; - _weaponInfo = [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,_bc,_dragModel,_atmosphereModel,_barrelTwist,_twistDirection,_caliber,_bulletLength,_bulletMass]; - GVAR(data) set [_key, _weaponInfo]; - TRACE_1("setting cache",_weaponInfo); -}; + TRACE_8("setting cache",_airFriction,_muzzleVelocity,_bc,_dragModel,_atmosphereModel,_caliber,_bulletLength,_bulletMass); + TRACE_4("setting cache",_scopeBaseAngle,_boreHeight,_barrelTwist,_twistDirection); -_weaponInfo + [_scopeBaseAngle, _boreHeight, _airFriction, _muzzleVelocity, _bc, _dragModel, _atmosphereModel, _barrelTwist, _twistDirection, _caliber, _bulletLength, _bulletMass] +}, true] // return From 271b3115028350909f4b4e5ed108b486df1389c4 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 1 Feb 2026 10:53:17 -0800 Subject: [PATCH 2/2] Update addons/xm157/functions/fnc_ballistics_getData.sqf Co-authored-by: PabstMirror --- addons/xm157/functions/fnc_ballistics_getData.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xm157/functions/fnc_ballistics_getData.sqf b/addons/xm157/functions/fnc_ballistics_getData.sqf index a0454e265ac..f73f2d3384d 100644 --- a/addons/xm157/functions/fnc_ballistics_getData.sqf +++ b/addons/xm157/functions/fnc_ballistics_getData.sqf @@ -24,7 +24,7 @@ if (_magazineClass == "") exitWith { private _weaponClass = primaryWeapon _unit; -GVAR(data) getOrDefault [[_weaponClass, _magazineClass], { +GVAR(data) getOrDefaultCall [[_weaponClass, _magazineClass], { private _ammoClass = getText (configFile >> "CfgMagazines" >> _magazineClass >> "ammo"); TRACE_3("new weapon/mag",_weaponClass,_magazineClass,_ammoClass);