Add IR Flashlights (#6563)

* Initial IR flashlight tests

* More experiments

* Rewrite using engine IR lights

* Rework ranges, fix bugs, add docs

* Fix uncommented DISABLE_COMPILE_CACHE

Co-authored-by: jonpas <jonpas33@gmail.com>

* Markdown fixes

Co-authored-by: jonpas <jonpas33@gmail.com>

* Markdown fixes

Co-authored-by: jonpas <jonpas33@gmail.com>

* Markdown fixes

Co-authored-by: jonpas <jonpas33@gmail.com>

* Markdown fixes

Co-authored-by: jonpas <jonpas33@gmail.com>

* Markdown fixes

Co-authored-by: jonpas <jonpas33@gmail.com>

* Use baseWeapon instead of custom property

* Add baseWeapon to SPIR

---------

Co-authored-by: jonpas <jonpas33@gmail.com>
This commit is contained in:
BaerMitUmlaut 2023-09-17 09:32:39 +02:00 committed by GitHub
parent a0dd4400e6
commit d6faac5881
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 975 additions and 9 deletions

View File

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

View File

@ -0,0 +1,17 @@
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 {
init = QUOTE(call COMPILE_FILE(XEH_postInit));
};
};

View File

@ -0,0 +1,82 @@
class SlotInfo;
class PointerSlot: SlotInfo {
compatibleItems[] += {
"ACE_DBAL_A3_Red",
"ACE_DBAL_A3_Red_IP",
"ACE_DBAL_A3_Red_II",
"ACE_DBAL_A3_Red_VP",
"ACE_DBAL_A3_Red_LR",
"ACE_DBAL_A3_Red_LR_IP",
"ACE_DBAL_A3_Red_LR_II",
"ACE_DBAL_A3_Red_LR_VP",
"ACE_DBAL_A3_Green",
"ACE_DBAL_A3_Green_IP",
"ACE_DBAL_A3_Green_II",
"ACE_DBAL_A3_Green_VP",
"ACE_DBAL_A3_Green_LR",
"ACE_DBAL_A3_Green_LR_IP",
"ACE_DBAL_A3_Green_LR_II",
"ACE_DBAL_A3_Green_LR_VP",
"ACE_SPIR",
"ACE_SPIR_Medium",
"ACE_SPIR_Narrow",
"ACE_SPIR_LR",
"ACE_SPIR_LR_Medium",
"ACE_SPIR_LR_Narrow"
};
};
class PointerSlot_Rail: PointerSlot {
class compatibleItems {
ACE_DBAL_A3_Red = 1;
ACE_DBAL_A3_Red_IP = 1;
ACE_DBAL_A3_Red_II = 1;
ACE_DBAL_A3_Red_VP = 1;
ACE_DBAL_A3_Red_LR = 1;
ACE_DBAL_A3_Red_LR_IP = 1;
ACE_DBAL_A3_Red_LR_II = 1;
ACE_DBAL_A3_Red_LR_VP = 1;
ACE_DBAL_A3_Green = 1;
ACE_DBAL_A3_Green_IP = 1;
ACE_DBAL_A3_Green_II = 1;
ACE_DBAL_A3_Green_VP = 1;
ACE_DBAL_A3_Green_LR = 1;
ACE_DBAL_A3_Green_LR_IP = 1;
ACE_DBAL_A3_Green_LR_II = 1;
ACE_DBAL_A3_Green_LR_VP = 1;
ACE_SPIR = 1;
ACE_SPIR_Medium = 1;
ACE_SPIR_Narrow = 1;
ACE_SPIR_LR = 1;
ACE_SPIR_LR_Medium = 1;
ACE_SPIR_LR_Narrow = 1;
};
};
class asdg_SlotInfo;
class asdg_FrontSideRail: asdg_SlotInfo {
class compatibleItems {
ACE_DBAL_A3_Red = 1;
ACE_DBAL_A3_Red_IP = 1;
ACE_DBAL_A3_Red_II = 1;
ACE_DBAL_A3_Red_VP = 1;
ACE_DBAL_A3_Red_LR = 1;
ACE_DBAL_A3_Red_LR_IP = 1;
ACE_DBAL_A3_Red_LR_II = 1;
ACE_DBAL_A3_Red_LR_VP = 1;
ACE_DBAL_A3_Green = 1;
ACE_DBAL_A3_Green_IP = 1;
ACE_DBAL_A3_Green_II = 1;
ACE_DBAL_A3_Green_VP = 1;
ACE_DBAL_A3_Green_LR = 1;
ACE_DBAL_A3_Green_LR_IP = 1;
ACE_DBAL_A3_Green_LR_II = 1;
ACE_DBAL_A3_Green_LR_VP = 1;
ACE_SPIR = 1;
ACE_SPIR_Medium = 1;
ACE_SPIR_Narrow = 1;
ACE_SPIR_LR = 1;
ACE_SPIR_LR_Medium = 1;
ACE_SPIR_LR_Narrow = 1;
};
};

