diff --git a/ace_advanced_ballistics.dll b/ace_advanced_ballistics.dll index 705a90b2ef..f5f5c19c26 100644 Binary files a/ace_advanced_ballistics.dll and b/ace_advanced_ballistics.dll differ diff --git a/addons/atragmx/config.cpp b/addons/atragmx/config.cpp index d7cb846c60..125d4a488e 100644 --- a/addons/atragmx/config.cpp +++ b/addons/atragmx/config.cpp @@ -6,7 +6,7 @@ class CfgPatches { units[] = {"ACE_Item_ATragMX"}; weapons[] = {"ACE_ATragMX"}; requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ACE_common", "ACE_weather"}; + requiredAddons[] = {"ACE_Advanced_Ballistics", "ACE_common", "ACE_weather"}; author = ECSTRING(common,ACETeam); authors[] = {"Ruthberg"}; url = ECSTRING(main,URL); diff --git a/addons/atragmx/functions/fnc_calculate_distance_at_velocity.sqf b/addons/atragmx/functions/fnc_calculate_distance_at_velocity.sqf index f86ef5d28a..9641804fbe 100644 --- a/addons/atragmx/functions/fnc_calculate_distance_at_velocity.sqf +++ b/addons/atragmx/functions/fnc_calculate_distance_at_velocity.sqf @@ -29,11 +29,7 @@ private _distance = 0; while {_velocity > _thresholdVelocity} do { private _bc = GVAR(targetSolutionInput) select 14; private _dragModel = GVAR(targetSolutionInput) select 15; - private _drag = if (missionNamespace getVariable [QEGVAR(advanced_ballistics,extensionAvailable), false]) then { - parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _velocity])) - } else { - ([_dragModel, _bc, _velocity] call EFUNC(advanced_ballistics,calculateRetardation)) - }; + private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _velocity])); _distance = _distance + _velocity * __DELTA_T; _velocity = _velocity - (_drag * __DELTA_T); }; diff --git a/addons/atragmx/functions/fnc_calculate_solution.sqf b/addons/atragmx/functions/fnc_calculate_solution.sqf index d98c46c5fb..940b3dc2ec 100644 --- a/addons/atragmx/functions/fnc_calculate_solution.sqf +++ b/addons/atragmx/functions/fnc_calculate_solution.sqf @@ -90,7 +90,7 @@ _wind1 = [cos(270 - _windDirection * 30) * _windSpeed1, sin(270 - _windDirection _wind2 = [cos(270 - _windDirection * 30) * _windSpeed2, sin(270 - _windDirection * 30) * _windSpeed2, 0]; _windDrift = 0; if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { - _bc = [_bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel] call EFUNC(advanced_ballistics,calculateAtmosphericCorrection); + _bc = parseNumber(("ace_advanced_ballistics" callExtension format["atmosphericCorrection:%1:%2:%3:%4:%5", _bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel])); }; private ["_speedTotal", "_stepsTotal", "_speedAverage"]; @@ -125,11 +125,7 @@ while {_TOF < 15 && (_bulletPos select 1) < _targetRange} do { _trueSpeed = vectorMagnitude _trueVelocity; if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { - private _drag = if (missionNamespace getVariable [QEGVAR(advanced_ballistics,extensionAvailable), false]) then { - parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed])) - } else { - ([_dragModel, _bc, _trueSpeed] call EFUNC(advanced_ballistics,calculateRetardation)) - }; + private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed])); _bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag); } else { _bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction); diff --git a/addons/atragmx/functions/fnc_update_zero_range.sqf b/addons/atragmx/functions/fnc_update_zero_range.sqf index 3d56dc81eb..5cf175faf7 100644 --- a/addons/atragmx/functions/fnc_update_zero_range.sqf +++ b/addons/atragmx/functions/fnc_update_zero_range.sqf @@ -17,9 +17,6 @@ [] call FUNC(parse_input); -private ["_scopeBaseAngle"]; -_scopeBaseAngle = (GVAR(workingMemory) select 3); - private ["_bulletMass", "_boreHeight", "_airFriction", "_muzzleVelocity", "_bc", "_dragModel", "_atmosphereModel"]; _bulletMass = GVAR(workingMemory) select 12; _boreHeight = GVAR(workingMemory) select 5; @@ -46,12 +43,13 @@ if (!GVAR(atmosphereModeTBH)) then { _relativeHumidity = 50; }; -{ - private _result = [_scopeBaseAngle, _bulletMass, _boreHeight, _airFriction, _muzzleVelocity, _temperature, _barometricPressure, _relativeHumidity, 1000, [0, 0], 0, 0, 0, _zeroRange, _bc, _dragModel, _atmosphereModel, false, 1.5, 0, 0, 0] call FUNC(calculate_solution); - private _offset = (_result select 0) / 60; - _scopeBaseAngle = _scopeBaseAngle + _offset; - if (_offset < 0.01) exitWith {}; -} forEach [1, 2, 3]; +private _scopeBaseAngle = if (!(missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) then { + private _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngleVanilla:%1:%2:%3:%4", _zeroRange, _muzzleVelocity, _airFriction, _boreHeight]; + (parseNumber _zeroAngle) +} else { + private _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngle:%1:%2:%3:%4:%5:%6:%7:%8:%9", _zeroRange, _muzzleVelocity, _boreHeight, _temperature, _barometricPressure, _relativeHumidity, _bc, _dragModel, _atmosphereModel]; + (parseNumber _zeroAngle) +}; GVAR(workingMemory) set [2, _zeroRange]; GVAR(workingMemory) set [3, _scopeBaseAngle]; diff --git a/addons/rangecard/functions/fnc_calculateSolution.sqf b/addons/rangecard/functions/fnc_calculateSolution.sqf index 945c2aa512..1e2cb38ba7 100644 --- a/addons/rangecard/functions/fnc_calculateSolution.sqf +++ b/addons/rangecard/functions/fnc_calculateSolution.sqf @@ -94,7 +94,7 @@ _wind1 = [cos(270 - _windDirection * 30) * _windSpeed1, sin(270 - _windDirection _wind2 = [cos(270 - _windDirection * 30) * _windSpeed2, sin(270 - _windDirection * 30) * _windSpeed2, 0]; _windDrift = 0; if (_useABConfig) then { - _bc = [_bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel] call EFUNC(advanced_ballistics,calculateAtmosphericCorrection); + _bc = parseNumber(("ace_advanced_ballistics" callExtension format["atmosphericCorrection:%1:%2:%3:%4:%5", _bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel])); }; private ["_airFrictionCoef", "_airDensity"]; @@ -131,11 +131,7 @@ while {_TOF < 6 && (_bulletPos select 1) < _targetRange} do { _trueSpeed = vectorMagnitude _trueVelocity; if (_useABConfig) then { - private _drag = if (missionNamespace getVariable [QEGVAR(advanced_ballistics,extensionAvailable), false]) then { - parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed])) - } else { - ([_dragModel, _bc, _trueSpeed] call EFUNC(advanced_ballistics,calculateRetardation)) - }; + private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed])); _bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag); } else { _bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction * _airFrictionCoef); diff --git a/addons/rangecard/functions/fnc_updateRangeCard.sqf b/addons/rangecard/functions/fnc_updateRangeCard.sqf index 37d738648d..633df5e4c6 100644 --- a/addons/rangecard/functions/fnc_updateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_updateRangeCard.sqf @@ -158,12 +158,13 @@ if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) t _cacheEntry = missionNamespace getVariable format[QGVAR(%1_%2_%3_%4), _zeroRange, _ammoClass, _weaponClass, missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]]; if (isNil {_cacheEntry}) then { - private _scopeBaseAngle = 0; - { - private _offset = [_scopeBaseAngle, _zeroRange, _muzzleVelocity, _airFriction, 1000, _boreHeight, EGVAR(scopes,zeroReferenceTemperature), EGVAR(scopes,zeroReferenceBarometricPressure), EGVAR(scopes,zeroReferenceHumidity), _bc, _dragModel, _atmosphereModel, _useABConfig] call EFUNC(scopes,calculateZeroAngle); - _scopeBaseAngle = _scopeBaseAngle + _offset; - if (_offset < 0.01) exitWith {}; - } forEach [1, 2, 3]; + private _scopeBaseAngle = if (!_useABConfig) then { + private _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngleVanilla:%1:%2:%3:%4", _zeroRange, _muzzleVelocity, _airFriction, _boreHeight]; + (parseNumber _zeroAngle) + } else { + private _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngle:%1:%2:%3:%4:%5:%6:%7:%8:%9", _zeroRange, _muzzleVelocity, _boreHeight, EGVAR(scopes,zeroReferenceTemperature), EGVAR(scopes,zeroReferenceBarometricPressure), EGVAR(scopes,zeroReferenceHumidity), _bc, _dragModel, _atmosphereModel]; + (parseNumber _zeroAngle) + }; if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] && missionNamespace getVariable [QEGVAR(advanced_ballistics,ammoTemperatureEnabled), false]) then { { private _mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift); diff --git a/addons/scopes/XEH_PREP.hpp b/addons/scopes/XEH_PREP.hpp index 7bfcf34268..8d79196650 100644 --- a/addons/scopes/XEH_PREP.hpp +++ b/addons/scopes/XEH_PREP.hpp @@ -2,7 +2,6 @@ PREP(adjustScope); PREP(adjustZero); PREP(applyScopeAdjustment); -PREP(calculateZeroAngle); PREP(calculateZeroAngleCorrection); PREP(canAdjustZero); PREP(firedEH); diff --git a/addons/scopes/functions/fnc_calculateZeroAngle.sqf b/addons/scopes/functions/fnc_calculateZeroAngle.sqf deleted file mode 100644 index a65a6e99d7..0000000000 --- a/addons/scopes/functions/fnc_calculateZeroAngle.sqf +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Author: Ruthberg - * Calculates zero angle - * - * Arguments: - * 0: zero angle - * 1: zero range - * 2: muzzle velocity - * 3: air friction - * 4: simulation steps - * 5: bore height - * 6: temperature - * 7: barometric pressure - * 8: relative humidity - * 9: ballistic coefficient - * 10: drag model - * 11: atmosphere model - * 12: advanced_ballistics - * - * Return Value: - * 0: zero angle (Degrees) - * - * Example: - * call ace_scopes_fnc_calculateZeroAngle - * - * Public: No - */ -#include "script_component.hpp" -params [ - "_zeroAngle", "_zeroRange", "_muzzleVelocity", "_airFriction", "_simSteps", "_boreHeight", - "_temperature", "_barometricPressure", "_relativeHumidity", "_bc", "_dragModel", "_atmosphereModel", - "_advancedBallistics" -]; - -private ["_bulletPos", "_bulletVelocity", "_bulletAccel", "_bulletSpeed", "_gravity", "_deltaT"]; -_bulletPos = [0, 0, 0]; -_bulletVelocity = [0, 0, 0]; -_bulletAccel = [0, 0, 0]; -_bulletSpeed = 0; -_gravity = [0, sin(_zeroAngle) * -9.80665, cos(_zeroAngle) * -9.80665]; -_deltaT = 1 / _simSteps; - -private ["_TOF"]; -_TOF = 0; - -if (_advancedBallistics) then { - _bc = [_bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel] call EFUNC(advanced_ballistics,calculateAtmosphericCorrection); -}; - -_bulletPos set [0, 0]; -_bulletPos set [1, 0]; -_bulletPos set [2, -(_boreHeight / 100)]; - -_bulletVelocity set [0, 0]; -_bulletVelocity set [1, Cos(_zeroAngle) * _muzzleVelocity]; -_bulletVelocity set [2, Sin(_zeroAngle) * _muzzleVelocity]; - -while {_TOF < 15 && (_bulletPos select 1) < _zeroRange} do { - _bulletSpeed = vectorMagnitude _bulletVelocity; - - if (_advancedBallistics) then { - private _drag = if (missionNamespace getVariable [QEGVAR(advanced_ballistics,extensionAvailable), false]) then { - parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _bulletSpeed])) - } else { - ([_dragModel, _bc, _bulletSpeed] call EFUNC(advanced_ballistics,calculateRetardation)) - }; - _bulletAccel = (vectorNormalized _bulletVelocity) vectorMultiply (-1 * _drag); - } else { - _bulletAccel = _bulletVelocity vectorMultiply (_bulletSpeed * _airFriction); - }; - - _bulletAccel = _bulletAccel vectorAdd _gravity; - - _bulletVelocity = _bulletVelocity vectorAdd (_bulletAccel vectorMultiply _deltaT); - _bulletPos = _bulletPos vectorAdd (_bulletVelocity vectorMultiply _deltaT); - - _TOF = _TOF + _deltaT; -}; - -if ((_bulletPos select 1) > 0) then { - _zeroAngle = - atan((_bulletPos select 2) / (_bulletPos select 1)); -}; - -_zeroAngle diff --git a/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf b/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf index 59984a57ae..bcf1779f84 100644 --- a/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf +++ b/addons/scopes/functions/fnc_calculateZeroAngleCorrection.sqf @@ -19,49 +19,46 @@ params ["_oldZeroRange", "_newZeroRange", "_boreHeight"/*in cm*/, "_weapon", "_ammo", "_magazine", "_advancedBallistics"]; -// Get Weapon and Ammo Configurations -private _AmmoCacheEntry = uiNamespace getVariable format[QEGVAR(advanced_ballistics,%1), _ammo]; -if (isNil "_AmmoCacheEntry") then { - _AmmoCacheEntry = _ammo call EFUNC(advanced_ballistics,readAmmoDataFromConfig); -}; -private _WeaponCacheEntry = uiNamespace getVariable format[QEGVAR(advanced_ballistics,%1), _weapon]; -if (isNil "_WeaponCacheEntry") then { - _WeaponCacheEntry = _weapon call EFUNC(advanced_ballistics,readWeaponDataFromConfig); -}; - -_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable"]; -_WeaponCacheEntry params ["_barrelTwist", "_twistDirection", "_barrelLength"]; - -_initSpeed = getNumber(configFile >> "CfgMagazines" >> _magazine >> "initSpeed"); -_initSpeedCoef = getNumber(configFile >> "CfgWeapons" >> _weapon >> "initSpeed"); +private _airFriction = getNumber (configFile >> "CfgAmmo" >> _ammo >> "airFriction"); +private _initSpeed = getNumber(configFile >> "CfgMagazines" >> _magazine >> "initSpeed"); +private _initSpeedCoef = getNumber(configFile >> "CfgWeapons" >> _weapon >> "initSpeed"); if (_initSpeedCoef > 0) then { _initSpeed = _initSpeedCoef; }; if (_initSpeedCoef < 0) then { _initSpeed = _initSpeed * (-1 * _initSpeedCoef); }; -private _vanillaZero = 0; // in degrees -{ - private _offset = [_vanillaZero, _oldZeroRange, _initSpeed, _airFriction, 1000, 0, 0, 0, 0, 0, 0, "", false] call FUNC(calculateZeroAngle); - _vanillaZero = _vanillaZero + _offset; - if (_offset < 0.01) exitWith {}; -} forEach [1, 2, 3]; -if (_advancedBallistics) then { +private _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngleVanilla:%1:%2:%3:%4", _oldZeroRange, _initSpeed, _airFriction, 0]; +private _vanillaZero = parseNumber _zeroAngle; + +private _trueZero = if (!_advancedBallistics) then { + _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngleVanilla:%1:%2:%3:%4", _newZeroRange, _initSpeed, _airFriction, _boreHeight]; + (parseNumber _zeroAngle) +} else { + // Get Weapon and Ammo Configurations + private _AmmoCacheEntry = uiNamespace getVariable format[QEGVAR(advanced_ballistics,%1), _ammo]; + if (isNil "_AmmoCacheEntry") then { + _AmmoCacheEntry = _ammo call EFUNC(advanced_ballistics,readAmmoDataFromConfig); + }; + private _WeaponCacheEntry = uiNamespace getVariable format[QEGVAR(advanced_ballistics,%1), _weapon]; + if (isNil "_WeaponCacheEntry") then { + _WeaponCacheEntry = _weapon call EFUNC(advanced_ballistics,readWeaponDataFromConfig); + }; + + _AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable"]; + _WeaponCacheEntry params ["_barrelTwist", "_twistDirection", "_barrelLength"]; + if (missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]) then { private _barrelVelocityShift = [_barrelLength, _muzzleVelocityTable, _barrelLengthTable, _initSpeed] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift); _initSpeed = _initSpeed + _barrelVelocityShift; }; + + _zeroAngle = "ace_advanced_ballistics" callExtension format ["zeroAngle:%1:%2:%3:%4:%5:%6:%7:%8:%9", _newZeroRange, _initSpeed, _boreHeight, GVAR(zeroReferenceTemperature), GVAR(zeroReferenceBarometricPressure), GVAR(zeroReferenceHumidity), _ballisticCoefficients select 0, _dragModel, _atmosphereModel]; + (parseNumber _zeroAngle) }; -private _zeroAngle = 0; // in degrees -{ - private _offset = [_zeroAngle, _newZeroRange, _initSpeed, _airFriction, 1000, _boreHeight, GVAR(zeroReferenceTemperature), GVAR(zeroReferenceBarometricPressure), GVAR(zeroReferenceHumidity), _ballisticCoefficients select 0, _dragModel, _atmosphereModel, _advancedBallistics] call FUNC(calculateZeroAngle); - _zeroAngle = _zeroAngle + _offset; - if (_offset < 0.01) exitWith {}; -} forEach [1, 2, 3]; - -private _zeroAngleCorrection = _zeroAngle - _vanillaZero; +private _zeroAngleCorrection = _trueZero - _vanillaZero; missionNamespace setVariable [format[QGVAR(%1_%2_%3_%4_%5_%6_%7), _oldZeroRange, _newZeroRange, _boreHeight, _weapon, _ammo, _magazine, _advancedBallistics], _zeroAngleCorrection]; diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index e9082ad2d1..89a0d0b060 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -5,9 +5,12 @@ #include #include #include +#include +#define DELTA_T 0.02f #define GRAVITY 9.80665f +#define DEGREES(X) (X * 180 / M_PI) #define ABSOLUTE_ZERO_IN_CELSIUS -273.15f #define KELVIN(t) (t - ABSOLUTE_ZERO_IN_CELSIUS) #define CELSIUS(t) (t + ABSOLUTE_ZERO_IN_CELSIUS) @@ -229,6 +232,113 @@ double calculateRetard(int DragFunction, double DragCoefficient, double Velocity return 0.0; } +double calculateVanillaZeroAngle(double zeroRange, double muzzleVelocity, double airFriction, double boreHeight) { + double zeroAngle = 0.0f; + + for (int i = 0; i < 10; i++) { + double lx = 0.0f; + double ly = 0.0f; + + double px = 0.0f; + double py = -boreHeight / 100.0f; + + double gx = std::sin(zeroAngle) * -GRAVITY; + double gy = std::cos(zeroAngle) * -GRAVITY; + + double vx = std::cos(zeroAngle) * muzzleVelocity; + double vy = std::sin(zeroAngle) * muzzleVelocity; + + double tof = 0.0f; + double v = 0.0f; + + while (tof < 8.0f && px < zeroRange) { + lx = px; + ly = py; + + v = std::sqrt(vx*vx + vy*vy); + + double ax = vx * v * airFriction; + double ay = vy * v * airFriction; + ax += gx; + ay += gy; + + px += vx * DELTA_T * 0.5; + py += vy * DELTA_T * 0.5; + vx += ax * DELTA_T; + vy += ay * DELTA_T; + px += vx * DELTA_T * 0.5; + py += vy * DELTA_T * 0.5; + + tof += DELTA_T; + } + + double y = ly + (zeroRange - lx) * (py - ly) / (px - lx); + double offset = -std::atan(y / zeroRange); + zeroAngle += offset; + + if (std::abs(offset) < 0.0001f) { + break; + } + } + + return zeroAngle; +} + +double calculateZeroAngle(double zeroRange, double muzzleVelocity, double boreHeight, double temperature, double pressure, double humidity, double ballisticCoefficient, int dragModel, char* atmosphereModel) { + double zeroAngle = 0.0f; + + ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, humidity, atmosphereModel); + + for (int i = 0; i < 10; i++) { + double lx = 0.0f; + double ly = 0.0f; + + double px = 0.0f; + double py = -boreHeight / 100.0f; + + double gx = std::sin(zeroAngle) * -GRAVITY; + double gy = std::cos(zeroAngle) * -GRAVITY; + + double vx = std::cos(zeroAngle) * muzzleVelocity; + double vy = std::sin(zeroAngle) * muzzleVelocity; + + double tof = 0.0f; + double v = 0.0f; + + while (tof < 8.0f && px < zeroRange) { + lx = px; + ly = py; + + v = std::sqrt(vx*vx + vy*vy); + + double retard = calculateRetard(dragModel, ballisticCoefficient, v); + double ax = vx / v * -retard; + double ay = vy / v * -retard; + ax += gx; + ay += gy; + + px += vx * DELTA_T * 0.5; + py += vy * DELTA_T * 0.5; + vx += ax * DELTA_T; + vy += ay * DELTA_T; + px += vx * DELTA_T * 0.5; + py += vy * DELTA_T * 0.5; + + tof += DELTA_T; + } + + double y = ly + (zeroRange - lx) * (py - ly) / (px - lx); + double offset = -std::atan(y / zeroRange); + zeroAngle += offset; + + if (std::abs(offset) < 0.0001f) { + break; + } + } + + return zeroAngle; +} + extern "C" { EXPORT void __stdcall RVExtension(char *output, int outputSize, const char *function); @@ -639,6 +749,33 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridBuildingNums.reserve(gridCells); map->gridSurfaceIsWater.reserve(gridCells); + strncpy_s(output, outputSize, outputStr.str().c_str(), _TRUNCATE); + EXTENSION_RETURN(); + } else if (!strcmp(mode, "zeroAngleVanilla")) { + double zeroRange = strtod(strtok_s(NULL, ":", &next_token), NULL); + double initSpeed = strtod(strtok_s(NULL, ":", &next_token), NULL); + double airFriction = strtod(strtok_s(NULL, ":", &next_token), NULL); + double boreHeight = strtod(strtok_s(NULL, ":", &next_token), NULL); + + double zeroAngle = calculateVanillaZeroAngle(zeroRange, initSpeed, airFriction, boreHeight); + + outputStr << DEGREES(zeroAngle); + strncpy_s(output, outputSize, outputStr.str().c_str(), _TRUNCATE); + EXTENSION_RETURN(); + } else if (!strcmp(mode, "zeroAngle")) { + double zeroRange = strtod(strtok_s(NULL, ":", &next_token), NULL); + double muzzleVelocity = strtod(strtok_s(NULL, ":", &next_token), NULL); + double boreHeight = strtod(strtok_s(NULL, ":", &next_token), NULL); + double temperature = strtod(strtok_s(NULL, ":", &next_token), NULL); + double pressure = strtod(strtok_s(NULL, ":", &next_token), NULL); + double humidity = strtod(strtok_s(NULL, ":", &next_token), NULL); + double ballisticCoefficient = strtod(strtok_s(NULL, ":", &next_token), NULL); + int dragModel = strtol(strtok_s(NULL, ":", &next_token), NULL, 10); + char* atmosphereModel = strtok_s(NULL, ":", &next_token); + + double zeroAngle = calculateZeroAngle(zeroRange, muzzleVelocity, boreHeight, temperature, pressure, humidity, ballisticCoefficient, dragModel, atmosphereModel); + + outputStr << DEGREES(zeroAngle); strncpy_s(output, outputSize, outputStr.str().c_str(), _TRUNCATE); EXTENSION_RETURN(); }