Initial draft of the range card implementation.

This commit is contained in:
ulteq 2015-05-28 19:17:29 +02:00
parent b2330ae641
commit 697710d40d
23 changed files with 884 additions and 0 deletions

View File

@ -0,0 +1 @@
z\ace\addons\rangecard

View File

@ -0,0 +1,11 @@
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE( call COMPILE_FILE(XEH_preInit) );
};
};
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE( call COMPILE_FILE(XEH_postInit) );
};
};

View File

@ -0,0 +1,60 @@
class CfgVehicles {
class Man;
class CAManBase: Man {
class ACE_Actions {
class ACE_Weapon {
class GVAR(copyRangeCard) {
displayName = "$STR_ACE_RangeCard_CopyRangeCard";
distance = 2.0;
condition = QUOTE(_target call FUNC(canCopy));
statement = QUOTE(_target call FUNC(updateClassNames));
icon = QUOTE(PATHTOF(UI\RangeCard_Icon.paa));
};
};
};
class ACE_SelfActions {
class ACE_Equipment {
class GVAR(open) {
displayName = "$STR_ACE_RangeCard_OpenRangeCard";
condition = QUOTE(call FUNC(canShow) && !GVAR(RangeCardOpened));
statement = QUOTE(false call FUNC(openRangeCard));
showDisabled = 0;
priority = 0.1;
icon = QUOTE(PATHTOF(UI\RangeCard_Icon.paa));
exceptions[] = {"notOnMap"};
};
class GVAR(openCopy) {
displayName = "$STR_ACE_RangeCard_OpenRangeCardCopy";
condition = QUOTE(call FUNC(canShowCopy) && !GVAR(RangeCardOpened));
statement = QUOTE(true call FUNC(openRangeCard));
showDisabled = 0;
priority = 0.1;
icon = QUOTE(PATHTOF(UI\RangeCard_Icon.paa));
exceptions[] = {"notOnMap"};
};
};
};
};
class Item_Base_F;
class ACE_Item_RangeCard: Item_Base_F {
author = "Ruthberg";
scope = 2;
scopeCurator = 2;
displayName = "Range Card";
vehicleClass = "Items";
class TransportItems {
class ACE_RangeCard {
name = "ACE_RangeCard";
count = 1;
};
};
};
class Box_NATO_Support_F;
class ACE_Box_Misc: Box_NATO_Support_F {
class TransportItems {
MACRO_ADDITEM(ACE_RangeCard,6);
};
};
};

View File

@ -0,0 +1,19 @@
class CfgWeapons {
class ACE_ItemCore;
class InventoryItem_Base_F;
class ACE_RangeCard: ACE_ItemCore {
author[] = {"Ruthberg"};
scope = 2;
displayName = "$STR_ACE_RangeCard_Name";
descriptionShort = "$STR_ACE_RangeCard_Description";
picture = PATHTOF(UI\RangeCard_Icon.paa);
icon = "iconObject_circle";
mapSize = 0.034;
class ItemInfo: InventoryItem_Base_F {
mass = 1;
};
};
};

View File