View File

@ -0,0 +1,395 @@
// Attenuation and Flashlight seem to not work with inheritance
#define VISIBLE_POINTER_FLASHLIGHT \
class Flashlight { \
color[] = {0, 0, 0}; \
ambient[] = {0, 0, 0}; \
size = 0; \
innerAngle = 0; \
outerAngle = 0; \
position = "laser pos"; \
direction = "laser dir"; \
useFlare = 0; \
flareSize = 0; \
flareMaxDistance = 0; \
coneFadeCoef = 0; \
intensity = 0; \
irLight = 0; \
volumeShape = ""; \
scale[] = {0, 0, 0}; \
class Attenuation { \
constant = 0; \
linear = 0; \
quadratic = 0; \
start = 0; \
hardLimitStart = 0; \
hardLimitEnd = 0; \
}; \
}
#define DBAL_A3_FLASHLIGHT \
class Flashlight { \
color[] = {1, 1, 1}; \
ambient[] = {1, 1, 1}; \
size = 1; \
innerAngle = 10; \
outerAngle = 12; \
position = "laser pos"; \
direction = "laser dir"; \
useFlare = 1; \
flareSize = 1.4; \
flareMaxDistance = 200; \
coneFadeCoef = 6; \
intensity = 100; \
irLight = 1; \
volumeShape = "a3\data_f\VolumeLightFlashlight.p3d"; \
scale[] = {0.25, 0.25, 1}; \
class Attenuation { \
constant = 1; \
linear = 0; \
quadratic = 0.008; \
start = 1; \
hardLimitStart = 220; \
hardLimitEnd = 250; \
}; \
}
#define DBAL_A3_FLASHLIGHT_LR \
class Flashlight { \
color[] = {1, 1, 1}; \
ambient[] = {1, 1, 1}; \
size = 1; \
innerAngle = 10; \
outerAngle = 12; \
position = "laser pos"; \
direction = "laser dir"; \
useFlare = 1; \
flareSize = 1.4; \
flareMaxDistance = 200; \
coneFadeCoef = 6; \
intensity = 200; \
irLight = 1; \
volumeShape = "a3\data_f\VolumeLightFlashlight.p3d"; \
scale[] = {0.25, 0.25, 1}; \
class Attenuation { \
constant = 1; \
linear = 0; \
quadratic = 0.001; \
start = 1; \
hardLimitStart = 570; \
hardLimitEnd = 600; \
}; \
}
#define SPIR_FLASHLIGHT(hardLimitStart,hardLimitEnd) \
color[] = {1, 1, 1}; \
ambient[] = {1, 1, 1}; \
size = 1; \
position = "flash dir"; \
direction = "flash"; \
useFlare = 1; \
flareSize = 1.4; \
flareMaxDistance = 100; \
irLight = 1; \
volumeShape = "a3\data_f\VolumeLightFlashlight.p3d"; \
class Attenuation { \
constant = 1; \
linear = 0; \
quadratic = 0.02; \
start = 1; \
hardLimitStart = hardLimitStart; \
hardLimitEnd = hardLimitEnd; \
}
#define SPIR_FLASHLIGHT_LR(hardLimitStart,hardLimitEnd) \
color[] = {1, 1, 1}; \
ambient[] = {1, 1, 1}; \
size = 1; \
position = "flash dir"; \
direction = "flash"; \
useFlare = 1; \
flareSize = 1.4; \
flareMaxDistance = 100; \
irLight = 1; \
volumeShape = "a3\data_f\VolumeLightFlashlight.p3d"; \
class Attenuation { \
constant = 1; \
linear = 0; \
quadratic = 0.002; \
start = 1; \
hardLimitStart = hardLimitStart; \
hardLimitEnd = hardLimitEnd; \
}
#define POINTER \
class Pointer { \
irLaserPos = "laser pos"; \
irLaserEnd = "laser dir"; \
irDistance = 5; \
}
class CfgWeapons {
class acc_pointer_IR;
class acc_flashlight;
class InventoryFlashlightItem_Base_F;
// DBAL-A3 (red pointer)
class ACE_DBAL_A3_Red: acc_pointer_IR {
author = ECSTRING(common,ACETeam);
displayName = CSTRING(DBAL_A3_Red);
descriptionUse = CSTRING(DBAL_A3_DescriptionUse);
descriptionShort = CSTRING(DBAL_A3_DescriptionShort);
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_IP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_VP";
MRT_SwitchItemHintText = CSTRING(Mode_IRDual);
baseWeapon = "ACE_DBAL_A3_Red";
class ItemInfo: InventoryFlashLightItem_Base_F {
DBAL_A3_FLASHLIGHT;
POINTER;
};
};
class ACE_DBAL_A3_Red_IP: ACE_DBAL_A3_Red {
scope = 1;
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_II";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red";
MRT_SwitchItemHintText = CSTRING(Mode_IRPointer);
class ItemInfo: InventoryFlashLightItem_Base_F {
class Flashlight {};
POINTER;
};
};
class ACE_DBAL_A3_Red_II: ACE_DBAL_A3_Red {
scope = 1;
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_VP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_IP";
MRT_SwitchItemHintText = CSTRING(Mode_IRIlluminator);
class ItemInfo: InventoryFlashLightItem_Base_F {
DBAL_A3_FLASHLIGHT;
};
};
class ACE_DBAL_A3_Red_VP: ACE_DBAL_A3_Red {
scope = 1;
ACE_laserpointer = 1;
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_II";
MRT_SwitchItemHintText = CSTRING(Mode_VisiblePointer);
class ItemInfo: InventoryFlashLightItem_Base_F {
VISIBLE_POINTER_FLASHLIGHT;
POINTER;
};
};
// DBAL-A3 (red pointer, long range)
class ACE_DBAL_A3_Red_LR: ACE_DBAL_A3_Red {
scope = 1;
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_LR_IP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_LR_VP";
baseWeapon = "ACE_DBAL_A3_Red_LR";
class ItemInfo: InventoryFlashLightItem_Base_F {
DBAL_A3_FLASHLIGHT_LR;
POINTER;
};
};
class ACE_DBAL_A3_Red_LR_IP: ACE_DBAL_A3_Red_IP {
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_LR_II";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_LR";
baseWeapon = "ACE_DBAL_A3_Red_LR";
};
class ACE_DBAL_A3_Red_LR_II: ACE_DBAL_A3_Red_II {
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_LR_VP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_LR_IP";
baseWeapon = "ACE_DBAL_A3_Red_LR";
class ItemInfo: InventoryFlashLightItem_Base_F {
DBAL_A3_FLASHLIGHT_LR;
};
};
class ACE_DBAL_A3_Red_LR_VP: ACE_DBAL_A3_Red_VP {
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Red_LR";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Red_LR_II";
baseWeapon = "ACE_DBAL_A3_Red_LR";
};
// DBAL-A3 (green pointer)
class ACE_DBAL_A3_Green: ACE_DBAL_A3_Red {
scope = 2;
displayName = CSTRING(DBAL_A3_Green);
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_IP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_VP";
baseWeapon = "ACE_DBAL_A3_Green";
};
class ACE_DBAL_A3_Green_IP: ACE_DBAL_A3_Red_IP {
displayName = CSTRING(DBAL_A3_Green);
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_II";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green";
baseWeapon = "ACE_DBAL_A3_Green";
};
class ACE_DBAL_A3_Green_II: ACE_DBAL_A3_Red_II {
displayName = CSTRING(DBAL_A3_Green);
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_VP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_IP";
baseWeapon = "ACE_DBAL_A3_Green";
};
class ACE_DBAL_A3_Green_VP: ACE_DBAL_A3_Red_VP {
displayName = CSTRING(DBAL_A3_Green);
ACE_laserpointer = 2;
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_II";
baseWeapon = "ACE_DBAL_A3_Green";
};
// DBAL-A3 (green pointer, long range)
class ACE_DBAL_A3_Green_LR: ACE_DBAL_A3_Green {
scope = 1;
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_LR_IP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_LR_VP";
baseWeapon = "ACE_DBAL_A3_Green_LR";
class ItemInfo: InventoryFlashLightItem_Base_F {
DBAL_A3_FLASHLIGHT;
POINTER;
};
};
class ACE_DBAL_A3_Green_LR_IP: ACE_DBAL_A3_Green_IP {
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_LR_II";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_LR";
baseWeapon = "ACE_DBAL_A3_Green_LR";
};
class ACE_DBAL_A3_Green_LR_II: ACE_DBAL_A3_Green_II {
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_LR_VP";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_LR_IP";
baseWeapon = "ACE_DBAL_A3_Green_LR";
class ItemInfo: InventoryFlashLightItem_Base_F {
DBAL_A3_FLASHLIGHT;
};
};
class ACE_DBAL_A3_Green_LR_VP: ACE_DBAL_A3_Green_VP {
MRT_SwitchItemNextClass = "ACE_DBAL_A3_Green_LR";
MRT_SwitchItemPrevClass = "ACE_DBAL_A3_Green_LR_II";
baseWeapon = "ACE_DBAL_A3_Green_LR";
};
// SPIR
class ACE_SPIR: acc_flashlight {
author = ECSTRING(common,ACETeam);
displayName = "SPIR";
descriptionUse = CSTRING(SPIR_DescriptionUse);
descriptionShort = CSTRING(SPIR_DescriptionShort);
MRT_SwitchItemNextClass = "ACE_SPIR_Medium";
MRT_SwitchItemPrevClass = "ACE_SPIR_Narrow";
MRT_SwitchItemHintText = CSTRING(Mode_Wide);
baseWeapon = "ACE_SPIR";
class ItemInfo: InventoryFlashlightItem_Base_F {
class Flashlight {
SPIR_FLASHLIGHT(50,70);
innerAngle = 20;
outerAngle = 32;
coneFadeCoef = 2;
intensity = 50;
scale[] = {1, 1, 1};
};
};
};
class ACE_SPIR_Medium: ACE_SPIR {
scope = 1;
MRT_SwitchItemNextClass = "ACE_SPIR_Narrow";
MRT_SwitchItemPrevClass = "ACE_SPIR";
MRT_SwitchItemHintText = CSTRING(Mode_Medium);
class ItemInfo: InventoryFlashlightItem_Base_F {
class Flashlight {
SPIR_FLASHLIGHT(80,100);
intensity = 100;
innerAngle = 10;
outerAngle = 12;
coneFadeCoef = 3;
scale[] = {1, 1, 5};
};
};
};
class ACE_SPIR_Narrow: ACE_SPIR {
scope = 1;
MRT_SwitchItemNextClass = "ACE_SPIR";
MRT_SwitchItemPrevClass = "ACE_SPIR_Medium";
MRT_SwitchItemHintText = CSTRING(Mode_Narrow);
class ItemInfo: InventoryFlashlightItem_Base_F {
class Flashlight {
SPIR_FLASHLIGHT(120,150);
intensity = 200;
innerAngle = 5;
outerAngle = 6;
coneFadeCoef = 4;
scale[] = {1, 1, 10};
};
};
};
// SPIR (long range)
class ACE_SPIR_LR: ACE_SPIR {
scope = 1;
MRT_SwitchItemNextClass = "ACE_SPIR_LR_Medium";
MRT_SwitchItemPrevClass = "ACE_SPIR_LR_Narrow";
baseWeapon = "ACE_SPIR_LR";
class ItemInfo: InventoryFlashlightItem_Base_F {
class Flashlight {
SPIR_FLASHLIGHT_LR(80,100);
innerAngle = 20;
outerAngle = 32;
coneFadeCoef = 2;
intensity = 50;
scale[] = {1, 1, 1};
};
};
};
class ACE_SPIR_LR_Medium: ACE_SPIR_LR {
MRT_SwitchItemNextClass = "ACE_SPIR_LR_Narrow";
MRT_SwitchItemPrevClass = "ACE_SPIR_LR";
MRT_SwitchItemHintText = CSTRING(Mode_Medium);
class ItemInfo: InventoryFlashlightItem_Base_F {
class Flashlight {
SPIR_FLASHLIGHT_LR(100,120);
intensity = 100;
innerAngle = 10;
outerAngle = 12;
coneFadeCoef = 3;
scale[] = {1, 1, 5};
};
};
};
class ACE_SPIR_LR_Narrow: ACE_SPIR_LR {
MRT_SwitchItemNextClass = "ACE_SPIR_LR";
MRT_SwitchItemPrevClass = "ACE_SPIR_LR_Medium";
MRT_SwitchItemHintText = CSTRING(Mode_Narrow);
class ItemInfo: InventoryFlashlightItem_Base_F {
class Flashlight {
SPIR_FLASHLIGHT_LR(180,200);
intensity = 200;
innerAngle = 5;
outerAngle = 6;
coneFadeCoef = 4;
scale[] = {1, 1, 10};
};
};
};
};

