Skip to content

Commit

Permalink
Merge pull request #5793 from acemod/advanced-ballistics-muzzle-veloc…
Browse files Browse the repository at this point in the history
…ity-variation

Advanced Ballistics - Muzzle velocity variation
  • Loading branch information
ulteq authored Nov 23, 2017
2 parents ed872d5 + d6164cb commit 9154a92
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 23 deletions.
7 changes: 7 additions & 0 deletions addons/advanced_ballistics/ACE_Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ class ACE_Settings {
value = 0;
};
*/
class GVAR(muzzleVelocityVariationEnabled) {
category = CSTRING(DisplayName);
displayName = CSTRING(muzzleVelocityVariationEnabled_DisplayName);
description = CSTRING(muzzleVelocityVariationEnabled_Description);
typeName = "BOOL";
value = 1;
};
class GVAR(ammoTemperatureEnabled) {
category = CSTRING(DisplayName);
displayName = CSTRING(ammoTemperatureEnabled_DisplayName);
Expand Down
6 changes: 6 additions & 0 deletions addons/advanced_ballistics/CfgVehicles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ class CfgVehicles {
defaultValue = 0;
};
*/
class muzzleVelocityVariationEnabled {
displayName = CSTRING(muzzleVelocityVariation_DisplayName);
description = CSTRING(muzzleVelocityVariation_Description);
typeName = "BOOL";
defaultValue = 1;
};
class ammoTemperatureEnabled {
displayName = CSTRING(ammoTemperatureEnabled_DisplayName);
description = CSTRING(ammoTemperatureEnabled_Description);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ for "_i" from 0 to (count _cfgWeapons)-1 do {
if (isNil "_WeaponCacheEntry") then {
_WeaponCacheEntry = _weapon call FUNC(readWeaponDataFromConfig);
};
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable"];
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable", "_muzzleVelocityVariationSD"];
_WeaponCacheEntry params ["_barrelTwist", "_twistDirection", "_barrelLength"];

private _barrelVelocityShift = [_barrelLength, _muzzleVelocityTable, _barrelLengthTable, _vanillaInitialSpeed] call FUNC(calculateBarrelLengthVelocityShift);
Expand Down
36 changes: 17 additions & 19 deletions addons/advanced_ballistics/functions/fnc_handleFired.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -48,36 +48,36 @@ if (isNil "_WeaponCacheEntry") then {
_WeaponCacheEntry = _weapon call FUNC(readWeaponDataFromConfig);
};

_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable"];
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable", "_muzzleVelocityVariationSD"];
_WeaponCacheEntry params ["_barrelTwist", "_twistDirection", "_barrelLength"];

private _temperature = nil; // We need the variable in this scope. So we need to init it here.

private _ammoCount = _unit ammo _muzzle;

private _bulletVelocity = velocity _projectile;
private _muzzleVelocity = vectorMagnitude _bulletVelocity;

private _barrelVelocityShift = 0;
if (GVAR(barrelLengthInfluenceEnabled)) then {
_barrelVelocityShift = [_barrelLength, _muzzleVelocityTable, _barrelLengthTable, _muzzleVelocity] call FUNC(calculateBarrelLengthVelocityShift);
_muzzleVelocity = _muzzleVelocity + ([_barrelLength, _muzzleVelocityTable, _barrelLengthTable, _muzzleVelocity] call FUNC(calculateBarrelLengthVelocityShift));
};

private _ammoTemperatureVelocityShift = 0;
private _temperature = nil; //Need the variable in this scope. So we need to init it here.

if (GVAR(ammoTemperatureEnabled)) then {
_temperature = ((getPosASL _unit) select 2) call EFUNC(weather,calculateTemperatureAtHeight);
_ammoTemperatureVelocityShift = ([_ammoTempMuzzleVelocityShifts, _temperature] call FUNC(calculateAmmoTemperatureVelocityShift));
_muzzleVelocity = _muzzleVelocity + ([_ammoTempMuzzleVelocityShifts, _temperature] call FUNC(calculateAmmoTemperatureVelocityShift));
};

if (GVAR(ammoTemperatureEnabled) || GVAR(barrelLengthInfluenceEnabled)) then {
private _muzzleVelocityShift = _barrelVelocityShift + _ammoTemperatureVelocityShift;
TRACE_4("shift",_muzzleVelocity,_muzzleVelocityShift, _barrelVelocityShift, _ammoTemperatureVelocityShift);
if (_muzzleVelocityShift != 0) then {
_muzzleVelocity = _muzzleVelocity + _muzzleVelocityShift;
_bulletVelocity = _bulletVelocity vectorAdd ((vectorNormalized _bulletVelocity) vectorMultiply (_muzzleVelocityShift));
_projectile setVelocity _bulletVelocity;
};
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)
private _z = sqrt(-2.0 * log(0.00000001 max (-_seed random 1))) * cos(_seed random 360);

_muzzleVelocity = _muzzleVelocity * (_z * _muzzleVelocityVariationSD + 1);
};

_bulletVelocity = (vectorNormalized _bulletVelocity) vectorMultiply _muzzleVelocity;
_projectile setVelocity _bulletVelocity;

if (_abort) exitWith {
if (missionNamespace getVariable [QEGVAR(windDeflection,enabled), false]) then {
EGVAR(windDeflection,trackedBullets) pushBack [_projectile, getNumber(configFile >> "CfgAmmo" >> _ammo >> "airFriction")];
Expand Down Expand Up @@ -108,8 +108,6 @@ if (_caliber * _bulletLength * _bulletMass * _barrelTwist > 0) then {

GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000;

private _ammoCount = _unit ammo _muzzle;

"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17:%18", GVAR(currentbulletID), _ammoCount, _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _transonicStabilityCoef, getPosASL _projectile, _bulletVelocity, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6];

GVAR(allBullets) pushBack [_projectile, _caliber, _bulletTraceVisible, GVAR(currentbulletID)];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ params ["_logic","_units", "_activated"];
if !(_activated) exitWith {};

[_logic, QGVAR(enabled), "enabled"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(muzzleVelocityVariationEnabled), "muzzleVelocityVariationEnabled"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(ammoTemperatureEnabled), "ammoTemperatureEnabled"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(barrelLengthInfluenceEnabled), "barrelLengthInfluenceEnabled"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(bulletTraceEnabled), "bulletTraceEnabled"] call EFUNC(common,readSettingFromModule);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ private _atmosphereModel = getText(_ammoConfig >> "ACE_standardAtmosphere");
if (_atmosphereModel isEqualTo "") then {
_atmosphereModel = "ICAO";
};
private _muzzleVelocityVariationSD = DEFAULT_MUZZLE_VELOCITY_VARIATION_SD;
if (isNumber (_ammoConfig >> "ACE_muzzleVelocityVariationSD")) then {
_muzzleVelocityVariationSD = getNumber(_ammoConfig >> "ACE_muzzleVelocityVariationSD") / 100;
};
private _ammoTempMuzzleVelocityShifts = getArray(_ammoConfig >> "ACE_ammoTempMuzzleVelocityShifts");
private _muzzleVelocityTable = getArray(_ammoConfig >> "ACE_muzzleVelocities");
private _barrelLengthTable = getArray(_ammoConfig >> "ACE_barrelLengths");
Expand Down Expand Up @@ -89,7 +93,7 @@ if ((_typicalSpeed > 0) && {_typicalSpeed < 360}) then {
};
};

private _result = [_airFriction, _caliber, _bulletLength, _bulletMass, _transonicStabilityCoef, _dragModel, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _ammoTempMuzzleVelocityShifts, _muzzleVelocityTable, _barrelLengthTable];
private _result = [_airFriction, _caliber, _bulletLength, _bulletMass, _transonicStabilityCoef, _dragModel, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _ammoTempMuzzleVelocityShifts, _muzzleVelocityTable, _barrelLengthTable, _muzzleVelocityVariationSD];

uiNamespace setVariable [format[QGVAR(%1), _this], _result];

Expand Down
3 changes: 3 additions & 0 deletions addons/advanced_ballistics/script_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@
#define STD_AIR_DENSITY_ICAO 1.22498
#define STD_AIR_DENSITY_ASM 1.20885

// Standard deviation of the default muzzle velocity variation (0.3%)
#define DEFAULT_MUZZLE_VELOCITY_VARIATION_SD 0.003

#define EXTENSION_REQUIRED_VERSION "1.0"
8 changes: 8 additions & 0 deletions addons/advanced_ballistics/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,14 @@
<Chinese>在全自動模式開火時,關閉先進彈道系統</Chinese>
<Chinesesimp>在全自动模式开火时,关闭先进弹道系统</Chinesesimp>
</Key>
<Key ID="STR_ACE_Advanced_Ballistics_muzzleVelocityVariationEnabled_DisplayName">
<English>Enable Muzzle Velocity Variation</English>
<German>Variation der Mündungsgeschwindigkeit aktivieren</German>
</Key>
<Key ID="STR_ACE_Advanced_Ballistics_muzzleVelocityVariationEnabled_Description">
<English>Simulates slight variations in muzzle velocity between each shot</English>
<German>Simuliert leichte Variationen der Mündungsgeschwindigkeit zwischen jedem Schuss.</German>
</Key>
<Key ID="STR_ACE_Advanced_Ballistics_ammoTemperatureEnabled_DisplayName">
<English>Enable Ammo Temperature Simulation</English>
<Polish>Symulacja temp. amunicji</Polish>
Expand Down
18 changes: 18 additions & 0 deletions addons/ballistics/CfgAmmo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class CfgAmmo {
ACE_caliber=5.69;
ACE_bulletLength=23.012;
ACE_bulletMass=4.9896;
ACE_muzzleVelocityVariationSD=0.4;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.361};
ACE_velocityBoundaries[]={};
Expand Down Expand Up @@ -123,6 +124,7 @@ class CfgAmmo {
ACE_caliber=6.706;
ACE_bulletLength=34.646;
ACE_bulletMass=9.0072;
ACE_muzzleVelocityVariationSD=0.35;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.290};
ACE_velocityBoundaries[]={};
Expand All @@ -137,6 +139,7 @@ class CfgAmmo {
ACE_caliber=6.706;
ACE_bulletLength=36.22;
ACE_bulletMass=9.072;
ACE_muzzleVelocityVariationSD=0.3;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.317};
ACE_velocityBoundaries[]={};
Expand Down Expand Up @@ -177,6 +180,7 @@ class CfgAmmo {
ACE_caliber=7.823;
ACE_bulletLength=31.496;
ACE_bulletMass=11.34;
ACE_muzzleVelocityVariationSD=0.4;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.243};
ACE_velocityBoundaries[]={};
Expand All @@ -193,6 +197,7 @@ class CfgAmmo {
ACE_caliber=7.823;
ACE_bulletLength=31.496;
ACE_bulletMass=11.34;
ACE_muzzleVelocityVariationSD=0.45;
ACE_ammoTempMuzzleVelocityShifts[]={-5.3, -5.1, -4.6, -4.2, -3.4, -2.6, -1.4, -0.3, 1.4, 3.0, 5.2};
ACE_ballisticCoefficients[]={0.243};
ACE_velocityBoundaries[]={};
Expand All @@ -209,6 +214,7 @@ class CfgAmmo {
ACE_caliber=7.823;
ACE_bulletLength=31.496;
ACE_bulletMass=8.424;
ACE_muzzleVelocityVariationSD=0.45;
ACE_ammoTempMuzzleVelocityShifts[]={-2.655, -2.547, -2.285, -2.012, -1.698, -1.280, -0.764, -0.153, 0.596, 1.517, 2.619};
ACE_ballisticCoefficients[]={0.377};
ACE_velocityBoundaries[]={};
Expand Down Expand Up @@ -257,6 +263,7 @@ class CfgAmmo {
ACE_caliber=7.823;
ACE_bulletLength=34.366;
ACE_bulletMass=12.312;
ACE_muzzleVelocityVariationSD=0.45;
ACE_ammoTempMuzzleVelocityShifts[]={-5.3, -5.1, -4.6, -4.2, -3.4, -2.6, -1.4, -0.3, 1.4, 3.0, 5.2};
ACE_ballisticCoefficients[]={0.268};
ACE_velocityBoundaries[]={};
Expand All @@ -273,6 +280,7 @@ class CfgAmmo {
ACE_caliber=7.823;
ACE_bulletLength=37.821;
ACE_bulletMass=14.256;
ACE_muzzleVelocityVariationSD=0.45;
ACE_ammoTempMuzzleVelocityShifts[]={-5.3, -5.1, -4.6, -4.2, -3.4, -2.6, -1.4, -0.3, 1.4, 3.0, 5.2};
ACE_ballisticCoefficients[]={0.310};
ACE_velocityBoundaries[]={};
Expand All @@ -289,6 +297,7 @@ class CfgAmmo {
ACE_caliber=7.823;
ACE_bulletLength=40.691;
ACE_bulletMass=14.904;
ACE_muzzleVelocityVariationSD=0.35;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.368};
ACE_velocityBoundaries[]={};
Expand Down Expand Up @@ -376,6 +385,7 @@ class CfgAmmo {
ACE_caliber=9.296;
ACE_bulletLength=34.29;
ACE_bulletMass=14.904;
ACE_muzzleVelocityVariationSD=0.4;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.368};
ACE_velocityBoundaries[]={};
Expand All @@ -392,6 +402,7 @@ class CfgAmmo {
ACE_bulletLength=55.1942;
ACE_bulletMass=27.1507; // 419 gr
ACE_transonicStabilityCoef=1;
ACE_muzzleVelocityVariationSD=0.2;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.434};
ACE_velocityBoundaries[]={};
Expand All @@ -409,6 +420,7 @@ class CfgAmmo {
ACE_bulletLength=41.4528;
ACE_bulletMass=19.7637; // 305 gr
ACE_transonicStabilityCoef=1;
ACE_muzzleVelocityVariationSD=0.2;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.279};
ACE_velocityBoundaries[]={};
Expand All @@ -423,6 +435,7 @@ class CfgAmmo {
ACE_caliber=8.585;
ACE_bulletLength=39.573;
ACE_bulletMass=16.2;
ACE_muzzleVelocityVariationSD=0.3;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.322};
ACE_velocityBoundaries[]={};
Expand Down Expand Up @@ -451,6 +464,7 @@ class CfgAmmo {
ACE_caliber=8.585;
ACE_bulletLength=43.18;
ACE_bulletMass=19.44;
ACE_muzzleVelocityVariationSD=0.3;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.368};
ACE_velocityBoundaries[]={};
Expand All @@ -467,6 +481,7 @@ class CfgAmmo {
ACE_caliber=8.585;
ACE_bulletLength=38.989;
ACE_bulletMass=16.3941242;
ACE_muzzleVelocityVariationSD=0.4;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.290};
ACE_velocityBoundaries[]={};
Expand Down Expand Up @@ -499,6 +514,7 @@ class CfgAmmo {
ACE_caliber=12.954;
ACE_bulletLength=58.674;
ACE_bulletMass=41.9256;
ACE_muzzleVelocityVariationSD=0.35;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.670};
ACE_velocityBoundaries[]={};
Expand All @@ -516,6 +532,7 @@ class CfgAmmo {
ACE_caliber=12.954;
ACE_bulletLength=58.674;
ACE_bulletMass=41.9904;
ACE_muzzleVelocityVariationSD=0.4;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={0.670};
ACE_velocityBoundaries[]={};
Expand All @@ -531,6 +548,7 @@ class CfgAmmo {
ACE_caliber=12.954;
ACE_bulletLength=64.516;
ACE_bulletMass=48.6;
ACE_muzzleVelocityVariationSD=0.2;
ACE_ammoTempMuzzleVelocityShifts[]={-26.55, -25.47, -22.85, -20.12, -16.98, -12.80, -7.64, -1.53, 5.96, 15.17, 26.19};
ACE_ballisticCoefficients[]={1.050};
ACE_velocityBoundaries[]={};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private _trueZero = if (!_advancedBallistics) then {
_WeaponCacheEntry = _weapon call EFUNC(advanced_ballistics,readWeaponDataFromConfig);
};

_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable"];
_AmmoCacheEntry params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "_transonicStabilityCoef", "_dragModel", "_ballisticCoefficients", "_velocityBoundaries", "_atmosphereModel", "_ammoTempMuzzleVelocityShifts", "_muzzleVelocityTable", "_barrelLengthTable", "_muzzleVelocityVariationSD"];
_WeaponCacheEntry params ["_barrelTwist", "_twistDirection", "_barrelLength"];

if (missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]) then {
Expand Down
6 changes: 5 additions & 1 deletion docs/wiki/framework/advanced-ballistics-framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,15 @@ class CfgAmmo {
ACE_bulletLength = 23.012; // Bullet Length in mm
ACE_bulletMass = 4.0176; // Mass in grams (example is roughly 62 grains)
// Standard deviation of the muzzle velocity variation in percent
// Example: With a muzzle velocity of 850 m/s and a standard deviation of 0.35%, 68% of the shots will be between 847 m/s and 853 m/s
ACE_muzzleVelocityVariationSD = 0.35;
// Array of muzzle velocity shifts in m/s with 11 data points from -15 °C to 35 °C
// Example: At 0°C the shift will be -21.0
ACE_ammoTempMuzzleVelocityShifts[] = {-27.20, -26.44, -23.76, -21.00, -17.54, -13.10, -7.95, -1.62, 6.24, 15.48, 27.75};
//Array of ballistic coefficients (contains one element more than the velocity boundary array)
// Array of ballistic coefficients (contains one element more than the velocity boundary array)
ACE_ballisticCoefficients[] = {0.151};
ACE_velocityBoundaries[] = {}; // Array of velocity boundaries
Expand Down
Loading

0 comments on commit 9154a92

Please sign in to comment.