@ -0,0 +1,10 @@
ace_rangecards
===============
Adds range cards
## Maintainers
The people responsible for merging changes to this component or answering potential questions.
- [Ruthberg] (http://github.com/Ulteq)

View File

@ -0,0 +1,198 @@
#define ST_LEFT 0
#define ST_RIGHT 1
#define ST_CENTER 2
class RscListNBox;
class ScrollBar;
class RangeCard_RscText {
idc=-1;
type=0;
style=ST_CENTER;
colorDisabled[]={0,0,0,0.0};
colorBackground[]={0,0,0,0};
colorText[]={0,0,0,1};
text="";
x=0;
y=0;
h=0.028;
w=0.06;
font="TahomaB";
SizeEx=0.025;
shadow=0;
};
class RangeCard_RscListNBox: RscListNBox {
idc=-1;
type=102;
style=0;
font="TahomaB";
sizeEx=0.026;
rowHeight=0.027;
colorDisabled[]={0,0,0,0.0};
colorBackground[]={1,1,1,1};
colorText[]={0,0,0,1};
colorScrollbar[]={0.95,0.95,0.95,1};
colorSelect[]={0,0,0,1};
colorSelect2[]={0,0,0,1};
colorSelectBackground[]={1,1,1,0};
colorSelectBackground2[]={1,1,1,0};
period=0;
LineSpacing=0;
maxHistoryDelay=1.0;
autoScrollSpeed=-1;
autoScrollDelay=5;
autoScrollRewind=0;
soundSelect[]={"",0.09,1};
drawSideArrows=0;
idcLeft=-1;
idcRight=-1;
class ScrollBar {
color[]={1,1,1,0.6};
colorActive[]={1,1,1,1};
colorDisabled[]={1,1,1,0.3};
};
class ListScrollBar : ScrollBar {
};
};
class ACE_RangeCard_Dialog {
idd = -1;
movingEnable = 1;
onLoad = "uiNamespace setVariable ['RangleCard_Display', (_this select 0)]";
onUnload = QUOTE(_this call FUNC(onCloseDialog));
objects[] = {};
class controls {
class BACKGROUND {
moving=1;
type=0;
font="TahomaB";
SizeEX=0.025;
idc=-1;
style=48;
x="safezoneX";
y="safezoneY+0.181889";
w="1.62727*3/4";
h="1.62727";
colorBackground[]={1,1,1,1};
colorText[]={1,1,1,1};
text=QUOTE(PATHTOF(UI\RangeCard.paa));
};
class CAPTION_TEXT_1: RangeCard_RscText {
idc=770000;
style=ST_LEFT;
x="safezoneX+0.18";
y="safezoneY+0.181889+0.0";
w="0.56*1.62727*3/4";
text=".408 CheyTac - 410 gr Predator Projectiles";
};
class CAPTION_TEXT_2: CAPTION_TEXT_1 {
idc=770001;
SizeEx=0.022;
y="safezoneY+0.181889+0.03";
text="Drop Tables for B.P.: 1013.25mb; Corrected for MVV at Air/Ammo Temperatures -15-35 °C";
};
class CAPTION_TEXT_3: CAPTION_TEXT_2 {
idc=770002;
y="safezoneY+0.181889+0.06";
text="CheyTac Intervention - 29'' 1:13'' twist (M-200)";
};
class ZERO_RANGE_TEXT: RangeCard_RscText {
idc=77003;
style=ST_LEFT;
SizeEx=0.028;
x="safezoneX+0.885";
y="safezoneY+0.181889+0.01";
w="0.125*1.62727*3/4";
text="100m ZERO";
};
class BAROMETRIC_PRESSURE_TEXT: ZERO_RANGE_TEXT {
idc=77004;
colorText[]={1,0,0,0.8};
y="safezoneY+0.181889+0.05";
text="B.P.: 1013.25mb";
};
class TARGET_RANGE_TEXT_1: RangeCard_RscText {
idc=770010;
colorText[]={1,1,1,1};
x="safezoneX+0.185";
y="safezoneY+0.181889+0.098";
text="Target";
};
class TARGET_RANGE_TEXT_2: TARGET_RANGE_TEXT_1 {
idc=770011;
SizeEx=0.03;
y="safezoneY+0.181889+0.125";
text="Range";
};
class TARGET_RANGE_TEXT_3: TARGET_RANGE_TEXT_1 {
idc=770012;
y="safezoneY+0.181889+0.152";
text="(m)";
};
class BULLET_DROP_TEXT_1: RangeCard_RscText {
idc=770013;
x="safezoneX+0.25";
y="safezoneY+0.181889+0.095";
w="0.405*1.62727*3/4";
text="Bullet Drop (MRADs)";
};
class WIND_LEAD_CAPTION_LIST: RangeCard_RscListNBox {
idc=770100;
sizeEx=0.021;
x="safezoneX+0.728";
y="safezoneY+0.181889+0.091";
w="0.25*1.62727*3/4";
h="0.0909445";
columns[]={(0.03/2), (0.985/2)};
idcLeft=770101;
idcRight=770102;
};
class TEMPERATURE_CAPTION_LIST_1: RangeCard_RscListNBox {
idc=770200;
x="safezoneX+0.24";
y="safezoneY+0.181889+0.125";
w="0.405*1.62727*3/4";
h="0.0909445";
columns[]={(0/9), (1/9), (2/9), (3/9), (4/9), (5/9), (5.9/9), (6.9/9), (7.8/9)};
idcLeft=770201;
idcRight=770202;
};
class TEMPERATURE_CAPTION_LIST_2: RangeCard_RscListNBox {
idc=770300;
x="safezoneX+0.728";
y="safezoneY+0.181889+0.15";
w="0.25*1.62727*3/4";
h="0.0909445";
columns[]={(0/6), (0.9/6), (1.8/6), (2.9/6), (3.8/6), (4.8/6)};
idcLeft=770301;
idcRight=770302;
};
class RANGE_CARD_DATA: RangeCard_RscListNBox {
idc=770400;
x="safezoneX+0.182";
y="safezoneY+0.181889+0.194";
w="0.72*1.62727*3/4";
h="1.62727";
columns[]={(0/16), (1.2/16), (2.2/16), (3.2/16), (4.2/16), (5.1/16), (6.1/16), (7.1/16), (8.1/16),
(9/16), (10.2/16), (11/16), (11.9/16), (12.8/16), (13.7/16), (14.6/16)};
idcLeft=770401;
idcRight=770402;
};
class FOOTNOTE_TEXT_1: CAPTION_TEXT_1 {
idc=770020;
SizeEx=0.022;
y="safezoneY+1.72431";
w="0.705*1.62727*3/4";
text="For best results keep ammunition at ambient air temperature. Tables calculated for the above listed barrel";
};
class FOOTNOTE_TEXT_2: FOOTNOTE_TEXT_1 {
idc=770021;
y="safezoneY+1.72431+0.024";
text="and load with optic mounted 1.5'' above line of bore.";
};
};
};

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,11 @@
#include "script_component.hpp"
#include "initKeybinds.sqf"
GVAR(RangeCardOpened) = false;
GVAR(ammoClass) = "B_65x39_Caseless";
GVAR(weaponClass) = "arifle_MXM_F";
GVAR(ammoClassCopy) = "";//"ACE_762x51_Ball_M118LR";
GVAR(weaponClassCopy) = "";//srifle_DMR_06_olive_F";

View File

@ -0,0 +1,14 @@
#include "script_component.hpp"
ADDON = false;
PREP(calculateSolution);
PREP(canCopy);
PREP(canShow);
PREP(canShowCopy);
PREP(onCloseDialog);
PREP(openRangeCard);
PREP(updateClassNames);
PREP(updateRangeCard);
ADDON = true;

View File

@ -0,0 +1,17 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
units[] = {"ACE_Item_RangeCard"};
weapons[] = {"ACE_RangeCard"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ACE_Advanced_Ballistics"};
author = "Ruthberg";
VERSION_CONFIG;
};
};
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"
#include "CfgWeapons.hpp"
#include "RscTitles.hpp"