4
addons/irlight/README.md Normal file
View File

@ -0,0 +1,4 @@
ace_irlight
===================
Adds IR flashlights.

View File

@ -0,0 +1,3 @@
PREP(getGlowOffset);
PREP(initItemContextMenu);
PREP(onLightToggled);

View File

@ -0,0 +1,30 @@
#include "script_component.hpp"
[] call FUNC(initItemContextMenu);
addUserActionEventHandler ["headlights", "Deactivate", FUNC(onLightToggled)];
["ACE3 Equipment", QGVAR(hold), LLSTRING(MomentarySwitch), {
ACE_player action ["GunLightOn", ACE_player];
ACE_player action ["IRLaserOn", ACE_player];
[] call FUNC(onLightToggled);
true
}, {
ACE_player action ["GunLightOff", ACE_player];
ACE_player action ["IRLaserOff", ACE_player];
[] call FUNC(onLightToggled);
true
}] call CBA_fnc_addKeybind;
["CBA_attachmentSwitched", {
params ["", "", "_item"];
private _substr = _item select [0, 8];
if (
ACE_player getVariable [QGVAR(isTurnedOn), false]
&& {_substr == "ACE_SPIR" || {_substr == "ACE_DBAL"}}
) then {
ACE_player action ["GunLightOn", ACE_player];
ACE_player action ["IRLaserOn", ACE_player];
};
}] call CBA_fnc_addEventHandler;

