2023-09-12 18:58:10 +00:00
|
|
|
|
#include "..\script_component.hpp"
|
2015-04-05 19:08:55 +00:00
|
|
|
|
/*
|
2024-08-17 15:50:38 +00:00
|
|
|
|
* Author: Glowbal, Ruthberg, Brett Mayson
|
2015-04-07 19:46:43 +00:00
|
|
|
|
*
|
2016-02-06 21:48:26 +00:00
|
|
|
|
* Handles advanced ballistics for (BulletBase) projectiles. Called from the unified fired EH only for players.
|
2015-04-05 19:08:55 +00:00
|
|
|
|
*
|
|
|
|
|
* Arguments:
|
2016-02-06 21:48:26 +00:00
|
|
|
|
* None. Parameters inherited from EFUNC(common,firedEH)
|
2015-04-05 19:08:55 +00:00
|
|
|
|
*
|
|
|
|
|
* Return Value:
|
2015-08-05 03:01:30 +00:00
|
|
|
|
* None
|
2015-04-05 19:08:55 +00:00
|
|
|
|
*
|
2017-06-08 13:31:51 +00:00
|
|
|
|
* Example:
|
|
|
|
|
* [] call ace_advanced_ballistics_fnc_handleFired
|
|
|
|
|
*
|
2015-04-05 19:08:55 +00:00
|
|
|
|
* Public: No
|
|
|
|
|
*/
|
|
|
|
|
|
2016-02-06 21:48:26 +00:00
|
|
|
|
//IGNORE_PRIVATE_WARNING ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle", "_gunner", "_turret"];
|
2024-02-05 17:04:24 +00:00
|
|
|
|
TRACE_10("firedEH:",_unit,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile,_vehicle,_gunner,_turret);
|
2015-08-06 08:58:07 +00:00
|
|
|
|
|
2024-06-18 14:08:03 +00:00
|
|
|
|
if !(_ammo isKindOf "BulletBase") exitWith {};
|
2016-02-06 21:48:26 +00:00
|
|
|
|
if (!alive _projectile) exitWith {};
|
2015-08-06 08:58:07 +00:00
|
|
|
|
if (underwater _unit) exitWith {};
|
2017-11-23 12:44:47 +00:00
|
|
|
|
|
2017-11-30 23:13:54 +00:00
|
|
|
|
private _abort = !local _unit;
|
|
|
|
|
if (_abort) then {
|
|
|
|
|
private _bulletVelocity = velocity _projectile;
|
|
|
|
|
private _muzzleVelocity = vectorMagnitude _bulletVelocity;
|
2020-06-13 20:45:09 +00:00
|
|
|
|
|
2017-11-30 23:13:54 +00:00
|
|
|
|
private _maxRange = uiNamespace getVariable format[QGVAR(maxRange_%1), _ammo];
|
|
|
|
|
if (isNil "_maxRange") then {
|
|
|
|
|
private _airFriction = getNumber(configFile >> "CfgAmmo" >> _ammo >> "airFriction");
|
2021-10-27 00:17:22 +00:00
|
|
|
|
private _vanillaInitialSpeed = getNumber (configFile >> "CfgMagazines" >> _magazine >> "initSpeed");
|
|
|
|
|
_maxRange = if (_airFriction < 0) then {
|
2017-12-02 11:34:52 +00:00
|
|
|
|
private _maxTime = ((_vanillaInitialSpeed - BULLET_TRACE_MIN_VELOCITY) / (BULLET_TRACE_MIN_VELOCITY * -_airFriction * _vanillaInitialSpeed)) max getNumber(configFile >> "CfgAmmo" >> _ammo >> "tracerEndTime");
|
|
|
|
|
-ln(1 - _airFriction * _vanillaInitialSpeed * _maxTime) / _airFriction
|
2017-11-30 23:13:54 +00:00
|
|
|
|
} else {
|
2017-12-02 11:34:52 +00:00
|
|
|
|
_vanillaInitialSpeed * getNumber(configFile >> "CfgAmmo" >> _ammo >> "tracerEndTime")
|
2017-11-30 23:13:54 +00:00
|
|
|
|
};
|
2021-10-27 00:17:22 +00:00
|
|
|
|
_maxRange = _maxRange * 1.3; // Adding 30% more to range just to be safe
|
2017-11-30 23:13:54 +00:00
|
|
|
|
uiNamespace setVariable [format[QGVAR(maxRange_%1), _ammo], _maxRange];
|
|
|
|
|
};
|
|
|
|
|
if (ACE_player distance _unit > _maxRange && {ACE_player distance ((getPosASL _unit) vectorAdd ((vectorNormalized _bulletVelocity) vectorMultiply _maxRange)) > _maxRange}) exitWith {};
|
2020-06-13 20:45:09 +00:00
|
|
|
|
|
2017-11-30 23:13:54 +00:00
|
|
|
|
private _ammoCount = (_unit ammo _muzzle) + 1;
|
|
|
|
|
private _tracersEvery = getNumber(configFile >> "CfgMagazines" >> _magazine >> "tracersEvery");
|
|
|
|
|
private _lastRoundsTracer = getNumber(configFile >> "CfgMagazines" >> _magazine >> "lastRoundsTracer");
|
|
|
|
|
if (_ammoCount <= _lastRoundsTracer || {_tracersEvery > 0 && {(_ammoCount - _lastRoundsTracer) % _tracersEvery == 0}}) exitWith { _abort = false };
|
2020-06-13 20:45:09 +00:00
|
|
|
|
|
2017-11-30 23:13:54 +00:00
|
|
|
|
if (GVAR(bulletTraceEnabled) && {_muzzleVelocity > BULLET_TRACE_MIN_VELOCITY} && {cameraView == "GUNNER"}) then {
|
|
|
|
|
if (currentWeapon ACE_player == binocular ACE_player) exitWith { _abort = false };
|
|
|
|
|
if (currentWeapon ACE_player == primaryWeapon ACE_player && {count primaryWeaponItems ACE_player > 2}) then {
|
|
|
|
|
private _opticsName = (primaryWeaponItems ACE_player) select 2;
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _opticType = getNumber(configFile >> "CfgWeapons" >> _opticsName >> "ItemInfo" >> "opticType");
|
2017-11-30 23:13:54 +00:00
|
|
|
|
if (_opticType == 2) exitWith { _abort = false };
|
2015-04-25 10:59:26 +00:00
|
|
|
|
};
|
2015-05-17 09:45:55 +00:00
|
|
|
|
};
|
2015-04-25 10:59:26 +00:00
|
|
|
|
};
|
2017-12-02 13:18:35 +00:00
|
|
|
|
if (_abort) exitWith {};
|
2015-04-12 09:48:21 +00:00
|
|
|
|
|
2015-08-06 08:58:07 +00:00
|
|
|
|
// Get Weapon and Ammo Configurations
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _AmmoCacheEntry = uiNamespace getVariable format[QGVAR(%1), _ammo];
|
2015-08-06 08:58:07 +00:00
|
|
|
|
if (isNil "_AmmoCacheEntry") then {
|
2024-08-17 15:50:38 +00:00
|
|
|
|
_AmmoCacheEntry = _ammo call FUNC(readAmmoDataFromConfig);
|
2015-05-08 15:20:56 +00:00
|
|
|
|
};
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _WeaponCacheEntry = uiNamespace getVariable format[QGVAR(%1), _weapon];
|
2015-08-06 08:58:07 +00:00
|
|
|
|
if (isNil "_WeaponCacheEntry") then {
|
2024-08-17 15:50:38 +00:00
|
|
|
|
_WeaponCacheEntry = _weapon call FUNC(readWeaponDataFromConfig);
|
2015-05-08 15:20:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-11-19 17:48:26 +00:00
|
|
|
|
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable", "_muzzleVelocityVariationSD"];
|
2015-08-05 08:28:02 +00:00
|
|
|
|
_WeaponCacheEntry params ["_barrelTwist", "_twistDirection", "_barrelLength"];
|
|
|
|
|
|
2017-11-19 17:48:26 +00:00
|
|
|
|
private _temperature = nil; // We need the variable in this scope. So we need to init it here.
|
|
|
|
|
|
|
|
|
|
private _ammoCount = _unit ammo _muzzle;
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _bulletVelocity = velocity _projectile;
|
|
|
|
|
private _muzzleVelocity = vectorMagnitude _bulletVelocity;
|
2015-04-05 19:08:55 +00:00
|
|
|
|
|
2015-04-12 14:17:49 +00:00
|
|
|
|
if (GVAR(barrelLengthInfluenceEnabled)) then {
|
2017-11-19 17:48:26 +00:00
|
|
|
|
_muzzleVelocity = _muzzleVelocity + ([_barrelLength, _muzzleVelocityTable, _barrelLengthTable, _muzzleVelocity] call FUNC(calculateBarrelLengthVelocityShift));
|
2015-04-05 19:08:55 +00:00
|
|
|
|
};
|
2015-04-12 14:17:49 +00:00
|
|
|
|
if (GVAR(ammoTemperatureEnabled)) then {
|
2015-08-06 08:58:07 +00:00
|
|
|
|
_temperature = ((getPosASL _unit) select 2) call EFUNC(weather,calculateTemperatureAtHeight);
|
2017-11-19 17:48:26 +00:00
|
|
|
|
_muzzleVelocity = _muzzleVelocity + ([_ammoTempMuzzleVelocityShifts, _temperature] call FUNC(calculateAmmoTemperatureVelocityShift));
|
2015-04-05 19:08:55 +00:00
|
|
|
|
};
|
2017-11-19 17:48:26 +00:00
|
|
|
|
if (GVAR(muzzleVelocityVariationEnabled)) then {
|
|
|
|
|
private _time = round (CBA_missionTime / 2);
|
|
|
|
|
// Generate seed from publicly known values (via Cantor pairing function)
|
|
|
|
|
private _seed = 0.5 * (_time + _ammoCount) * (_time + _ammoCount + 1) + _ammoCount;
|
|
|
|
|
// Generate normally distributed random number (via Box–Muller transform)
|
2017-11-25 16:45:09 +00:00
|
|
|
|
private _z = sqrt(-2.0 * ln(0.00000001 max (-_seed random 1))) * cos(_seed random 360);
|
2020-06-13 20:45:09 +00:00
|
|
|
|
|
2017-11-19 17:48:26 +00:00
|
|
|
|
_muzzleVelocity = _muzzleVelocity * (_z * _muzzleVelocityVariationSD + 1);
|
2015-08-06 08:58:07 +00:00
|
|
|
|
};
|
2015-08-06 11:35:55 +00:00
|
|
|
|
|
2017-11-19 17:48:26 +00:00
|
|
|
|
_bulletVelocity = (vectorNormalized _bulletVelocity) vectorMultiply _muzzleVelocity;
|
|
|
|
|
_projectile setVelocity _bulletVelocity;
|
|
|
|
|
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _bulletTraceVisible = false;
|
2017-11-30 23:13:54 +00:00
|
|
|
|
if (GVAR(bulletTraceEnabled) && {_muzzleVelocity > BULLET_TRACE_MIN_VELOCITY} && {cameraView == "GUNNER"}) then {
|
2016-04-20 15:48:25 +00:00
|
|
|
|
if (currentWeapon ACE_player == binocular ACE_player) then {
|
2015-04-25 11:15:54 +00:00
|
|
|
|
_bulletTraceVisible = true;
|
|
|
|
|
} else {
|
|
|
|
|
if (currentWeapon ACE_player == primaryWeapon ACE_player && count primaryWeaponItems ACE_player > 2) then {
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _opticsName = (primaryWeaponItems ACE_player) select 2;
|
|
|
|
|
private _opticType = getNumber(configFile >> "CfgWeapons" >> _opticsName >> "ItemInfo" >> "opticType");
|
2015-04-25 11:15:54 +00:00
|
|
|
|
_bulletTraceVisible = _opticType == 2;
|
|
|
|
|
};
|
|
|
|
|
};
|
2015-04-05 19:08:55 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _stabilityFactor = 1.5;
|
2017-11-22 22:16:17 +00:00
|
|
|
|
if (_caliber * _bulletLength * _bulletMass * _barrelTwist > 0) then {
|
2015-08-06 08:58:07 +00:00
|
|
|
|
if (isNil "_temperature") then {
|
|
|
|
|
_temperature = ((getPosASL _unit) select 2) call EFUNC(weather,calculateTemperatureAtHeight);
|
|
|
|
|
};
|
2017-10-10 14:39:59 +00:00
|
|
|
|
private _barometricPressure = ((getPosASL _projectile) select 2) call EFUNC(weather,calculateBarometricPressure);
|
2015-04-07 19:27:04 +00:00
|
|
|
|
_stabilityFactor = [_caliber, _bulletLength, _bulletMass, _barrelTwist, _muzzleVelocity, _temperature, _barometricPressure] call FUNC(calculateStabilityFactor);
|
2015-04-05 19:08:55 +00:00
|
|
|
|
};
|
|
|
|
|
|
2024-08-17 15:50:38 +00:00
|
|
|
|
("ace" callExtension [
|
|
|
|
|
"ballistics:bullet:new", [
|
|
|
|
|
_ammoCount,
|
|
|
|
|
_airFriction,
|
|
|
|
|
_ballisticCoefficients,
|
|
|
|
|
_velocityBoundaries,
|
|
|
|
|
_atmosphereModel,
|
|
|
|
|
_dragModel,
|
|
|
|
|
_stabilityFactor,
|
|
|
|
|
_twistDirection,
|
|
|
|
|
_transonicStabilityCoef,
|
|
|
|
|
_bulletVelocity,
|
|
|
|
|
EGVAR(common,mapLatitude),
|
|
|
|
|
EGVAR(weather,currentTemperature),
|
|
|
|
|
EGVAR(common,mapAltitude),
|
|
|
|
|
EGVAR(weather,currentHumidity),
|
|
|
|
|
EGVAR(weather,currentOvercast),
|
|
|
|
|
CBA_missionTime toFixed 6
|
|
|
|
|
]
|
|
|
|
|
]) params ["_id", "_code"];
|
|
|
|
|
if (_code == 0) then {
|
|
|
|
|
GVAR(allBullets) set [_id, [_projectile, _caliber, _bulletTraceVisible]];
|
|
|
|
|
};
|