View File

@ -0,0 +1,218 @@
/*
* Author: Ruthberg
* Calculates the range card data
*
* Arguments:
* 0: Scope base angle <NUMBER>
* 1: Bullet mass <NUMBER>
* 2: Bore height <NUMBER>
* 3: air friction <NUMBER>
* 4: muzzle velocity <NUMBER>
* 5: temperature <NUMBER>
* 6: barometric pressure <NUMBER>
* 7: relative humidity <NUMBER>
* 8: simulation steps <NUMBER>
* 9: wind speed <ARRAY>
* 10: wind direction <NUMBER>
* 11: inclination angle <NUMBER>
* 12: target speed <NUMBER>
* 13: target range <NUMBER>
* 14: ballistic coefficient <NUMBER>
* 15: drag model <NUMBER>
* 16: atmosphere model <STRING>
* 17: Store range card data? <BOOL>
* 18: Stability factor <NUMBER>
* 19: Twist Direction <NUMBER>
* 20: Latitude <NUMBER>
* 21: Range Card Slot <NUMBER>
*
* Return Value:
* 0: Elevation (MOA) <NUMBER>
* 1: Windage (MOA) <ARRAY>
* 2: Lead (MOA) <NUMBER>
* 3: Time of fligth (SECONDS) <NUMBER>
* 4: Remaining velocity (m/s) <NUMBER>
* 5: Remaining kinetic energy (ft·lb) <NUMBER>
* 6: Vertical coriolis drift (MOA) <NUMBER>
* 7: Horizontal coriolis drift (MOA) <NUMBER>
* 8: Spin drift (MOA) <NUMBER>
*
* Example:
* call ace_rangecard_calculate_range_card_data
*
* Public: No
*/
#include "script_component.hpp"
private ["_scopeBaseAngle", "_bulletMass", "_boreHeight", "_airFriction", "_muzzleVelocity", "_temperature", "_barometricPressure", "_relativeHumidity", "_simSteps", "_windSpeed1", "_windSpeed2", "_windDirection", "_inclinationAngle", "_targetSpeed", "_targetRange", "_drag", "_bc", "_dragModel", "_atmosphereModel", "_storeRangeCardData", "_stabilityFactor", "_twistDirection", "_latitude", "_directionOfFire", "_rangeCardSlot"];
_scopeBaseAngle = _this select 0;
_bulletMass = _this select 1;
_boreHeight = _this select 2;
_airFriction = _this select 3;
_muzzleVelocity = _this select 4;
_temperature = _this select 5;
_barometricPressure = _this select 6;
_relativeHumidity = _this select 7;
_simSteps = _this select 8;
_windSpeed1 = (_this select 9) select 0;
_windSpeed2 = (_this select 9) select 1;
_windDirection = _this select 10;
_inclinationAngle = _this select 11;
_targetSpeed = _this select 12;
_targetRange = _this select 13;
_bc = _this select 14;
_dragModel = _this select 15;
_atmosphereModel = _this select 16;
_storeRangeCardData = _this select 17;
_stabilityFactor = _this select 18;
_twistDirection = _this select 19;
_latitude = _this select 20;
_directionOfFire = _this select 21;
_rangeCardSlot = _this select 22;
if (_storeRangeCardData) then {
GVAR(rangeCardDataMVs) pushBack format[" %1", round(_muzzleVelocity)];
};
private ["_bulletPos", "_bulletVelocity", "_bulletAccel", "_bulletSpeed", "_gravity", "_deltaT"];
_bulletPos = [0, 0, 0];
_bulletVelocity = [0, 0, 0];
_bulletAccel = [0, 0, 0];
_bulletSpeed = 0;
_gravity = [0, sin(_scopeBaseAngle + _inclinationAngle) * -9.80665, cos(_scopeBaseAngle + _inclinationAngle) * -9.80665];
_deltaT = 1 / _simSteps;
private ["_elevation", "_windage1", "_windage2", "_lead", "_TOF", "_trueVelocity", "_trueSpeed", "_kineticEnergy", "_verticalCoriolis", "_verticalDeflection", "_horizontalCoriolis", "_horizontalDeflection", "_spinDrift", "_spinDeflection"];
_elevation = 0;
_windage1 = 0;
_windage2 = 0;
_lead = 0;
_TOF = 0;
_trueVelocity = [0, 0, 0];
_trueSpeed = 0;
_verticalCoriolis = 0;
_verticalDeflection = 0;
_horizontalCoriolis = 0;
_horizontalDeflection = 0;
_spinDrift = 0;
_spinDeflection = 0;
private ["_n", "_range", "_rangeFactor"];
_n = 0;
_range = 0;
_rangeFactor = 1;
if (_storeRangeCardData) then {
if (GVAR(currentUnit) == 1) then {
_rangeFactor = 1.0936133;
};
};
private ["_wind1", "_wind2", "_windDrift"];
_wind1 = [cos(270 - _windDirection * 30) * _windSpeed1, sin(270 - _windDirection * 30) * _windSpeed1, 0];
_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);
};
private ["_speedTotal", "_stepsTotal", "_speedAverage"];
_speedTotal = 0;
_stepsTotal = 0;
_speedAverage = 0;
private ["_eoetvoesMultiplier"];
_eoetvoesMultiplier = 0;
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
_eoetvoesMultiplier = 2 * (0.0000729 * _muzzleVelocity / -9.80665) * cos(_latitude) * sin(_directionOfFire);
};
_TOF = 0;
_bulletPos set [0, 0];
_bulletPos set [1, 0];
_bulletPos set [2, -(_boreHeight / 100)];
_bulletVelocity set [0, 0];
_bulletVelocity set [1, Cos(_scopeBaseAngle) * _muzzleVelocity];
_bulletVelocity set [2, Sin(_scopeBaseAngle) * _muzzleVelocity];
while {_TOF < 6 && (_bulletPos select 1) < _targetRange} do {
_bulletSpeed = vectorMagnitude _bulletVelocity;
_speedTotal = _speedTotal + _bulletSpeed;
_stepsTotal = _stepsTotal + 1;
_speedAverage = (_speedTotal / _stepsTotal);
if (_speedAverage > 400 && _bulletSpeed < 340) exitWith {};
if (atan((_bulletPos select 2) / (abs(_bulletPos select 1) + 1)) < -2.25) exitWith {};
_trueVelocity = _bulletVelocity vectorDiff _wind1;
_trueSpeed = vectorMagnitude _trueVelocity;
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
_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))
};
_bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag);
} else {
_bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction);
};
_bulletAccel = _bulletAccel vectorAdd _gravity;
_bulletVelocity = _bulletVelocity vectorAdd (_bulletAccel vectorMultiply _deltaT);
_bulletPos = _bulletPos vectorAdd (_bulletVelocity vectorMultiply _deltaT);
_TOF = _TOF + _deltaT;
if (_storeRangeCardData) then {
_range = GVAR(rangeCardStartRange) + _n * GVAR(rangeCardIncrement);
if ((_bulletPos select 1) * _rangeFactor >= _range && _range <= GVAR(rangeCardEndRange)) then {
if ((_bulletPos select 1) > 0) then {
_elevation = - atan((_bulletPos select 2) / (_bulletPos select 1));
_windage1 = - atan((_bulletPos select 0) / (_bulletPos select 1));
};
if (_range != 0) then {
_lead = (_targetSpeed * _TOF) / (Tan(3.38 / 60) * _range);
};
private ["_elevationString", "_windageString", "_leadString"];
_elevationString = Str(round(-_elevation * 60 / 3.38 * 10) / 10);
if (_elevationString == "0") then {
_elevationString = "-0.0";
};
if (_elevationString find "." == -1) then {
_elevationString = _elevationString + ".0";
};
_windageString = Str(round(_windage1 * 60 / 3.38 * 10) / 10);
if (_windageString find "." == -1) then {
_windageString = _windageString + ".0";
};
_leadString = Str(round(_lead * 10) / 10);
if (_leadString find "." == -1) then {
_leadString = _leadString + ".0";
};
(GVAR(rangeCardDataElevation) select _rangeCardSlot) set [_n, _elevationString];
(GVAR(rangeCardDataWindage) select _rangeCardSlot) set [_n, _windageString];
(GVAR(rangeCardDataLead) select _rangeCardSlot) set [_n, _leadString];
_n = _n + 1;
};
};
};
if ((_bulletPos select 1) > 0) then {
_elevation = - atan((_bulletPos select 2) / (_bulletPos select 1));
_windage1 = - atan((_bulletPos select 0) / (_bulletPos select 1));
_windDrift = (_wind2 select 0) * (_TOF - _targetRange / _muzzleVelocity);
_windage2 = - atan(_windDrift / (_bulletPos select 1));
};
if (_targetRange != 0) then {
_lead = (_targetSpeed * _TOF) / (Tan(3.38 / 60) * _targetRange);
};
_kineticEnergy = 0.5 * (_bulletMass / 1000 * (_bulletSpeed ^ 2));
_kineticEnergy = _kineticEnergy * 0.737562149;
[_elevation * 60, [_windage1 * 60, _windage2 * 60], _lead, _TOF, _bulletSpeed, _kineticEnergy, _verticalCoriolis * 60, _horizontalCoriolis * 60, _spinDrift * 60]