View File

@ -0,0 +1,9 @@
#include "script_component.hpp"
ADDON = false;
PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
ADDON = true;

View File

@ -0,0 +1,3 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

19
addons/irlight/config.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_common", "ace_laserpointer"};
author = ECSTRING(common,ACETeam);
authors[] = {"BaerMitUmlaut", "OmniMan"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgEventHandlers.hpp"
#include "CfgJointRails.hpp"
#include "CfgWeapons.hpp"

Binary file not shown.

View File

@ -0,0 +1,79 @@
ambient[] = {0, 0, 0, 1};
diffuse[] = {0, 0, 0, 1};
forcedDiffuse[] = {0, 0, 0, 1};
emmisive[] = {775, 121, 549, 0};
specular[] = {0, 0, 0, 1};
specularPower = 30;
PixelShaderID = "Super";
VertexShaderID = "Super";
class Stage1 {
texture = "#(argb,8,8,3)color(0.5,0.5,1,1,NOHQ)";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};
class Stage2 {
texture = "#(argb,8,8,3)color(0.5,0.5,0.5,0.5,DT)";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};
class Stage3 {
texture = "#(argb,8,8,3)color(1.0,1.0,1.0,0.0,MC)";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};
class Stage4 {
texture = "#(argb,8,8,3)color(1.0,1.0,1.0,1.0,AS)";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};
class Stage5 {
texture = "#(argb,8,8,3)color(1,0.0,1,0,SMDI)";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};
class Stage6 {
texture = "#(ai,64,64,1)fresnel(0.4,0.2)";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};
class Stage7 {
texture = "a3\data_f\env_land_co.paa";
useWorldEnvMap = "true";
uvSource = "tex";
class uvTransform {
aside[] = {1, 0, 0};
up[] = {0, 1, 0};
dir[] = {0, 0, 0};
pos[] = {0, 0, 0};
};
};

View File

@ -0,0 +1,8 @@
class CfgModels {
class Default {
sectionsInherit = "";
sections[] = {""};
skeletonName = "";
};
class irglow: Default {};
};

View File

@ -0,0 +1,42 @@
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Creates a scripted test light to test weapon lights without reloading.
*
* Arguments:
* 0: Flashlight class name <STRING>
*
* Return Value:
* None
*
* Example:
* "ACE_SPIR" call compile preprocessFileLineNumbers "\z\ace\addons\irlight\dev\createTestLight.sqf"
*
* Public: No
*/
params ["_className"];
private _cfg = configFile >> "CfgWeapons" >> _className >> "ItemInfo" >> "Flashlight";
deleteVehicle lgt;
lgt = "#lightreflector" createVehicleLocal [0, 0, 0];
lgt attachTo [player, [0.0396804,0.237947,0.104276], "proxy:\a3\characters_f\proxies\weapon.001", true];
lgt setLightIntensity getNumber (_cfg >> "intensity");
lgt setLightColor (getArray (_cfg >> "color") select [0, 3]);
lgt setLightAmbient (getArray (_cfg >> "ambient") select [0, 3]);
lgt setLightConePars [
getNumber (_cfg >> "outerAngle"),
getNumber (_cfg >> "innerAngle"),
getNumber (_cfg >> "coneFadeCoef")
];
attenuation = [
getNumber (_cfg >> "Attenuation" >> "start"),
getNumber (_cfg >> "Attenuation" >> "constant"),
getNumber (_cfg >> "Attenuation" >> "linear"),
getNumber (_cfg >> "Attenuation" >> "quadratic"),
getNumber (_cfg >> "Attenuation" >> "hardLimitStart"),
getNumber (_cfg >> "Attenuation" >> "hardLimitEnd")
];
lgt setLightAttenuation attenuation;

View File

@ -0,0 +1,41 @@
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Gets the player model offset of the IR laser origin.
* Currently unused, see onLightToggled.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_irlight_fnc_getGlowOffset
*
* Public: No
*/
if (isNil QGVAR(offsetCache)) then {
GVAR(offsetCache) = createHashMap;
};
private _weapon = currentWeapon ACE_player;
private _laser = ((weaponsItems ACE_player) select {_x#0 == _weapon})#0#2;
GVAR(offsetCache) getOrDefaultCall [[_weapon, _laser], {
private _model = getText (configFile >> "CfgWeapons" >> _weapon >> "model");
private _dummy = createSimpleObject [_model, [0, 0, 0], true];
private _proxyOffset = _dummy selectionPosition ["\a3\data_f\proxies\weapon_slots\SIDE.001", 1];
_proxyOffset = [_proxyOffset#1, _proxyOffset#0 * -1, _proxyOffset#2];
deleteVehicle _dummy;
_model = getText (configFile >> "CfgWeapons" >> _laser >> "model");
_dummy = createSimpleObject [_model, [0, 0, 0], true];
private _selection = getText (configFile >> "CfgWeapons" >> _laser >> "ItemInfo" >> "Pointer" >> "irLaserPos");
private _laserOffset = _dummy selectionPosition [_selection, "Memory"];
_laserOffset = [_laserOffset#1, _laserOffset#0 * -1, _laserOffset#2 * -1];
deleteVehicle _dummy;
_proxyOffset vectorAdd _laserOffset
}, true];

View File

@ -0,0 +1,52 @@
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Initializes the item context menu for the DBAL.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_irlight_fnc_initItemContextMenu
*
* Public: No
*/
{
_x params ["_variant", "_displayName"];
[
"ACE_DBAL_A3_Red", "POINTER", _displayName, [], "", {
params ["", "", "_item", "", "_variant"];
private _baseClass = getText (configFile >> "CfgWeapons" >> _item >> "baseWeapon");
_item != _baseClass + _variant
}, {
params ["", "", "_item", "", "_variant"];
private _baseClass = getText (configFile >> "CfgWeapons" >> _item >> "baseWeapon");
ACE_player removePrimaryWeaponItem _item;
ACE_player addPrimaryWeaponItem (_baseClass + _variant);
playSound "click";
if (_turnedOn) then {
// Force update of flashlight
ACE_player action ["GunLightOff", ACE_player];
{
ACE_player action ["GunLightOn", ACE_player];
ACE_player action ["IRLaserOn", ACE_player];
} call CBA_fnc_execNextFrame;
};
}, false, _variant
] call CBA_fnc_addItemContextMenuOption;
} forEach [
["", LSTRING(Mode_IRDual)],
["_IP", LSTRING(Mode_IRPointer)],
["_II", LSTRING(Mode_IRIlluminator)],
["_VP", LSTRING(Mode_VisiblePointer)]
];

View File

@ -0,0 +1,36 @@
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Handles toggling flashlights on and off.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_irlight_fnc_onLightToggled
*
* Public: No
*/
private _isTurnedOn = ACE_player isFlashlightOn primaryWeapon ACE_player
|| ACE_player isIRLaserOn primaryWeapon ACE_player;
ACE_player setVariable [QGVAR(isTurnedOn), _isTurnedOn];
// This is a surprise tool that will help us later
// Requires: https://feedback.bistudio.com/T170774
/*
deleteVehicle (ACE_player getVariable [QGVAR(glow), objNull]);
if (ACE_player isIRLaserOn currentWeapon ACE_player) then {
private _offset = [] call FUNC(getGlowOffset);
private _glow = createSimpleObject [QPATHTOF(data\irglow.p3d), [0, 0, 0]];
_glow attachTo [ACE_player, _offset, "proxy:\a3\characters_f\proxies\weapon.001", true];
_glow setObjectTexture [0, "#(rgb,8,8,3)color(0.35,0,0.38,0.1)"];
_glow setObjectScale 0.1;
ACE_player setVariable [QGVAR(glow), _glow];
};
*/

View File

@ -0,0 +1,17 @@
#define COMPONENT irlight
#define COMPONENT_BEAUTIFIED IR Lights
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_IRLIGHT
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_IRLIGHT
#define DEBUG_SETTINGS DEBUG_SETTINGS_IRLIGHT
#endif
#include "\z\ace\addons\main\script_macros.hpp"

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="IRLight">
<Key ID="STR_ACE_IRLight_DBAL_A3_Red">
<English>DBAL-A3 (red)</English>
<German>DBAL-A3 (rot)</German>
</Key>
<Key ID="STR_ACE_IRLight_DBAL_A3_Green">
<English>DBAL-A3 (green)</English>
<German>DBAL-A3 (grün)</German>
</Key>
<Key ID="STR_ACE_IRLight_DBAL_A3_DescriptionUse">
<English>&lt;t color='#9cf953'&gt;Use: &lt;/t&gt;Turn Laser ON/OFF&lt;br&gt;Double click to switch mode</English>
<German>&lt;t color='#9cf953'&gt;Benutzen: &lt;/t&gt;Laser EIN/AUS&lt;br&gt;Doppelklick um Modus zu wechseln</German>
</Key>
<Key ID="STR_ACE_IRLight_DBAL_A3_DescriptionShort">
<English>Dual Beam Aiming Laser</English>
<German>Doppelstrahllaservisier</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_VisiblePointer">
<English>Visible Laser</English>
<German>Sichtbarer Laser</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_IRPointer">
<English>IR Laser</English>
<German>IR-Laser</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_IRIlluminator">
<English>IR Illuminator</English>
<German>IR-Taschenlampe</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_IRDual">
<English>IR Laser and Illuminator</English>
<German>IR-Laser und -Licht</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_Wide">
<English>Wide Beam</English>
<German>Breiter Lichtstrahl</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_Medium">
<English>Medium Beam</English>
<German>Mittlerer Lichtstrahl</German>
</Key>
<Key ID="STR_ACE_IRLight_Mode_Narrow">
<English>Narrow Beam</English>
<German>Schmaler Lichtstrahl</German>
</Key>
<Key ID="STR_ACE_IRLight_SPIR_DescriptionUse">
<English>&lt;t color='#9cf953'&gt;Use: &lt;/t&gt;Turn Light ON/OFF&lt;br&gt;Double click to switch mode</English>
<German>&lt;t color='#9cf953'&gt;Benutzen: &lt;/t&gt;Licht EIN/AUS&lt;br&gt;Doppelklick um Modus zu wechseln</German>
</Key>
<Key ID="STR_ACE_IRLight_SPIR_DescriptionShort">
<English>Special Purpose IR LED Illuminator</English>
<German>Infrarot LED Taschenlampe</German>
</Key>
<Key ID="STR_ACE_IRLight_MomentarySwitch">
<English>Illuminator / Laser Momentary Switch</English>
<German>Licht / Laser Tastschalter</German>
</Key>
</Package>
</Project>

View File

@ -62,14 +62,19 @@ GVAR(greenLaserUnits) = [];
};
TRACE_3("",_weapon,_laser,_laserID);
if (_laserID isEqualTo 1) exitWith {
GVAR(redLaserUnits) pushBackUnique _unit;
GVAR(greenLaserUnits) deleteAt (GVAR(greenLaserUnits) find _unit);
};
if (_laserID isEqualTo 2) exitWith {
GVAR(greenLaserUnits) pushBackUnique _unit;
GVAR(redLaserUnits) deleteAt (GVAR(redLaserUnits) find _unit);
switch (_laserID) do {
case 0: {
GVAR(redLaserUnits) deleteAt (GVAR(redLaserUnits) find _unit);
GVAR(greenLaserUnits) deleteAt (GVAR(greenLaserUnits) find _unit);
};
case 1: {
GVAR(redLaserUnits) pushBackUnique _unit;
GVAR(greenLaserUnits) deleteAt (GVAR(greenLaserUnits) find _unit);
};
case 2: {
GVAR(greenLaserUnits) pushBackUnique _unit;
GVAR(redLaserUnits) deleteAt (GVAR(redLaserUnits) find _unit);
};
};
};

View File

@ -32,7 +32,7 @@ if (isNil "_isFlashlight") then {
_weaponConfig >> "FlashLight"
] findIf {
isText (_x >> "ACE_Flashlight_Colour")
|| {!(getArray (_x >> "ambient") in [[], [0,0,0]])}
|| {!(getArray (_x >> "ambient") in [[], [0,0,0]]) && {getNumber (_x >> "irLight") == 0}}
} != -1 // return
} != -1;

View File

@ -171,6 +171,18 @@ ACE_HuntIR_monitor | HuntIR monitor | ACE_ItemCore |
ACE_HuntIR_M203 | HuntIR Round | Grenade shell |
ACE_HuntIR_Box | HuntIR Transport Box | ammo box |
### IR Lights
`Added in 3.16.0`
Class Name | In-Game Name | Type |
---------- | --------- | ---------
ACE_DBAL_A3_Red | DBAL-A3 (red) | Weapon accessory |
ACE_DBAL_A3_Red_LR | DBAL-A3 (red) | Weapon accessory |
ACE_DBAL_A3_Green | DBAL-A3 (green) | Weapon accessory |
ACE_DBAL_A3_Green_LR | DBAL-A3 (green) | Weapon accessory |
ACE_SPIR | SPIR | Weapon accessory |
ACE_SPIR_LR | SPIR | Weapon accessory |
### Kestrel
`Added in 3.0.0`

View File

@ -0,0 +1,50 @@
---
layout: wiki
title: IR Lights
component: irlight
description: IR flashlights and multi function lasers.
group: feature
category: equipment
parent: wiki
mod: ace
version:
major: 3
minor: 16
patch: 0
---
## 1. Overview
### 1.1 DBAL-A3
The DBAL-A3 is a multi function laser and can be run in the following modes:
- IR laser and IR illuminator
- IR laser
- IR illuminator
- Visible laser
### 1.2 SPIR
The SPIR is an IR only flashlight. It uses a diffused laser, which improves its effective range considerably compared to a conventional flashlight. It has three modes with different beam widths to allow both easy terrain navigation and engagements at longer ranges during difficult lighting conditions.
### 1.3 Long Range Variants
Due to Arma 3's dated lighting system, flashlights can shine through objects and walls. To avoid these visual bugs, we have opted to tone down their range considerably compared to their real life counterparts. Although the DBAL-A3 has a range of up to 4000 m according to its manufacturer, such intense lights are simply not feasible in Arma.
Realism focused players which are not bothered by some visual bugs can use the long range variants of the DBAL-A3 and the SPIR. They are, besides their increased lighting power, identical to their normal range counterparts and can be accessed by appending `_LR` to the class name (see [Class Names](../class-names#ir-lights)). They still provide a lower lighting range than their real life counter parts, but should offer a nice middleground.
| Attachment | Normal Range | Long Range |
| ---------- | --------------- | ---------------- |
| DBAL-A3 | 220 m | 570 m |
| SPIR | 50 / 80 / 120 m | 80 / 100 / 180 m |
## 2. Usage
## 2.1 Momentary Switch
ACE IR Lights adds a keybind in the equipment category to temporarily turn on a flashlight or laser while holding down the key. There is no default keybind set.
## 2.2 Function Mode Switching
The DBAL-A3 function mode can be switched using the [CBA Accessory Functions](https://github.com/CBATeam/CBA_A3/wiki/Accessory-Functions) (default: <kbd>Ctrl</kbd> + <kbd>L</kbd>) or the item context menu, which can be accessed by double clicking the attachment in the inventory menu.