diff --git a/addons/milr/$PBOPREFIX$ b/addons/milr/$PBOPREFIX$ new file mode 100644 index 00000000000..85c833b6b80 --- /dev/null +++ b/addons/milr/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\milr diff --git a/addons/milr/CfgEventHandlers.hpp b/addons/milr/CfgEventHandlers.hpp new file mode 100644 index 00000000000..a86d374e7f5 --- /dev/null +++ b/addons/milr/CfgEventHandlers.hpp @@ -0,0 +1,15 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); + }; +}; +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preInit)); + }; +}; +class Extended_PostInit_EventHandlers { + class ADDON { + clientInit = QUOTE(call COMPILE_SCRIPT(XEH_clientInit)); + }; +}; diff --git a/addons/milr/CfgJointRails.hpp b/addons/milr/CfgJointRails.hpp new file mode 100644 index 00000000000..a76e4813f7f --- /dev/null +++ b/addons/milr/CfgJointRails.hpp @@ -0,0 +1,18 @@ +// lol +class SlotInfo; +class PointerSlot: SlotInfo { + compatibleItems[] += {QGVAR(base),QGVAR(000),QGVAR(002),QGVAR(004),QGVAR(006),QGVAR(008),QGVAR(010),QGVAR(012),QGVAR(014),QGVAR(016),QGVAR(018),QGVAR(020),QGVAR(022),QGVAR(024),QGVAR(026),QGVAR(028),QGVAR(030),QGVAR(032),QGVAR(034),QGVAR(036),QGVAR(038),QGVAR(040),QGVAR(042),QGVAR(044),QGVAR(046),QGVAR(048),QGVAR(050),QGVAR(052),QGVAR(054),QGVAR(056),QGVAR(058),QGVAR(060),QGVAR(062),QGVAR(064),QGVAR(066),QGVAR(068),QGVAR(070),QGVAR(072),QGVAR(074),QGVAR(076),QGVAR(078),QGVAR(080),QGVAR(082),QGVAR(084),QGVAR(086),QGVAR(088),QGVAR(090),QGVAR(092),QGVAR(094),QGVAR(096),QGVAR(098),QGVAR(100),QGVAR(110),QGVAR(120),QGVAR(130),QGVAR(140),QGVAR(150),QGVAR(160),QGVAR(170),QGVAR(180),QGVAR(190),QGVAR(200),QGVAR(210),QGVAR(220),QGVAR(230),QGVAR(240),QGVAR(250),QGVAR(260),QGVAR(270),QGVAR(280),QGVAR(290),QGVAR(300)}; +}; + +class PointerSlot_Rail: PointerSlot { + class compatibleItems { + GVAR(base)=1;GVAR(000)=1;GVAR(002)=1;GVAR(004)=1;GVAR(006)=1;GVAR(008)=1;GVAR(010)=1;GVAR(012)=1;GVAR(014)=1;GVAR(016)=1;GVAR(018)=1;GVAR(020)=1;GVAR(022)=1;GVAR(024)=1;GVAR(026)=1;GVAR(028)=1;GVAR(030)=1;GVAR(032)=1;GVAR(034)=1;GVAR(036)=1;GVAR(038)=1;GVAR(040)=1;GVAR(042)=1;GVAR(044)=1;GVAR(046)=1;GVAR(048)=1;GVAR(050)=1;GVAR(052)=1;GVAR(054)=1;GVAR(056)=1;GVAR(058)=1;GVAR(060)=1;GVAR(062)=1;GVAR(064)=1;GVAR(066)=1;GVAR(068)=1;GVAR(070)=1;GVAR(072)=1;GVAR(074)=1;GVAR(076)=1;GVAR(078)=1;GVAR(080)=1;GVAR(082)=1;GVAR(084)=1;GVAR(086)=1;GVAR(088)=1;GVAR(090)=1;GVAR(092)=1;GVAR(094)=1;GVAR(096)=1;GVAR(098)=1;GVAR(100)=1;GVAR(110)=1;GVAR(120)=1;GVAR(130)=1;GVAR(140)=1;GVAR(150)=1;GVAR(160)=1;GVAR(170)=1;GVAR(180)=1;GVAR(190)=1;GVAR(200)=1;GVAR(210)=1;GVAR(220)=1;GVAR(230)=1;GVAR(240)=1;GVAR(250)=1;GVAR(260)=1;GVAR(270)=1;GVAR(280)=1;GVAR(290)=1;GVAR(300)=1; + }; +}; + +class asdg_SlotInfo; +class asdg_FrontSideRail: asdg_SlotInfo { + class compatibleItems { + GVAR(base)=1;GVAR(000)=1;GVAR(002)=1;GVAR(004)=1;GVAR(006)=1;GVAR(008)=1;GVAR(010)=1;GVAR(012)=1;GVAR(014)=1;GVAR(016)=1;GVAR(018)=1;GVAR(020)=1;GVAR(022)=1;GVAR(024)=1;GVAR(026)=1;GVAR(028)=1;GVAR(030)=1;GVAR(032)=1;GVAR(034)=1;GVAR(036)=1;GVAR(038)=1;GVAR(040)=1;GVAR(042)=1;GVAR(044)=1;GVAR(046)=1;GVAR(048)=1;GVAR(050)=1;GVAR(052)=1;GVAR(054)=1;GVAR(056)=1;GVAR(058)=1;GVAR(060)=1;GVAR(062)=1;GVAR(064)=1;GVAR(066)=1;GVAR(068)=1;GVAR(070)=1;GVAR(072)=1;GVAR(074)=1;GVAR(076)=1;GVAR(078)=1;GVAR(080)=1;GVAR(082)=1;GVAR(084)=1;GVAR(086)=1;GVAR(088)=1;GVAR(090)=1;GVAR(092)=1;GVAR(094)=1;GVAR(096)=1;GVAR(098)=1;GVAR(100)=1;GVAR(110)=1;GVAR(120)=1;GVAR(130)=1;GVAR(140)=1;GVAR(150)=1;GVAR(160)=1;GVAR(170)=1;GVAR(180)=1;GVAR(190)=1;GVAR(200)=1;GVAR(210)=1;GVAR(220)=1;GVAR(230)=1;GVAR(240)=1;GVAR(250)=1;GVAR(260)=1;GVAR(270)=1;GVAR(280)=1;GVAR(290)=1;GVAR(300)=1; + }; +}; diff --git a/addons/milr/CfgWeapons.hpp b/addons/milr/CfgWeapons.hpp new file mode 100644 index 00000000000..ef25e212df7 --- /dev/null +++ b/addons/milr/CfgWeapons.hpp @@ -0,0 +1,39 @@ +#pragma hemtt suppress pw3_padded_arg file +#define CONCAT(a,b) a####b +#define ZERO(NUM) class GVAR(NUM): GVAR(base) { \ + scope = 1; \ + class ItemInfo: InventoryFlashLightItem_Base_F { \ + mass = 7; \ + class Pointer { \ + irLaserPos = "laser pos"; \ + irLaserEnd = QUOTE(CONCAT(laser ,NUM)); \ + irDistance = 5; \ + }; \ + class FlashLight {}; \ + }; \ +} + +class CfgWeapons { + class ItemCore; + class InventoryFlashLightItem_Base_F; + class GVAR(base): ItemCore { + scope = 2; + inertia = 0.1; + author = ECSTRING(common,ACETeam); + displayName = "MILR"; + descriptionUse = "$STR_A3_cfgWeapons_use_pointer_IR0"; + descriptionShort = CSTRING(descriptionShort); + picture = "\A3\weapons_F\Data\UI\gear_accv_pointer_CA.paa"; + model = QPATHTOF(data\ace_milr.p3d); + class ItemInfo: InventoryFlashLightItem_Base_F { // do not use inheritance on ItemInfo/Pointer as it breaks something + mass = 7; // big chonky box + class Pointer { + irLaserPos = "laser pos"; + irLaserEnd = "laser dir"; + irDistance = 5; + }; + class FlashLight {}; + }; + }; + ZERO(000);ZERO(002);ZERO(004);ZERO(006);ZERO(008);ZERO(010);ZERO(012);ZERO(014);ZERO(016);ZERO(018);ZERO(020);ZERO(022);ZERO(024);ZERO(026);ZERO(028);ZERO(030);ZERO(032);ZERO(034);ZERO(036);ZERO(038);ZERO(040);ZERO(042);ZERO(044);ZERO(046);ZERO(048);ZERO(050);ZERO(052);ZERO(054);ZERO(056);ZERO(058);ZERO(060);ZERO(062);ZERO(064);ZERO(066);ZERO(068);ZERO(070);ZERO(072);ZERO(074);ZERO(076);ZERO(078);ZERO(080);ZERO(082);ZERO(084);ZERO(086);ZERO(088);ZERO(090);ZERO(092);ZERO(094);ZERO(096);ZERO(098);ZERO(100);ZERO(110);ZERO(120);ZERO(130);ZERO(140);ZERO(150);ZERO(160);ZERO(170);ZERO(180);ZERO(190);ZERO(200);ZERO(210);ZERO(220);ZERO(230);ZERO(240);ZERO(250);ZERO(260);ZERO(270);ZERO(280);ZERO(290);ZERO(300); +}; diff --git a/addons/milr/README.md b/addons/milr/README.md new file mode 100644 index 00000000000..43fe0093b05 --- /dev/null +++ b/addons/milr/README.md @@ -0,0 +1,8 @@ +ace_milr +========== + +IR Pointer capable of rangefinding and adjusting beam zero based on ballistic calculations + + +#### Items Added: +`ace_milr_base` diff --git a/addons/milr/XEH_PREP.hpp b/addons/milr/XEH_PREP.hpp new file mode 100644 index 00000000000..52af24297c0 --- /dev/null +++ b/addons/milr/XEH_PREP.hpp @@ -0,0 +1,5 @@ +PREP(display_init); +PREP(display_refresh); +PREP(getRange); +PREP(keyPress); +PREP(pfeh); diff --git a/addons/milr/XEH_clientInit.sqf b/addons/milr/XEH_clientInit.sqf new file mode 100644 index 00000000000..d4e87dc43f0 --- /dev/null +++ b/addons/milr/XEH_clientInit.sqf @@ -0,0 +1,55 @@ +#include "script_component.hpp" +#include "\a3\ui_f\hpp\defineDIKCodes.inc" + +if (!hasInterface) exitWith {}; + +GVAR(currentPointer) = ""; +GVAR(pfid) = -1; +GVAR(data) = createHashMap; + +["ACE3 Equipment", QGVAR(range), [format ["MILR - %1", localize "str_a3_rscdisplayarsenal_stat_range"]], { + ["range", true] call FUNC(keyPress); +}, { + ["range", false] call FUNC(keyPress); +}, [DIK_TAB, [false, false, false]], false, 0] call CBA_fnc_addKeybind; + +private _fnc_updatePointer = { + params ["_player"]; + private _pointer = (_player weaponAccessories (currentWeapon _player)) param [1, ""]; + if (_pointer == GVAR(currentPointer)) exitWith {}; // fast exit if no change + GVAR(currentPointer) = _pointer; + + if (_pointer isKindOf [QGVAR(base), configFile >> "CfgWeapons"]) then { + if (GVAR(pfid) == -1) then { + TRACE_1("Adding PFEH",_pointer); + GVAR(pfid) = [LINKFUNC(pfeh), 0, []] call CBA_fnc_addPerFrameHandler; + }; + } else { + if (GVAR(pfid) != -1) then { + TRACE_1("Stopping PFEH",_pointer); + [GVAR(pfid)] call CBA_fnc_removePerFrameHandler; + GVAR(pfid) = -1; + }; + }; +}; +["loadout", _fnc_updatePointer] call CBA_fnc_addplayerEventHandler; +["weapon", _fnc_updatePointer, true] call CBA_fnc_addplayerEventHandler; + + +#ifdef ENABLE_QUICK_TESTING +player addPrimaryWeaponItem "ace_milr_base"; +[player] call CBA_fnc_addUnitTrackProjectiles; +player addItem "ace_rangecard"; + +["recompile", "recompile", "recompile", { + private _start = diag_tickTime; + [] call ACE_PREP_RECOMPILE; + [] call ace_common_fnc_dumpPerformanceCounters; + private _end = diag_tickTime; + systemChat format ["recompile took [%1 ms]", (1000 * (_end - _start)) toFixed 1]; + if (productVersion #4 == "Diag") then { + call compile "diag_mergeConfigFile ['P:\z\ace\addons\milr\config.cpp']"; + }; + false +}, {false}, [0x21, [false, false, false]], false] call CBA_fnc_addKeybind; // F Key +#endif diff --git a/addons/milr/XEH_preInit.sqf b/addons/milr/XEH_preInit.sqf new file mode 100644 index 00000000000..b47cf6628db --- /dev/null +++ b/addons/milr/XEH_preInit.sqf @@ -0,0 +1,9 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +ADDON = true; diff --git a/addons/milr/XEH_preStart.sqf b/addons/milr/XEH_preStart.sqf new file mode 100644 index 00000000000..022888575ed --- /dev/null +++ b/addons/milr/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/milr/config.cpp b/addons/milr/config.cpp new file mode 100644 index 00000000000..26eb61a8da3 --- /dev/null +++ b/addons/milr/config.cpp @@ -0,0 +1,31 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {QGVAR(base)}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_interaction"}; + author = ECSTRING(common,ACETeam); + authors[] = {"PabstMirror"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgWeapons.hpp" +#include "CfgJointRails.hpp" + +class GVAR(display) { + onLoad = QUOTE(call FUNC(display_init)); + idd = -1; + class Controls {}; +}; +class RscStructuredText; +class GVAR(structuredText): RscStructuredText { + colorText[] = {0.7,0.7,0.7,1}; + size = 0.05; // not safezone scaled + shadow = 0; +}; diff --git a/addons/milr/data/ace_milr.p3d b/addons/milr/data/ace_milr.p3d new file mode 100644 index 00000000000..5f537eb37b7 Binary files /dev/null and b/addons/milr/data/ace_milr.p3d differ diff --git a/addons/milr/data/plastic.rvmat b/addons/milr/data/plastic.rvmat new file mode 100644 index 00000000000..7935340c3a9 --- /dev/null +++ b/addons/milr/data/plastic.rvmat @@ -0,0 +1,92 @@ +ambient[]={1,0.98500001,0.97000003,1}; +diffuse[]={1,0.98500001,0.97000003,1}; +forcedDiffuse[]={0,0,0,0}; +emmisive[]={0,0,0,1}; +specular[]={0.0001,0.0001,0.0001,0}; +specularPower=2000; +PixelShaderID="Super"; +VertexShaderID="Super"; +class Stage1 +{ + texture="#(argb,8,8,3)color(0.5,0.5,1,1)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage2 +{ + texture = "#(argb,8,8,3)color(0.5,0.5,0.5,1,DT)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {5,-4,0}; + up[] = {8,1.931601,0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage3 +{ + texture = "#(argb,8,8,3)color(0,0,0,0,MC)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage4 +{ + texture="#(argb,8,8,3)color(0,1,1,1)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage5 +{ + texture="#(argb,8,8,3)color(1,1,1,1)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage6 +{ + texture = "#(ai,64,128,1)fresnel(1.5,1.22)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage7 +{ + texture = "a3\data_f\env_land_co.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; diff --git a/addons/milr/dev/blender_mem.py b/addons/milr/dev/blender_mem.py new file mode 100644 index 00000000000..b985ff92e18 --- /dev/null +++ b/addons/milr/dev/blender_mem.py @@ -0,0 +1,58 @@ +import bpy +import bmesh +import math + +def add_vertex_to_vgroup(new_cord, group_name): + me = obj.data + # Create a BMesh instance to handle the edit + bm = bmesh.new() + bm.from_mesh(me) + # Add a new vertex at a specific coordinate + new_vert = bm.verts.new(new_cord) + bm.verts.index_update() # Update indices after adding new vertex + new_index = new_vert.index + # Write the BMesh data back to the mesh and clean up (destroys new_vert) + bm.to_mesh(me) + bm.free() + me.update() + vgroup = obj.vertex_groups.new(name=group_name) + if vgroup.name != group_name: + raise Exception("Vertex group name mismatch") + vgroup.add([new_index], 1.0, 'ADD') + + +# Get the active object's mesh +obj = bpy.context.active_object +if not(obj and obj.type == 'MESH'): + raise Exception("not selected") + +# start by cleaning out all old groups +obj.vertex_groups.clear() + +base_x = 0.14 +base_y = 0.0 +base_z = 0.05 +delta_x = 0.1 +add_vertex_to_vgroup((base_x - delta_x, base_y, base_z), "laser pos") +add_vertex_to_vgroup((base_x, base_y, base_z), "laser dir") + +count = 0 +for i in range(0, 100, 2): + count += 1 + angle = i / 10 + z = base_z + math.tan(angle/1000) * delta_x + new_cord = (base_x, base_y, z) + group_name = f"laser {i:03}" + print(f"adding {group_name} at {new_cord}") + add_vertex_to_vgroup(new_cord, group_name) + +for i in range(100, 310, 10): + count += 1 + angle = i / 10 + z = base_z + math.tan(angle/1000) * delta_x + new_cord = (base_x, base_y, z) + group_name = f"laser {i:03}" + print(f"adding {group_name} at {new_cord}") + add_vertex_to_vgroup(new_cord, group_name) + +print(f"finished with {count} total") diff --git a/addons/milr/dev/rails.py b/addons/milr/dev/rails.py new file mode 100644 index 00000000000..feb9813af74 --- /dev/null +++ b/addons/milr/dev/rails.py @@ -0,0 +1,28 @@ + +out_compatibleArray = " compatibleItems[] += {QGVAR(base)," +out_compatibleClasses = " GVAR(base)=1;" +out_weapons = "" + +def addItem(i): + global out_compatibleArray, out_compatibleClasses, out_weapons + name = f"GVAR({i:03})" + out_compatibleArray += f"Q{name}," + out_compatibleClasses += f"{name}=1;" + out_weapons += f"ZERO({i:03});" + +for i in range(0, 100, 2): + addItem(i) +for i in range(100, 302, 10): + addItem(i) + + + +out_compatibleArray = out_compatibleArray.rstrip(",") + "};" + +print("--- GENERATED OUTPUT ---") +print("--- compat array:") +print(out_compatibleArray) +print("--- compat classes:") +print(out_compatibleClasses) +print("--- weapons:") +print(out_weapons) diff --git a/addons/milr/functions/fnc_display_init.sqf b/addons/milr/functions/fnc_display_init.sqf new file mode 100644 index 00000000000..0cfdb3b4853 --- /dev/null +++ b/addons/milr/functions/fnc_display_init.sqf @@ -0,0 +1,41 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Display Initialization (only for the local player) + * + * Arguments: + * 0: Display + * + * Return Value: + * None + * + * Example: + * [display, "abc"] call ace_milr_fnc_display_init + * + * Public: No + */ +params ["_display"]; +if (isNull _display) exitWith { ERROR("MILR display is null"); }; + +uiNamespace setVariable [QGVAR(display), _display]; + +private _ctrlBackground = _display ctrlCreate ["RscPicture", -1]; +_ctrlBackground ctrlSetText "#(argb,8,8,3)color(0.05,0.05,0.05,1)"; +_ctrlBackground ctrlSetPosition [0,0,1,1]; +_ctrlBackground ctrlCommit 0; + +// private _ctrlBackground = _display ctrlCreate ["RscPicture", -1]; // rough safezone +// _ctrlBackground ctrlSetText "#(argb,8,8,3)color(0.22352941,0.101960786,1,1)"; +// _ctrlBackground ctrlSetPosition [0.02,0.02,.95,.42]; +// _ctrlBackground ctrlCommit 0; + +private _ctrlRange = _display ctrlCreate [QGVAR(structuredText), IDC_MILR_RANGE]; +_ctrlRange ctrlSetPosition [0,0.025,0.95,0.3]; +_ctrlRange ctrlCommit 0; + +private _ctrlElev = _display ctrlCreate [QGVAR(structuredText), IDC_MILR_ELEV]; +_ctrlElev ctrlSetPosition [0.05,0.3,0.35,0.12]; +_ctrlElev ctrlSetBackgroundColor [0.9,0.9,0.9,1]; +_ctrlElev ctrlCommit 0; + +call FUNC(display_refresh); diff --git a/addons/milr/functions/fnc_display_refresh.sqf b/addons/milr/functions/fnc_display_refresh.sqf new file mode 100644 index 00000000000..84b56191065 --- /dev/null +++ b/addons/milr/functions/fnc_display_refresh.sqf @@ -0,0 +1,40 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Refreshes the item's display + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call ace_milr_fnc_display_refresh + * + * Public: No + */ +private _display = uiNamespace getVariable [QGVAR(display), displayNull]; +if (isNull _display) exitWith { ERROR("MILR display is null"); }; + +private _ctrlRange = _display displayCtrl IDC_MILR_RANGE; +private _range = GVAR(data) getOrDefault ["range", -1]; +private _rangeText = text (if (_range > 0) then { + format ["%1m", _range toFixed 0] +} else { + "----m" +}); +_rangeText setAttributes ["color", "#FFFFFF", "font", "EtelkaMonospacePro", "align", "right", "size", "5"]; +_ctrlRange ctrlSetStructuredText composeText [_rangeText]; + +private _ctrlElev = _display displayCtrl IDC_MILR_ELEV; +private _elev = GVAR(data) getOrDefault ["elevationMRAD", 0]; +private _elevText = text (call { + if (_range == RANGE_IN_PROGRESS) exitWith { "RANGING" }; + if (_elev <= 0) exitWith { "---" }; + if (_elev < 30) exitWith { format ["%1 +", _elev toFixed 1] }; + format ["%1 !!!", _elev toFixed 0] // out of limits +}); +_elevText setAttributes ["color", "#000000", "font", "EtelkaMonospacePro", "align", "left", "size", "2.3"]; +_ctrlElev ctrlSetStructuredText composeText [_elevText]; +displayUpdate _display; diff --git a/addons/milr/functions/fnc_getRange.sqf b/addons/milr/functions/fnc_getRange.sqf new file mode 100644 index 00000000000..35afcb83346 --- /dev/null +++ b/addons/milr/functions/fnc_getRange.sqf @@ -0,0 +1,31 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Gets the range to the target the player's weapon is aiming at + * + * Arguments: + * 0: Player + * + * Return Value: + * None + * + * Example: + * [player] call ace_milr_fnc_getRange + * + * Public: No + */ +params ["_player"]; +private _posHandRel = _player selectionPosition "head"; +// for some fancy stuff see https://community.bistudio.com/wiki/selectionVectorDirAndUp +private _posHandASL = _player modelToWorldVisualWorld _posHandRel; +private _dir = _player weaponDirection currentWeapon _player; +private _posEndASL = _posHandASL vectorAdd (_dir vectorMultiply RANGEFINDER_MAX_RANGE); + +private _vehicle = vehicle _player; +private _intersects = lineIntersectsSurfaces [_posHandASL, _posEndASL, _player, _vehicle]; + +if (_intersects isEqualTo []) exitWith { RANGE_NO_RETURNS }; +(_intersects select 0) params ["_intersectPosASL"]; +private _distance = _posHandASL distance _intersectPosASL; +if (_distance < RANGEFINDER_MIN_RANGE) exitWith { RANGE_TOO_CLOSE }; +_distance diff --git a/addons/milr/functions/fnc_keyPress.sqf b/addons/milr/functions/fnc_keyPress.sqf new file mode 100644 index 00000000000..529b64f97ec --- /dev/null +++ b/addons/milr/functions/fnc_keyPress.sqf @@ -0,0 +1,42 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Key Handler + * + * Arguments: + * 0: Key Function + * 1: Key Down + * + * Return Value: + * Key Handled + * + * Example: + * ["range", true] call ace_milr_fnc_keyPress + * + * Public: No + */ +if (GVAR(pfid) == -1) exitWith { false }; // fast exit if not equipped +params ["_func", "_keyDown"]; +private _player = ACE_player; +if !([_player, objNull, ["isNotInside"]] call EFUNC(common,canInteractWith)) exitWith { false }; +if !(_player call CBA_fnc_canUseWeapon) exitWith { false }; + +switch (_func) do { + case "range": { + if (_keyDown) then { + GVAR(data) set ["range", RANGE_IN_PROGRESS]; + GVAR(data) set ["range_keyDownStart", CBA_missionTime]; + } else { + private _holdTime = CBA_missionTime - (GVAR(data) getOrDefault ["range_keyDownStart", 0]); + // very long hold to clear + private _range = if (_holdTime < 5) then { [_player] call FUNC(getRange) } else { 0 }; + TRACE_1("Updating range",_range); + GVAR(data) set ["range", _range]; + // systemChat format ["DEBUG: range: %1 meters", _range]; + }; + }; + default { ERROR_1("Unknown keyPress function: %1",_func); }; +}; +call FUNC(display_refresh); + +true // return diff --git a/addons/milr/functions/fnc_pfeh.sqf b/addons/milr/functions/fnc_pfeh.sqf new file mode 100644 index 00000000000..738668ad76e --- /dev/null +++ b/addons/milr/functions/fnc_pfeh.sqf @@ -0,0 +1,66 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Updates the displaced laser when needed + * + * Arguments: + * 0: PFEH Data + * + * Return Value: + * None + * + * Example: + * [] call ace_milr_fnc_pfeh + * + * Public: No + */ + +params ["_pfData"]; // empty array on init +private _player = ACE_player; +private _range = GVAR(data) getOrDefault ["range", 0]; +private _zero = currentZeroing _player; +// possible ToDo ballistic tilt as well? + +if ([_range, _zero, GVAR(currentPointer)] isEqualTo _pfData) exitWith {}; // no state change + +private _player = ACE_player; +if !(_player call CBA_fnc_canUseWeapon) exitWith {}; // in vehicle etc + +private _item = if ((GVAR(data) getOrDefault ["range", 0]) == RANGE_IN_PROGRESS) then { + QGVAR(000) +} else { + private _elevationMRAD = if (_range <= 0) then { + 0 + } else { + GVAR(data) set ["zero_range", _zero]; // set zero for xm157 + ([_range, 0, 0, 0, GVAR(data)] call EFUNC(xm157,ballistics_calculator)) params ["_be","_bw"]; + TRACE_2("ballistics_calculator",_be,_bw); + // systemChat format ["DEBUG Ballistics: %1 - %2", _be, _bw]; + _be + }; + GVAR(data) set ["elevationMRAD", _elevationMRAD]; + + if (_elevationMRAD <= 0) exitWith { + QGVAR(000) // negative or zero, just use base item (see how much a problem this is with high weapon zeroing) + }; + _elevationMRAD = (_elevationMRAD max 0) min 30; // clamp + private _best10step = if (_elevationMRAD <= 10) then { // tenths of MRADs, variable precision + 2 * round (_elevationMRAD * 5); // 0-10 @ 2x increments + } else { + 10 * round (_elevationMRAD); // 10-30 @ 10x increments + }; + // get best item for the elevation + format ["%1_%2", QUOTE(ADDON), [_best10step, 3] call CBA_fnc_formatNumber]; +}; + +if (_item != GVAR(currentPointer)) then { + TRACE_1("Updating Item",_item); + // systemChat format ["DEBUG New Item: %1", _item]; + _player addPrimaryWeaponItem _item; +}; + +_pfData set [0, _range]; +_pfData set [1, _zero]; +_pfData set [2, GVAR(currentPointer)]; + +call FUNC(display_refresh); diff --git a/addons/milr/script_component.hpp b/addons/milr/script_component.hpp new file mode 100644 index 00000000000..9ea5e874cfd --- /dev/null +++ b/addons/milr/script_component.hpp @@ -0,0 +1,28 @@ +#define COMPONENT milr +#define COMPONENT_BEAUTIFIED MILR +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS +// #define ENABLE_QUICK_TESTING + +#ifdef DEBUG_ENABLED_MILR + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_MILR + #define DEBUG_SETTINGS DEBUG_SETTINGS_MILR +#endif + +#include "\z\ace\addons\main\script_macros.hpp" + +#define RANGEFINDER_MAX_RANGE 3000 +#define RANGEFINDER_MIN_RANGE 10 + +#define IDC_MILR_RANGE 90001 +#define IDC_MILR_ELEV 90002 + +#define RANGE_NO_RETURNS -1 +#define RANGE_TOO_CLOSE -2 +#define RANGE_IN_PROGRESS -3 diff --git a/addons/milr/stringtable.xml b/addons/milr/stringtable.xml new file mode 100644 index 00000000000..b1b54609791 --- /dev/null +++ b/addons/milr/stringtable.xml @@ -0,0 +1,8 @@ + + + + + IR Laser Pointer and Rangefinder + + + diff --git a/addons/xm157/functions/fnc_ballistics_calculator.sqf b/addons/xm157/functions/fnc_ballistics_calculator.sqf index 30c2999f889..05b14493d7d 100644 --- a/addons/xm157/functions/fnc_ballistics_calculator.sqf +++ b/addons/xm157/functions/fnc_ballistics_calculator.sqf @@ -8,6 +8,7 @@ * 1: Direction of Fire (deg) - Yaw * 2: Inlination (deg) - Pitch * 3: Bank (deg) - Roll + * 4: Custom Data (default: default data) * * Return Value: * Elevation and Windage in MRAD, Time Of Flight @@ -18,9 +19,10 @@ * Public: No */ -params ["_targetRange", "_directionOfFire", "_inclinationAngle", "_bank"]; +params ["_targetRange", "_directionOfFire", "_inclinationAngle", "_bank", ["_data", GVAR(data)]]; -private _weaponInfo = [] call FUNC(ballistics_getData); +private _zeroRange = _data getOrDefault ["zero_range", 100]; // 100 is the scope's `discreteDistance` so this doesn't need to be set explicitly +private _weaponInfo = [_zeroRange] call FUNC(ballistics_getData); if (_weaponInfo isEqualTo []) exitWith { [0, 0, 0] // return @@ -41,11 +43,11 @@ _weaponInfo params [ "_bulletMass" ]; -private _latitude = GVAR(data) getOrDefault ["latitude", 0]; +private _latitude = _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 _windSpeed = _data getOrDefault ["wind_speed", 0]; +private _windDirection = 22.5 * (_data getOrDefault ["wind_dir", 0]); private _wind = [sin (_directionOfFire - _windDirection), -cos (_directionOfFire - _windDirection), 0] vectorMultiply _windSpeed; // Get atmosphere diff --git a/addons/xm157/functions/fnc_ballistics_getData.sqf b/addons/xm157/functions/fnc_ballistics_getData.sqf index f73f2d3384d..5fa0ccd9249 100644 --- a/addons/xm157/functions/fnc_ballistics_getData.sqf +++ b/addons/xm157/functions/fnc_ballistics_getData.sqf @@ -4,31 +4,31 @@ * Gets ballistic info for a weapon, mag and ammo. * * Arguments: - * None + * 0: Zeroing * * Return Value: * Weapon Info * * Example: - * [] call ace_xm157_fnc_ballistics_getData + * [100] call ace_xm157_fnc_ballistics_getData * * Public: No */ -private _unit = ACE_player; -private _magazineClass = (primaryWeaponMagazine _unit) param [0, ""]; +params ["_zeroRange"]; +private _unit = ace_player; +private _magazineClass = (primaryWeaponMagazine _unit) param [0, ""]; if (_magazineClass == "") exitWith { [] // return }; - private _weaponClass = primaryWeapon _unit; +private _optic = (primaryWeaponItems _unit) param [2, ""]; -GVAR(data) getOrDefaultCall [[_weaponClass, _magazineClass], { +GVAR(data) getOrDefaultCall [["ballistics", _weaponClass, _magazineClass, _optic, _zeroRange], { private _ammoClass = getText (configFile >> "CfgMagazines" >> _magazineClass >> "ammo"); - TRACE_3("new weapon/mag",_weaponClass,_magazineClass,_ammoClass); + TRACE_4("new",_weaponClass,_magazineClass,_optic,_zeroRange); - private _zeroRange = 100; private _boreHeight = [_unit, 0] call EFUNC(scopes,getBoreHeight); (_ammoClass call EFUNC(advanced_ballistics,readAmmoDataFromConfig)) params ["_airFriction", "_caliber", "_bulletLength", "_bulletMass", "", "_dragModel", "_ballisticCoefficients", "", "_atmosphereModel", "", "_muzzleVelocityTable", "_barrelLengthTable"];