View File

@ -0,0 +1,18 @@
/*
* Authors: Ruthberg
* Checks if the target has a copyable range card
*
* Arguments:
* unit <OBJECT>
*
* Return Value:
* canShow (bool)
*
* Example:
* [] call ace_rangecard_fnc_canCopy
*
* Public: No
*/
#include "script_component.hpp"
((primaryWeapon _this) != "" && [_this] call EFUNC(common,isPlayer) && [_this, "ACE_RangeCard"] call EFUNC(common,hasItem))

View File

@ -0,0 +1,18 @@
/*
* Authors: Ruthberg
* Tests if the Range Card can be shown
*
* Arguments:
* Nothing
*
* Return Value:
* canShow (bool)
*
* Example:
* [] call ace_rangecard_fnc_canShow
*
* Public: No
*/
#include "script_component.hpp"
(GVAR(ammoClass) != "" && GVAR(weaponClass) != "" && !GVAR(RangeCardOpened) && !(underwater ACE_player) && ("ACE_RangeCard" in (uniformItems ACE_player)) || ("ACE_RangeCard" in (vestItems ACE_player)))

View File

@ -0,0 +1,18 @@
/*
* Authors: Ruthberg
* Tests if the Range Card copy can be shown
*
* Arguments:
* Nothing
*
* Return Value:
* canShow (bool)
*
* Example:
* [] call ace_rangecard_fnc_canShowCopy
*
* Public: No
*/
#include "script_component.hpp"
(GVAR(ammoClassCopy) != "" && GVAR(weaponClassCopy) != "" && !GVAR(RangeCardOpened) && !(underwater ACE_player) && ("ACE_RangeCard" in (uniformItems ACE_player)) || ("ACE_RangeCard" in (vestItems ACE_player)))

View File

@ -0,0 +1,4 @@
#include "script_component.hpp"
uiNamespace setVariable ['RangleCard_Display', nil];
GVAR(RangeCardOpened) = false;

View File

@ -0,0 +1,36 @@
/*
* Authors: Ruthberg
* Opens the range card dialog
*
* Arguments:
* Open copy? <BOOLEAN>
*
* Return Value:
* Nothing
*
* Example:
* call ace_rangecard_fnc_openRangeCard
*
* Public: No
*/
#include "script_component.hpp"
if (GVAR(RangeCardOpened)) exitWith {};
if (_this) then {
if (GVAR(ammoClassCopy) != "" && GVAR(weaponClassCopy) != "") then {
GVAR(RangeCardOpened) = true;
createDialog "ACE_RangeCard_Dialog";
[GVAR(ammoClassCopy), GVAR(weaponClassCopy)] call FUNC(updateRangeCard);
};
} else {
if (ACE_player call FUNC(updateClassNames)) then {
GVAR(RangeCardOpened) = true;
createDialog "ACE_RangeCard_Dialog";
[GVAR(ammoClass), GVAR(weaponClass)] call FUNC(updateRangeCard);
};
};

View File

@ -0,0 +1,43 @@
/*
* Authors: Ruthberg
* Updates the ammo and weapon class names
*
* Arguments:
* unit <OBJECT>
*
* Return Value:
* Update successful? <BOOLEAN>
*
* Example:
* unit call ace_rangecard_fnc_updateClassNames
*
* Public: No
*/
#include "script_component.hpp"
private ["_unit", "_ammoClass", "_weaponClass", "_ammo", "_ammoConfig", "_parentClasses"];
_unit = _this;
_ammoClass = "";
_weaponClass = primaryWeapon _unit;
if (_weaponClass == "") exitWith { (GVAR(ammoClass) != "" && GVAR(weaponClass) != "") };
{
_ammo = getText (configFile >> "CfgMagazines" >> _x >> "ammo");
_ammoConfig = (configFile >> "CfgAmmo" >> _ammo);
_parentClasses = [_ammoConfig, true] call BIS_fnc_returnParents;
if ("BulletBase" in _parentClasses) exitWith { _ammoClass = _ammo; };
} forEach (primaryWeaponMagazine _unit);
if (_ammoClass == "") exitWith { (GVAR(ammoClass) != "" && GVAR(weaponClass) != "") };
if (_unit == ACE_player) then {
GVAR(ammoClass) = _ammoClass;
GVAR(weaponClass) = _weaponClass;
} else {
GVAR(ammoClassCopy) = _ammoClass;
GVAR(weaponClassCopy) = _weaponClass;
};
true

View File

@ -0,0 +1,118 @@
/*
* Authors: Ruthberg
* Updates the range card data
*
* Arguments:
* 0: ammo class <STRING>
* 1: weapon class <STRING>
*
* Return Value:
* Nothing
*
* Example:
* [mode] call ace_rangecard_fnc_openRangeCard
*
* Public: No
*/
#include "script_component.hpp"
PARAMS_2(_ammoClass,_weaponClass);
if (_ammoClass == "" || _weaponClass == "") exitWith {};
lnbClear 770100;
lnbClear 770200;
lnbClear 770300;
lnbClear 770400;
lnbAddRow [770100, ["4mps Wind(MRADs)", "1mps LEAD(MRADs)"]];
lnbAddRow [770100, ["Air/Ammo Temp", "Air/Ammo Temp"]];
lnbAddRow [770200, ["-15°C", " -5°C", " 5°C", " 10°C", " 15°C", " 20°C", " 25°C", " 30°C", " 35°C"]];
lnbAddRow [770300, ["-15°C", " 10°C", " 35°C", "-15°C", " 10°C", " 35°C"]];
GVAR(rangeCardDataElevation) = [[], [], [], [], [], [], [], [], []];
GVAR(rangeCardDataWindage) = [[], [], [], [], [], [], [], [], []];
GVAR(rangeCardDataLead) = [[], [], [], [], [], [], [], [], []];
GVAR(rangeCardDataMVs) = [];
GVAR(lastValidRow) = [];
GVAR(currentUnit) = 2;
GVAR(rangeCardStartRange) = 100;
GVAR(rangeCardIncrement) = 50;
GVAR(rangeCardEndRange) = GVAR(rangeCardStartRange) + 49 * GVAR(rangeCardIncrement);
_ammoConfig = _ammoClass call EFUNC(advanced_ballistics,readAmmoDataFromConfig);
_weaponConfig = _weaponClass call EFUNC(advanced_ballistics,readWeaponDataFromConfig);
_airFriction = _ammoConfig select 0;
_barrelTwist = _weaponConfig select 0;
_barrelLength = _weaponConfig select 2;
_muzzleVelocity = [_barrelLength, _ammoConfig select 10, _ammoConfig select 11, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift);
ctrlSetText [770000, format["%1'' - %2 gr (%3)", round((_ammoConfig select 1) * 39.3700787) / 1000, round((_ammoConfig select 3) * 15.4323584), _ammoClass]];
ctrlSetText [770002, format["Barrel: %1'' 1:%2'' twist", round(_barrelLength * 0.0393700787), round(_barrelTwist * 0.0393700787)]];
_bc = (_ammoConfig select 6) select 0;
_dragModel = _ammoConfig select 5;
_atmosphereModel = _ammoConfig select 8;
_boreHeight = 3.81;
_zeroRange = 100;
_barometricPressure = EGVAR(weather,altitude) call EFUNC(weather,calculateBarometricPressure);
_relativeHumidity = 0.5;
ctrlSetText [770001, format["Drop Tables for B.P.: %1mb; Corrected for MVV at Air/Ammo Temperatures -15-35 °C", round(_barometricPressure * 100) / 100]];
ctrlSetText [77004 , format["B.P.: %1mb", round(_barometricPressure * 100) / 100]];
_cacheEntry = missionNamespace getVariable format[QGVAR(%1_%2), _ammoClass, _weaponClass];
if (isNil {_cacheEntry}) then {
{
_mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift);
_mv = _muzzleVelocity + _mvShift;
_result = [0, 0, _boreHeight, _airFriction, _mv, _x, 1013.25, 0.5, 1000, [0, 0], 0, 0, 0, _zeroRange, _bc, _dragModel, _atmosphereModel, false, 1.5, 0, 0, 0] call FUNC(calculateSolution);
_scopeBaseAngle = (_result select 0) / 60;
[_scopeBaseAngle,27,_boreHeight,_airFriction,_mv,_x,_barometricPressure,_relativeHumidity,1000,[4,0],3,0,4,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,true,1.5,1,46,23,_forEachIndex] call FUNC(calculateSolution);
} forEach [-15, -5, 5, 10, 15, 20, 25, 30, 35];
for "_i" from 0 to 9 do {
GVAR(lastValidRow) pushBack count (GVAR(rangeCardDataElevation) select _i);
while {count (GVAR(rangeCardDataElevation) select _i) < 50} do {
(GVAR(rangeCardDataElevation) select _i) pushBack "###";
(GVAR(rangeCardDataWindage) select _i) pushBack "##";
(GVAR(rangeCardDataLead) select _i) pushBack "##";
};
};
missionNamespace setVariable [format[QGVAR(%1_%2), _ammoClass, _weaponClass], [GVAR(rangeCardDataElevation), GVAR(rangeCardDataWindage), GVAR(rangeCardDataLead), GVAR(rangeCardDataMVs), GVAR(lastValidRow)]];
} else {
GVAR(rangeCardDataElevation) = _cacheEntry select 0;
GVAR(rangeCardDataWindage) = _cacheEntry select 1;
GVAR(rangeCardDataLead) = _cacheEntry select 2;
GVAR(rangeCardDataMVs) = _cacheEntry select 3;
GVAR(lastValidRow) = _cacheEntry select 4;
};
lnbAddRow [770200, GVAR(rangeCardDataMVs)];
for "_i" from 0 to 49 do {
lnbAddRow [770400, [Str(GVAR(rangeCardStartRange) + GVAR(rangeCardIncrement) * _i), (GVAR(rangeCardDataElevation) select 0) select _i, (GVAR(rangeCardDataElevation) select 1) select _i, (GVAR(rangeCardDataElevation) select 2) select _i,
(GVAR(rangeCardDataElevation) select 3) select _i, (GVAR(rangeCardDataElevation) select 4) select _i, (GVAR(rangeCardDataElevation) select 5) select _i,
(GVAR(rangeCardDataElevation) select 6) select _i, (GVAR(rangeCardDataElevation) select 7) select _i, (GVAR(rangeCardDataElevation) select 8) select _i,
(GVAR(rangeCardDataWindage) select 0) select _i, (GVAR(rangeCardDataWindage) select 3) select _i, (GVAR(rangeCardDataWindage) select 8) select _i,
(GVAR(rangeCardDataLead) select 0) select _i, (GVAR(rangeCardDataLead) select 3) select _i, (GVAR(rangeCardDataLead) select 8) select _i]];
};
#define __dsp (uiNamespace getVariable "RangleCard_Display")
#define __ctrlListNBox (__dsp displayCtrl 770400)
{
__ctrlListNBox lnbSetColor [[_x, 0], [1, 1, 1, 1]];
} forEach [0, 8, 18, 28, 38, 48];
{
for "_i" from (GVAR(lastValidRow) select _x) to 49 do {
__ctrlListNBox lnbSetColor [[_i, _forEachIndex + 1], [0, 0, 0, 0.6]];
};
} forEach [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 3, 8, 0, 3, 8];

View File

@ -0,0 +1 @@
#include "\z\ace\addons\rangecard\script_component.hpp"

View File

@ -0,0 +1,31 @@
["ACE3 Equipment", QGVAR(RangeCardDialogKey), localize "STR_ACE_RangeCard_RangeCardDialogKey",
{
// Conditions: canInteract, canShow
if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false};
if (GVAR(RangeCardOpened)) exitWith {
closeDialog 0;
false
};
if !(call FUNC(canShow)) exitWith {false};
// Statement
false call FUNC(openRangeCard);
true
},
{false},
[0, [false, false, false]], false, 0] call CBA_fnc_addKeybind; // (empty default key)
["ACE3 Equipment", QGVAR(RangeCardCopyDialogKey), localize "STR_ACE_RangeCard_RangeCardCopyDialogKey",
{
// Conditions: canInteract, canShowCopy
if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false};
if (GVAR(RangeCardOpened)) exitWith {
closeDialog 0;
false
};
if !(call FUNC(canShowCopy)) exitWith {false};
// Statement
true call FUNC(openRangeCard);
true
},
{false},
[0, [false, false, false]], false, 0] call CBA_fnc_addKeybind; // (empty default key)

View File

@ -0,0 +1,12 @@
#define COMPONENT rangecard
#include "\z\ace\addons\main\script_mod.hpp"
#ifdef DEBUG_ENABLED_RANGECARD
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_RANGECARD
#define DEBUG_SETTINGS DEBUG_SETTINGS_RANGECARD
#endif
#include "\z\ace\addons\main\script_macros.hpp"

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="RangeCard">
<Key ID="STR_ACE_RangeCard_Name">
<English>Range Card</English>
</Key>
<Key ID="STR_ACE_RangeCard_Description">
<English>50 METER increments -- MRAD/MRAD (reticle/turrets)</English>
</Key>
<Key ID="STR_ACE_RangeCard_OpenRangeCard">
<English>Open Range Card</English>
</Key>
<Key ID="STR_ACE_RangeCard_OpenRangeCardCopy">
<English>Open Range Card Copy</English>
</Key>
<Key ID="STR_ACE_RangeCard_RangeCardDialogKey">
<English>Open Range Card</English>
</Key>
<Key ID="STR_ACE_RangeCard_RangeCardCopyDialogKey">
<English>Open Range Card Copy</English>
</Key>
<Key ID="STR_ACE_RangeCard_CopyRangeCard">
<English>Copy Range Card</English>
</Key>
</Package>
</Project>