diff --git a/README.md b/README.md index 8721a3f217..83950e8236 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,23 @@

- +

- - ACE version - - - ACE download - - - ACE issues - - - ACE license - + + ACE version + + + ACE download + + + ACE issues + + + ACE license +

Requires the latest version of CBA A3 | BIF thread

-**ACE 3** is a joint effort by the teams behind **ACE2**, **AGM** and **CSE** to improve the realism and authenticity of Arma 3. +**ACE3** is a joint effort by the teams behind **ACE2**, **AGM** and **CSE** to improve the realism and authenticity of Arma 3. This mod is entirely **open-source**, and everyone is free to propose changes or maintain their own, customized version as long as they make their changes open to the public in accordance with the GNU General Public License (for more information check the license file attached to this project). diff --git a/TO_MERGE/agm/Optics/agm_optics_pip.p3d b/TO_MERGE/agm/Optics/agm_optics_pip.p3d new file mode 100644 index 0000000000..d331ce4acd Binary files /dev/null and b/TO_MERGE/agm/Optics/agm_optics_pip.p3d differ diff --git a/TO_MERGE/agm/Optics/clientInit.sqf b/TO_MERGE/agm/Optics/clientInit.sqf new file mode 100644 index 0000000000..7dca46fdc4 --- /dev/null +++ b/TO_MERGE/agm/Optics/clientInit.sqf @@ -0,0 +1,25 @@ +// TMR: Optics initialization and functions +// (C) 2013 Ryan Schultz. See LICENSE. + +// Request a resource layer from the game engine. +AGM_Optics_scopeRSC = ["AGM_Optics_Scope"] call BIS_fnc_rscLayer; + +// Set global variables +AGM_Optics_inScope = false; // Is the scope up? +AGM_Optics_currentOptic = ""; // What optic is attached right now? + +0 = 0 spawn { + waituntil {!isNull (findDisplay 46)}; + + [] call AGM_Optics_fnc_initScope; + + // PiP technique by BadBenson + AGM_Optics_Camera = "camera" camCreate (positioncameratoworld [0,0,0]); + AGM_Optics_Camera camSetFov 0.7; + AGM_Optics_Camera camSetTarget player; + AGM_Optics_Camera camCommit 1; + "agm_optics_rendertarget0" setPiPEffect [2, 1.0, 1.0, 1.0, 0.0, [0.0, 1.0, 0.0, 0.25], [1.0, 0.0, 1.0, 1.0], [0.199, 0.587, 0.114, 0.0]]; + AGM_Optics_Camera cameraEffect ["INTERNAL", "BACK","agm_optics_rendertarget0"]; + + waitUntil {[] call AGM_Optics_fnc_mainLoop; False}; +}; diff --git a/TO_MERGE/agm/Optics/config.cpp b/TO_MERGE/agm/Optics/config.cpp new file mode 100644 index 0000000000..429c57cbe2 --- /dev/null +++ b/TO_MERGE/agm/Optics/config.cpp @@ -0,0 +1,454 @@ +class CfgPatches { + class AGM_Optics { + units[] = {}; + weapons[] = {}; + requiredVersion = 0.60; + requiredAddons[] = {AGM_Core}; + version = 0.1; + author[] = {"Taosenai"}; + authorUrl = "http://www.ryanschultz.org/tmr/"; + }; +}; + +class CfgFunctions { + class AGM_Optics { + class AGM_Optics { + file = "AGM_Optics\functions"; + class firedEH; + class hideScope; + class initScope; + class mainLoop; + }; + }; +}; + +class Extended_PostInit_EventHandlers { + class AGM_Optics { + clientInit = "call compile preProcessFileLineNumbers '\AGM_Optics\clientInit.sqf'"; + }; +}; + +class Extended_FiredBIS_EventHandlers { + class CAManBase { + class AGM_Optics { + clientFiredBIS = "_this call AGM_Optics_fnc_firedEH;"; + }; + }; +}; + +class CfgOpticsEffect { + class AGM_OpticsRadBlur1 { + type = "radialblur"; + params[] = {0.015, 0, 0.14, 0.2}; + priority = 950; + }; +}; + + +class CfgWeapons { + class ItemCore; + class InventoryItem_Base_F; + class InventoryMuzzleItem_Base_F; + class InventoryOpticsItem_Base_F; + + class optic_Hamr : ItemCore { + displayName = "HAMR 4x"; + descriptionShort = "High Accuracy Multi-Range Optic
Magnification: 4x
Reticle: CM-RW 6.5mm"; + scope = 2; + weaponInfoType = "AGM_RscWeapon"; + + AGM_Optics_enhanced = 1; + AGM_Optics_reticle = "\AGM_Optics\data\hamr\hamr-reticle65_ca.paa"; + AGM_Optics_reticleIllum = "\AGM_Optics\data\hamr\hamr-reticle65Illum_ca.paa"; + AGM_Optics_body = "\AGM_Optics\data\hamr\hamr-body_ca.paa"; + AGM_Optics_bodyNight = "\AGM_Optics\data\hamr\hamr-bodyNight_ca.paa"; + + model = "\A3\weapons_f\acc\acco_hamr_F"; + + class ItemInfo : InventoryOpticsItem_Base_F { + mass = 4; + optics = 1; + optictype = 1; + rmbhint = "HAMR"; + modeloptics = "\AGM_Optics\agm_optics_pip.p3d"; + + class OpticsModes { + class Hamr2Collimator { + AGM_Optics_enhanced = 0; + opticsID = 1; + useModelOptics = 0; + opticsppeffects[] = {}; + opticsFlare = 0; + opticsDisablePeripherialVision = 0; + opticsZoomMin = 0.375; + opticsZoomMax = 1; + opticsZoomInit = 0.75; + memoryPointCamera = "eye"; + visionMode[] = {}; + distanceZoomMin = 300; + distanceZoomMax = 300; + }; + + class Hamr2Scope { + cameradir = ""; + distanceZoomMin = 300; + distanceZoomMax = 300; + memorypointcamera = "opticView"; + opticsdisableperipherialvision = 0; + opticsdisplayname = "IHAMR"; + opticsflare = 1; + opticsid = 2; + opticsppeffects[] = {"OpticsCHAbera2", "OpticsBlur1", "AGM_OpticsRadBlur1"}; + opticszoominit = 0.0872664626; + opticszoommax = 0.0872664626; + opticszoommin = 0.0872664626; + discretefov[] = {0.0872664626}; + discreteinitindex = 0; + usemodeloptics = 1; + modeloptics = "\AGM_Optics\agm_optics_pip.p3d"; + visionmode[] = {"Normal", "NVG"}; + }; + }; + }; + }; + + class optic_Arco : ItemCore { + descriptionshort = "Advanced Rifle Combat Optic
Magnification: 4x
Reticle: SpecterDR 6.5mm"; + displayname = "ARCO 4x"; + picture = "\A3\weapons_F\Data\UI\gear_acco_Arco_CA.paa"; + scope = 2; + weaponInfoType = "AGM_RscWeapon"; + + model = "\A3\weapons_f\acc\acco_Arco_F"; + + AGM_Optics_enhanced = 1; + AGM_Optics_reticle = "\AGM_Optics\data\arco\arco-reticle65_ca.paa"; + AGM_Optics_reticleIllum = "\AGM_Optics\data\arco\arco-reticle65Illum_ca.paa"; + AGM_Optics_body = "\AGM_Optics\data\arco\arco-body_ca.paa"; + AGM_Optics_bodyNight = "\AGM_Optics\data\arco\arco-bodyNight_ca.paa"; + + class ItemInfo: InventoryOpticsItem_Base_F { + mass = 4; + optics = 1; + optictype = 1; + rmbhint = "ARCO"; + + class OpticsModes { + class ARCO2collimator { + AGM_Optics_enhanced = 0; + cameradir = ""; + distancezoommax = 300; + distancezoommin = 300; + memorypointcamera = "eye"; + opticsdisableperipherialvision = 0; + opticsdisplayname = "CQB"; + opticsflare = 0; + opticsid = 1; + opticsppeffects[] = {}; + opticszoominit = 0.75; + opticszoommax = 1.1; + opticszoommin = 0.375; + usemodeloptics = 0; + visionmode[] = {}; + }; + class ARCO2scope: ARCO2collimator { + cameradir = ""; + distanceZoomMin = 300; + distanceZoomMax = 300; + memorypointcamera = "opticView"; + opticsdisableperipherialvision = 0; + opticsdisplayname = "ARCO"; + opticsflare = 1; + opticsid = 2; + opticsppeffects[] = {"OpticsCHAbera2", "OpticsBlur1", "AGM_OpticsRadBlur1"}; + opticszoominit = 0.0872664626; // 0.0872664626 rad = 5 degrees + opticszoommax = 0.0872664626; // SpecterDR 4x is 6 degrees + opticszoommin = 0.0872664626; // Scope graphic in game covers 1 degree + discretefov[] = {0.0872664626}; + discreteinitindex = 0; + usemodeloptics = 1; + modeloptics = "\AGM_Optics\data\AGM_Optics_reticle90.p3d"; + visionmode[] = {"Normal"}; + }; + }; + }; + }; + + class optic_MRCO : ItemCore { + displayName = "MRCO 1x/4x"; + descriptionShort = "Medium Range Combat Optic
Magnification: 1x/4x
Reticle: Pitbull Gen II 5.56mm"; + scope = 2; + weaponInfoType = "AGM_RscWeapon"; + + AGM_Optics_enhanced = 1; + AGM_Optics_reticle = "\AGM_Optics\data\mrco\mrco-reticle556_ca.paa"; + AGM_Optics_reticleIllum = "\AGM_Optics\data\mrco\mrco-reticle556Illum_ca.paa"; + AGM_Optics_body = "\AGM_Optics\data\mrco\mrco-body_ca.paa"; + AGM_Optics_bodyNight = "\AGM_Optics\data\mrco\mrco-bodyNight_ca.paa"; + + class ItemInfo : InventoryOpticsItem_Base_F { + opticType = 1; + mass = 4; + optics = 1; + modelOptics = "\A3\Weapons_f_beta\acc\reticle_MRCO_F"; + + class OpticsModes { + class MRCOcq { + AGM_Optics_enhanced = 0; + opticsID = 1; + useModelOptics = 0; + opticsPPEffects[] = {}; + opticsFlare = 0; + opticsDisablePeripherialVision = 0; + opticsZoomMin = 0.375; + opticsZoomMax = 1; + opticsZoomInit = 0.75; + memoryPointCamera = "eye"; + visionMode[] = {}; + distanceZoomMin = 100; + distanceZoomMax = 100; + }; + + class MRCOscope { + cameradir = ""; + distanceZoomMin = 300; + distanceZoomMax = 300; + memorypointcamera = "eye"; + opticsdisableperipherialvision = 0; + opticsdisplayname = "MRCO"; + opticsflare = 1; + opticsid = 2; + opticsppeffects[] = {"OpticsCHAbera2", "OpticsBlur2", "AGM_OpticsRadBlur1"}; + opticszoominit = 0.0872664626; + opticszoommax = 0.0872664626; + opticszoommin = 0.0872664626; + discretefov[] = {0.0872664626}; + discreteinitindex = 0; + usemodeloptics = 1; + modeloptics = "\AGM_Optics\data\AGM_Optics_reticle90.p3d"; + visionmode[] = {"Normal"}; + }; + }; + }; + }; + + class optic_Nightstalker : ItemCore { + class ItemInfo: InventoryOpticsItem_Base_F { + class OpticsModes { + class NCTALKEP {}; + class Iron : NCTALKEP { + opticsppeffects[] = {}; // Fix Arma 3 bug + }; + }; + }; + }; + + class optic_SOS: ItemCore { + class ItemInfo: InventoryOpticsItem_Base_F { + modelOptics = "\AGM_Optics\agm_optics_pip.p3d"; + class OpticsModes { + class Snip { + visionMode[] = {"Normal","TI","NVG"}; + thermalMode[] = {5,6}; + opticsPPEffects[] = {"OpticsCHAbera1","radblur"}; + modelOptics[] = {"\AGM_Optics\agm_optics_pip.p3d","\AGM_Optics\agm_optics_pip.p3d"}; + }; + }; + + }; + }; + + class optic_DMS : ItemCore { + class ItemInfo: InventoryOpticsItem_Base_F { + class OpticsModes { + class Snip {}; + class Iron : Snip { + opticsppeffects[] = {}; // Fix Arma 3 bug + }; + }; + }; + }; + + class optic_LRPS : ItemCore { + descriptionshort = "Nightforce NXS Riflescope
Magnification: 5.5-22x"; + displayname = "NXS 5.5-22x"; + weaponinfotype = "AGM_RscWeapon"; + + AGM_Optics_enhanced = 1; + AGM_Optics_reticle = "\AGM_Optics\data\sos\sos-reticleMLR_ca.paa"; + AGM_Optics_reticleIllum = "\AGM_Optics\data\sos\sos-reticleMLRIllum_ca.paa"; + AGM_Optics_body = "\AGM_Optics\data\sos\sos-body_ca.paa"; + AGM_Optics_bodyNight = "\AGM_Optics\data\sos\sos-bodyNight_ca.paa"; + + class ItemInfo: InventoryOpticsItem_Base_F { + modeloptics = "\AGM_Optics\data\AGM_Optics_reticle90.p3d"; + weaponinfotype = "RscWeaponRangeZeroingFOV"; + opticType = 2; // Sniper optics + + class OpticsModes { + // Based on Nightforce NXS 5.5-22 scope + class Snip { + cameradir = ""; + discretedistance[] = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300}; + discretedistanceinitindex = 0; + discreteinitindex = 0; + distancezoommax = 2300; + distancezoommin = 100; + memorypointcamera = "opticView"; + modeloptics = "\AGM_Optics\data\AGM_Optics_reticle90.p3d"; + opticsdisableperipherialvision = 1; + opticsdisplayname = "SOS"; + opticsflare = 1; + opticsid = 1; + opticsppeffects[] = {"OpticsCHAbera1", "OpticsBlur1", "AGM_OpticsRadBlur1"}; + // How to determine opticszoom + // First do the basic math based on the listed FOV of the scope to + // get a baseline FOV + // 0.1 meter at 100 meters = 1 mrad + // + // 5.5x FOV -- 5.3 m at 100 m = 53 mrad + // = 0.053 rad = 3.037 deg FOV + + // 22x FOV -- 1.4 m at 100m = 14 mrad + // = 0.014 rad = 0.802 deg + + // The FOV you give the engine is based on a rather larger scope outline, so we + // have to do this extra work ourselves. + + // At 1680x1050 + // The width of a TMR optic viewfield is 864px + // The engine viewport width (which is what the below FOV is based on) is 980 + // (864/980) = (FOV to give engine / true FOV of optic) + // 864/980 * 0.053 = 0.04673 + // 864/980 * 0.014 = 0.01234 + + // Measured experimentally, these values seem quite right. + // Certainly they're close enough after you account for pixel density, etc. + + opticszoominit = 0.01234; + opticszoommax = 0.04673; + opticszoommin = 0.01234; + discretefov[] = {}; + usemodeloptics = 1; + visionmode[] = {"Normal"}; + }; + }; + }; + }; + + class optic_Yorris : ItemCore { + descriptionshort = "Burris FastFire II Red Dot Sight
Magnification: 1x"; + displayname = "FastFire II"; + }; + + class optic_MRD : ItemCore { + descriptionshort = "Eotech MRDS Red Dot Sight
Magnification: 1x"; + displayname = "MRDS"; + }; + + class optic_Holosight : ItemCore { + descriptionshort = "Eotech XPS3 Holographic Sight
Magnification: 1x"; + displayname = "XPS3 Holo"; + }; +}; + +class RscOpticsText; +class RscOpticsValue; +class RscInGameUI { + class RscUnitInfo; + class RscWeaponZeroing; + class AGM_RscWeapon : RscWeaponZeroing { + idd = -1; + controls[] = {"CA_Zeroing", "CA_FOVMode"}; + + onLoad ="with uiNameSpace do { AGM_OpticsIGUI = _this select 0 }"; + + class CA_FOVMode : RscOpticsValue { + idc = 154; + style = 2; + colorText[] = {0, 0, 0, 0}; + x = 0; + y = 0; + w = 0; + h = 0; + }; + }; +}; + +class RscTitles { + class AGM_Optics_Scope { + idd = -1; + onLoad = "with uiNameSpace do { AGM_Optics_Scope = _this select 0 };"; + onUnload = ""; + movingEnable = 1; + duration = 10000; + controls[] = {"Reticle", "ReticleNight", "BodyNight", "Body"}; + + class Reticle { + colorBackground[] = {0,0,0, 0}; + colorText[] = {1,1,1, 1}; + fade = 0; + font = "PuristaMedium"; + h = SafeZoneH; + idc = 1; + lineSpacing = 1.0; + movingEnable = 1; + size = 0; + sizeEx = 1; + style = 48; + text = ""; + type = 0; + w = SafeZoneWAbs / ((getResolution select 0) / (getResolution select 1)); + x = (SafeZoneXAbs + SafeZoneWAbs/2 - (SafeZoneWAbs / ((getResolution select 0) / (getResolution select 1)))/2); + y = SafeZoneY; + }; + + class ReticleNight : Reticle { + idc = 2; + text = ""; + }; + + class Body : Reticle { + idc = 6; + text = ""; + x = (SafeZoneXAbs + SafeZoneWAbs/2 - (SafeZoneWAbs / ((getResolution select 0) / (getResolution select 1)))); + y = SafeZoneY - (SafeZoneH/2); + w = SafeZoneWAbs / ((getResolution select 0) / (getResolution select 1)) * 2; + h = SafeZoneH * 2; + }; + + class BodyNight : Body { + idc = 5; + text = ""; + }; + }; +}; + +class PreloadTextures { + class CfgWeapons { + class optic_hamr { + AGM_Optics_body= "*"; + AGM_Optics_bodyNight = "*"; + AGM_Optics_reticle = "*"; + AGM_Optics_reticleIllum = "*"; + }; + class optic_arco { + AGM_Optics_body= "*"; + AGM_Optics_bodyNight = "*"; + AGM_Optics_reticle = "*"; + AGM_Optics_reticleIllum = "*"; + }; + class optic_mrco { + AGM_Optics_body= "*"; + AGM_Optics_bodyNight = "*"; + AGM_Optics_reticle = "*"; + AGM_Optics_reticleIllum = "*"; + }; + class optic_LRPS { + AGM_Optics_body= "*"; + AGM_Optics_bodyNight = "*"; + AGM_Optics_reticle = "*"; + AGM_Optics_reticleIllum = "*"; + }; + }; +}; diff --git a/TO_MERGE/agm/Optics/data/arco/arco-bodyNight_ca.paa b/TO_MERGE/agm/Optics/data/arco/arco-bodyNight_ca.paa new file mode 100644 index 0000000000..9b186b56f4 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/arco/arco-bodyNight_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/arco/arco-body_ca.paa b/TO_MERGE/agm/Optics/data/arco/arco-body_ca.paa new file mode 100644 index 0000000000..193b14a92c Binary files /dev/null and b/TO_MERGE/agm/Optics/data/arco/arco-body_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/arco/arco-reticle65Illum_ca.paa b/TO_MERGE/agm/Optics/data/arco/arco-reticle65Illum_ca.paa new file mode 100644 index 0000000000..d193051e81 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/arco/arco-reticle65Illum_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/arco/arco-reticle65_ca.paa b/TO_MERGE/agm/Optics/data/arco/arco-reticle65_ca.paa new file mode 100644 index 0000000000..671417fd4b Binary files /dev/null and b/TO_MERGE/agm/Optics/data/arco/arco-reticle65_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/black.rvmat b/TO_MERGE/agm/Optics/data/black.rvmat new file mode 100644 index 0000000000..431d76689f --- /dev/null +++ b/TO_MERGE/agm/Optics/data/black.rvmat @@ -0,0 +1,8 @@ +ambient[]={0,0,0,0.89999998}; +diffuse[]={0,0,0,0.89999998}; +forcedDiffuse[]={0,0,0,1}; +emmisive[]={0,0,0,1}; +specular[]={0,0,0,0}; +specularPower=1; +PixelShaderID="Normal"; +VertexShaderID="Basic"; diff --git a/TO_MERGE/agm/Optics/data/em.rvmat b/TO_MERGE/agm/Optics/data/em.rvmat new file mode 100644 index 0000000000..a491df4b9a --- /dev/null +++ b/TO_MERGE/agm/Optics/data/em.rvmat @@ -0,0 +1,20 @@ +ambient[]={1,1,1,1}; +diffuse[]={1,1,1,1}; +forcedDiffuse[]={0,0,0,0}; +emmisive[]={1,1,1,1}; +specular[]={1,0.99956858,1,1}; +specularPower=1; +PixelShaderID="Normal"; +VertexShaderID="Basic"; +class Stage1 +{ + 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}; + }; +}; diff --git a/TO_MERGE/agm/Optics/data/hamr/hamr-bodyNight_ca.paa b/TO_MERGE/agm/Optics/data/hamr/hamr-bodyNight_ca.paa new file mode 100644 index 0000000000..422b13f7f1 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/hamr/hamr-bodyNight_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/hamr/hamr-body_ca.paa b/TO_MERGE/agm/Optics/data/hamr/hamr-body_ca.paa new file mode 100644 index 0000000000..6b55916c5f Binary files /dev/null and b/TO_MERGE/agm/Optics/data/hamr/hamr-body_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/hamr/hamr-reticle65Illum_ca.paa b/TO_MERGE/agm/Optics/data/hamr/hamr-reticle65Illum_ca.paa new file mode 100644 index 0000000000..7af73234fc Binary files /dev/null and b/TO_MERGE/agm/Optics/data/hamr/hamr-reticle65Illum_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/hamr/hamr-reticle65_ca.paa b/TO_MERGE/agm/Optics/data/hamr/hamr-reticle65_ca.paa new file mode 100644 index 0000000000..2cbf329c89 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/hamr/hamr-reticle65_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/mrco/mrco-bodyNight_ca.paa b/TO_MERGE/agm/Optics/data/mrco/mrco-bodyNight_ca.paa new file mode 100644 index 0000000000..381fdd3e97 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/mrco/mrco-bodyNight_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/mrco/mrco-body_ca.paa b/TO_MERGE/agm/Optics/data/mrco/mrco-body_ca.paa new file mode 100644 index 0000000000..bfcaa9828f Binary files /dev/null and b/TO_MERGE/agm/Optics/data/mrco/mrco-body_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/mrco/mrco-reticle556Illum_ca.paa b/TO_MERGE/agm/Optics/data/mrco/mrco-reticle556Illum_ca.paa new file mode 100644 index 0000000000..5bf836d593 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/mrco/mrco-reticle556Illum_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/mrco/mrco-reticle556_ca.paa b/TO_MERGE/agm/Optics/data/mrco/mrco-reticle556_ca.paa new file mode 100644 index 0000000000..e7b8599f83 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/mrco/mrco-reticle556_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/scopeblack-100_ca.paa b/TO_MERGE/agm/Optics/data/scopeblack-100_ca.paa new file mode 100644 index 0000000000..d0232dc0cc Binary files /dev/null and b/TO_MERGE/agm/Optics/data/scopeblack-100_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/scopeblack-70_ca.paa b/TO_MERGE/agm/Optics/data/scopeblack-70_ca.paa new file mode 100644 index 0000000000..62b06d7f84 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/scopeblack-70_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/scopeblack-80_ca.paa b/TO_MERGE/agm/Optics/data/scopeblack-80_ca.paa new file mode 100644 index 0000000000..f74e3e41f1 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/scopeblack-80_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/scopeblack-90_ca.paa b/TO_MERGE/agm/Optics/data/scopeblack-90_ca.paa new file mode 100644 index 0000000000..2240dcc5fe Binary files /dev/null and b/TO_MERGE/agm/Optics/data/scopeblack-90_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/sos/sos-bodyNight_ca.paa b/TO_MERGE/agm/Optics/data/sos/sos-bodyNight_ca.paa new file mode 100644 index 0000000000..22f008b17a Binary files /dev/null and b/TO_MERGE/agm/Optics/data/sos/sos-bodyNight_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/sos/sos-body_ca.paa b/TO_MERGE/agm/Optics/data/sos/sos-body_ca.paa new file mode 100644 index 0000000000..37c6d47d63 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/sos/sos-body_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/sos/sos-reticleMLRIllum_ca.paa b/TO_MERGE/agm/Optics/data/sos/sos-reticleMLRIllum_ca.paa new file mode 100644 index 0000000000..65d0afb2e2 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/sos/sos-reticleMLRIllum_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/sos/sos-reticleMLR_ca.paa b/TO_MERGE/agm/Optics/data/sos/sos-reticleMLR_ca.paa new file mode 100644 index 0000000000..48bc7f4e00 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/sos/sos-reticleMLR_ca.paa differ diff --git a/TO_MERGE/agm/Optics/data/tmr_optics_reticle100.p3d b/TO_MERGE/agm/Optics/data/tmr_optics_reticle100.p3d new file mode 100644 index 0000000000..365c9d5555 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/tmr_optics_reticle100.p3d differ diff --git a/TO_MERGE/agm/Optics/data/tmr_optics_reticle70.p3d b/TO_MERGE/agm/Optics/data/tmr_optics_reticle70.p3d new file mode 100644 index 0000000000..cbb0181a17 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/tmr_optics_reticle70.p3d differ diff --git a/TO_MERGE/agm/Optics/data/tmr_optics_reticle80.p3d b/TO_MERGE/agm/Optics/data/tmr_optics_reticle80.p3d new file mode 100644 index 0000000000..cbb0181a17 Binary files /dev/null and b/TO_MERGE/agm/Optics/data/tmr_optics_reticle80.p3d differ diff --git a/TO_MERGE/agm/Optics/data/tmr_optics_reticle90.p3d b/TO_MERGE/agm/Optics/data/tmr_optics_reticle90.p3d new file mode 100644 index 0000000000..c2f1ae5ceb Binary files /dev/null and b/TO_MERGE/agm/Optics/data/tmr_optics_reticle90.p3d differ diff --git a/TO_MERGE/agm/Optics/data/tmr_reticle_clear.p3d b/TO_MERGE/agm/Optics/data/tmr_reticle_clear.p3d new file mode 100644 index 0000000000..89a29d7d8c Binary files /dev/null and b/TO_MERGE/agm/Optics/data/tmr_reticle_clear.p3d differ diff --git a/TO_MERGE/agm/Optics/functions/fn_firedEH.sqf b/TO_MERGE/agm/Optics/functions/fn_firedEH.sqf new file mode 100644 index 0000000000..1030fceefd --- /dev/null +++ b/TO_MERGE/agm/Optics/functions/fn_firedEH.sqf @@ -0,0 +1,149 @@ +/* + * Original Author: Taosenai + * Adapted By: KoffeinFlummi + * + * Animates the scope when firing. + * + * Arguments: + * 0: Unit + * 1: Weapon + * 2: Muzzle + * 3: Mode + * 4: Ammo + * 5: Magazine + * 6: Projectile + * + * Return Value: + * None + */ + +if (_this select 0 != AGM_player) exitwith {}; // Sanity check + +0 = _this spawn { + disableSerialization; + + _weaponType = _this select 1; + _config = configFile >> "CfgWeapons" >> _weaponType; + _scope = uiNameSpace getVariable "AGM_Optics_Scope"; + + // @todo + _recoilMulti = getNumber (_config >> "tmr_smallarms_recoil_shakeMultiplier"); // Will be 0 if undefined + + if (_recoilMulti == 0) then { + _recoilMulti = 1; + }; + if (_recoilMulti > 2.6) then { + _recoilMulti = 2.6; // Don't get too high + }; + + // Reduce the reticle movement as the player drops into lower, supported stances. + _detectStance = (player selectionPosition "Neck" select 2); + if (_detectStance < 1.3) then { + _recoilMulti = _recoilMulti - 0.10; + }; + if (_detectStance < 0.7) then { + _recoilMulti = _recoilMulti - 0.20; + }; + + // Reduce reticle movement if the player is rested (tmr_autorest). + if (player getVariable ["tmr_autorest_rested", false]) then { + _recoilMulti = _recoilMulti - 0.20; + }; + + // Reduce reticle movement if the player is deployed (tmr_autorest). + if (player getVariable ["tmr_autorest_deployed", false]) then { + _recoilMulti = _recoilMulti - 0.30; + }; + _recoilMulti = 1; + // @endtodo + + + // Constants which determine how the scope recoils + _recoilScope = 0.03 * _recoilMulti + random 0.0015; + _recoilRing = 0.03 * _recoilMulti + random 0.0015; + + _randomScopeShiftX = 0.005 * _recoilMulti - random 0.011; + + _randomReticleShiftX = 0.0036 * _recoilMulti + random 0.0045; // Always tend up and right; + _randomReticleShiftY = -0.0046 * _recoilMulti - random 0.0055; + + ///////// + // Center everything + + // getResolution select 4 should return the aspect ratio, but it's totally wrong + // for triple head displays. We'll compute it manually. + _aspectRatio = (getResolution select 0) / (getResolution select 1); + + _reticleX = (SafeZoneXAbs + SafeZoneWAbs/2 - (SafeZoneWAbs / _aspectRatio)/2); + _reticleY = SafeZoneY; + _reticleW = SafeZoneWAbs / _aspectRatio; + _reticleH = SafeZoneH; + + // Reticle + (_scope displayCtrl 1) ctrlSetPosition [_reticleX, _reticleY, _reticleW, _reticleH]; + // Reticle night (illum) + (_scope displayCtrl 2) ctrlSetPosition [_reticleX, _reticleY, _reticleW, _reticleH]; + + _bodyX = (SafeZoneXAbs + SafeZoneWAbs/2 - (SafeZoneWAbs / _aspectRatio)); + _bodyY = SafeZoneY - (SafeZoneH/2); + _bodyW = SafeZoneWAbs / _aspectRatio * 2; + _bodyH = SafeZoneH * 2; + + // Body night + (_scope displayCtrl 5) ctrlSetPosition [_bodyX, _bodyY, _bodyW, _bodyH]; + // Body + (_scope displayCtrl 6) ctrlSetPosition [_bodyX, _bodyY, _bodyW, _bodyH]; + + _centerDelay = 0.01; + (_scope displayCtrl 1) ctrlCommit _centerDelay; + (_scope displayCtrl 2) ctrlCommit _centerDelay; + (_scope displayCtrl 5) ctrlCommit _centerDelay; + (_scope displayCtrl 6) ctrlCommit _centerDelay; + + ///////// + // Create and commit recoil effect + + // Move reticle + + (_scope displayCtrl 1) ctrlSetPosition [_reticleX - (_recoilScope/2) + _randomReticleShiftX, _reticleY - (_recoilScope/2) + _randomReticleShiftY, _reticleW + _recoilScope, _reticleH + _recoilScope]; + (_scope displayCtrl 2) ctrlSetPosition [_reticleX - (_recoilScope/2) + _randomReticleShiftX, _reticleY - (_recoilScope/2) + _randomReticleShiftY, _reticleW + _recoilScope, _reticleH + _recoilScope]; + + // Move body + + (_scope displayCtrl 5) ctrlSetPosition [_bodyX - (_recoilScope/2) + _randomScopeShiftX, _bodyY - (_recoilScope/2), _bodyW + _recoilScope, _bodyH + _recoilScope]; + (_scope displayCtrl 6) ctrlSetPosition [_bodyX - (_recoilScope/2) + _randomScopeShiftX, _bodyY - (_recoilScope/2), _bodyW + _recoilScope, _bodyH + _recoilScope]; + + _recoilDelay = 0.036; + _fa = false; + _cwm = currentWeaponMode player; + if (_cwm == "FullAuto" || _cwm == "manual" || _cwm == "Burst") then { + _recoilDelay = getNumber (_config >> _cwm >> "reloadTime")/2.2; + _fa = true; + }; + (_scope displayCtrl 1) ctrlCommit _recoilDelay; + (_scope displayCtrl 2) ctrlCommit _recoilDelay; + (_scope displayCtrl 5) ctrlCommit _recoilDelay; + (_scope displayCtrl 6) ctrlCommit _recoilDelay; + + ////////////// + + waituntil {sleep 0.01; ctrlCommitted (_scope displayCtrl 6)}; + + ////////////// + + ////// + // Bring them all back + (_scope displayCtrl 1) ctrlSetPosition [_reticleX, _reticleY, _reticleW, _reticleH]; + (_scope displayCtrl 2) ctrlSetPosition [_reticleX, _reticleY, _reticleW, _reticleH]; + (_scope displayCtrl 5) ctrlSetPosition [_bodyX, _bodyY, _bodyW, _bodyH]; + (_scope displayCtrl 6) ctrlSetPosition [_bodyX, _bodyY, _bodyW, _bodyH]; + + _recenterDelay = 0.09; + if (_fa) then { + _recenterDelay = getNumber (_config >> _cwm >> "reloadTime")/2.2; + }; + (_scope displayCtrl 1) ctrlCommit _recenterDelay; + (_scope displayCtrl 2) ctrlCommit _recenterDelay; + (_scope displayCtrl 5) ctrlCommit _recenterDelay; + (_scope displayCtrl 6) ctrlCommit _recenterDelay; +}; diff --git a/TO_MERGE/agm/Optics/functions/fn_hideScope.sqf b/TO_MERGE/agm/Optics/functions/fn_hideScope.sqf new file mode 100644 index 0000000000..8b048f1bd7 --- /dev/null +++ b/TO_MERGE/agm/Optics/functions/fn_hideScope.sqf @@ -0,0 +1,19 @@ +/* + * Original Author: Taosenai + * Adapted By: KoffeinFlummi + * + * Hides the scope. + * + */ + +private ["_scope"]; + +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 1) ctrlSetTextColor [1,1,1,0]; +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 2) ctrlSetTextColor [1,1,1,0]; +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 5) ctrlSetTextColor [1,1,1,0]; +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 6) ctrlSetTextColor [1,1,1,0]; + +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 1) ctrlCommit 0; +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 2) ctrlCommit 0; +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 5) ctrlCommit 0; +((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 6) ctrlCommit 0; diff --git a/TO_MERGE/agm/Optics/functions/fn_initScope.sqf b/TO_MERGE/agm/Optics/functions/fn_initScope.sqf new file mode 100644 index 0000000000..f2e078ebbe --- /dev/null +++ b/TO_MERGE/agm/Optics/functions/fn_initScope.sqf @@ -0,0 +1,25 @@ +/* + * Original Author: Taosenai + * Adapted By: KoffeinFlummi + * + * Initializes the scope resources. + * + */ + +private ["_display"]; + +// Make sure we only cutRsc when the resource isn't already available +if (isNil {uiNameSpace getVariable "AGM_Optics_Scope"} or {isNull (uiNameSpace getVariable "AGM_Optics_Scope")}) exitWith { + AGM_Optics_scopeRSC cutRsc ["AGM_Optics_Scope","PLAIN",0]; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 1) ctrlSetTextColor [1,1,1,0]; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 2) ctrlSetTextColor [1,1,1,0]; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 5) ctrlSetTextColor [1,1,1,0]; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 6) ctrlSetTextColor [1,1,1,0]; + + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 1) ctrlCommit 0; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 2) ctrlCommit 0; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 5) ctrlCommit 0; + ((uiNameSpace getVariable "AGM_Optics_Scope") displayCtrl 6) ctrlCommit 0; + True +}; +False diff --git a/TO_MERGE/agm/Optics/functions/fn_mainLoop.sqf b/TO_MERGE/agm/Optics/functions/fn_mainLoop.sqf new file mode 100644 index 0000000000..e73b56db37 --- /dev/null +++ b/TO_MERGE/agm/Optics/functions/fn_mainLoop.sqf @@ -0,0 +1,94 @@ +/* + * Original Author: Taosenai + * Adapted By: KoffeinFlummi + * + * Monitors the RscInGameUI and displays the overlays when needed. + * + * Arguments: + * None + * + * Return Value: + * None + */ + +if !(cameraOn == AGM_player && {alive AGM_player} && {!visibleMap} && {ctrlShown ((uinamespace getVariable "AGM_OpticsIGUI") displayCtrl 154)}) exitWith { + // Failed the state check, hide the scope if it's up + if (AGM_Optics_inScope) then { + // Hide the scope + AGM_Optics_inScope = false; + AGM_Optics_inScope_FOV = ([] call cba_fnc_getFOV) select 0; + + [] call AGM_Optics_fnc_hideScope; + }; +}; + +AGM_Optics_Camera setposATL (positioncameratoworld [0,0,0.4]); +AGM_Optics_Camera camPrepareTarget (positioncameratoworld [0,0,50]); +AGM_Optics_Camera camCommitPrepared 0; + +if (cameraView == "Gunner") then { + AGM_Optics_Camera camsetFOV 0.7; + AGM_Optics_Camera camcommit 0; +} else { + AGM_Optics_Camera camsetFOV 0.01; + AGM_Optics_Camera camcommit 0; +}; + +private ["_optic", "_scope"]; + +disableSerialization; + +// Get the name of the attached optic +_optic = (primaryWeaponItems AGM_player) select 2; +_scope = uiNameSpace getVariable "AGM_Optics_Scope"; + +// Init the scope (if needed) +[] call AGM_Optics_fnc_initScope; + +// Check if the optic has changed since we last drew it +_doUpdateAllLayers = false; +if (AGM_Optics_currentOptic != _optic) then { + AGM_Optics_currentOptic = _optic; + _doUpdateAllLayers = true; +}; + +// Check if Splendid Camera, unit switch, etc. has blanked out our displays for no good reason (grrr) +if (ctrlText (_scope displayCtrl 1) == "") then { + _doUpdateAllLayers = true; +}; + +// Draw the correct layers (don't show them) +if (_doUpdateAllLayers) then { + (_scope displayCtrl 1) ctrlSetText getText (configFile >> "CfgWeapons" >> _optic >> "AGM_Optics_reticle"); + (_scope displayCtrl 2) ctrlSetText getText (configFile >> "CfgWeapons" >> _optic >> "AGM_Optics_reticleIllum"); + (_scope displayCtrl 5) ctrlSetText getText (configFile >> "CfgWeapons" >> _optic >> "AGM_Optics_bodyNight"); + (_scope displayCtrl 6) ctrlSetText getText (configFile >> "CfgWeapons" >> _optic >> "AGM_Optics_body"); +}; + +// Stop processing if already in the scope view and FOV hasn't changed +if (AGM_Optics_inScope) exitwith {}; + +// Mark that we're in enhanced scope view +AGM_Optics_inScope = true; + +// Calculate lighting +_lighting = sunOrMoon; // 1 is day, 0 is night + +_nightOpacity = 1; +_dayOpacity = (0 max moonIntensity * (1 - (0 max overcast)))/5; + +if (_lighting == 1) then { + _nightOpacity = 0; + _dayOpacity = 1; +}; + +// Apply lighting and make layers visible +(_scope displayCtrl 1) ctrlSetTextColor [1,1,1,1]; +(_scope displayCtrl 2) ctrlSetTextColor [1,1,1,_nightOpacity]; +(_scope displayCtrl 5) ctrlSetTextColor [1,1,1,_nightOpacity]; +(_scope displayCtrl 6) ctrlSetTextColor [1,1,1,_dayOpacity]; + +(_scope displayCtrl 1) ctrlCommit 0; +(_scope displayCtrl 2) ctrlCommit 0; +(_scope displayCtrl 5) ctrlCommit 0; +(_scope displayCtrl 6) ctrlCommit 0; diff --git a/addons/common/HintConfig.hpp b/addons/common/HintConfig.hpp index 5dc0e6384a..bd74ac510a 100644 --- a/addons/common/HintConfig.hpp +++ b/addons/common/HintConfig.hpp @@ -53,17 +53,6 @@ class RscTitles { }; }; - class ACE_EventHandlerHelper: ACE_Rsc_Display_Base { - idd = -1; - class controls { - class CameraView: RscMapControl { - onDraw = "if (cameraView != uiNamespace getVariable 'ACE_EventHandler_CameraMode') then {uiNamespace setVariable ['ACE_EventHandler_CameraMode', cameraView]; {[uiNamespace getVariable 'ACE_EventHandler_CameraMode'] call _x; nil} count ((missionNamespace getVariable 'ACE_EventHandler_CameraMode') select 2);};"; - idc = -1; - w = 0; - h = 0; - }; - }; - }; class ACE_EventHandlerHelper2: ACE_Rsc_Display_Base { class controls { class MapMarkerCreated: RscMapControl { diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf index de848941fd..39132e0df5 100644 --- a/addons/common/XEH_preInit.sqf +++ b/addons/common/XEH_preInit.sqf @@ -6,9 +6,7 @@ ADDON = false; // ACE Common Function PREP(addActionEventHandler); PREP(addActionMenuEventHandler); -PREP(addCameraEventHandler); PREP(addCanInteractWithCondition); -PREP(addCustomEventHandler); PREP(addLineToDebugDraw); PREP(addMapMarkerCreatedEventHandler); PREP(addScrollWheelEventHandler); @@ -21,8 +19,6 @@ PREP(beingCarried); PREP(binarizeNumber); PREP(blurScreen); PREP(cachedCall); -PREP(callCustomEventHandlers); -PREP(callCustomEventHandlersGlobal); PREP(canGetInPosition); PREP(canInteract); PREP(canInteractWith); @@ -150,9 +146,7 @@ PREP(readSettingFromModule); PREP(receiveRequest); PREP(removeActionEventHandler); PREP(removeActionMenuEventHandler); -PREP(removeCameraEventHandler); PREP(removeCanInteractWithCondition); -PREP(removeCustomEventHandler); PREP(removeMapMarkerCreatedEventHandler); PREP(removeScrollWheelEventHandler); PREP(removeSpecificMagazine); @@ -258,8 +252,6 @@ if (hasInterface) then { ACE_player = missionNamespace getVariable ["BIS_fnc_moduleRemoteControl_unit", player]; uiNamespace setVariable ["ACE_player", ACE_player]; - // Raise custom event. @todo, remove - [missionNamespace, "playerChanged", [ACE_player, _oldPlayer]] call FUNC(callCustomEventHandlers); // Raise ACE event ["playerChanged", [ACE_player, _oldPlayer]] call FUNC(localEvent); }; diff --git a/addons/common/functions/fnc_addCameraEventHandler.sqf b/addons/common/functions/fnc_addCameraEventHandler.sqf deleted file mode 100644 index 45fdb3bdca..0000000000 --- a/addons/common/functions/fnc_addCameraEventHandler.sqf +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Author: commy2 - * - * Add a camera view event handler. The event script is called when the camera view changes. - * The argument of the called function is stored in the _this variable and has as first element the new camera mode. Possible arguments are ["INTERNAL"], ["EXTERNAL"], ["GUNNER"] and ["GROUP"]. - * - * Argument: - * 0: Code to execute (Code or String) - * - * Return value: - * ID of the event script (used to remove it later). - */ -#include "script_component.hpp" - -private ["_statement", "_actionsVar", "_id", "_actionIDs", "_actions"]; - -_statement = _this select 0; - -if (typeName _statement == "STRING") then { - _statement = compile _statement; -}; - -_actionsVar = missionNamespace getVariable ["ACE_EventHandler_CameraMode", [-1, [], []]]; - -_id = (_actionsVar select 0) + 1; -_actionIDs = _actionsVar select 1; -_actions = _actionsVar select 2; - -if (_id == 0) then { - uiNamespace setVariable ["ACE_EventHandler_CameraMode", cameraView]; - (QGVAR(EventHandlerHelper) call BIS_fnc_rscLayer) cutRsc [QGVAR(EventHandlerHelper), "PLAIN"]; -}; - -_actionIDs pushBack _id; -_actions pushBack _statement; - -missionNamespace setVariable ["ACE_EventHandler_CameraMode", [_id, _actionIDs, _actions]]; - -_id diff --git a/addons/common/functions/fnc_addCustomEventHandler.sqf b/addons/common/functions/fnc_addCustomEventHandler.sqf deleted file mode 100644 index e31730dbb3..0000000000 --- a/addons/common/functions/fnc_addCustomEventHandler.sqf +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Author: commy2 - * - * Add a custom event to a unit. The event scripts are called by FUNC(callCustomEventHandlers). - * - * Argument: - * 0: Object the event should be assigned to or namespace (Object OR Namespace) - * 1: Name of the event (String) - * 2: Code to execute (Code or String) - * - * Return value: - * ID of the event script (used to remove it later). - */ -#include "script_component.hpp" - -private ["_object", "_type", "_statement", "_name", "_actionsVar", "_id", "_actionIDs", "_actions"]; - -_object = _this select 0; -_type = _this select 1; -_statement = _this select 2; - -if (typeName _statement == "STRING") then { - _statement = compile _statement; -}; - -_name = format ["ACE_CustomEventHandlers_%1", _type]; - -_actionsVar = _object getVariable [_name, [-1, [], []]]; - -_id = (_actionsVar select 0) + 1; -_actionIDs = _actionsVar select 1; -_actions = _actionsVar select 2; - -_actionIDs pushBack _id; -_actions pushBack _statement; - -_object setVariable [_name, [_id, _actionIDs, _actions]]; - -_id diff --git a/addons/common/functions/fnc_cachedCall.sqf b/addons/common/functions/fnc_cachedCall.sqf index 0c9aafcfc8..03916b8600 100644 --- a/addons/common/functions/fnc_cachedCall.sqf +++ b/addons/common/functions/fnc_cachedCall.sqf @@ -1,6 +1,6 @@ /* * Author: CAA-Picard and Jaynus - * Returns the result of the function and caches it up to a given time + * Returns the result of the function and caches it up to a given time or event * * Arguments: * 0: Parameters @@ -8,6 +8,7 @@ * 2: Namespace to store the cache on * 3: Cache uid * 4: Max duration of the cache + * 5: Event that clears the cache (Optional) * * Return Value: * Result of the function @@ -20,6 +21,40 @@ EXPLODE_5_PVT(_this,_params,_function,_namespace,_uid,_duration); if (((_namespace getVariable [_uid, [-99999]]) select 0) < diag_tickTime) then { _namespace setVariable [_uid, [diag_tickTime + _duration, _params call _function]]; + + // Does the cache needs to be cleared on an event? + if (count _this > 5) then { + private ["_event","_varName","_cacheList"]; + _event = _this select 5; + _varName = format [QGVAR(clearCache_%1),_event]; + _cacheList = missionNamespace getVariable _varName; + + // If there was no EH to clear these caches, add one + if (isNil {_cacheList}) then { + _cacheList = []; + missionNamespace setVariable [_varName, _cacheList]; + + [_event, { + private ["_varName","_cacheList"]; + // _eventName is defined on the function that calls the event + #ifdef DEBUG_MODE_FULL + diag_log text format ["ACE: Clear cached variables on event: %1", _eventName]; + #endif + // Get the list of caches to clear + _varName = format [QGVAR(clearCache_%1),_eventName]; + _cacheList = missionNamespace getVariable [_varName, []]; + // Erase all the cached results + { + _x call FUNC(eraseCache); + } forEach _cacheList; + // Empty the list + missionNamespace setVariable [_varName, []]; + }] call FUNC(addEventhandler); + }; + + // Add this cache to the list of the event + _cacheList pushBack [_namespace, _uid]; + }; #ifdef DEBUG_MODE_FULL diag_log format ["Calculated result: %1 %2", _namespace, _uid]; } else { diff --git a/addons/common/functions/fnc_callCustomEventHandlers.sqf b/addons/common/functions/fnc_callCustomEventHandlers.sqf deleted file mode 100644 index 4b822e0754..0000000000 --- a/addons/common/functions/fnc_callCustomEventHandlers.sqf +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Author: commy2 - * - * Execute all custom event script assigned to this object. - * - * Argument: - * 0: Object the eventhandlers are assigned to or namespace (Object or Namespace) - * 1: Name of the event (String) - * 2: Arguments passed to the eventhandler script (Array, optional default: [Object the event handlers are assigned to]) - * - * Return value: - * None. - */ -#include "script_component.hpp" - -private ["_object", "_type", "_argument", "_name", "_actions"]; - -_object = _this select 0; -_type = _this select 1; -_argument = _this select 2; - -if (isNil "_argument") then {_argument = [_object]}; - -_name = format ["ACE_CustomEventHandlers_%1", _type]; - -_actions = (_object getVariable [_name, [-1, [], []]]) select 2; - -{ - _argument call _x; nil; -} count _actions; -nil diff --git a/addons/common/functions/fnc_callCustomEventHandlersGlobal.sqf b/addons/common/functions/fnc_callCustomEventHandlersGlobal.sqf deleted file mode 100644 index e1dddd5916..0000000000 --- a/addons/common/functions/fnc_callCustomEventHandlersGlobal.sqf +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Author: commy2 - * - * Execute all custom event script assigned to this object on every machine. - * - * Argument: - * 0: Object the eventhandlers are assigned to or namespace (Object or Namespace) - * 1: Name of the event (String) - * 2: Arguments passed to the eventhandler script (Array, optional default: [Object the event handlers are assigned to]) - * - * Return value: - * None. - */ -#include "script_component.hpp" - -[_this, QUOTE(FUNC(callCustomEventHandlers)), 2] call FUNC(execRemoteFnc); diff --git a/addons/common/functions/fnc_canInteractWith.sqf b/addons/common/functions/fnc_canInteractWith.sqf index b74f2092b4..667aec38b3 100644 --- a/addons/common/functions/fnc_canInteractWith.sqf +++ b/addons/common/functions/fnc_canInteractWith.sqf @@ -1,16 +1,16 @@ /* * Author: commy2 - * * Check if the unit can interact. * * Arguments: - * 0: The player. (Object) - * 1: The interaction target. objNull to ignore. (Object) - * 2: Exceptions. What general conditions are to skip? (Array) + * 0: The player. + * 1: The interaction target. objNull to ignore. + * 2: Exceptions. What general conditions are to skip? (Optional) * * Return Value: * Unit can interact? * + * Public: No */ #include "script_component.hpp" @@ -18,7 +18,11 @@ private ["_unit", "_target", "_exceptions"]; _unit = _this select 0; _target = _this select 1; -_exceptions = _this select 2; +_exceptions = if (count _this > 2) then { + _this select 2; +} else { + []; +}; _exceptions = [_exceptions, {toLower _this}] call FUNC(map); diff --git a/addons/common/functions/fnc_progressBar.sqf b/addons/common/functions/fnc_progressBar.sqf index 15fbab1e24..69b91237e6 100644 --- a/addons/common/functions/fnc_progressBar.sqf +++ b/addons/common/functions/fnc_progressBar.sqf @@ -1,24 +1,24 @@ /* -* Author: commy2, Glowbal, PabstMirror -* -* Draw progress bar and execute given function if succesful. -* Finish/Failure/Conditional are all passed [_args, _elapsedTime, _totalTime, _errorCode] -* -* Argument: -* 0: NUMBER - Total Time (in game "time" seconds) -* 1: ARRAY - Arguments, passed to condition, fail and finish -* 2: CODE or STRING - On Finish: Code called or STRING raised as event. -* 3: CODE or STRING - On Failure: Code called or STRING raised as event. -* 4: STRING - (Optional) Localized Title -* 5: CODE - (Optional) Code to check each frame -* 6: ARRAY - (Optional) Exceptions for checking EGVAR(common,canInteractWith) -* -* Return value: -* Nothing -* -* Example: -* [5, [], {Hint "Finished!"}, {hint "Failure!"}, "My Title"] call ace_common_fnc_progressBar -*/ + * Author: commy2, Glowbal, PabstMirror + * + * Draw progress bar and execute given function if succesful. + * Finish/Failure/Conditional are all passed [_args, _elapsedTime, _totalTime, _errorCode] + * + * Argument: + * 0: NUMBER - Total Time (in game "time" seconds) + * 1: ARRAY - Arguments, passed to condition, fail and finish + * 2: CODE or STRING - On Finish: Code called or STRING raised as event. + * 3: CODE or STRING - On Failure: Code called or STRING raised as event. + * 4: STRING - (Optional) Localized Title + * 5: CODE - (Optional) Code to check each frame + * 6: ARRAY - (Optional) Exceptions for checking EFUNC(common,canInteractWith) + * + * Return value: + * Nothing + * + * Example: + * [5, [], {Hint "Finished!"}, {hint "Failure!"}, "My Title"] call ace_common_fnc_progressBar + */ #include "script_component.hpp" @@ -36,65 +36,69 @@ createDialog QGVAR(ProgressBar_Dialog); (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlSetText _localizedTitle; if (GVAR(SettingProgressBarLocation) == 1) then { - private "_ctrlPos"; - _ctrlPos = [1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2), 29 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2), 38 * (((safezoneW / safezoneH) min 1.2) / 40), 0.8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)]; - (uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlSetPosition _ctrlPos; - (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlSetPosition _ctrlPos; - (uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlCommit 0; - (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlCommit 0; + private "_ctrlPos"; + _ctrlPos = [1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2), 29 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2), 38 * (((safezoneW / safezoneH) min 1.2) / 40), 0.8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)]; + (uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlSetPosition _ctrlPos; + (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlSetPosition _ctrlPos; + (uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlCommit 0; + (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlCommit 0; }; _perFrameFunction = { - PARAMS_2(_parameters,_pfhID); - EXPLODE_8_PVT(_parameters,_args,_onFinish,_onFail,_condition,_player,_startTime,_totalTime,_exceptions); - private ["_elapsedTime", "_errorCode"]; + PARAMS_2(_parameters,_pfhID); + EXPLODE_8_PVT(_parameters,_args,_onFinish,_onFail,_condition,_player,_startTime,_totalTime,_exceptions); + private ["_elapsedTime", "_errorCode"]; - _elapsedTime = time - _startTime; - _errorCode = -1; + _elapsedTime = time - _startTime; + _errorCode = -1; - if (isNull (uiNamespace getVariable [QGVAR(ctrlProgressBar), controlNull])) then { - _errorCode = 1; - } else { - if (ACE_player != _player) then { - _errorCode = 2; + if (isNull (uiNamespace getVariable [QGVAR(ctrlProgressBar), controlNull])) then { + _errorCode = 1; } else { - if (!([_args, _elapsedTime, _totalTime, _errorCode] call _condition)) then { - _errorCode = 3; - } else { - if (!([_player, objNull, _exceptions] call EGVAR(common,canInteractWith))) then { - _errorCode = 4; + if (ACE_player != _player) then { + _errorCode = 2; } else { - if (_elapsedTime >= _totalTime) then { - _errorCode = 0; - }; + if (!([_args, _elapsedTime, _totalTime, _errorCode] call _condition)) then { + _errorCode = 3; + } else { + if (!([_player, objNull, _exceptions] call EFUNC(common,canInteractWith))) then { + _errorCode = 4; + } else { + if (_elapsedTime >= _totalTime) then { + _errorCode = 0; + }; + }; + }; }; - }; }; - }; - if (_errorCode != -1) then { - //Error or Success, close dialog and remove PFEH - closeDialog 0; - [_pfhID] call CBA_fnc_removePerFrameHandler; + if (_errorCode != -1) then { + //Error or Success, close dialog and remove PFEH - if (_errorCode == 0) then { - if ((typeName _onFinish) == (typeName "")) then { - [_onFinish, [_args, _elapsedTime, _totalTime, _errorCode]] call FUNC(localEvent); - } else { - [_args, _elapsedTime, _totalTime, _errorCode] call _onFinish; - }; + //Only close dialog if it's the progressBar: + if (!isNull (uiNamespace getVariable [QGVAR(ctrlProgressBar), controlNull])) then { + closeDialog 0; + }; + [_pfhID] call CBA_fnc_removePerFrameHandler; + + if (_errorCode == 0) then { + if ((typeName _onFinish) == (typeName "")) then { + [_onFinish, [_args, _elapsedTime, _totalTime, _errorCode]] call FUNC(localEvent); + } else { + [_args, _elapsedTime, _totalTime, _errorCode] call _onFinish; + }; + } else { + if ((typeName _onFail) == (typeName "")) then { + [_onFail, [_args, _elapsedTime, _totalTime, _errorCode]] call FUNC(localEvent); + } else { + [_args, _elapsedTime, _totalTime, _errorCode] call _onFail; + }; + }; } else { - if ((typeName _onFail) == (typeName "")) then { - [_onFail, [_args, _elapsedTime, _totalTime, _errorCode]] call FUNC(localEvent); - } else { - [_args, _elapsedTime, _totalTime, _errorCode] call _onFail; - }; + //Update Progress Bar (ratio of elepased:total) + (uiNamespace getVariable QGVAR(ctrlProgressBar)) progressSetPosition (_elapsedTime / _totalTime); }; - } else { - //Update Progress Bar (ratio of elepased:total) - (uiNamespace getVariable QGVAR(ctrlProgressBar)) progressSetPosition (_elapsedTime / _totalTime); - }; }; [_perFrameFunction, 0, [_args, _onFinish, _onFail, _condition, _player, time, _totalTime, _exceptions]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/common/functions/fnc_removeCameraEventHandler.sqf b/addons/common/functions/fnc_removeCameraEventHandler.sqf deleted file mode 100644 index 0fe8953078..0000000000 --- a/addons/common/functions/fnc_removeCameraEventHandler.sqf +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Author: commy2 - * - * Remove a camera view event handler. - * - * Argument: - * 0: ID of the event handler (Number) - * - * Return value: - * None. - */ -#include "script_component.hpp" - -private ["_id", "_actionsVar", "_currentId", "_actionIDs", "_actions"]; - -_id = _this select 0; - -_actionsVar = missionNamespace getVariable ["ACE_EventHandler_CameraMode", [-1, [], []]]; - -_currentId = _actionsVar select 0; -_actionIDs = _actionsVar select 1; -_actions = _actionsVar select 2; - -_id = _actionIDs find _id; - -if (_id == -1) exitWith {}; - -_actionIDs set [_id, -1]; -_actionIDs = _actionIDs - [-1]; - -_actions set [_id, []];//{} -_actions = _actions - [[]];//[{}] - -missionNamespace setVariable ["ACE_EventHandler_CameraMode", [_currentId, _actionIDs, _actions]]; diff --git a/addons/common/functions/fnc_removeCustomEventHandler.sqf b/addons/common/functions/fnc_removeCustomEventHandler.sqf deleted file mode 100644 index 771ea9f5bf..0000000000 --- a/addons/common/functions/fnc_removeCustomEventHandler.sqf +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Author: commy2 - * - * Remove a custom event handler from an object. - * - * Argument: - * 0: Unit the event handler is assigned to or namespace (Object OR Namespace) - * 1: Name of the event (String) - * 2: ID of the event handler (Number) - * - * Return value: - * None. - */ -#include "script_component.hpp" - -private ["_object", "_type", "_id", "_name", "_actionsVar", "_currentId", "_actionIDs", "_actions"]; - -_object = _this select 0; -_type = _this select 1; -_id = _this select 2; - -_name = format ["ACE_CustomEventHandlers_%1", _type]; - -_actionsVar = _object getVariable [_name, [-1, [], []]]; - -_currentId = _actionsVar select 0; -_actionIDs = _actionsVar select 1; -_actions = _actionsVar select 2; - -_id = _actionIDs find _id; - -if (_id == -1) exitWith {}; - -_actionIDs set [_id, -1]; -_actionIDs = _actionIDs - [-1]; - -_actions set [_id, []];//{} -_actions = _actions - [[]];//[{}] - -_object setVariable [_name, [_currentId, _actionIDs, _actions]]; diff --git a/addons/disposable/CfgEventHandlers.hpp b/addons/disposable/CfgEventHandlers.hpp index 304f304774..02d0cb625f 100644 --- a/addons/disposable/CfgEventHandlers.hpp +++ b/addons/disposable/CfgEventHandlers.hpp @@ -1,44 +1,44 @@ class Extended_PreInit_EventHandlers { - class ADDON { - init = QUOTE( call COMPILE_FILE(XEH_preInit) ); - }; + class ADDON { + init = QUOTE( call COMPILE_FILE(XEH_preInit) ); + }; }; class Extended_PostInit_EventHandlers { - class ADDON { - clientInit = QUOTE( call COMPILE_FILE(XEH_postInitClient) ); - }; + class ADDON { + clientInit = QUOTE( call COMPILE_FILE(XEH_postInitClient) ); + }; }; class Extended_FiredBIS_EventHandlers { - class CAManBase { - class ADDON { - firedBIS = QUOTE( _this call FUNC(replaceATWeapon) ); + class CAManBase { + class ADDON { + firedBIS = QUOTE( _this call FUNC(replaceATWeapon) ); + }; }; - }; }; // handle preloaded missile class Extended_Init_EventHandlers { - class CAManBase { - class ADDON { - init = QUOTE( _this call FUNC(takeLoadedATWeapon) ); + class CAManBase { + class ADDON { + init = QUOTE( _this call FUNC(takeLoadedATWeapon) ); + }; }; - }; }; class Extended_Take_EventHandlers { - class CAManBase { - class ADDON { - take = QUOTE( _this call FUNC(takeLoadedATWeapon); [_this select 0] call FUNC(updateInventoryDisplay); ); + class CAManBase { + class ADDON { + take = QUOTE( _this call FUNC(takeLoadedATWeapon); [_this select 0] call FUNC(updateInventoryDisplay); ); + }; }; - }; }; class Extended_Put_EventHandlers { - class CAManBase { - class ADDON { - put = QUOTE( [_this select 0] call FUNC(updateInventoryDisplay); ); + class CAManBase { + class ADDON { + put = QUOTE( [_this select 0] call FUNC(updateInventoryDisplay); ); + }; }; - }; }; diff --git a/addons/disposable/CfgMagazines.hpp b/addons/disposable/CfgMagazines.hpp index 993d53f46c..8fbae08dfd 100644 --- a/addons/disposable/CfgMagazines.hpp +++ b/addons/disposable/CfgMagazines.hpp @@ -1,24 +1,24 @@ class CfgMagazines { - class NLAW_F; - class ACE_PreloadedMissileDummy: NLAW_F { // The dummy magazine - author = "$STR_ACE_Common_ACETeam"; - scope = 1; - displayName = "$STR_ACE_Disposable_PreloadedMissileDummy"; - picture = PATHTOEF(common,UI\blank_CO.paa); - weaponPoolAvailable = 0; - mass = 0; - }; - class ACE_FiredMissileDummy: ACE_PreloadedMissileDummy { - count = 0; - }; - class ACE_UsedTube_F: NLAW_F { - author = "$STR_ACE_Common_ACETeam"; - displayName = "$STR_ACE_Disposable_UsedTube"; - descriptionShort = "$STR_ACE_Disposable_UsedTubeDescription"; - displayNameShort = "-"; - count = 0; - weaponPoolAvailable = 0; - modelSpecial = ""; - mass = 0; - }; + class NLAW_F; + class ACE_PreloadedMissileDummy: NLAW_F { // The dummy magazine + author = "$STR_ACE_Common_ACETeam"; + scope = 1; + displayName = "$STR_ACE_Disposable_PreloadedMissileDummy"; + picture = PATHTOEF(common,UI\blank_CO.paa); + weaponPoolAvailable = 0; + mass = 0; + }; + class ACE_FiredMissileDummy: ACE_PreloadedMissileDummy { + count = 0; + }; + class ACE_UsedTube_F: NLAW_F { + author = "$STR_ACE_Common_ACETeam"; + displayName = "$STR_ACE_Disposable_UsedTube"; + descriptionShort = "$STR_ACE_Disposable_UsedTubeDescription"; + displayNameShort = "-"; + count = 0; + weaponPoolAvailable = 0; + modelSpecial = ""; + mass = 0; + }; }; diff --git a/addons/disposable/CfgVehicles.hpp b/addons/disposable/CfgVehicles.hpp index b3b9436484..13d4cedf4b 100644 --- a/addons/disposable/CfgVehicles.hpp +++ b/addons/disposable/CfgVehicles.hpp @@ -1,146 +1,146 @@ class CfgVehicles { - #define MACRO_NONLAW \ - class TransportMagazines { \ - class _xx_NLAW_F { \ - count = 0; \ - }; \ +#define MACRO_NONLAW \ + class TransportMagazines { \ + class _xx_NLAW_F { \ + count = 0; \ + }; \ + }; + + class ReammoBox_F; + class NATO_Box_Base: ReammoBox_F {}; + class Box_NATO_Ammo_F: NATO_Box_Base { + MACRO_NONLAW + }; + class Box_NATO_WpsLaunch_F: NATO_Box_Base { + MACRO_NONLAW }; - class ReammoBox_F; - class NATO_Box_Base: ReammoBox_F {}; - class Box_NATO_Ammo_F: NATO_Box_Base { - MACRO_NONLAW - }; - class Box_NATO_WpsLaunch_F: NATO_Box_Base { - MACRO_NONLAW - }; + class IND_Box_Base: ReammoBox_F {}; + class Box_IND_WpsLaunch_F: IND_Box_Base { + MACRO_NONLAW + }; + class Box_IND_Ammo_F: IND_Box_Base { + MACRO_NONLAW + }; - class IND_Box_Base: ReammoBox_F {}; - class Box_IND_WpsLaunch_F: IND_Box_Base { - MACRO_NONLAW - }; - class Box_IND_Ammo_F: IND_Box_Base { - MACRO_NONLAW - }; + class B_supplyCrate_F: ReammoBox_F { + MACRO_NONLAW + }; + class I_supplyCrate_F: B_supplyCrate_F { + MACRO_NONLAW + }; + class C_supplyCrate_F: ReammoBox_F { + MACRO_NONLAW + }; - class B_supplyCrate_F: ReammoBox_F { - MACRO_NONLAW - }; - class I_supplyCrate_F: B_supplyCrate_F { - MACRO_NONLAW - }; - class C_supplyCrate_F: ReammoBox_F { - MACRO_NONLAW - }; + class B_AssaultPack_rgr; + class B_AssaultPack_rgr_LAT: B_AssaultPack_rgr { + MACRO_NONLAW + }; + class B_AssaultPack_rgr_ReconLAT: B_AssaultPack_rgr { + MACRO_NONLAW + }; - class B_AssaultPack_rgr; - class B_AssaultPack_rgr_LAT: B_AssaultPack_rgr { - MACRO_NONLAW - }; - class B_AssaultPack_rgr_ReconLAT: B_AssaultPack_rgr { - MACRO_NONLAW - }; + class B_Carryall_mcamo; + class B_AssaultPack_mcamo_Ammo: B_Carryall_mcamo { + MACRO_NONLAW + }; + class B_Carryall_oli; + class I_Fieldpack_oli_Ammo: B_Carryall_oli { + MACRO_NONLAW + }; - class B_Carryall_mcamo; - class B_AssaultPack_mcamo_Ammo: B_Carryall_mcamo { - MACRO_NONLAW - }; - class B_Carryall_oli; - class I_Fieldpack_oli_Ammo: B_Carryall_oli { - MACRO_NONLAW - }; + class B_AssaultPack_dgtl; + class I_Fieldpack_oli_LAT: B_AssaultPack_dgtl { + MACRO_NONLAW + }; - class B_AssaultPack_dgtl; - class I_Fieldpack_oli_LAT: B_AssaultPack_dgtl { - MACRO_NONLAW - }; + class CargoNet_01_ammo_base_F; + class B_CargoNet_01_ammo_F: CargoNet_01_ammo_base_F { + MACRO_NONLAW + }; + class I_CargoNet_01_ammo_F: CargoNet_01_ammo_base_F { + MACRO_NONLAW + }; - class CargoNet_01_ammo_base_F; - class B_CargoNet_01_ammo_F: CargoNet_01_ammo_base_F { - MACRO_NONLAW - }; - class I_CargoNet_01_ammo_F: CargoNet_01_ammo_base_F { - MACRO_NONLAW - }; + class Slingload_01_Base_F; + class B_Slingload_01_Cargo_F: Slingload_01_Base_F { + MACRO_NONLAW + }; - class Slingload_01_Base_F; - class B_Slingload_01_Cargo_F: Slingload_01_Base_F { + class Tank_F; + class APC_Tracked_01_base_F: Tank_F { + MACRO_NONLAW + }; + /*class B_APC_Tracked_01_base_F: APC_Tracked_01_base_F { MACRO_NONLAW - }; - - class Tank_F; - class APC_Tracked_01_base_F: Tank_F { - MACRO_NONLAW - }; - /*class B_APC_Tracked_01_base_F: APC_Tracked_01_base_F { - MACRO_NONLAW - }; - class B_APC_Tracked_01_rcws_F: B_APC_Tracked_01_base_F { - MACRO_NONLAW - }; - class B_APC_Tracked_01_CRV_F: B_APC_Tracked_01_base_F { - MACRO_NONLAW - }; - class B_APC_Tracked_01_AA_F: B_APC_Tracked_01_base_F { - MACRO_NONLAW - };*/ - - class Car_F; - class MRAP_01_base_F: Car_F { - MACRO_NONLAW - }; - /*class MRAP_01_gmg_base_F: MRAP_01_base_F { - MACRO_NONLAW - }; - class MRAP_01_hmg_base_F: MRAP_01_gmg_base_F { - MACRO_NONLAW - }; - class B_MRAP_01_F: MRAP_01_base_F { - MACRO_NONLAW - }; - class B_MRAP_01_gmg_F: MRAP_01_gmg_base_F { - MACRO_NONLAW - }; - class B_MRAP_01_hmg_F: MRAP_01_hmg_base_F { - MACRO_NONLAW - };*/ - - class MRAP_03_base_F: Car_F { - MACRO_NONLAW - }; - /*class MRAP_03_hmg_base_F: MRAP_03_base_F { - MACRO_NONLAW - }; - class MRAP_03_gmg_base_F: MRAP_03_hmg_base_F { - MACRO_NONLAW - }; - class I_MRAP_03_F: MRAP_03_base_F { - MACRO_NONLAW - }; - class I_MRAP_03_hmg_F: MRAP_03_hmg_base_F { - MACRO_NONLAW - }; - class I_MRAP_03_gmg_F: MRAP_03_gmg_base_F { - MACRO_NONLAW - };*/ - - class Wheeled_APC_F: Car_F {}; - class APC_Wheeled_03_base_F: Wheeled_APC_F { - MACRO_NONLAW - }; - class APC_Wheeled_01_base_F: Wheeled_APC_F { - MACRO_NONLAW - }; - /*class B_APC_Wheeled_01_base_F: APC_Wheeled_01_base_F { - MACRO_NONLAW - }; - class B_APC_Wheeled_01_cannon_F: B_APC_Wheeled_01_base_F { - MACRO_NONLAW - }; - class I_APC_Wheeled_03_base_F: APC_Wheeled_03_base_F { - MACRO_NONLAW - }; - class I_APC_Wheeled_03_cannon_F: I_APC_Wheeled_03_base_F { - MACRO_NONLAW - };*/ +}; +class B_APC_Tracked_01_rcws_F: B_APC_Tracked_01_base_F { + MACRO_NONLAW +}; +class B_APC_Tracked_01_CRV_F: B_APC_Tracked_01_base_F { + MACRO_NONLAW +}; +class B_APC_Tracked_01_AA_F: B_APC_Tracked_01_base_F { + MACRO_NONLAW +};*/ + + class Car_F; + class MRAP_01_base_F: Car_F { + MACRO_NONLAW + }; + /*class MRAP_01_gmg_base_F: MRAP_01_base_F { + MACRO_NONLAW +}; +class MRAP_01_hmg_base_F: MRAP_01_gmg_base_F { + MACRO_NONLAW +}; +class B_MRAP_01_F: MRAP_01_base_F { + MACRO_NONLAW +}; +class B_MRAP_01_gmg_F: MRAP_01_gmg_base_F { + MACRO_NONLAW +}; +class B_MRAP_01_hmg_F: MRAP_01_hmg_base_F { + MACRO_NONLAW +};*/ + + class MRAP_03_base_F: Car_F { + MACRO_NONLAW + }; + /*class MRAP_03_hmg_base_F: MRAP_03_base_F { + MACRO_NONLAW +}; +class MRAP_03_gmg_base_F: MRAP_03_hmg_base_F { + MACRO_NONLAW +}; +class I_MRAP_03_F: MRAP_03_base_F { + MACRO_NONLAW +}; +class I_MRAP_03_hmg_F: MRAP_03_hmg_base_F { + MACRO_NONLAW +}; +class I_MRAP_03_gmg_F: MRAP_03_gmg_base_F { + MACRO_NONLAW +};*/ + + class Wheeled_APC_F: Car_F {}; + class APC_Wheeled_03_base_F: Wheeled_APC_F { + MACRO_NONLAW + }; + class APC_Wheeled_01_base_F: Wheeled_APC_F { + MACRO_NONLAW + }; + /*class B_APC_Wheeled_01_base_F: APC_Wheeled_01_base_F { + MACRO_NONLAW +}; +class B_APC_Wheeled_01_cannon_F: B_APC_Wheeled_01_base_F { + MACRO_NONLAW +}; +class I_APC_Wheeled_03_base_F: APC_Wheeled_03_base_F { + MACRO_NONLAW +}; +class I_APC_Wheeled_03_cannon_F: I_APC_Wheeled_03_base_F { + MACRO_NONLAW +};*/ }; diff --git a/addons/disposable/CfgWeapons.hpp b/addons/disposable/CfgWeapons.hpp index 4bd36ce3ed..965d97521c 100644 --- a/addons/disposable/CfgWeapons.hpp +++ b/addons/disposable/CfgWeapons.hpp @@ -1,18 +1,18 @@ class CfgWeapons { - class Launcher_Base_F; - class launch_NLAW_F: Launcher_Base_F { - ACE_UsedTube = "ACE_launch_NLAW_Used_F"; // The class name of the used tube. - magazines[] = {"ACE_PreloadedMissileDummy"}; // The dummy magazine - }; - class ACE_launch_NLAW_Used_F: launch_NLAW_F { // the used tube should be a sub class of the disposable launcher - scope = 1; - ACE_isUsedLauncher = 1; - author = "$STR_ACE_Common_ACETeam"; - displayName = "$STR_ACE_Disposable_UsedTube"; - descriptionShort = "$STR_ACE_Disposable_UsedTubeDescription"; - magazines[] = {"ACE_FiredMissileDummy"}; // This will disable the used launcher class from being fired again. - //picture = ""; @todo - //model = ""; @todo - weaponPoolAvailable = 0; - }; + class Launcher_Base_F; + class launch_NLAW_F: Launcher_Base_F { + ACE_UsedTube = "ACE_launch_NLAW_Used_F"; // The class name of the used tube. + magazines[] = {"ACE_PreloadedMissileDummy"}; // The dummy magazine + }; + class ACE_launch_NLAW_Used_F: launch_NLAW_F { // the used tube should be a sub class of the disposable launcher + scope = 1; + ACE_isUsedLauncher = 1; + author = "$STR_ACE_Common_ACETeam"; + displayName = "$STR_ACE_Disposable_UsedTube"; + descriptionShort = "$STR_ACE_Disposable_UsedTubeDescription"; + magazines[] = {"ACE_FiredMissileDummy"}; // This will disable the used launcher class from being fired again. + //picture = ""; @todo + //model = ""; @todo + weaponPoolAvailable = 0; + }; }; diff --git a/addons/disposable/README.md b/addons/disposable/README.md index 7dd85fff32..73418cd49d 100644 --- a/addons/disposable/README.md +++ b/addons/disposable/README.md @@ -1,7 +1,7 @@ ace_disposable ============== -Makes the NLAW a disposable one-way weapon. +Makes the NLAW a disposable one-shot weapon. ## Maintainers diff --git a/addons/disposable/XEH_postInitClient.sqf b/addons/disposable/XEH_postInitClient.sqf index 17911f5da5..1fe598137f 100644 --- a/addons/disposable/XEH_postInitClient.sqf +++ b/addons/disposable/XEH_postInitClient.sqf @@ -4,10 +4,8 @@ #include "script_component.hpp" -if (isNil QGVAR(UpdateInventoryDisplay_EHID)) then { - GVAR(UpdateInventoryDisplay_EHID) = ["inventoryDisplayLoaded",{ +["inventoryDisplayLoaded",{ _player = ACE_player; - [_player, secondaryWeapon _player] call FUNC(takeLoadedATWeapon); + [_player] call FUNC(takeLoadedATWeapon); [_player, (_this select 0)] call FUNC(updateInventoryDisplay); - }] call EFUNC(common,addEventHandler); -}; +}] call EFUNC(common,addEventHandler); \ No newline at end of file diff --git a/addons/disposable/XEH_preInit.sqf b/addons/disposable/XEH_preInit.sqf index 26543c369a..020187b730 100644 --- a/addons/disposable/XEH_preInit.sqf +++ b/addons/disposable/XEH_preInit.sqf @@ -2,7 +2,6 @@ ADDON = false; -PREP(aiDropWeaponCallback); PREP(replaceATWeapon); PREP(takeLoadedATWeapon); PREP(updateInventoryDisplay); diff --git a/addons/disposable/config.cpp b/addons/disposable/config.cpp index be2b52735a..0f256824d7 100644 --- a/addons/disposable/config.cpp +++ b/addons/disposable/config.cpp @@ -1,15 +1,15 @@ #include "script_component.hpp" class CfgPatches { - class ADDON { - units[] = {}; - weapons[] = {}; - requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ace_common"}; - author[] = {"commy2"}; - authorUrl = "https://github.com/commy2/"; - VERSION_CONFIG; - }; + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common"}; + author[] = {"commy2"}; + authorUrl = "https://github.com/commy2/"; + VERSION_CONFIG; + }; }; #include "CfgEventHandlers.hpp" diff --git a/addons/disposable/functions/fnc_aiDropWeaponCallback.sqf b/addons/disposable/functions/fnc_aiDropWeaponCallback.sqf deleted file mode 100644 index f6947f7e44..0000000000 --- a/addons/disposable/functions/fnc_aiDropWeaponCallback.sqf +++ /dev/null @@ -1,32 +0,0 @@ -/* -* Author: bux, commy2 -* -* Remove the ai's missle launcher tube -* -* Return value: -* Nothing -*/ - -#include "script_component.hpp" - -private ["_unit", "_tube", "_projectile", "_logic"]; - -_unit = (_this select 0) select 0; -_tube = (_this select 0) select 1; -_projectile = (_this select 0) select 2; - -if (!isNull _projectile) exitWith {}; - -//remove frameEH -[(_this select 1)] call cba_fnc_removePerFrameHandler; - -if ([_unit] call EFUNC(common,isPlayer)) exitWith {}; //Just in case a player took control -if (!alive _unit) exitWith {}; //No point doing this for dead - -//If AI still has tube, throw it on ground -if (secondaryWeapon _unit == _tube) then { - _logic = createVehicle ["GroundWeaponHolder", position _unit, [], 0, "CAN_COLLIDE"]; - _logic addWeaponCargoGlobal [_tube, 1]; // @todo secondary weapon items - - _unit removeWeaponGlobal _tube; -}; diff --git a/addons/disposable/functions/fnc_replaceATWeapon.sqf b/addons/disposable/functions/fnc_replaceATWeapon.sqf index ea107d1643..8c55209123 100644 --- a/addons/disposable/functions/fnc_replaceATWeapon.sqf +++ b/addons/disposable/functions/fnc_replaceATWeapon.sqf @@ -1,38 +1,79 @@ /* - * Author: commy2 - * + * Author: bux, commy2 * Replace the disposable launcher with the used dummy. - * - * Argument: - * Input from "Fired" eventhandler - * - * Return value: + * + * Arguments: + * 0: unit - Object the event handler is assigned to + * 1: weapon - Fired weapon + * 2: muzzle - Muzzle that was used + * 3: mode - Current mode of the fired weapon + * 4: ammo - Ammo used + * 5: magazine - magazine name which was used + * 6: projectile - Object of the projectile that was shot + * + * Return Value: * Nothing + * + * Example: + * [fromBisFiredEH] call ace_disposable_fnc_replaceATWeapon; + * + * Public: No */ - #include "script_component.hpp" -private ["_unit", "_tube", "_projectile"]; +private ["_unit", "_weapon", "_projectile", "_replacementTube", "_items"]; _unit = _this select 0; -_tube = getText (configFile >> "CfgWeapons" >> (_this select 1) >> "ACE_UsedTube"); +_weapon = _this select 1; _projectile = _this select 6; if (!local _unit) exitWith {}; -if (_tube == "") exitWith {}; -private "_items"; +_replacementTube = getText (configFile >> "CfgWeapons" >> _weapon >> "ACE_UsedTube"); +if (_replacementTube == "") exitWith {}; //If no replacement defined just exit +if (_weapon != (secondaryWeapon _unit)) exitWith {}; //just to be sure + +//Save array of items attached to launcher _items = secondaryWeaponItems _unit; - -_unit addWeapon _tube; -_unit selectWeapon _tube; +//Replace the orginal weapon with the 'usedTube' weapon +_unit addWeapon _replacementTube; +//Makes sure the used tube is still equiped +_unit selectWeapon _replacementTube; +//Re-add all attachments to the used tube { - if (_x != "") then {_unit addSecondaryWeaponItem _x}; + if (_x != "") then {_unit addSecondaryWeaponItem _x}; } forEach _items; -// AI + +// AI - Remove the ai's missle launcher tube after the missle has exploded if !([_unit] call EFUNC(common,isPlayer)) then { - //waits until _projectile is null, so random 0-2 tickTime seconds after that - [FUNC(aiDropWeaponCallback), 2, [_unit, _tube, _projectile]] call CBA_fnc_addPerFrameHandler; + [{ + EXPLODE_2_PVT(_this,_params,_pfhId); + EXPLODE_3_PVT(_params,_unit,_tube,_projectile); + + //don't do anything until projectile is null (exploded/max range) + if (isNull _projectile) then { + //Remove PFEH: + [_pfhId] call cba_fnc_removePerFrameHandler; + + //If (tube is dropped) OR (is dead) OR (is player) just exit + if (((secondaryWeapon _unit) != _tube) || {!alive _unit} || {([_unit] call EFUNC(common,isPlayer))}) exitWith {}; + + private ["_items", "_container"]; + + // _items = secondaryWeaponItems _unit; + _container = createVehicle ["GroundWeaponHolder", position _unit, [], 0, "CAN_COLLIDE"]; + _container setPosAsl (getPosAsl _unit); + _container addWeaponCargoGlobal [_tube, 1]; + + //This will duplicate attachements, because we will be adding a weapon that may already have attachments on it + //We either need a way to add a clean weapon, or a way to add a fully configured weapon to a container: + // { + // if (_x != "") then {_container addItemCargoGlobal [_x, 1];}; + // } forEach _items; + + _unit removeWeaponGlobal _tube; + }; + }, 1, [_unit, _replacementTube, _projectile]] call CBA_fnc_addPerFrameHandler; }; diff --git a/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf b/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf index ea1b1fb379..de3875dfa0 100644 --- a/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf +++ b/addons/disposable/functions/fnc_takeLoadedATWeapon.sqf @@ -1,48 +1,50 @@ /* * Author: commy2 - * * Handle the take event. Add a dummy magazine if a disposable rocket launcher is taken. - * - * Argument: - * Input from "Take" eventhandler - * - * Return value: - * Nothing + * + * Arguments: + * 0: unit - Object the event handler is assigned to + * + * Return Value: + * None + * + * Example: + * [fromTakeEH] call ace_disposable_fnc_takeLoadedATWeapon; + * + * Public: No */ - #include "script_component.hpp" private ["_unit", "_launcher", "_config"]; -_unit = _this select 0; -_launcher = secondaryWeapon _unit; - +PARAMS_1(_unit); if (!local _unit) exitWith {}; +_launcher = secondaryWeapon _unit; _config = configFile >> "CfgWeapons" >> _launcher; if (isClass _config && {getText (_config >> "ACE_UsedTube") != ""} && {getNumber (_config >> "ACE_isUsedLauncher") != 1} && {count secondaryWeaponMagazine _unit == 0}) then { - private ["_magazine", "_isLauncherSelected"]; + private ["_magazine", "_isLauncherSelected"]; - _magazine = getArray (_config >> "magazines") select 0; + _magazine = getArray (_config >> "magazines") select 0; - _isLauncherSelected = currentWeapon _unit == _launcher; + _isLauncherSelected = currentWeapon _unit == _launcher; - _unit removeMagazines _magazine; + _unit removeMagazines _magazine; - if (backpack _unit == "") then { - _unit addBackpack "Bag_Base"; + if (backpack _unit == "") then { + _unit addBackpack "Bag_Base"; - _unit addMagazine _magazine; - _unit addWeapon _launcher; + _unit addMagazine _magazine; + _unit addWeapon _launcher; - removeBackpack _unit; - } else { - _unit addMagazine _magazine; - _unit addWeapon _launcher; - }; + removeBackpack _unit; + } else { + _unit addMagazine _magazine; + _unit addWeapon _launcher; + }; - if (_isLauncherSelected) then { - _unit selectWeapon _launcher; - }; + if (_isLauncherSelected) then { + _unit selectWeapon _launcher; + }; }; diff --git a/addons/disposable/functions/fnc_updateInventoryDisplay.sqf b/addons/disposable/functions/fnc_updateInventoryDisplay.sqf index f33ed0dc73..3f9d6f9802 100644 --- a/addons/disposable/functions/fnc_updateInventoryDisplay.sqf +++ b/addons/disposable/functions/fnc_updateInventoryDisplay.sqf @@ -1,26 +1,28 @@ /* * Author: bux, commy2 - * * Hide or show the secondary weapon magazine inventory slot to prevent unloading of dummy magazines. - * - * Argument: - * 0: The player. (Object) - * - * Return value: - * Nothing + * + * Arguments: + * 0: unit - Object the event handler is assigned to + * + * Return Value: + * None + * + * Example: + * [player] call ace_disposable_fnc_updateInventoryDisplay; + * + * Public: No */ - #include "script_component.hpp" -private ["_player", "_display"]; +disableSerialization; -_player = _this select 0; +PARAMS_1(_player); +DEFAULT_PARAM(1,_display,(findDisplay 602)); _player removeMagazines "ACE_PreloadedMissileDummy"; _player removeMagazines "ACE_FiredMissileDummy"; -disableSerialization; -_display = [_this, 1, (findDisplay 602)] call BIS_fnc_param; if (isNull _display) exitWith {}; private ["_launcher", "_control", "_config"]; @@ -28,21 +30,21 @@ private ["_launcher", "_control", "_config"]; _launcher = secondaryWeapon _player; if (_launcher == "" || {getText (configFile >> "CfgWeapons" >> _launcher >> "ACE_UsedTube") == ""}) then { - _control = _display displayCtrl 627; - _config = configFile >> "RscDisplayInventory" >> "controls" >> "SlotSecondaryMagazine"; - _control ctrlSetPosition [getNumber (_config >> "x"), getNumber (_config >> "y"), getNumber (_config >> "w"), getNumber (_config >> "h")]; - _control ctrlCommit 0; + _control = _display displayCtrl 627; + _config = configFile >> "RscDisplayInventory" >> "controls" >> "SlotSecondaryMagazine"; + _control ctrlSetPosition [getNumber (_config >> "x"), getNumber (_config >> "y"), getNumber (_config >> "w"), getNumber (_config >> "h")]; + _control ctrlCommit 0; - _control = _display displayCtrl 1251; - _config = configFile >> "RscDisplayInventory" >> "controls" >> "BackgroundSlotSecondaryMagazine"; - _control ctrlSetPosition [getNumber (_config >> "x"), getNumber (_config >> "y"), getNumber (_config >> "w"), getNumber (_config >> "h")]; - _control ctrlCommit 0; + _control = _display displayCtrl 1251; + _config = configFile >> "RscDisplayInventory" >> "controls" >> "BackgroundSlotSecondaryMagazine"; + _control ctrlSetPosition [getNumber (_config >> "x"), getNumber (_config >> "y"), getNumber (_config >> "w"), getNumber (_config >> "h")]; + _control ctrlCommit 0; } else { - _control = _display displayCtrl 627; - _control ctrlSetPosition [0, 0, 0, 0]; - _control ctrlCommit 0; + _control = _display displayCtrl 627; + _control ctrlSetPosition [0, 0, 0, 0]; + _control ctrlCommit 0; - _control = _display displayCtrl 1251; - _control ctrlSetPosition [0, 0, 0, 0]; - _control ctrlCommit 0; + _control = _display displayCtrl 1251; + _control ctrlSetPosition [0, 0, 0, 0]; + _control ctrlCommit 0; }; diff --git a/addons/dragging/functions/fnc_setCarryable.sqf b/addons/dragging/functions/fnc_setCarryable.sqf index d1dd9cf1a9..630f212b97 100644 --- a/addons/dragging/functions/fnc_setCarryable.sqf +++ b/addons/dragging/functions/fnc_setCarryable.sqf @@ -48,5 +48,8 @@ if (_type in _initializedClasses) exitWith {}; _initializedClasses pushBack _type; GVAR(initializedClasses_carry) = _initializedClasses; -[_type, 0, ["ACE_MainActions", QGVAR(carry)], localize "STR_ACE_Dragging_Carry", "", "", {[_player, _target] call FUNC(carryObject)}, {[_player, _target] call FUNC(canCarry)}, 2] call EFUNC(interact_menu,addClassAction); -[_type, 0, ["ACE_MainActions", QGVAR(drop_carry)], localize "STR_ACE_Dragging_Drop", "", "", {[_player, _target] call FUNC(dropObject_carry)}, {[_player, _target] call FUNC(canDrop_carry)}, 2] call EFUNC(interact_menu,addClassAction); +_carryAction = [QGVAR(drag), localize "STR_ACE_Dragging_Carry", "", {[_player, _target] call FUNC(carryObject)}, {[_player, _target] call FUNC(canCarry)}] call EFUNC(interact_menu,createAction); +_dropAction = [QGVAR(drop), localize "STR_ACE_Dragging_Drop", "", {[_player, _target] call FUNC(dropObject_carry)}, {[_player, _target] call FUNC(canDrop_carry)}] call EFUNC(interact_menu,createAction); + +[_type, 0, ["ACE_MainActions"], _carryAction] call EFUNC(interact_menu,addActionToClass); +[_type, 0, ["ACE_MainActions"], _dropAction] call EFUNC(interact_menu,addActionToClass); diff --git a/addons/dragging/functions/fnc_setDraggable.sqf b/addons/dragging/functions/fnc_setDraggable.sqf index 82ebc201e2..b6e26a6f0a 100644 --- a/addons/dragging/functions/fnc_setDraggable.sqf +++ b/addons/dragging/functions/fnc_setDraggable.sqf @@ -48,5 +48,8 @@ if (_type in _initializedClasses) exitWith {}; _initializedClasses pushBack _type; GVAR(initializedClasses) = _initializedClasses; -[_type, 0, ["ACE_MainActions", QGVAR(drag)], localize "STR_ACE_Dragging_Drag", "", "", {[_player, _target] call FUNC(startDrag)}, {[_player, _target] call FUNC(canDrag)}, 2] call EFUNC(interact_menu,addClassAction); -[_type, 0, ["ACE_MainActions", QGVAR(drop)], localize "STR_ACE_Dragging_Drop", "", "", {[_player, _target] call FUNC(dropObject)}, {[_player, _target] call FUNC(canDrop)}, 2] call EFUNC(interact_menu,addClassAction); +_dragAction = [QGVAR(drag), localize "STR_ACE_Dragging_Drag", "", {[_player, _target] call FUNC(startDrag)}, {[_player, _target] call FUNC(canDrag)}] call EFUNC(interact_menu,createAction); +_dropAction = [QGVAR(drop), localize "STR_ACE_Dragging_Drop", "", {[_player, _target] call FUNC(dropObject)}, {[_player, _target] call FUNC(canDrop)}] call EFUNC(interact_menu,createAction); + +[_type, 0, ["ACE_MainActions"], _dragAction] call EFUNC(interact_menu,addActionToClass); +[_type, 0, ["ACE_MainActions"], _dropAction] call EFUNC(interact_menu,addActionToClass); diff --git a/addons/fcs/initKeybinds.sqf b/addons/fcs/initKeybinds.sqf index c30e93dba0..7d1cc8f09b 100644 --- a/addons/fcs/initKeybinds.sqf +++ b/addons/fcs/initKeybinds.sqf @@ -3,7 +3,7 @@ ["ACE3", QGVAR(lazeTarget), localize "STR_ACE_FCS_LaseTarget", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !((!GVAR(enabled) && FUNC(canUseFCS)) || FUNC(canUseRangefinder)) exitWith {false}; @@ -20,7 +20,7 @@ GVAR(isDownStateKey1) = false; // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(GVAR(enabled) && FUNC(canUseFCS)) exitWith {false}; @@ -33,7 +33,7 @@ ["ACE3", QGVAR(adjustRangeUp), localize "STR_ACE_FCS_AdjustRangeUp", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(call FUNC(canUseRangefinder) || FUNC(canUseFCS)) exitWith {false}; @@ -47,7 +47,7 @@ ["ACE3", QGVAR(adjustRangDown), localize "STR_ACE_FCS_AdjustRangeDown", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(call FUNC(canUseRangefinder) || FUNC(canUseFCS)) exitWith {false}; diff --git a/addons/frag/CfgAmmo.hpp b/addons/frag/CfgAmmo.hpp index c9d13d3ce3..58ed5573e1 100644 --- a/addons/frag/CfgAmmo.hpp +++ b/addons/frag/CfgAmmo.hpp @@ -26,7 +26,7 @@ class CfgAmmo { ACE_FRAG_SKIP = 0; ACE_FRAG_FORCE = 1; // This is a good high-drag frag type for grenades. - ACE_FRAG_CLASSES[] = {"ACE_frag_medium_HD"}; + ACE_FRAG_CLASSES[] = {"ACE_frag_tiny_HD"}; /* These values are based on the M67 Grenade, should be tweaked for individual grenades. diff --git a/addons/frag/XEH_post_init.sqf b/addons/frag/XEH_post_init.sqf index 25cb5132c8..ed0e715376 100644 --- a/addons/frag/XEH_post_init.sqf +++ b/addons/frag/XEH_post_init.sqf @@ -1,8 +1,8 @@ #include "script_component.hpp" -[QUOTE(ffsBIS), "oneachframe", QUOTE(FUNC(onFrame))] call BIS_fnc_addStackedEventHandler; if(isServer) then { - [QGVAR(frag_eh), { _this call FUNC(frago); }] call CBA_fnc_addClientToServerEventhandler; + [QGVAR(frag_eh), { _this call FUNC(frago); }] call ace_common_fnc_addEventHandler; }; +/* GVAR(replacedBisArtyWrapper) = false; [] spawn { waitUntil { @@ -15,3 +15,4 @@ GVAR(replacedBisArtyWrapper) = false; GVAR(replacedBisArtyWrapper) }; }; +*/ \ No newline at end of file diff --git a/addons/frag/XEH_pre_Init.sqf b/addons/frag/XEH_pre_Init.sqf index 406e6e7f63..5b3aa36b18 100644 --- a/addons/frag/XEH_pre_Init.sqf +++ b/addons/frag/XEH_pre_Init.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" -#define ACE_TRACE_DRAW_INC 1 + ADDON = false; PREP(fired); @@ -14,7 +14,7 @@ GVAR(trackedObjects) = []; GVAR(blackList) = []; GVAR(traceFrags) = false; -GVAR(replacedBisArtyWrapper) = false; +GVAR(replacedBisArtyWrapper) = true; GVAR(TOTALFRAGS) = 0; diff --git a/addons/frag/functions/fnc_addManualTrack.sqf b/addons/frag/functions/fnc_addManualTrack.sqf index 1719842240..066499f6aa 100644 --- a/addons/frag/functions/fnc_addManualTrack.sqf +++ b/addons/frag/functions/fnc_addManualTrack.sqf @@ -3,5 +3,5 @@ private ["_round"]; _round = _this select 0; if(alive _round) then { GVAR(trackedObjects) set[(count GVAR(trackedObjects)), _round]; - [FUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), (typeOf _round), time, objNull, false, 0, 0]] call cba_fnc_addPerFrameHandler; + [DFUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), (typeOf _round), time, objNull, false, 0, 0]] call cba_fnc_addPerFrameHandler; }; \ No newline at end of file diff --git a/addons/frag/functions/fnc_addTrack.sqf b/addons/frag/functions/fnc_addTrack.sqf index 4ffaef5a7c..65ad3b6a22 100644 --- a/addons/frag/functions/fnc_addTrack.sqf +++ b/addons/frag/functions/fnc_addTrack.sqf @@ -17,4 +17,4 @@ _objTVel = sqrt((_objVel select 0)^2 + (_objVel select 1)^2 + (_objVel select 2) _positions set[(count _positions), [(getPos _obj), _objTVel]]; _data = [_origin, typeOf _origin, typeOf _obj, _objTVel, _positions, _color]; GVAR(traces) set[_index, _data]; -[FUNC(trackTrace), 0, [_obj, _index, time]] call cba_fnc_addPerFrameHandler; \ No newline at end of file +[DFUNC(trackTrace), 0, [_obj, _index, time]] call cba_fnc_addPerFrameHandler; \ No newline at end of file diff --git a/addons/frag/functions/fnc_doSpall.sqf b/addons/frag/functions/fnc_doSpall.sqf index 92b67e0256..5560a4f0af 100644 --- a/addons/frag/functions/fnc_doSpall.sqf +++ b/addons/frag/functions/fnc_doSpall.sqf @@ -44,13 +44,12 @@ if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { _exit = false; _vm = 1; _velocity = _initialData select 5; - _unitDir = _velocity call BIS_fnc_unitVector; _oldVelocity = _velocity call BIS_fnc_magnitude; _curVelocity = (velocity _round) call BIS_fnc_magnitude; if(alive _round) then { - _diff = [_velocity, (velocity _round)] call FUNC(vectorDiffFast); + _diff = _velocity vectorDiff (velocity _round); _polar = _diff call CBA_fnc_vect2polar; // player sideChat format["polar: %1", _polar]; if((abs(_polar select 1) > 45 || abs(_polar select 2) > 45)) then { @@ -63,7 +62,7 @@ if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { }; }; if(!_exit) then { - _unitDir = _velocity call BIS_fnc_unitVector; + _unitDir = vectorNormalized _velocity; _pos = _hpData select 3; _spallPos = nil; for "_i" from 0 to 100 do { @@ -137,7 +136,6 @@ if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; _fragment setPosASL _spallPos; _fragment setVelocity _spallFragVect; - // [fnc_spallTrackPFH, 0, [_fragment, diag_tickTime]] call cba_fnc_addPerFrameHandler; if(GVAR(traceFrags)) then { [player, _fragment, [1,0.5,0,1]] call FUNC(addTrack); }; @@ -159,7 +157,6 @@ if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; _fragment setPosASL _spallPos; _fragment setVelocity _spallFragVect; - // [fnc_spallTrackPFH, 0, [_fragment, diag_tickTime]] call cba_fnc_addPerFrameHandler; if(GVAR(traceFrags)) then { [player, _fragment, [1,0,0,1]] call FUNC(addTrack); }; diff --git a/addons/frag/functions/fnc_fired.sqf b/addons/frag/functions/fnc_fired.sqf index 5910d2481b..a6e934c667 100644 --- a/addons/frag/functions/fnc_fired.sqf +++ b/addons/frag/functions/fnc_fired.sqf @@ -1,5 +1,4 @@ #include "script_component.hpp" -/* private ["_gun", "_type", "_round", "_doFragTrack", "_doSpall"]; if !(isNil QGVAR(enabled) && {GVAR(enabled)}) exitWith {}; @@ -23,7 +22,7 @@ if(_gun == player) then { }; }; }; -_doSpall = true; +_doSpall = false; if(_doSpall) then { if(GVAR(spallIsTrackingCount) <= 0) then { GVAR(spallHPData) = []; @@ -36,15 +35,14 @@ if(_doSpall) then { }; }; // player sideChat format["c: %1", GVAR(spallIsTrackingCount)]; -[player, _round, [1,0,0,1]] call FUNC(addTrack); +[player, _round, [1,0,0,1]] call nou_fnc_addTrack; if(_doFragTrack && alive _round) then { - GVAR(trackedObjects) set[(count GVAR(trackedObjects)), _round]; + GVAR(trackedObjects) pushBack _round; _spallTrack = []; _spallTrackID = []; - [FUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), _type, time, _gun, _doSpall, _spallTrack, _spallTrackID]] call cba_fnc_addPerFrameHandler; + [DFUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), _type, time, _gun, _doSpall, _spallTrack, _spallTrackID]] call cba_fnc_addPerFrameHandler; if(_doSpall) then { [_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack); }; // player sideChat "WTF2"; }; -*/ \ No newline at end of file diff --git a/addons/frag/functions/fnc_frag_trace.sqf b/addons/frag/functions/fnc_frag_trace.sqf index 9b0c8dc3db..f4e14fa12a 100644 --- a/addons/frag/functions/fnc_frag_trace.sqf +++ b/addons/frag/functions/fnc_frag_trace.sqf @@ -6,5 +6,5 @@ _shell = _params select 0; if(alive _shell) then { drop ["\Ca\Data\Cl_basic","","Billboard",1,30,(getPos _shell),[0,0,0],1,1.275,1.0,0.0,[0.5],[[0,1,0,1]],[0],0.0,2.0,"","",""]; } else { - [_this select 1] call FUNC(removeBISPFH); + [_this select 1] call cba_fnc_removePerFrameHandler; }; \ No newline at end of file diff --git a/addons/frag/functions/fnc_frago.sqf b/addons/frag/functions/fnc_frago.sqf index 88ec0c4742..79eea53cd7 100644 --- a/addons/frag/functions/fnc_frago.sqf +++ b/addons/frag/functions/fnc_frago.sqf @@ -130,11 +130,12 @@ if(_isArmed && (count _objects) > 0) then { _targetVel = (velocity _target); - _targetPos set[2, (_targetPos select 2)+_add]; + _targetPos set[0, (_targetPos select 0)+((_targetVel select 0)*(_distance/_fragPower))]; _targetPos set[1, (_targetPos select 1)+((_targetVel select 1)*(_distance/_fragPower))]; - - _baseVec = [_lastPos, _targetPos] call BIS_fnc_vectorFromXToY; + _targetPos set[2, (_targetPos select 2)+_add]; + + _baseVec = _lastPos vectorFromTo _targetPos; _dir = floor(_baseVec call CBA_fnc_vectDir); _currentCount = _fragArcs select _dir; @@ -213,7 +214,6 @@ if(_isArmed && (count _objects) > 0) then { _fragObj setVelocity _vel; #ifdef DEBUG_MODE_FULL GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; - // [FUNC(frag_trace), 0, [_fragObj]] call cba_fnc_addPerFrameHandler; GVAR(traceFrags) = true; #endif if(GVAR(traceFrags)) then { diff --git a/addons/frag/functions/fnc_spallHP.sqf b/addons/frag/functions/fnc_spallHP.sqf index aeba4e7a5d..89ba572ce2 100644 --- a/addons/frag/functions/fnc_spallHP.sqf +++ b/addons/frag/functions/fnc_spallHP.sqf @@ -21,7 +21,7 @@ if((_this select 0) <= (count GVAR(spallHPData))) then { // diag_log text format["%1: %2", _forEachIndex, _x]; // } forEach _hp; // } forEach (_this select 1); - [FUNC(doSpall), 0, [_this, _forEachIndex]] call cba_fnc_addPerFrameHandler; + [DFUNC(doSpall), 0, [_this, _forEachIndex]] call cba_fnc_addPerFrameHandler; // player sideChat "WEEE"; } forEach (_this select 1); }; diff --git a/addons/frag/functions/fnc_stopTracing.sqf b/addons/frag/functions/fnc_stopTracing.sqf index 02b4fd7f59..693390fff2 100644 --- a/addons/frag/functions/fnc_stopTracing.sqf +++ b/addons/frag/functions/fnc_stopTracing.sqf @@ -1,5 +1,5 @@ #include "script_component.hpp" if(GVAR(tracesStarted)) then { GVAR(tracesStarted) = false; - [GVAR(traceID)] call FUNC(removeBISPFH); + [GVAR(traceID)] call cba_fnc_removePerFrameHandler; }; \ No newline at end of file diff --git a/addons/frag/functions/fnc_trackFragRound.sqf b/addons/frag/functions/fnc_trackFragRound.sqf index 2780a85664..0a8e3948d0 100644 --- a/addons/frag/functions/fnc_trackFragRound.sqf +++ b/addons/frag/functions/fnc_trackFragRound.sqf @@ -12,7 +12,7 @@ _spallTrack = _params select 7; _foundObjectHPIds = _params select 8; if (!alive _round) then { - [_this select 1] call FUNC(removeBISPFH); + [_this select 1] call cba_fnc_removePerFrameHandler; if(_time != time && {_round in GVAR(trackedObjects)} && {!(_round in GVAR(blackList))}) then { GVAR(trackedObjects) = GVAR(trackedObjects) - [_round]; _skip = getNumber (configFile >> "CfgAmmo" >> _type >> "ACE_FRAG_SKIP"); @@ -22,7 +22,7 @@ if (!alive _round) then { _force = getNumber (configFile >> "CfgAmmo" >> _type >> "ACE_FRAG_FORCE"); _fragPower = getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt(_indirectRange)); if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then { - [QGVAR(frag_eh), _params] call CBA_fnc_clientToServerEvent; + [QGVAR(frag_eh), _params] call ace_common_fnc_serverEvent; GVAR(trackedObjects) = GVAR(trackedObjects) - [_round]; }; }; @@ -38,7 +38,7 @@ if (!alive _round) then { }; } else { if(!(_round in GVAR(trackedObjects)) || {_round in GVAR(blackList)}) then { - [_this select 1] call FUNC(removeBISPFH); + [_this select 1] call cba_fnc_removePerFrameHandler; if(_round in GVAR(blackList)) then { GVAR(blackList) = GVAR(blackList) - [_round]; }; diff --git a/addons/frag/functions/fnc_trackTrace.sqf b/addons/frag/functions/fnc_trackTrace.sqf index 71b4a9a866..628fece605 100644 --- a/addons/frag/functions/fnc_trackTrace.sqf +++ b/addons/frag/functions/fnc_trackTrace.sqf @@ -10,5 +10,5 @@ if(alive _tracerObj && (count GVAR(traces)) > 0) then { _objTVel = sqrt((_objVel select 0)^2 + (_objVel select 1)^2 + (_objVel select 2)^2); _positions set[(count _positions), [(getPos _tracerObj), _objTVel]]; } else { - [(_this select 1)] call FUNC(removeBISPFH); + [(_this select 1)] call cba_fnc_removePerFrameHandler; }; \ No newline at end of file diff --git a/addons/frag/script_component.hpp b/addons/frag/script_component.hpp index 274270cbbb..371067db3e 100644 --- a/addons/frag/script_component.hpp +++ b/addons/frag/script_component.hpp @@ -1,7 +1,7 @@ #define COMPONENT frag #include "\z\ace\Addons\main\script_mod.hpp" -#define DEBUG_ENABLED_FRAG +//#define DEBUG_ENABLED_FRAG #ifdef DEBUG_ENABLED_FRAG #define DEBUG_MODE_FULL @@ -11,4 +11,6 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_FRAG #endif -#include "\z\ace\Addons\main\script_macros.hpp" \ No newline at end of file +#include "\z\ace\Addons\main\script_macros.hpp" + +#define ACE_TRACE_DRAW_INC 1 \ No newline at end of file diff --git a/addons/gforces/$PBOPREFIX$ b/addons/gforces/$PBOPREFIX$ index 215e681d94..15f2f61c42 100644 --- a/addons/gforces/$PBOPREFIX$ +++ b/addons/gforces/$PBOPREFIX$ @@ -1 +1 @@ -z\ace\addons\hearing \ No newline at end of file +z\ace\addons\gforces diff --git a/addons/grenades/XEH_postInit.sqf b/addons/grenades/XEH_postInit.sqf index 6229871679..7572a41c10 100644 --- a/addons/grenades/XEH_postInit.sqf +++ b/addons/grenades/XEH_postInit.sqf @@ -13,7 +13,7 @@ GVAR(flashbangPPEffectCC) ppEffectForceInNVG true; ["ACE3", QGVAR(switchGrenadeMode), localize "STR_ACE_Grenades_SwitchGrenadeMode", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if (!([ACE_player] call EFUNC(common,canUseWeapon))) exitWith {false}; diff --git a/addons/interact_menu/XEH_preInit.sqf b/addons/interact_menu/XEH_preInit.sqf index 487f1c017f..4ede3196fe 100644 --- a/addons/interact_menu/XEH_preInit.sqf +++ b/addons/interact_menu/XEH_preInit.sqf @@ -2,21 +2,25 @@ ADDON = false; -PREP(addAction); -PREP(addClassAction); +PREP(addActionToClass); +PREP(addActionToObject); PREP(compileMenu); PREP(compileMenuSelfAction); PREP(collectActiveActionTree); +PREP(createAction); +PREP(findActionNode); +PREP(isSubPath); PREP(keyDown); PREP(keyDownSelfAction); PREP(keyUp); PREP(keyUpSelfAction); -PREP(removeAction); -PREP(removeClassAction); +PREP(removeActionFromClass); +PREP(removeActionFromObject); PREP(render); -PREP(renderIcon); PREP(renderBaseMenu); +PREP(renderIcon); PREP(renderMenu); +PREP(splitPath); GVAR(keyDown) = false; GVAR(keyDownSelfAction) = false; @@ -26,7 +30,6 @@ GVAR(lastTime) = diag_tickTime; GVAR(rotationAngle) = 0; GVAR(selectedAction) = [[],[]]; -GVAR(selectedStatement) = {}; GVAR(actionSelected) = false; GVAR(selectedTarget) = objNull; @@ -40,6 +43,7 @@ GVAR(lastPath) = []; GVAR(expanded) = false; GVAR(startHoverTime) = diag_tickTime; +GVAR(expandedTime) = diag_tickTime; GVAR(iconCtrls) = []; GVAR(iconCount) = 0; diff --git a/addons/interact_menu/functions/fnc_addAction.sqf b/addons/interact_menu/functions/fnc_addAction.sqf deleted file mode 100644 index c7dd6ecab3..0000000000 --- a/addons/interact_menu/functions/fnc_addAction.sqf +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Author: commy2, NouberNou and CAA-Picard - * Add an ACE action to an object, under a certain config path - * Note: This function is NOT global. - * - * Argument: - * 0: Object the action should be assigned to - * 1: Type of action, 0 for actions, 1 for self-actions - * 2: Full path of the new action - * 3: Name of the action shown in the menu - * 4: Icon - * 5: Position (Position or Selection Name) or - * 6: Statement - * 7: Condition - * 8: Distance - * 9: Other parameters (Optional) - * - * Return value: - * The entry full path, which can be used to remove the entry, or add children entries . - * - * Example: - * [cursorTarget,0,["ACE_TapShoulderRight","VulcanPinch"],"Vulcan Pinch","",[0,0,0],{_target setDamage 1;},{true},100] call ace_interact_menu_fnc_addAction; - * - * Public: No - */ -#include "script_component.hpp" - -EXPLODE_9_PVT(_this,_object,_typeNum,_fullPath,_displayName,_icon,_position,_statement,_condition,_distance); - -private ["_varName","_actions","_params","_entry"]; - -_varName = [QGVAR(actions),QGVAR(selfActions)] select _typeNum; -_actions = _object getVariable [_varName, []]; -if((count _actions) == 0) then { - _object setVariable [_varName, _actions]; -}; - -_params = [false,false,false,false]; -if (count _this > 9) then { - _params = _this select 9; -}; - -_entry = [ - [ - _displayName, - _icon, - _position, - _statement, - _condition, - _distance, - _params, - + _fullPath - ], - [] - ]; - -_actions pushBack _entry; - -_fullPath diff --git a/addons/interact_menu/functions/fnc_addActionToClass.sqf b/addons/interact_menu/functions/fnc_addActionToClass.sqf new file mode 100644 index 0000000000..c93342cfda --- /dev/null +++ b/addons/interact_menu/functions/fnc_addActionToClass.sqf @@ -0,0 +1,45 @@ +/* + * Author: CAA-Picard + * Insert an ACE action to a class, under a certain path + * Note: This function is NOT global. + * + * Argument: + * 0: TypeOf of the class + * 1: Type of action, 0 for actions, 1 for self-actions + * 2: Parent path of the new action + * 3: Action + * + * Return value: + * The entry full path, which can be used to remove the entry, or add children entries . + * + * Example: + * [typeOf cursorTarget, 0, ["ACE_TapShoulderRight"],VulcanPinchAction] call ace_interact_menu_fnc_addActionToClass; + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_4_PVT(_this,_objectType,_typeNum,_parentPath,_action); + +// Ensure the config menu was compiled first +if (_typeNum == 0) then { + [_objectType] call FUNC(compileMenu); +} else { + [_objectType] call FUNC(compileMenuSelfAction); +}; + +private ["_varName","_actionTrees", "_parentNode"]; +_varName = format [[QGVAR(Act_%1), QGVAR(SelfAct_%1)] select _typeNum, _objectType]; +_actionTrees = missionNamespace getVariable [_varName, []]; +if((count _actionTrees) == 0) then { + missionNamespace setVariable [_varName, _actionTrees]; +}; + +_parentNode = [_actionTrees, _parentPath] call FUNC(findActionNode); +if (isNil {_parentNode}) exitWith {}; + +// Add action node as children of the correct node of action tree +(_parentNode select 1) pushBack [_action,[]]; + +// Return the full path +(+ _parentPath) pushBack (_action select 0) diff --git a/addons/interact_menu/functions/fnc_addActionToObject.sqf b/addons/interact_menu/functions/fnc_addActionToObject.sqf new file mode 100644 index 0000000000..223247057a --- /dev/null +++ b/addons/interact_menu/functions/fnc_addActionToObject.sqf @@ -0,0 +1,35 @@ +/* + * Author: CAA-Picard + * Insert an ACE action to an object, under a certain config path + * Note: This function is NOT global. + * + * Argument: + * 0: Object the action should be assigned to + * 1: Type of action, 0 for actions, 1 for self-actions + * 2: Parent path of the new action + * 3: Action + * + * Return value: + * The entry full path, which can be used to remove the entry, or add children entries . + * + * Example: + * [typeOf cursorTarget, 0, ["ACE_TapShoulderRight"],VulcanPinchAction] call ace_interact_menu_fnc_addActionToClass; + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_4_PVT(_this,_object,_typeNum,_parentPath,_action); + +private ["_varName","_actionList"]; +_varName = [QGVAR(actions),QGVAR(selfActions)] select _typeNum; +_actionList = _object getVariable [_varName, []]; +if((count _actionList) == 0) then { + _object setVariable [_varName, _actionList]; +}; + +// Add action and parent path to the list of object actions +_actionList pushBack [_action, +_parentPath]; + +// Return the full path +(+ _parentPath) pushBack (_action select 0) diff --git a/addons/interact_menu/functions/fnc_addClassAction.sqf b/addons/interact_menu/functions/fnc_addClassAction.sqf deleted file mode 100644 index 4931328af2..0000000000 --- a/addons/interact_menu/functions/fnc_addClassAction.sqf +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Author: CAA-Picard - * Add an ACE action to a class, under a certain path - * Note: This function is NOT global. - * - * Argument: - * 0: TypeOf of the class - * 1: Type of action, 0 for actions, 1 for self-actions - * 2: Full path of the new action - * 3: Name of the action shown in the menu - * 4: Icon - * 5: Position (Position or Selection Name) or - * 6: Statement - * 7: Condition - * 8: Distance - * 9: Other parameters (Optional) - * - * Return value: - * The entry full path, which can be used to remove the entry, or add children entries . - * - * Example: - * [typeOf cursorTarget, 0,["ACE_TapShoulderRight","VulcanPinch"],"Vulcan Pinch","",[0,0,0],{_target setDamage 1;},{true},100] call ace_interact_menu_fnc_addClassAction; - * - * Public: No - */ -#include "script_component.hpp" - -EXPLODE_9_PVT(_this,_objectType,_typeNum,_fullPath,_displayName,_icon,_position,_statement,_condition,_distance); - -// Ensure the config menu was compiled first -if (_typeNum == 0) then { - [_objectType] call FUNC(compileMenu); -} else { - [_objectType] call FUNC(compileMenuSelfAction); -}; - -private ["_varName","_actions","_params","_entry", "_parentLevel", "_foundParentLevel", "_fnc_findFolder"]; - -_varName = format [[QGVAR(Act_%1), QGVAR(SelfAct_%1)] select _typeNum, _objectType]; -_actions = missionNamespace getVariable [_varName, []]; -if((count _actions) == 0) then { - missionNamespace setVariable [_varName, _actions]; -}; - -_params = [false,false,false,false]; -if (count _this > 9) then { - _params = _this select 9; -}; - -// Search the class action trees and find where to insert the entry -_parentLevel = _actions; -_foundParentLevel = false; - -_fnc_findFolder = { - EXPLODE_3_PVT(_this,_fullPath,_level,_classActions); - - if (count _fullPath == _level + 1) then { - _parentLevel = _classActions; - _foundParentLevel = true; - }; - - if (_foundParentLevel) exitWith {}; - - { - EXPLODE_2_PVT(_x,_actionData,_actionChildren); - if (((_actionData select 7) select _level) isEqualTo (_fullPath select _level)) exitWith { - // The action should go somewhere in here - [_fullPath, _level + 1, _actionChildren] call _fnc_findFolder; - }; - } forEach _classActions; -}; - -[_fullPath, 0, _actions] call _fnc_findFolder; - -// Exit if there's no entry point to insert this action -if (!_foundParentLevel) exitWith {}; - -_entry = [ - [ - _displayName, - _icon, - _position, - _statement, - _condition, - _distance, - _params, - + _fullPath - ], - [] - ]; - -_parentLevel pushBack _entry; - -_fullPath diff --git a/addons/interact_menu/functions/fnc_collectActiveActionTree.sqf b/addons/interact_menu/functions/fnc_collectActiveActionTree.sqf index 42f762de3f..36d4dc548d 100644 --- a/addons/interact_menu/functions/fnc_collectActiveActionTree.sqf +++ b/addons/interact_menu/functions/fnc_collectActiveActionTree.sqf @@ -5,6 +5,7 @@ * Argument: * 0: Object * 1: Original action tree + * 2: Parent path * * Return value: * Active children @@ -13,24 +14,39 @@ */ #include "script_component.hpp" -EXPLODE_2_PVT(_this,_object,_origAction); +EXPLODE_3_PVT(_this,_object,_origAction,_parentPath); EXPLODE_2_PVT(_origAction,_origActionData,_origActionChildren); -private ["_resultingAction","_target","_player","_activeChildren","_action","_actionData","_x"]; +private ["_target","_player","_fullPath","_activeChildren","_dynamicChildren","_action","_actionData","_x"]; _target = _object; _player = ACE_player; // Return nothing if the action itself is not active -if !([_target, ACE_player] call (_origActionData select 4)) exitWith { +if !([_target, ACE_player, _origActionData select 6] call (_origActionData select 4)) exitWith { [] }; +_fullPath = +_parentPath; +_fullPath pushBack (_origActionData select 0); _activeChildren = []; +// If there's a statement to dynamically insert children then execute it +if !({} isEqualTo (_origActionData select 5)) then { + _dynamicChildren = [_target, ACE_player, _origActionData select 6] call (_origActionData select 5); + + // Collect dynamic children class actions + { + _action = [_x select 2, _x, _fullPath] call FUNC(collectActiveActionTree); + if ((count _action) > 0) then { + _activeChildren pushBack _action; + }; + } forEach _dynamicChildren; +}; + // Collect children class actions { - _action = [_object, _x] call FUNC(collectActiveActionTree); + _action = [_object, _x, _fullPath] call FUNC(collectActiveActionTree); if ((count _action) > 0) then { _activeChildren pushBack _action; }; @@ -38,26 +54,15 @@ _activeChildren = []; // Collect children object actions { - _action = _x; - _actionData = _action select 0; + EXPLODE_2_PVT(_x,_actionData,_pPath); // Check if the action is children of the original action - if ((count (_actionData select 7)) == (count (_origActionData select 7) + 1)) then { + if (count _pPath == count _fullPath && + {_pPath isEqualTo _fullPath}) then { - // Compare parent path to see if it's a suitable child - private "_isChild"; - _isChild = true; - { - if !(_x isEqualTo ((_actionData select 7) select _forEachIndex)) exitWith { - _isChild = false; - }; - } forEach (_origActionData select 7); - - if (_isChild) then { - _action = [_object, _action] call FUNC(collectActiveActionTree); - if ((count _action) > 0) then { - _activeChildren pushBack _action; - }; + _action = [_object, _action, _fullPath] call FUNC(collectActiveActionTree); + if ((count _action) > 0) then { + _activeChildren pushBack _action; }; }; } forEach GVAR(objectActions); @@ -69,4 +74,5 @@ if ((count _activeChildren) == 0 && ((_origActionData select 3) isEqualTo {})) e [] }; -[_origActionData, _activeChildren] + +[_origActionData, _activeChildren, _object] diff --git a/addons/interact_menu/functions/fnc_compileMenu.sqf b/addons/interact_menu/functions/fnc_compileMenu.sqf index e6a2744f03..0fd4f6adb4 100644 --- a/addons/interact_menu/functions/fnc_compileMenu.sqf +++ b/addons/interact_menu/functions/fnc_compileMenu.sqf @@ -27,8 +27,8 @@ if !(isNil {missionNamespace getVariable [_actionsVarName, nil]}) exitWith {}; private "_recurseFnc"; _recurseFnc = { private ["_actions", "_displayName", "_distance", "_icon", "_statement", "_selection", "_condition", "_showDisabled", - "_enableInside", "_canCollapse", "_runOnHover", "_children", "_entry", "_entryCfg", "_fullPath"]; - EXPLODE_2_PVT(_this,_actionsCfg,_parentPath); + "_enableInside", "_canCollapse", "_runOnHover", "_children", "_entry", "_entryCfg", "_insertChildren"]; + EXPLODE_1_PVT(_this,_actionsCfg); _actions = []; for "_i" from 0 to (count _actionsCfg) - 1 do { @@ -46,29 +46,30 @@ _recurseFnc = { if (_condition == "") then {_condition = "true"}; // Add canInteract (including exceptions) and canInteractWith to condition - _condition = _condition + format [QUOTE( && {[ARR_3(ACE_player, _target, %1)] call EGVAR(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")]; + _condition = _condition + format [QUOTE( && {[ARR_3(ACE_player, _target, %1)] call EFUNC(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")]; + + _insertChildren = compile (getText (_entryCfg >> "insertChildren")); _showDisabled = (getNumber (_entryCfg >> "showDisabled")) > 0; _enableInside = (getNumber (_entryCfg >> "enableInside")) > 0; _canCollapse = (getNumber (_entryCfg >> "canCollapse")) > 0; _runOnHover = (getNumber (_entryCfg >> "runOnHover")) > 0; - _fullPath = (+ _parentPath); - _fullPath pushBack (configName _entryCfg); - _condition = compile _condition; - _children = [_entryCfg, _fullPath] call _recurseFnc; + _children = [_entryCfg] call _recurseFnc; _entry = [ [ + configName _entryCfg, _displayName, _icon, - _selection, _statement, _condition, + _insertChildren, + [], + _selection, _distance, - [_showDisabled,_enableInside,_canCollapse,_runOnHover], - _fullPath + [_showDisabled,_enableInside,_canCollapse,_runOnHover] ], _children ]; @@ -81,20 +82,22 @@ _recurseFnc = { private "_actionsCfg"; _actionsCfg = configFile >> "CfgVehicles" >> _objectType >> "ACE_Actions"; -missionNamespace setVariable [_actionsVarName, [_actionsCfg, []] call _recurseFnc]; +missionNamespace setVariable [_actionsVarName, [_actionsCfg] call _recurseFnc]; /* [ [ [ + "MyAction", "My Action", "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa", - [0,0,0], { (_this select 0) setVelocity [0,0,10]; }, { true }, + {}, + [], + [0,0,0], 1, [false,false,false] - ["ACE_MainActions","TeamManagement","MyAction"] ], [children actions] ] diff --git a/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf b/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf index 81f4a25ef1..ebccc2ca42 100644 --- a/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf +++ b/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf @@ -27,8 +27,8 @@ if !(isNil {missionNamespace getVariable [_actionsVarName, nil]}) exitWith {}; private "_recurseFnc"; _recurseFnc = { private ["_actions", "_displayName", "_distance", "_icon", "_statement", "_selection", "_condition", "_showDisabled", - "_enableInside", "_canCollapse", "_runOnHover", "_children", "_entry", "_entryCfg", "_fullPath"]; - EXPLODE_2_PVT(_this,_actionsCfg,_parentPath); + "_enableInside", "_canCollapse", "_runOnHover", "_children", "_entry", "_entryCfg", "_insertChildren"]; + EXPLODE_1_PVT(_this,_actionsCfg); _actions = []; for "_i" from 0 to (count _actionsCfg) - 1 do { @@ -43,29 +43,30 @@ _recurseFnc = { if (_condition == "") then {_condition = "true"}; // Add canInteract (including exceptions) and canInteractWith to condition - _condition = _condition + format [QUOTE( && {[ARR_3(ACE_player, objNull, %1)] call EGVAR(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")]; + _condition = _condition + format [QUOTE( && {[ARR_3(ACE_player, objNull, %1)] call EFUNC(common,canInteractWith)} ), getArray (_entryCfg >> "exceptions")]; + + _insertChildren = compile (getText (_entryCfg >> "insertChildren")); _showDisabled = (getNumber (_entryCfg >> "showDisabled")) > 0; _enableInside = (getNumber (_entryCfg >> "enableInside")) > 0; _canCollapse = (getNumber (_entryCfg >> "canCollapse")) > 0; _runOnHover = (getNumber (_entryCfg >> "runOnHover")) > 0; - _fullPath = (+ _parentPath); - _fullPath pushBack (configName _entryCfg); - _condition = compile _condition; - _children = [_entryCfg, _fullPath] call _recurseFnc; + _children = [_entryCfg] call _recurseFnc; _entry = [ [ + configName _entryCfg, _displayName, _icon, - [0,0,0], _statement, _condition, + _insertChildren, + [], + [0,0,0], 10, //distace - [_showDisabled,_enableInside,_canCollapse,_runOnHover], - _fullPath + [_showDisabled,_enableInside,_canCollapse,_runOnHover] ], _children ]; @@ -82,16 +83,18 @@ _actionsCfg = configFile >> "CfgVehicles" >> _objectType >> "ACE_SelfActions"; _actions = [ [ [ + "ACE_SelfActions", "Self Actions", "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa", + {}, + { true }, + {}, + [], "Spine3", - { true }, - { true }, 10, - [false,true,false], - ["ACE_SelfActions"] + [false,true,false] ], - [_actionsCfg, ["ACE_SelfActions"]] call _recurseFnc + [_actionsCfg] call _recurseFnc ] ]; diff --git a/addons/interact_menu/functions/fnc_createAction.sqf b/addons/interact_menu/functions/fnc_createAction.sqf new file mode 100644 index 0000000000..785db2c8b9 --- /dev/null +++ b/addons/interact_menu/functions/fnc_createAction.sqf @@ -0,0 +1,74 @@ +/* + * Author: CAA-Picard + * Creates an isolated ACE action + * Note: This function is NOT global. + * + * Argument: + * 0: Action name + * 1: Name of the action shown in the menu + * 2: Icon + * 3: Statement + * 4: Condition + * 5: Insert children code (Optional) + * 6: Action parameters (Optional) + * 7: Position (Position or Selection Name) or (Optional) + * 8: Distance (Optional) + * 9: Other parameters (Optional) + * + * Return value: + * Action + * + * Example: + * [VulcanPinch","Vulcan Pinch",{_target setDamage 1;},{true},{},[parameters], [0,0,0], 100] call ace_interact_menu_fnc_createAction; + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_5_PVT(_this,_actionName,_displayName,_icon,_statement,_condition); + +private ["_insertChildren","_customParams","_position","_distance","_params"]; + +_insertChildren = if (count _this > 5) then { + _this select 5 +} else { + {} +}; + +_customParams = if (count _this > 6) then { + _this select 6 +} else { + [] +}; + +_position = if (count _this > 7) then { + _this select 7 +} else { + [0,0,0] +}; + +_distance = if (count _this > 8) then { + _this select 8 +} else { + 2 +}; + +_params = if (count _this > 9) then { + _this select 9 +} else { + [false,false,false,false] +}; + +[ + _actionName, + _displayName, + _icon, + _statement, + _condition, + + _insertChildren, + _customParams, + _position, + _distance, + _params +] diff --git a/addons/interact_menu/functions/fnc_findActionNode.sqf b/addons/interact_menu/functions/fnc_findActionNode.sqf new file mode 100644 index 0000000000..41dd32b7d8 --- /dev/null +++ b/addons/interact_menu/functions/fnc_findActionNode.sqf @@ -0,0 +1,56 @@ +/* + * Author: CAA-Picard + * Return action point from path + * Note: This function is NOT global. + * + * Argument: + * 0: List of Action Tree + * 1: Path + * + * Return value: + * Action node . + * + * Example: + * [_actionTree, ["ACE_TapShoulderRight","VulcanPinchAction"]] call ace_interact_menu_fnc_findActionNode; + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_2_PVT(_this,_actionTreeList,_parentPath); + +private ["_parentNode", "_foundParentNode", "_fnc_findFolder"]; + +// Hack to make this work on the root node too +if (count _parentPath == 0) exitWith { + [[],_actionTreeList] +}; + +// Search the class action trees and find where to insert the entry +_parentNode = [[],_actionTreeList]; +_foundParentNode = false; + +_fnc_findFolder = { + EXPLODE_3_PVT(_this,_parentPath,_level,_actionNode); + + { + EXPLODE_2_PVT(_x,_actionData,_actionChildren); + if ((_actionData select 0) isEqualTo (_parentPath select _level)) exitWith { + + if (count _parentPath == _level + 1) exitWith { + _parentNode = _x; + _foundParentNode = true; + }; + + // The action should go somewhere in here + [_parentPath, _level + 1, _x] call _fnc_findFolder; + }; + } forEach (_actionNode select 1); +}; + +[_parentPath, 0, [[],_actionTreeList]] call _fnc_findFolder; + +// Exit if there's no entry point to insert this action +if (!_foundParentNode) exitWith {}; + +_parentNode diff --git a/addons/interact_menu/functions/fnc_isSubPath.sqf b/addons/interact_menu/functions/fnc_isSubPath.sqf new file mode 100644 index 0000000000..1f086fb809 --- /dev/null +++ b/addons/interact_menu/functions/fnc_isSubPath.sqf @@ -0,0 +1,29 @@ +/* + * Author: CAA-Picard + * Check if the first path is a subpath of the other + * + * Argument: + * 0: LongPath + * 1: ShortPath + * + * Return value: + * Bool + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_2_PVT(_this,_longPath,_shortPath); + +private ["_isSubPath","_i"]; +_isSubPath = true; + +if (count _shortPath > count _longPath) exitWith {false}; + +for [{_i = 0},{_i < count _shortPath},{_i = _i + 1}] do { + if !((_longPath select _i) isEqualTo (_shortPath select _i)) exitWith { + _isSubPath = false; + }; +}; + +_isSubPath diff --git a/addons/interact_menu/functions/fnc_keyUp.sqf b/addons/interact_menu/functions/fnc_keyUp.sqf index 716d6dafd8..56285b4c79 100644 --- a/addons/interact_menu/functions/fnc_keyUp.sqf +++ b/addons/interact_menu/functions/fnc_keyUp.sqf @@ -14,9 +14,23 @@ if(GVAR(actionSelected)) then { this = GVAR(selectedTarget); + + private ["_player","_target","_actionData"]; _player = ACE_Player; _target = GVAR(selectedTarget); - [GVAR(selectedTarget), ACE_player] call GVAR(selectedStatement); + + // Clear the conditions caches + ["clearConditionCaches", []] call EFUNC(common,localEvent); + + // Check the action conditions + _actionData = GVAR(selectedAction) select 0; + if ([_target, _player, _actionData select 6] call (_actionData select 4)) then { + // Call the statement + [_target, _player, _actionData select 6] call (_actionData select 3); + + // Clear the conditions caches again if the action was performed + ["clearConditionCaches", []] call EFUNC(common,localEvent); + }; }; if (GVAR(keyDown)) then { diff --git a/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf b/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf index 6346696d53..2c5ab86a8c 100644 --- a/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf +++ b/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf @@ -18,9 +18,23 @@ if (uiNamespace getVariable [QGVAR(cursorMenuOpened),false]) then { if(GVAR(actionSelected)) then { this = GVAR(selectedTarget); + + private ["_player","_target","_actionData"]; _player = ACE_Player; _target = GVAR(selectedTarget); - [GVAR(selectedTarget), ACE_player] call GVAR(selectedStatement); + + // Clear the conditions caches + ["clearConditionCaches", []] call EFUNC(common,localEvent); + + // Check the action conditions + _actionData = GVAR(selectedAction) select 0; + if ([_target, _player, _actionData select 6] call (_actionData select 4)) then { + // Call the statement + [_target, _player, _actionData select 6] call (_actionData select 3); + + // Clear the conditions caches again if the action was performed + ["clearConditionCaches", []] call EFUNC(common,localEvent); + }; }; if (GVAR(keyDownSelfAction)) then { diff --git a/addons/interact_menu/functions/fnc_removeActionFromClass.sqf b/addons/interact_menu/functions/fnc_removeActionFromClass.sqf new file mode 100644 index 0000000000..aee1675fa7 --- /dev/null +++ b/addons/interact_menu/functions/fnc_removeActionFromClass.sqf @@ -0,0 +1,39 @@ +/* + * Author: CAA-Picard + * Removes an action from a class + * + * Argument: + * 0: TypeOf of the class + * 1: Type of action, 0 for actions, 1 for self-actions + * 2: Full path of the new action + * + * Return value: + * None + * + * Example: + * [typeOf cursorTarget, 0,["ACE_TapShoulderRight","VulcanPinch"]] call ace_interact_menu_fnc_removeActionFromClass; + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_3_PVT(_this,_objectType,_typeNum,_fullPath); + +private ["_res","_varName","_actionTrees"]; +_res = _fullPath call FUNC(splitPath); +EXPLODE_2_PVT(_res,_parentPath,_actionName); + +_varName = format [[QGVAR(Act_%1), QGVAR(SelfAct_%1)] select _typeNum, _objectType]; +_actionTrees = missionNamespace getVariable [_varName, []]; + +_parentNode = [_actionTrees, _parentPath] call FUNC(findActionNode); +if (isNil {_parentNode}) exitWith {}; + +// Iterate through children of the father +{ + if (((_x select 0) select 0) == _actionName) exitWith { + (_parentNode select 1) deleteAt _forEachIndex; + }; +} forEach (_parentNode select 1); + +_parentLevel deleteAt _actionIndex; diff --git a/addons/interact_menu/functions/fnc_removeAction.sqf b/addons/interact_menu/functions/fnc_removeActionFromObject.sqf similarity index 53% rename from addons/interact_menu/functions/fnc_removeAction.sqf rename to addons/interact_menu/functions/fnc_removeActionFromObject.sqf index 3c6988971d..dc5fdc05f0 100644 --- a/addons/interact_menu/functions/fnc_removeAction.sqf +++ b/addons/interact_menu/functions/fnc_removeActionFromObject.sqf @@ -1,30 +1,33 @@ -/* - * Author: commy2, NouberNou and CAA-Picard - * Remove an action from an object - * - * Argument: - * 0: Object the action is assigned to - * 1: Type of action, 0 for actions, 1 for self-actions - * 2: Full path of the action to remove - * - * Return value: - * None - * - * Example: - * [cursorTarget,0,["ACE_TapShoulderRight","VulcanPinch"]] call ace_interact_menu_fnc_removeAction; - * - * Public: No - */ -#include "script_component.hpp" - -EXPLODE_3_PVT(_this,_object,_typeNum,_fullPath); - -private ["_varName","_actions"]; -_varName = [QGVAR(actions),QGVAR(selfActions)] select _typeNum; -_actions = _object getVariable [_varName, []]; - -{ - if (((_x select 0) select 7) isEqualTo _fullPath) exitWith { - _actions deleteAt _forEachIndex; - }; -} forEach _actions; +/* + * Author: commy2, NouberNou and CAA-Picard + * Removes an action from an object + * + * Argument: + * 0: Object the action is assigned to + * 1: Type of action, 0 for actions, 1 for self-actions + * 2: Full path of the action to remove + * + * Return value: + * None + * + * Example: + * [cursorTarget,0,["ACE_TapShoulderRight","VulcanPinch"]] call ace_interact_menu_fnc_removeActionFromObject; + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_3_PVT(_this,_object,_typeNum,_fullPath); + +private ["_res","_varName","_actionList"]; +_res = _fullPath call FUNC(splitPath); +EXPLODE_2_PVT(_res,_parentPath,_actionName); + +_varName = [QGVAR(actions),QGVAR(selfActions)] select _typeNum; +_actionList = _object getVariable [_varName, []]; +{ + if (((_x select 0) select 0) isEqualTo _actionName && + {(_x select 1) isEqualTo _parentPath}) exitWith { + _actionList deleteAt _forEachIndex; + }; +} forEach _actionList; diff --git a/addons/interact_menu/functions/fnc_removeClassAction.sqf b/addons/interact_menu/functions/fnc_removeClassAction.sqf deleted file mode 100644 index 9ba29cd357..0000000000 --- a/addons/interact_menu/functions/fnc_removeClassAction.sqf +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Author: CAA-Picard - * Removes a class action from a class - * Note: This function is NOT global. - * - * Argument: - * 0: TypeOf of the class - * 1: Type of action, 0 for actions, 1 for self-actions - * 2: Full path of the new action - * - * Return value: - * None - * - * Example: - * [typeOf cursorTarget, 0,["ACE_TapShoulderRight","VulcanPinch"]] call ace_interact_menu_fnc_removeClassAction; - * - * Public: No - */ -#include "script_component.hpp" - -EXPLODE_3_PVT(_this,_objectType,_typeNum,_fullPath); - -private ["_varName","_actions","_parentLevel", "_actionIndex", "_foundAction", "_fnc_findFolder"]; - -_varName = format [[QGVAR(Act_%1), QGVAR(SelfAct_%1)] select _typeNum, _objectType]; -_actions = missionNamespace getVariable [_varName, []]; - -// Search the class action trees and find where to insert the entry -_parentLevel = _actions; -_actionIndex = -1; -_foundAction = false; - -_fnc_findFolder = { - EXPLODE_3_PVT(_this,_fullPath,_level,_classActions); - - if (count _fullPath == _level + 1) then { - _parentLevel = _classActions; - }; - - { - EXPLODE_2_PVT(_x,_actionData,_actionChildren); - if (((_actionData select 7) select _level) isEqualTo (_fullPath select _level)) exitWith { - if (_level + 1 == count _fullPath) exitWith { - _actionIndex = _forEachIndex; - _foundAction = true; - }; - [_fullPath, _level + 1, _actionChildren] call _fnc_findFolder; - }; - if (_foundAction) exitWith {}; - } forEach _classActions; -}; - -[_fullPath, 0, _actions] call _fnc_findFolder; - -// Exit if the action was not found -if (!_foundAction) exitWith {}; - -_entry = [ - [ - _displayName, - _icon, - _position, - _statement, - _condition, - _distance, - _params, - + _fullPath - ], - [] - ]; - -_parentLevel deleteAt _actionIndex; diff --git a/addons/interact_menu/functions/fnc_render.sqf b/addons/interact_menu/functions/fnc_render.sqf index 3930068c25..523520ee91 100644 --- a/addons/interact_menu/functions/fnc_render.sqf +++ b/addons/interact_menu/functions/fnc_render.sqf @@ -41,17 +41,17 @@ if (GVAR(keyDown)) then { // Iterate through object actions, find base level actions and render them if appropiate _actionsVarName = format [QGVAR(Act_%1), typeOf _target]; - GVAR(objectActions) = _target getVariable [QGVAR(actions), []]; + GVAR(objectActionList) = _target getVariable [QGVAR(actions), []]; { - _action = _x; // Only render them directly if they are base level actions - if (count ((_action select 0) select 7) == 1) then { + if (count (_x select 1) == 0) then { // Try to render the menu + _action = [_x,[]]; if ([_target, _action] call FUNC(renderBaseMenu)) then { _numInteractions = _numInteractions + 1; }; }; - } forEach GVAR(objectActions); + } forEach GVAR(objectActionList); // Iterate through base level class actions and render them if appropiate _classActions = missionNamespace getVariable [_actionsVarName, []]; @@ -80,7 +80,7 @@ if (GVAR(keyDown)) then { // Iterate through object actions, find base level actions and render them if appropiate _actionsVarName = format [QGVAR(SelfAct_%1), typeOf _target]; - GVAR(objectActions) = _target getVariable [QGVAR(selfActions), []]; + GVAR(objectActionList) = _target getVariable [QGVAR(selfActions), []]; /* { _action = _x; @@ -88,7 +88,7 @@ if (GVAR(keyDown)) then { if (count (_action select 7) == 1) then { [_target, _action, 0, [180, 360]] call FUNC(renderMenu); }; - } forEach GVAR(objectActions); + } forEach GVAR(objectActionList); */ // Iterate through base level class actions and render them if appropiate @@ -142,9 +142,8 @@ if(GVAR(keyDown) || GVAR(keyDownSelfAction)) then { drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,0,.75], _pos, 0.6*SafeZoneW, 0.6*SafeZoneW, GVAR(rotationAngle), "", 0.5, 0.025, "TahomaB"]; _foundTarget = true; GVAR(actionSelected) = true; - GVAR(selectedTarget) = (_closest select 0) select 0; GVAR(selectedAction) = (_closest select 0) select 1; - GVAR(selectedStatement) = ((GVAR(selectedAction)) select 0) select 3; + GVAR(selectedTarget) = (GVAR(selectedAction)) select 2; _misMatch = false; _hoverPath = (_closest select 2); @@ -153,29 +152,46 @@ if(GVAR(keyDown) || GVAR(keyDownSelfAction)) then { _misMatch = true; } else { { - if(_x != (_hoverPath select _forEachIndex)) exitWith { + if !(_x isEqualTo (_hoverPath select _forEachIndex)) exitWith { _misMatch = true; }; } forEach GVAR(lastPath); }; - if(_misMatch) then { - GVAR(lastPath) = _hoverPath; + if(_misMatch && {diag_tickTime-GVAR(expandedTime) > 0.25}) then { GVAR(startHoverTime) = diag_tickTime; + GVAR(lastPath) = _hoverPath; GVAR(expanded) = false; } else { if(!GVAR(expanded) && diag_tickTime-GVAR(startHoverTime) > 0.25) then { GVAR(expanded) = true; + + // Start the expanding menu animation only if the user is not going up the menu + if !([GVAR(menuDepthPath),GVAR(lastPath)] call FUNC(isSubPath)) then { + GVAR(expandedTime) = diag_tickTime; + }; GVAR(menuDepthPath) = +GVAR(lastPath); // Execute the current action if it's run on hover private "_runOnHover"; - _runOnHover = ((GVAR(selectedAction) select 0) select 6) select 3; + _runOnHover = ((GVAR(selectedAction) select 0) select 9) select 3; if (_runOnHover) then { this = GVAR(selectedTarget); _player = ACE_Player; _target = GVAR(selectedTarget); - [GVAR(selectedTarget), ACE_player] call GVAR(selectedStatement); + + // Clear the conditions caches + ["clearConditionCaches", []] call EFUNC(common,localEvent); + + // Check the action conditions + _actionData = GVAR(selectedAction) select 0; + if ([_target, _player, _actionData select 6] call (_actionData select 4)) then { + // Call the statement + [_target, _player, _actionData select 6] call (_actionData select 3); + + // Clear the conditions caches again if the action was performed + ["clearConditionCaches", []] call EFUNC(common,localEvent); + }; }; }; }; diff --git a/addons/interact_menu/functions/fnc_renderBaseMenu.sqf b/addons/interact_menu/functions/fnc_renderBaseMenu.sqf index e3a8a0c9a4..b73c3c4979 100644 --- a/addons/interact_menu/functions/fnc_renderBaseMenu.sqf +++ b/addons/interact_menu/functions/fnc_renderBaseMenu.sqf @@ -4,7 +4,7 @@ * * Argument: * 0: Object - * 1: Action data + * 1: Action node * 2: 3D position (Optional) * * Return value: @@ -16,25 +16,25 @@ private ["_distance","_pos","_weaponDir","_ref","_cameraPos","_sPos","_activeActionTree"]; -EXPLODE_2_PVT(_this,_object,_baseAction); -EXPLODE_1_PVT(_baseAction,_actionData); +EXPLODE_2_PVT(_this,_object,_baseActionNode); +EXPLODE_1_PVT(_baseActionNode,_actionData); -_distance = _actionData select 5; +_distance = _actionData select 8; // Obtain a 3D position for the action if((count _this) > 2) then { _pos = _this select 2; } else { - if(typeName (_actionData select 2) == "ARRAY") then { - _pos = _object modelToWorld (_actionData select 2); + if(typeName (_actionData select 7) == "ARRAY") then { + _pos = _object modelToWorld (_actionData select 7); } else { - if ((_actionData select 2) == "weapon") then { + if ((_actionData select 7) == "weapon") then { // Craft a suitable position for weapon interaction _weaponDir = _object weaponDirection currentWeapon _object; _ref = _weaponDir call EFUNC(common,createOrthonormalReference); _pos = (_object modelToWorld (_object selectionPosition "righthand")) vectorAdd ((_ref select 2) vectorMultiply 0.1); } else { - _pos = _object modelToWorld (_object selectionPosition (_actionData select 2)); + _pos = _object modelToWorld (_object selectionPosition (_actionData select 7)); }; }; // Compensate for movement during the frame to get rid of jittering @@ -59,19 +59,30 @@ if ((_sPos select 1) < safeZoneY || (_sPos select 1) > safeZoneY + safeZon // Collect active tree private "_uid"; -_uid = format [QGVAR(ATCache_%1), (_actionData select 7) select 0]; +_uid = format [QGVAR(ATCache_%1), _actionData select 0]; _activeActionTree = [ - [_object, _baseAction], + [_object, _baseActionNode, []], DFUNC(collectActiveActionTree), - _object, _uid, 0.2 + _object, _uid, 1.0, "interactMenuClosed" ] call EFUNC(common,cachedCall); - +/* +diag_log "Printing: _activeActionTree"; +_fnc_print = { + EXPLODE_2_PVT(_this,_level,_node); + EXPLODE_3_PVT(_node,_actionData,_children,_object); + diag_log text format ["Level %1 -> %2 on %3", _level, _actionData select 0, _object]; + { + [_level + 1, _x] call _fnc_print; + } forEach _children; +}; +[0, _activeActionTree] call _fnc_print; +*/ // Check if there's something left for rendering if (count _activeActionTree == 0) exitWith {false}; //EXPLODE_2_PVT(_activeActionTree,_actionData,_actionChildren); -[_object, _activeActionTree, _pos, [180,360]] call FUNC(renderMenu); +[[], _activeActionTree, _pos, [180,360]] call FUNC(renderMenu); true diff --git a/addons/interact_menu/functions/fnc_renderMenu.sqf b/addons/interact_menu/functions/fnc_renderMenu.sqf index ad604b9fa5..26b07dd475 100644 --- a/addons/interact_menu/functions/fnc_renderMenu.sqf +++ b/addons/interact_menu/functions/fnc_renderMenu.sqf @@ -3,7 +3,7 @@ * Render an interaction menu and it's children recursively * * Argument: - * 0: Object + * 0: Parent path * 1: Action data * 2: 3D position * 3: Angle range available for rendering @@ -17,14 +17,15 @@ private ["_menuInSelectedPath", "_path", "_menuDepth", "_currentRenderDepth", "_x", "_offset", "_newPos", "_forEachIndex"]; -EXPLODE_4_PVT(_this,_object,_action,_pos,_angles); -EXPLODE_2_PVT(_action,_actionData,_activeChildren); +EXPLODE_4_PVT(_this,_parentPath,_action,_pos,_angles); +EXPLODE_3_PVT(_action,_actionData,_activeChildren,_actionObject); EXPLODE_2_PVT(_angles,_centerAngle,_maxAngleSpan); -_menuDepth = (count GVAR(menuDepthPath)) - 1; +_menuDepth = (count GVAR(menuDepthPath)); // Store path to action -_path = [_object] + (_actionData select 7); +_path = +_parentPath; +_path pushBack [_actionData select 0,_actionObject]; // Check if the menu is on the selected path _menuInSelectedPath = true; @@ -32,7 +33,7 @@ _menuInSelectedPath = true; if (_forEachIndex >= (count GVAR(menuDepthPath))) exitWith { _menuInSelectedPath = false; }; - if (_x != (GVAR(menuDepthPath) select _forEachIndex)) exitWith { + if !(_x isEqualTo (GVAR(menuDepthPath) select _forEachIndex)) exitWith { _menuInSelectedPath = false; }; } forEach _path; @@ -42,12 +43,12 @@ _menuInSelectedPath = true; _color = "#FFFFFFFF"; if(!_menuInSelectedPath) then { //_menuDepth > 0 && if (_menuDepth > 0) then { - _color = format ["#%1FFFFFF", [255 * ((((count _path) - 2)/_menuDepth) max 0.25)] call EFUNC(common,toHex)]; + _color = format ["#%1FFFFFF", [255 * ((((count _path) - 1)/_menuDepth) max 0.25)] call EFUNC(common,toHex)]; } else { _color = format ["#%1FFFFFF", [255 * 0.75] call EFUNC(common,toHex)]; }; }; -[_actionData select 0, _color, _pos, 1, 1, 0, _actionData select 1, 0.5, 0.025, "TahomaB"] call FUNC(renderIcon); +[_actionData select 1, _color, _pos, 1, 1, 0, _actionData select 2, 0.5, 0.025, "TahomaB"] call FUNC(renderIcon); // Add the action to current options GVAR(currentOptions) pushBack [_this, _pos, _path]; @@ -55,26 +56,44 @@ GVAR(currentOptions) pushBack [_this, _pos, _path]; // Exit without rendering children if it isn't if !(_menuInSelectedPath) exitWith {true}; -private ["_angleSpan","_angle"]; +private ["_angleSpan","_angle","_angleInterval","_scale"]; _angleSpan = _maxAngleSpan min (55 * ((count _activeChildren) - 1)); if (_angleSpan >= 305) then { _angleSpan = 360; }; +_angleInterval = 55; +if (_angleSpan < 360) then { + if (count _activeChildren > 1) then { + _angleInterval = _angleSpan / (count _activeChildren - 1); + }; +} else { + _angleSpan / (count _activeChildren); +}; +if (count _activeChildren == 1) then { + _angleInterval = 60; +}; + +// Scale menu based on distance +_scale = (0.15 max (0.15 * ((positionCameraToWorld [0, 0, 0]) distance _pos))) / GVAR(selfMenuScale); +// Scale menu based on the amount of children +_scale = _scale * (((0.8 * (0.46 / sin (0.5 * _angleInterval))) min 1.4) max 0.5); +// Animate menu scale +if (_menuInSelectedPath && (_menuDepth == count _path)) then { + _scale = _scale * (0.3 + 0.7 * (((diag_tickTime - GVAR(expandedTime)) * 8) min 1)); +}; _angle = _centerAngle - _angleSpan / 2; { - _target = _object; + _target = _actionObject; _player = ACE_player; - _mod = (0.15 max (0.15 * ((positionCameraToWorld [0, 0, 0]) distance _pos))) / GVAR(selfMenuScale); - - _offset = ((GVAR(refSystem) select 1) vectorMultiply (-_mod * cos _angle)) vectorAdd - ((GVAR(refSystem) select 2) vectorMultiply (-_mod * sin _angle)); + _offset = ((GVAR(refSystem) select 1) vectorMultiply (-_scale * cos _angle)) vectorAdd + ((GVAR(refSystem) select 2) vectorMultiply (-_scale * sin _angle)); _newPos = ((_pos call EFUNC(common,positionToASL)) vectorAdd _offset) call EFUNC(common,ASLToPosition); - //drawLine3D [_pos, _newPos, [1,0,0,0.5]]; + //drawLine3D [_pos, _newPos, [1,0,0,0.8]]; - [_object, _x, _newPos, [_angle, 140]] call FUNC(renderMenu); + [_path, _x, _newPos, [_angle, 140]] call FUNC(renderMenu); if (_angleSpan == 360) then { _angle = _angle + _angleSpan / (count _activeChildren); diff --git a/addons/interact_menu/functions/fnc_splitPath.sqf b/addons/interact_menu/functions/fnc_splitPath.sqf new file mode 100644 index 0000000000..87140d0482 --- /dev/null +++ b/addons/interact_menu/functions/fnc_splitPath.sqf @@ -0,0 +1,27 @@ +/* + * Author: CAA-Picard + * Take full path and split it between parent path and action name + * + * Argument: + * Full path of the action to remove + * + * Return value: + * 0: Parent path + * 1: Action name + * + * Public: No + */ +#include "script_component.hpp" + +private ["_parentPath","_actionName"]; +_parentPath = []; +for [{_i = 0},{_i < (count _this) - 1},{_i = _i + 1}] do { + _parentPath pushBack (_this select _i); +}; +_actionName = if (count _this > 0) then { + _this select ((count _this) - 1); +} else { + "" +}; + +[_parentPath, _actionName] diff --git a/addons/interaction/CfgVehicles.hpp b/addons/interaction/CfgVehicles.hpp index 1bd1e81be2..51bdd6013d 100644 --- a/addons/interaction/CfgVehicles.hpp +++ b/addons/interaction/CfgVehicles.hpp @@ -31,7 +31,7 @@ class CfgVehicles { condition = QUOTE(true); statement = ""; icon = "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa"; - selection = "spine3"; + selection = "pelvis"; class ACE_TeamManagement { displayName = "$STR_ACE_Interaction_TeamManagement"; @@ -140,45 +140,52 @@ class CfgVehicles { enableInside = 1; }; }; + class ACE_Torso { + displayName = "$STR_ACE_Interaction_Torso"; + selection = "spine3"; + distance = 1.50; + condition = ""; + statement = ""; + }; class ACE_Head { displayName = "$STR_ACE_Interaction_Head"; selection = "pilot"; - distance = 2.0; + distance = 1.50; condition = ""; statement = ""; }; class ACE_ArmLeft { displayName = "$STR_ACE_Interaction_ArmLeft"; selection = "LeftForeArm"; - distance = 2.0; + distance = 1.50; condition = ""; statement = ""; }; class ACE_ArmRight { displayName = "$STR_ACE_Interaction_ArmRight"; selection = "RightForeArm"; - distance = 2.0; + distance = 1.50; condition = ""; statement = ""; }; class ACE_LegLeft { displayName = "$STR_ACE_Interaction_LegLeft"; selection = "LKnee"; - distance = 2.0; + distance = 1.50; condition = ""; statement = ""; }; class ACE_LegRight { displayName = "$STR_ACE_Interaction_LegRight"; selection = "RKnee"; - distance = 2.0; + distance = 1.50; condition = ""; statement = ""; }; class ACE_Weapon { displayName = "$STR_ACE_Interaction_Weapon"; selection = "weapon"; - distance = 2.0; + distance = 1.50; condition = ""; statement = ""; }; @@ -412,7 +419,14 @@ class CfgVehicles { condition = "true"; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class Tank: LandVehicle { class ACE_Actions { @@ -423,7 +437,14 @@ class CfgVehicles { condition = "true"; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class Air; @@ -436,7 +457,14 @@ class CfgVehicles { condition = "true"; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class Plane: Air { class ACE_Actions { @@ -447,7 +475,14 @@ class CfgVehicles { condition = "true"; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class Ship; @@ -469,7 +504,14 @@ class CfgVehicles { }; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class StaticWeapon: LandVehicle { @@ -481,7 +523,14 @@ class CfgVehicles { condition = "true"; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class StaticMortar; @@ -494,7 +543,14 @@ class CfgVehicles { condition = "true"; }; }; - class ACE_SelfActions {}; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addPassengersActions)); + }; + }; }; class thingX; diff --git a/addons/interaction/XEH_clientInit.sqf b/addons/interaction/XEH_clientInit.sqf index e303fae857..76647e54a3 100644 --- a/addons/interaction/XEH_clientInit.sqf +++ b/addons/interaction/XEH_clientInit.sqf @@ -19,7 +19,7 @@ GVAR(isOpeningDoor) = false; ["ACE3", QGVAR(openDoor), localize "STR_ACE_Interaction_OpenDoor", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if (GVAR(isOpeningDoor) || {[2] call FUNC(getDoor) select 1 == ''}) exitWith {false}; @@ -39,7 +39,7 @@ GVAR(isOpeningDoor) = false; ["ACE3", QGVAR(tapShoulder), localize "STR_ACE_Interaction_TapShoulder", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player, cursorTarget] call FUNC(canTapShoulder)) exitWith {false}; @@ -53,7 +53,7 @@ GVAR(isOpeningDoor) = false; ["ACE3", QGVAR(modifierKey), localize "STR_ACE_Interaction_ModifierKey", { // Conditions: canInteract - //if !([ACE_player, objNull, ["isNotDragging"]] call EGVAR(common,canInteractWith)) exitWith {false}; // not needed + //if !([ACE_player, objNull, ["isNotDragging"]] call EFUNC(common,canInteractWith)) exitWith {false}; // not needed // Statement ACE_Modifier = 1; diff --git a/addons/interaction/XEH_preInit.sqf b/addons/interaction/XEH_preInit.sqf index 6efa72778e..671535c36d 100644 --- a/addons/interaction/XEH_preInit.sqf +++ b/addons/interaction/XEH_preInit.sqf @@ -2,6 +2,8 @@ ADDON = false; +PREP(addPassengerActions); +PREP(addPassengersActions); PREP(addSelectableItem); PREP(applyButtons); PREP(canInteractWithCivilian); diff --git a/addons/interaction/config.cpp b/addons/interaction/config.cpp index a39e8f8bf5..d5d9d63d69 100644 --- a/addons/interaction/config.cpp +++ b/addons/interaction/config.cpp @@ -5,7 +5,7 @@ class CfgPatches { units[] = {}; weapons[] = {}; requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ace_common"}; + requiredAddons[] = {"ace_interact_menu"}; author[] = {"commy2", "KoffeinFlummi", "CAA-Picard", "bux578"}; authorUrl = "https://github.com/commy2/"; VERSION_CONFIG; diff --git a/addons/interaction/functions/fnc_addPassengerActions.sqf b/addons/interaction/functions/fnc_addPassengerActions.sqf new file mode 100644 index 0000000000..dfe3b2e9b6 --- /dev/null +++ b/addons/interaction/functions/fnc_addPassengerActions.sqf @@ -0,0 +1,31 @@ +/* + * Author: CAA-Picard + * Mount unit actions inside passenger submenu + * + * Argument: + * 0: Vehicle + * 1: Player + * 3: Parameters + * + * Return value: + * Children actions + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_3_PVT(_this,_vehicle,_player,_parameters); + +diag_log "addPassengerActions"; + +private ["_unit","_actions"]; +_unit = _parameters select 0; + +_varName = format [QEGVAR(interact_menu,Act_%1), typeOf _unit]; +_actionTrees = missionNamespace getVariable [_varName, []]; + +_actions = []; +// Mount unit MainActions menu +_actions pushBack [(_actionTrees select 0) select 0, (_actionTrees select 0) select 1, _unit]; + +_actions diff --git a/addons/interaction/functions/fnc_addPassengersActions.sqf b/addons/interaction/functions/fnc_addPassengersActions.sqf new file mode 100644 index 0000000000..de0c91e767 --- /dev/null +++ b/addons/interaction/functions/fnc_addPassengersActions.sqf @@ -0,0 +1,42 @@ +/* + * Author: CAA-Picard + * Create one action per passenger + * + * Argument: + * 0: Vehicle + * 1: Player + * 3: Parameters + * + * Return value: + * Children actions + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_3_PVT(_this,_vehicle,_player,_parameters); + +private ["_actions"]; +_actions = []; + +{ + _unit = _x; + if (_x != _player) then { + _actions pushBack + [ + [ + str(_unit), + [_unit, true] call EFUNC(common,getName), + "", + {}, + {true}, + {_this call FUNC(addPassengerActions);}, + [_unit] + ] call EFUNC(interact_menu,createAction), + [], + _unit + ]; + }; +} forEach crew _vehicle; + +_actions \ No newline at end of file diff --git a/addons/interaction/functions/fnc_openDoor.sqf b/addons/interaction/functions/fnc_openDoor.sqf index 0d67ae7a55..dc9150491d 100644 --- a/addons/interaction/functions/fnc_openDoor.sqf +++ b/addons/interaction/functions/fnc_openDoor.sqf @@ -47,7 +47,7 @@ playSound "ACE_Sound_Click"; !GVAR(isOpeningDoor) || {getPosASL ACE_player distance _position > 1} }; - if (!_usedMouseWheel && {time < _time} && {[ACE_player, objNull, []] call EGVAR(common,canInteractWith)}) then { + if (!_usedMouseWheel && {time < _time} && {[ACE_player, objNull, []] call EFUNC(common,canInteractWith)}) then { _phase = [0, 1] select (_house animationPhase (_animations select 0) < 0.5); {_house animate [_x, _phase]} forEach _animations; diff --git a/addons/interaction/functions/fnc_tapShoulder.sqf b/addons/interaction/functions/fnc_tapShoulder.sqf index 262012dbb9..297de3fff8 100644 --- a/addons/interaction/functions/fnc_tapShoulder.sqf +++ b/addons/interaction/functions/fnc_tapShoulder.sqf @@ -5,7 +5,7 @@ EXPLODE_3_PVT(_this,_tapper,_target,_shoulderNum); if (_target != ACE_player) exitWith { addCamShake [4, 0.5, 5]; - ACE_player playActionNow 'gestureAdvance'; + ACE_player playActionNow "PutDown"; if !(local _target) then { [[_tapper, _target, _shoulderNum], QUOTE(DFUNC(tapShoulder)), _target] call EFUNC(common,execRemoteFnc); }; diff --git a/addons/interaction/stringtable.xml b/addons/interaction/stringtable.xml index 76898cd227..4940d42e0f 100644 --- a/addons/interaction/stringtable.xml +++ b/addons/interaction/stringtable.xml @@ -5,6 +5,9 @@ Interactions >> + + Torso >> + Head >> @@ -650,5 +653,8 @@ Interakcja Interactuar + + Passengers >> + diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 8425c4ad1e..ff2c4d615e 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -190,15 +190,21 @@ #define GETVAR(var1,var2,var3) var1 GETVAR_SYS(var2,var3) #define GETMVAR(var1,var2) missionNamespace GETVAR_SYS(var1,var2) #define GETUVAR(var1,var2) uiNamespace GETVAR_SYS(var1,var2) +#define GETPRVAR(var1,var2) profileNamespace GETVAR_SYS(var1,var2) +#define GETPAVAR(var1,var2) parsingNamespace GETVAR_SYS(var1,var2) #define SETVAR(var1,var2,var3) var1 SETVAR_SYS(var2,var3) #define SETPVAR(var1,var2,var3) var1 SETPVAR_SYS(var2,var3) #define SETMVAR(var1,var2) missionNamespace SETVAR_SYS(var1,var2) #define SETUVAR(var1,var2) uiNamespace SETVAR_SYS(var1,var2) +#define SETPRVAR(var1,var2) profileNamespace SETVAR_SYS(var1,var2) +#define SETPAVAR(var1,var2) parsingNamespace SETVAR_SYS(var1,var2) #define GETGVAR(var1,var2) GETMVAR(GVAR(var1),var2) #define GETEGVAR(var1,var2,var3) GETMVAR(EGVAR(var1,var2),var3) +#define ARR_SELECT(ARRAY,INDEX,DEFAULT) if (count ARRAY > INDEX) then {ARRAY select INDEX} else {DEFAULT} + #define MACRO_ADDWEAPON(WEAPON,COUNT) class _xx_##WEAPON { \ weapon = #WEAPON; \ diff --git a/addons/maptools/$PBOPREFIX$ b/addons/maptools/$PBOPREFIX$ index 11a24a58d8..15fe8ae13f 100644 --- a/addons/maptools/$PBOPREFIX$ +++ b/addons/maptools/$PBOPREFIX$ @@ -1 +1 @@ -z\ace\Addons\map \ No newline at end of file +z\ace\Addons\maptools \ No newline at end of file diff --git a/addons/medical/ACE_Medical_Treatments.hpp b/addons/medical/ACE_Medical_Treatments.hpp index b34403148e..28a9b82d8c 100644 --- a/addons/medical/ACE_Medical_Treatments.hpp +++ b/addons/medical/ACE_Medical_Treatments.hpp @@ -1,16 +1,15 @@ class ACE_Medical_Actions { class Basic { - // @todo: localization class Bandage { - displayName = "Bandage"; - displayNameProgress = "Bandaging ..."; + displayName = "$STR_ACE_Medical_Bandage"; + displayNameProgress = "$STR_ACE_Medical_Bandaging"; treatmentLocations[] = {"All"}; requiredMedic = 0; treatmentTime = 5; treatmentTimeSelfCoef = 1; - items[] = {{QGVAR(fieldDressing), QGVAR(packingBandage), QGVAR(elasticBandage), QGVAR(quikClot)}}; + items[] = {{"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_quikclot"}}; condition = ""; itemConsumed = 1; @@ -25,28 +24,28 @@ class ACE_Medical_Actions { animationCallerSelfProne = "AinvPpneMstpSlayW[wpn]Dnon_medic"; }; class Morphine: Bandage { - displayName = "Morphine"; - displayNameProgress = "Injecting Morphine ..."; + displayName = "$STR_ACE_Medical_Inject_Morphine"; + displayNameProgress = "$STR_ACE_Medical_Injecting_Morphine"; treatmentTime = 2; - items[] = {QGVAR(morphine)}; + items[] = {"ACE_morphine"}; callbackSuccess = QUOTE(DFUNC(treatmentBasic_morphine)); animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; - class Epipen: Bandage { - displayName = "Epinephrine"; - displayNameProgress = "Injecting Epinephrine ..."; + class Epinephrine: Bandage { + displayName = "$STR_ACE_Medical_Inject_Epinephrine"; + displayNameProgress = "$STR_ACE_Medical_Injecting_Epinephrine"; requiredMedic = 1; treatmentTime = 3; - items[] = {QGVAR(epipen)}; + items[] = {"ACE_epinephrine"}; callbackSuccess = QUOTE(DFUNC(treatmentBasic_epipen)); animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; - class Bloodbag: Bandage { - displayName = "Blood Bag"; - displayNameProgress = "Transfusing Blood ..."; + class BloodIV: Bandage { + displayName = "$STR_ACE_Medical_Transfuse_Blood"; + displayNameProgress = "$STR_ACE_Medical_Transfusing_Blood"; requiredMedic = 1; treatmentTime = 20; - items[] = {{QGVAR(bloodIV), QGVAR(bloodIV_500), QGVAR(bloodIV_250)}}; + items[] = {{"ACE_bloodIV", "ACE_bloodIV_500", "ACE_bloodIV_250"}}; callbackSuccess = QUOTE(DFUNC(treatmentBasic_bloodbag)); animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; @@ -61,7 +60,7 @@ class ACE_Medical_Actions { // The time it takes for a treatment action to complete. Time is in seconds. treatmentTime = 5; // Item required for the action. Leave empty for no item required. - items[] = {QGVAR(fieldDressing)}; + items[] = {"ACE_fieldDressing"}; condition = ""; // Callbacks callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_bandage)); @@ -75,67 +74,67 @@ class ACE_Medical_Actions { animationCallerSelfProne = "AinvPpneMstpSlayW[wpn]Dnon_medic"; }; class PackingBandage: fieldDressing { - items[] = {QGVAR(packingBandage)}; + items[] = {"ACE_packingBandage"}; }; class ElasticBandage: fieldDressing { - items[] = {QGVAR(elasticBandage)}; + items[] = {"ACE_elasticBandage"}; }; class QuikClot: fieldDressing { - items[] = {QGVAR(quikClot)}; + items[] = {"ACE_quikclot"}; }; class Tourniquet: fieldDressing { - items[] = {QGVAR(tourniquet)}; + items[] = {"ACE_tourniquet"}; treatmentTime = 6; callbackSuccess = QUOTE(DFUNC(treatmentTourniquet)); condition = QUOTE(!([ARR_2(_this select 1, _this select 2)] call FUNC(hasTourniquetAppliedTo))); }; class Morphine: fieldDressing { - items[] = {QGVAR(morphine)}; + items[] = {"ACE_morphine"}; treatmentTime = 3; callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_medication)); animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; class Atropine: Morphine { - items[] = {QGVAR(atropine)}; + items[] = {"ACE_atropine"}; }; class Epinephrine: Morphine { - items[] = {QGVAR(epinephrine)}; + items[] = {"ACE_epinephrine"}; }; class BloodIV: fieldDressing { - items[] = {QGVAR(bloodIV)}; + items[] = {"ACE_bloodIV"}; requiredMedic = 1; treatmentTime = 7; callbackSuccess = QUOTE(DFUNC(treatmentIV)); animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; class BloodIV_500: BloodIV { - items[] = {QGVAR(bloodIV_500)}; + items[] = {"ACE_bloodIV_500"}; }; class BloodIV_250: BloodIV { - items[] = {QGVAR(bloodIV_250)}; + items[] = {"ACE_bloodIV_250"}; }; class PlasmaIV: BloodIV { - items[] = {QGVAR(plasmaIV)}; + items[] = {"ACE_plasmaIV"}; animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; class PlasmaIV_500: PlasmaIV { - items[] = {QGVAR(plasmaIV_500)}; + items[] = {"ACE_plasmaIV_500"}; }; class PlasmaIV_250: PlasmaIV { - items[] = {QGVAR(plasmaIV_250)}; + items[] = {"ACE_plasmaIV_250"}; }; class SalineIV: BloodIV { - items[] = {QGVAR(salineIV)}; + items[] = {"ACE_salineIV"}; animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; class SalineIV_500: SalineIV { - items[] = {QGVAR(salineIV_500)}; + items[] = {"ACE_salineIV_500"}; }; class SalineIV_250: SalineIV { - items[] = {QGVAR(salineIV_250)}; + items[] = {"ACE_salineIV_250"}; }; class SurgicalKit: fieldDressing { - items[] = {QGVAR(surgicalKit)}; + items[] = {"ACE_surgicalKit"}; treatmentLocations[] = {"MedicalFacility", "MedicalVehicle"}; requiredMedic = 2; treatmentTime = 15; @@ -144,7 +143,7 @@ class ACE_Medical_Actions { animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; }; class PersonalAidKit: fieldDressing { - items[] = {QGVAR(personalAidKit)}; + items[] = {"ACE_personalAidKit"}; treatmentLocations[] = {"All"}; requiredMedic = 1; treatmentTime = 15; @@ -192,7 +191,7 @@ class ACE_Medical_Actions { treatmentLocations[] = {"All"}; requiredMedic = 0; treatmentTime = 7.5; - items[] = {QGVAR(bodyBag)}; + items[] = {"ACE_bodyBag"}; condition = "!alive (_this select 1);"; callbackSuccess = QUOTE(DFUNC(actionPlaceInBodyBag)); callbackFailure = ""; diff --git a/addons/medical/CfgEventHandlers.hpp b/addons/medical/CfgEventHandlers.hpp index 9600675e46..6330819daa 100644 --- a/addons/medical/CfgEventHandlers.hpp +++ b/addons/medical/CfgEventHandlers.hpp @@ -42,3 +42,11 @@ class Extended_Local_EventHandlers { }; }; }; + +class Extended_Take_EventHandlers { + class CAManBase { + class ADDON { + take = QUOTE(call FUNC(itemCheck)); + }; + }; +}; diff --git a/addons/medical/CfgVehicles.hpp b/addons/medical/CfgVehicles.hpp index a15167f820..1efd4917fd 100644 --- a/addons/medical/CfgVehicles.hpp +++ b/addons/medical/CfgVehicles.hpp @@ -349,60 +349,67 @@ class CfgVehicles { class ACE_Head { runOnHover = 1; statement = QUOTE([ARR_3(_target, true, 0)] call DFUNC(displayPatientInformation)); + icon = PATHTOF(UI\icons\medical_cross.paa); - class Bandage_Head { - displayName = "Bandage Head"; + class Bandage { + displayName = "$STR_ACE_Medical_Bandage_HitHead"; distance = 2.0; - condition = QUOTE([ARR_4(_player, _target, 'head', 'Bandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'Bandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'Bandage')] call DFUNC(treatment)); showDisabled = 1; priority = 2; hotkey = "B"; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; // Advanced medical class FieldDressing { displayName = "Field Dressing"; distance = 5.0; - condition = QUOTE([ARR_4(_player, _target, 'head', 'FieldDressing')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'FieldDressing')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'FieldDressing')] call DFUNC(treatment)); showDisabled = 0; priority = 2; hotkey = ""; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; class PackingBandage: fieldDressing { displayName = "Packing Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'head', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'PackingBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\packingBandage.paa); }; class ElasticBandage: fieldDressing { displayName = "Elastic Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'head', 'ElasticBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'ElasticBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'ElasticBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\bandage.paa); }; class QuikClot: fieldDressing { displayName = "QuikClot"; - condition = QUOTE([ARR_4(_player, _target, 'head', 'QuikClot')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'QuikClot')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'QuikClot')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\bandage.paa); }; class CheckPulse: fieldDressing { displayName = "Check Pulse"; - condition = QUOTE([ARR_4(_player, _target, 'head', 'CheckPulse')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'CheckPulse')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'CheckPulse')] call DFUNC(treatment)); + icon = ""; }; class CheckBloodPressure: CheckPulse { displayName = "Check Blood Pressure"; - condition = QUOTE([ARR_4(_player, _target, 'head', 'CheckBloodPressure')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'CheckBloodPressure')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'CheckBloodPressure')] call DFUNC(treatment)); }; class CheckResponse: CheckPulse { displayName = "Check Response"; - condition = QUOTE([ARR_4(_player, _target, 'head', 'CheckResponse')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'head', 'CheckResponse')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'head', 'CheckResponse')] call DFUNC(treatment)); }; }; - class ACE_MainActions { + class ACE_Torso { class Medical { displayName = "Medical"; distance = 5.0; @@ -413,315 +420,343 @@ class CfgVehicles { priority = 2; hotkey = "M"; enableInside = 1; - class Bandage_Torso { - displayName = "Bandage Torso"; + icon = PATHTOF(UI\icons\medical_cross.paa); + + class Bandage { + displayName = "$STR_ACE_Medical_Bandage_HitBody"; distance = 2.0; - condition = QUOTE([ARR_4(_player, _target, 'body', 'Bandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'Bandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'Bandage')] call DFUNC(treatment)); showDisabled = 1; priority = 2; hotkey = "B"; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); + }; + + class TriageCard { + displayName = "Triage Card"; + distance = 2.0; + condition = "true"; + statement = QUOTE([ARR_2(_target, true)] call DFUNC(displayTriageCard)); + showDisabled = 1; + priority = 2; + hotkey = ""; + enableInside = 1; + icon = PATHTOF(UI\icons\triageCard.paa); }; // Advanced medical class FieldDressing { displayName = "Field Dressing"; distance = 5.0; - condition = QUOTE([ARR_4(_player, _target, 'body', 'FieldDressing')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'FieldDressing')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'FieldDressing')] call DFUNC(treatment)); showDisabled = 0; priority = 2; hotkey = ""; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; class PackingBandage: fieldDressing { displayName = "Packing Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'PackingBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\packingBandage.paa); }; class ElasticBandage: fieldDressing { displayName = "Elastic Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'ElasticBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'ElasticBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'ElasticBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\bandage.paa); }; class QuikClot: fieldDressing { displayName = "QuikClot"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'QuikClot')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'QuikClot')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'QuikClot')] call DFUNC(treatment)); - }; - class Morphine: fieldDressing { - displayName = "Morphine"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'Morphine')] call DFUNC(canTreat)); - statement = QUOTE([ARR_4(_player, _target, 'body', 'Morphine')] call DFUNC(treatment)); - }; - class Atropine: Morphine { - displayName = "Atropine"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'Atropine')] call DFUNC(canTreat)); - statement = QUOTE([ARR_4(_player, _target, 'body', 'Atropine')] call DFUNC(treatment)); - }; - class Epinephrine: Morphine { - displayName = "Epinephrine"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'Epinephrine')] call DFUNC(canTreat)); - statement = QUOTE([ARR_4(_player, _target, 'body', 'Epinephrine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\bandage.paa); }; class SurgicalKit: fieldDressing { displayName = "Use Surgical Kit"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'SurgicalKit')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'SurgicalKit')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'SurgicalKit')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\surgicalKit.paa); }; class PersonalAidKit: fieldDressing { displayName = "Use Personal Aid Kit"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'PackingBandage')] call DFUNC(treatment)); + icon = ""; }; class CPR: fieldDressing { displayName = "CPR"; - condition = QUOTE([ARR_4(_player, _target, 'body', 'CPR')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'body', 'CPR')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'body', 'CPR')] call DFUNC(treatment)); + icon = ""; }; }; }; class ACE_ArmLeft { runOnHover = 1; statement = QUOTE([ARR_3(_target, true, 2)] call DFUNC(displayPatientInformation)); + icon = PATHTOF(UI\icons\medical_cross.paa); - class Bandage_LeftArm { - displayName = "Bandage Left Arm"; + class Bandage { + displayName = "$STR_ACE_Medical_Bandage_HitLeftArm"; distance = 2.0; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Bandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Bandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'Bandage')] call DFUNC(treatment)); showDisabled = 1; priority = 2; hotkey = "B"; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; // Advanced medical class FieldDressing { displayName = "Field Dressing"; distance = 5.0; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'FieldDressing')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'FieldDressing')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'FieldDressing')] call DFUNC(treatment)); showDisabled = 0; priority = 2; hotkey = ""; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; class PackingBandage: fieldDressing { displayName = "Packing Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'PackingBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\packingBandage.paa); }; class ElasticBandage: fieldDressing { displayName = "Elastic Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'ElasticBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'ElasticBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'ElasticBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\bandage.paa); }; class QuikClot: fieldDressing { displayName = "QuikClot"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'QuikClot')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'QuikClot')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'QuikClot')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\bandage.paa); }; class Tourniquet: fieldDressing { displayName = "Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Tourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Tourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'Tourniquet')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\tourniquet.paa); }; class Morphine: fieldDressing { - displayName = "Morphine"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Morphine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Morphine"; + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Morphine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'Morphine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\autoInjector.paa); }; class Atropine: Morphine { displayName = "Atropine"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Atropine')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Atropine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'Atropine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\autoInjector.paa); }; class Epinephrine: Morphine { - displayName = "Epinephrine"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Epinephrine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Epinephrine"; + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'Epinephrine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'Epinephrine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\autoInjector.paa); }; class BloodIV: fieldDressing { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\iv.paa); }; class BloodIV_500: BloodIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV_500')] call DFUNC(treatment)); }; class BloodIV_250: BloodIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV_250')] call DFUNC(treatment)); }; class PlasmaIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'BloodIV')] call DFUNC(treatment)); }; class PlasmaIV_500: PlasmaIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'PlasmaIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'PlasmaIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'PlasmaIV_500')] call DFUNC(treatment)); }; class PlasmaIV_250: PlasmaIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'PlasmaIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'PlasmaIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'PlasmaIV_250')] call DFUNC(treatment)); }; class SalineIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV')] call DFUNC(treatment)); }; class SalineIV_500: SalineIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV_500')] call DFUNC(treatment)); }; class SalineIV_250: SalineIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'SalineIV_250')] call DFUNC(treatment)); }; class CheckPulse: fieldDressing { displayName = "Check Pulse"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'CheckPulse')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'CheckPulse')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'CheckPulse')] call DFUNC(treatment)); + icon = ""; }; class CheckBloodPressure: CheckPulse { displayName = "Check Blood Pressure"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'CheckBloodPressure')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'CheckBloodPressure')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'CheckBloodPressure')] call DFUNC(treatment)); }; class RemoveTourniquet: Tourniquet { displayName = "Remove Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'RemoveTourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_l', 'RemoveTourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_l', 'RemoveTourniquet')] call DFUNC(treatment)); }; }; class ACE_ArmRight { runOnHover = 1; statement = QUOTE([ARR_3(_target, true, 3)] call DFUNC(displayPatientInformation)); - class Bandage_RightArm { - displayName = "Bandage Right Arm"; + icon = PATHTOF(UI\icons\medical_cross.paa); + + class Bandage { + displayName = "$STR_ACE_Medical_Bandage_HitRightArm"; distance = 2.0; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(treatment)); showDisabled = 1; priority = 2; hotkey = "B"; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; // Advanced medical class FieldDressing { displayName = "Field Dressing"; distance = 5.0; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'FieldDressing')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'FieldDressing')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'FieldDressing')] call DFUNC(treatment)); showDisabled = 0; priority = 2; hotkey = ""; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; class PackingBandage: fieldDressing { displayName = "Packing Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'PackingBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\packingBandage.paa); }; class ElasticBandage: fieldDressing { displayName = "Elastic Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'ElasticBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'ElasticBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'ElasticBandage')] call DFUNC(treatment)); }; class QuikClot: fieldDressing { displayName = "QuikClot"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'QuikClot')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'QuikClot')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'QuikClot')] call DFUNC(treatment)); }; class Tourniquet: fieldDressing { displayName = "Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Tourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Tourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Tourniquet')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\tourniquet.paa); }; class Morphine: fieldDressing { - displayName = "Morphine"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Morphine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Morphine"; + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Morphine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Morphine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\autoInjector.paa); }; class Atropine: Morphine { displayName = "Atropine"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Atropine')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Atropine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Atropine')] call DFUNC(treatment)); }; class Epinephrine: Morphine { - displayName = "Epinephrine"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Epinephrine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Epinephrine"; + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Epinephrine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Epinephrine')] call DFUNC(treatment)); }; class BloodIV: fieldDressing { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\iv.paa); }; class BloodIV_500: BloodIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV_500')] call DFUNC(treatment)); }; class BloodIV_250: BloodIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV_250')] call DFUNC(treatment)); }; class PlasmaIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'BloodIV')] call DFUNC(treatment)); }; class PlasmaIV_500: PlasmaIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'PlasmaIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'PlasmaIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'PlasmaIV_500')] call DFUNC(treatment)); }; class PlasmaIV_250: PlasmaIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'PlasmaIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'PlasmaIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'PlasmaIV_250')] call DFUNC(treatment)); }; class SalineIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV')] call DFUNC(treatment)); }; class SalineIV_500: SalineIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV_500')] call DFUNC(treatment)); }; class SalineIV_250: SalineIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'SalineIV_250')] call DFUNC(treatment)); }; class CheckPulse: fieldDressing { displayName = "Check Pulse"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'CheckPulse')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'CheckPulse')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'CheckPulse')] call DFUNC(treatment)); + icon = ""; }; class CheckBloodPressure: CheckPulse { displayName = "Check Blood Pressure"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'CheckBloodPressure')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'CheckBloodPressure')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'CheckBloodPressure')] call DFUNC(treatment)); }; class RemoveTourniquet: Tourniquet { displayName = "Remove Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'RemoveTourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'RemoveTourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'RemoveTourniquet')] call DFUNC(treatment)); }; @@ -729,15 +764,18 @@ class CfgVehicles { class ACE_LegLeft { runOnHover = 1; statement = QUOTE([ARR_3(_target, true, 4)] call DFUNC(displayPatientInformation)); - class Bandage_LeftLeg { - displayName = "Bandage Left Leg"; + icon = PATHTOF(UI\icons\medical_cross.paa); + + class Bandage { + displayName = "$STR_ACE_Medical_Bandage_HitLeftLeg"; distance = 2.0; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Bandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Bandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'Bandage')] call DFUNC(treatment)); showDisabled = 1; priority = 2; hotkey = "B"; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; @@ -745,111 +783,119 @@ class CfgVehicles { class FieldDressing { displayName = "Field Dressing"; distance = 5.0; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'FieldDressing')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'FieldDressing')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'FieldDressing')] call DFUNC(treatment)); showDisabled = 0; priority = 2; hotkey = ""; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; class PackingBandage: fieldDressing { displayName = "Packing Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'PackingBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\packingBandage.paa); }; class ElasticBandage: fieldDressing { displayName = "Elastic Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'ElasticBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'ElasticBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'ElasticBandage')] call DFUNC(treatment)); }; class QuikClot: fieldDressing { displayName = "QuikClot"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'QuikClot')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'QuikClot')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'QuikClot')] call DFUNC(treatment)); }; class Tourniquet: fieldDressing { displayName = "Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Tourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Tourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'Tourniquet')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\tourniquet.paa); }; class Morphine: fieldDressing { - displayName = "Morphine"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Morphine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Morphine"; + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Morphine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'Morphine')] call DFUNC(treatment)); }; class Atropine: Morphine { displayName = "Atropine"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Atropine')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Atropine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'Atropine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\autoInjector.paa); }; class Epinephrine: Morphine { - displayName = "Epinephrine"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Epinephrine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Epinephrine"; + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Epinephrine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'Epinephrine')] call DFUNC(treatment)); }; class BloodIV: fieldDressing { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\iv.paa); }; class BloodIV_500: BloodIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV_500')] call DFUNC(treatment)); }; class BloodIV_250: BloodIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV_250')] call DFUNC(treatment)); }; class PlasmaIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'BloodIV')] call DFUNC(treatment)); }; class PlasmaIV_500: PlasmaIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'PlasmaIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'PlasmaIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'PlasmaIV_500')] call DFUNC(treatment)); }; class PlasmaIV_250: PlasmaIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'PlasmaIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'PlasmaIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'PlasmaIV_250')] call DFUNC(treatment)); }; class SalineIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV')] call DFUNC(treatment)); }; class SalineIV_500: SalineIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV_500')] call DFUNC(treatment)); }; class SalineIV_250: SalineIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'SalineIV_250')] call DFUNC(treatment)); }; class RemoveTourniquet: Tourniquet { displayName = "Remove Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'RemoveTourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'RemoveTourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'RemoveTourniquet')] call DFUNC(treatment)); }; }; class ACE_LegRight { runOnHover = 1; statement = QUOTE([ARR_3(_target, true, 5)] call DFUNC(displayPatientInformation)); - class Bandage_RightLeg { - displayName = "Bandage Right Leg"; + icon = PATHTOF(UI\icons\medical_cross.paa); + + class Bandage { + displayName = "$STR_ACE_Medical_Bandage_HitRightLeg"; distance = 2.0; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Bandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Bandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'Bandage')] call DFUNC(treatment)); showDisabled = 1; priority = 2; hotkey = "B"; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; @@ -857,96 +903,101 @@ class CfgVehicles { class FieldDressing { displayName = "Field Dressing"; distance = 5.0; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'FieldDressing')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'FieldDressing')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'FieldDressing')] call DFUNC(treatment)); showDisabled = 0; priority = 2; hotkey = ""; enableInside = 1; + icon = PATHTOF(UI\icons\bandage.paa); }; class PackingBandage: fieldDressing { displayName = "Packing Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'PackingBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'PackingBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'PackingBandage')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\packingBandage.paa); }; class ElasticBandage: fieldDressing { displayName = "Elastic Bandage"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'ElasticBandage')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'ElasticBandage')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'ElasticBandage')] call DFUNC(treatment)); }; class QuikClot: fieldDressing { displayName = "QuikClot"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'QuikClot')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'QuikClot')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'QuikClot')] call DFUNC(treatment)); }; class Tourniquet: fieldDressing { displayName = "Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Tourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Tourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'Tourniquet')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\tourniquet.paa); }; class Morphine: fieldDressing { - displayName = "Morphine"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Morphine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Morphine"; + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Morphine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'Morphine')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\autoInjector.paa); }; class Atropine: Morphine { displayName = "Atropine"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Atropine')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Atropine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'Atropine')] call DFUNC(treatment)); }; class Epinephrine: Morphine { - displayName = "Epinephrine"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Epinephrine')] call DFUNC(canTreat)); + displayName = "$STR_ACE_Medical_Inject_Epinephrine"; + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Epinephrine')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'Epinephrine')] call DFUNC(treatment)); }; class BloodIV: fieldDressing { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV')] call DFUNC(treatment)); + icon = PATHTOF(UI\icons\iv.paa); }; class BloodIV_500: BloodIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV_500')] call DFUNC(treatment)); }; class BloodIV_250: BloodIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV_250')] call DFUNC(treatment)); }; class PlasmaIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'BloodIV')] call DFUNC(treatment)); }; class PlasmaIV_500: PlasmaIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'PlasmaIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'PlasmaIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'PlasmaIV_500')] call DFUNC(treatment)); }; class PlasmaIV_250: PlasmaIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'PlasmaIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'PlasmaIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'PlasmaIV_250')] call DFUNC(treatment)); }; class SalineIV: BloodIV { displayName = "Give Blood IV (1000ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV')] call DFUNC(treatment)); }; class SalineIV_500: SalineIV { displayName = "Give Blood IV (500ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV_500')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV_500')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV_500')] call DFUNC(treatment)); }; class SalineIV_250: SalineIV { displayName = "Give Blood IV (250ml)"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV_250')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV_250')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'SalineIV_250')] call DFUNC(treatment)); }; class RemoveTourniquet: Tourniquet { displayName = "Remove Tourniquet"; - condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'RemoveTourniquet')] call DFUNC(canTreat)); + condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'RemoveTourniquet')] call DFUNC(canTreatCached)); statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'RemoveTourniquet')] call DFUNC(treatment)); }; }; @@ -1127,7 +1178,7 @@ class CfgVehicles { displayName = $STR_ACE_MEDICAL_BODYBAG_DISPLAY; }; class Item_Base_F; - class GVAR(fieldDressingItem): Item_Base_F { + class ACE_fieldDressingItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_BANDAGE_BASIC_DISPLAY; @@ -1135,14 +1186,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(fieldDressing) + class ACE_fieldDressing { - name = QGVAR(fieldDressing); + name = "ACE_fieldDressing"; count = 1; }; }; }; - class GVAR(packingBandageItem): Item_Base_F { + class ACE_packingBandageItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_PACKING_BANDAGE_DISPLAY; @@ -1150,14 +1201,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(packingBandage) + class ACE_packingBandage { - name = QGVAR(packingBandage); + name = "ACE_packingBandage"; count = 1; }; }; }; - class GVAR(elasticBandageItem): Item_Base_F { + class ACE_elasticBandageItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_BANDAGE_ELASTIC_DISPLAY; @@ -1165,14 +1216,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(elasticBandage) + class ACE_elasticBandage { - name = QGVAR(elasticBandage); + name = "ACE_elasticBandage"; count = 1; }; }; }; - class GVAR(tourniquetItem): Item_Base_F { + class ACE_tourniquetItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_TOURNIQUET_DISPLAY; @@ -1180,14 +1231,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(tourniquet) + class ACE_tourniquet { - name = QGVAR(tourniquet); + name = "ACE_tourniquet"; count = 1; }; }; }; - class GVAR(morphineItem): Item_Base_F { + class ACE_morphineItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_MORPHINE_DISPLAY; @@ -1195,14 +1246,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(morphine) + class ACE_morphine { - name = QGVAR(morphine); + name = "ACE_morphine"; count = 1; }; }; }; - class GVAR(atropineItem): Item_Base_F { + class ACE_atropineItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_ATROPINE_DISPLAY; @@ -1210,14 +1261,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(atropine) + class ACE_atropine { - name = QGVAR(atropine); + name = "ACE_atropine"; count = 1; }; }; }; - class GVAR(epinephrineItem): Item_Base_F { + class ACE_epinephrineItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_EPINEPHRINE_DISPLAY; @@ -1225,14 +1276,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(epinephrine) + class ACE_epinephrine { - name = QGVAR(epinephrine); + name = "ACE_epinephrine"; count = 1; }; }; }; - class GVAR(plasmaIVItem): Item_Base_F { + class ACE_plasmaIVItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_PLASMA_IV; @@ -1240,15 +1291,15 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(plasmaIV) + class ACE_plasmaIV { - name = QGVAR(plasmaIV); + name = "ACE_plasmaIV"; count = 1; }; }; }; - class GVAR(bloodIVItem): Item_Base_F { + class ACE_bloodIVItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_BLOOD_IV; @@ -1256,14 +1307,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(bloodIV) + class ACE_bloodIV { - name = QGVAR(bloodIV); + name = "ACE_bloodIV"; count = 1; }; }; }; - class GVAR(salineIVItem): Item_Base_F { + class ACE_salineIVItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_SALINE_IV; @@ -1271,14 +1322,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(salineIV) + class ACE_salineIV { - name = QGVAR(salineIV); + name = "ACE_salineIV"; count = 1; }; }; }; - class GVAR(quikClotItem): Item_Base_F { + class ACE_quikClotItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_QUIKCLOT_DISPLAY; @@ -1286,14 +1337,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(quikClot) + class ACE_quikClot { - name = QGVAR(quikClot); + name = "ACE_quikclot"; count = 1; }; }; }; - class GVAR(personalAidKitItem): Item_Base_F { + class ACE_personalAidKitItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_AID_KIT_DISPLAY; @@ -1301,14 +1352,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(personalAidKit) + class ACE_personalAidKit { - name = QGVAR(personalAidKit); + name = "ACE_personalAidKit"; count = 1; }; }; }; - class GVAR(surgicalKitItem): Item_Base_F { + class ACE_surgicalKitItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_SURGICALKIT_DISPLAY; @@ -1316,14 +1367,14 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(surgicalKit) + class ACE_surgicalKit { - name = QGVAR(surgicalKit); + name = "ACE_surgicalKit"; count = 1; }; }; }; - class GVAR(bodyBagItem): Item_Base_F { + class ACE_bodyBagItem: Item_Base_F { scope = 2; scopeCurator = 2; displayName = $STR_ACE_MEDICAL_BODYBAG_DISPLAY; @@ -1331,102 +1382,196 @@ class CfgVehicles { vehicleClass = "Items"; class TransportItems { - class GVAR(bodyBag) + class ACE_bodyBag { - name = QGVAR(bodyBag); + name = "ACE_bodyBag"; count = 1; }; }; }; class NATO_Box_Base; - class GVAR(supplyCrate): NATO_Box_Base { + class ACE_medicalSupplyCrate: NATO_Box_Base { scope = 2; accuracy = 1000; - displayName = "Medical Supply Crate [ACE]"; + displayName = "[ACE] Medical Supply Crate"; model = "\A3\weapons_F\AmmoBoxes\AmmoBox_F"; author = "Glowbal"; class TransportItems { - class GVAR(fieldDressing) { - name = QGVAR(fieldDressing); + class ACE_fieldDressing { + name = "ACE_fieldDressing"; count = 25; }; - class GVAR(packingBandage) { - name = QGVAR(packingBandage); + class ACE_packingBandage { + name = "ACE_packingBandage"; count = 25; }; - class GVAR(elasticBandage) { - name = QGVAR(elasticBandage); + class ACE_elasticBandage { + name = "ACE_elasticBandage"; count = 25; }; - class GVAR(tourniquet) { - name = QGVAR(tourniquet); + class ACE_tourniquet { + name = "ACE_tourniquet"; count = 15; }; - class GVAR(morphine) { - name = QGVAR(morphine); + class ACE_morphine { + name = "ACE_morphine"; count = 15; }; - class GVAR(atropine) { - name = QGVAR(atropine); + class ACE_atropine { + name = "ACE_atropine"; count = 15; }; - class GVAR(epinephrine) { - name = QGVAR(epinephrine); + class ACE_epinephrine { + name = "ACE_epinephrine"; count = 15; }; - class GVAR(plasmaIV) { - name = QGVAR(plasmaIV); + class ACE_plasmaIV { + name = "ACE_plasmaIV"; count = 7; }; - class GVAR(plasmaIV_500) { - name = QGVAR(plasmaIV_500); + class ACE_plasmaIV_500 { + name = "ACE_plasmaIV_500"; count = 7; }; - class GVAR(plasmaIV_250) { - name = QGVAR(plasmaIV_250); + class ACE_plasmaIV_250 { + name = "ACE_plasmaIV_250"; count = 7; }; - class GVAR(salineIV) { - name = QGVAR(salineIV); + class ACE_salineIV { + name = "ACE_salineIV"; count = 7; }; - class GVAR(salineIV_500) { - name = QGVAR(salineIV_500); + class ACE_salineIV_500 { + name = "ACE_salineIV_500"; count = 7; }; - class GVAR(salineIV_250) { - name = QGVAR(salineIV_250); + class ACE_salineIV_250 { + name = "ACE_salineIV_250"; count = 7; }; - class GVAR(bloodIV) { - name = QGVAR(bloodIV); + class ACE_bloodIV { + name = "ACE_bloodIV"; count = 7; }; - class GVAR(bloodIV_500) { - name = QGVAR(bloodIV_500); + class ACE_bloodIV_500 { + name = "ACE_bloodIV_500"; count = 7; }; - class GVAR(bloodIV_250) { - name = QGVAR(bloodIV_250); + class ACE_bloodIV_250 { + name = "ACE_bloodIV_250"; count = 7; }; - class GVAR(quikClot) { - name = QGVAR(quikClot); + class ACE_quikClot { + name = "ACE_quikclot"; count = 20; }; - class GVAR(personalAidKit) { - name = QGVAR(personalAidKit); + class ACE_personalAidKit { + name = "ACE_personalAidKit"; count = 3; }; - class GVAR(surgicalKit) { - name = QGVAR(surgicalKit); + class ACE_surgicalKit { + name = "ACE_surgicalKit"; count = 2; }; - class GVAR(bodyBag) { - name = QGVAR(bodyBag); + class ACE_bodyBag { + name = "ACE_bodyBag"; count = 5; }; }; }; + + // Patient unload from vehicle actions + class LandVehicle; + class Car: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; + class Tank: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; + + class Air; + class Helicopter: Air { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; + class Plane: Air { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; + + class Ship; + class Ship_F: Ship { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; + + class StaticWeapon: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; + + class StaticMortar; + class Mortar_01_base_F: StaticMortar { + class ACE_Actions { + class ACE_MainActions { + class ACE_UnloadPatients { + displayName = "$STR_ACE_Medical_UnloadPatient"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call FUNC(addUnloadPatientActions)); + }; + }; + }; + }; }; diff --git a/addons/medical/CfgWeapons.hpp b/addons/medical/CfgWeapons.hpp index 3eb30929d7..d0b1b786ed 100644 --- a/addons/medical/CfgWeapons.hpp +++ b/addons/medical/CfgWeapons.hpp @@ -1,29 +1,29 @@ class CfgWeapons { - class ItemCore; - class InventoryItem_Base_F; - class InventoryFirstAidKitItem_Base_F; - class MedikitItem; + class ItemCore; + class InventoryItem_Base_F; + class InventoryFirstAidKitItem_Base_F; + class MedikitItem; - // ITEMS - class FirstAidKit: ItemCore { - type = 0; - class ItemInfo: InventoryFirstAidKitItem_Base_F { - mass = 4; - type = 201; + // ITEMS + class FirstAidKit: ItemCore { + type = 0; + class ItemInfo: InventoryFirstAidKitItem_Base_F { + mass = 4; + type = 201; + }; }; - }; - class Medikit: ItemCore { - type = 0; - class ItemInfo: MedikitItem { - mass = 60; - type = 201; + class Medikit: ItemCore { + type = 0; + class ItemInfo: MedikitItem { + mass = 60; + type = 201; + }; }; - }; // @todo localize class ACE_ItemCore; - class GVAR(fieldDressing): ACE_ItemCore { + class ACE_fieldDressing: ACE_ItemCore { scope = 2; model = "\A3\Structures_F_EPA\Items\Medical\Bandage_F.p3d"; picture = QUOTE(PATHTOF(ui\items\fieldDressing.paa)); @@ -35,7 +35,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(packingBandage): ItemCore { + class ACE_packingBandage: ItemCore { scope = 2; value = 1; count = 1; @@ -50,7 +50,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(elasticBandage): ItemCore { + class ACE_elasticBandage: ItemCore { scope = 2; value = 1; count = 1; @@ -65,7 +65,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(tourniquet): ItemCore { + class ACE_tourniquet: ItemCore { scope = 2; value = 1; count = 1; @@ -80,7 +80,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(morphine): ItemCore { + class ACE_morphine: ItemCore { scope = 2; value = 1; count = 1; @@ -95,7 +95,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(atropine): ItemCore { + class ACE_atropine: ItemCore { scope = 2; value = 1; count = 1; @@ -110,7 +110,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(epinephrine): ItemCore { + class ACE_epinephrine: ItemCore { scope = 2; value = 1; count = 1; @@ -125,7 +125,7 @@ class CfgWeapons { type=201; }; }; - class GVAR(plasmaIV): ItemCore { + class ACE_plasmaIV: ItemCore { scope = 2; value = 1; count = 1; @@ -138,21 +138,21 @@ class CfgWeapons { type = 201; }; }; - class GVAR(plasmaIV_500): GVAR(plasmaIV) { + class ACE_plasmaIV_500: ACE_plasmaIV { displayName = $STR_ACE_MEDICAL_PLASMA_IV_500; class ItemInfo: InventoryItem_Base_F { mass = 5; type = 201; }; }; - class GVAR(plasmaIV_250): GVAR(plasmaIV) { + class ACE_plasmaIV_250: ACE_plasmaIV { displayName = $STR_ACE_MEDICAL_PLASMA_IV_250; class ItemInfo: InventoryItem_Base_F { mass = 2.5; type = 201; }; }; - class GVAR(bloodIV): ItemCore { + class ACE_bloodIV: ItemCore { scope = 2; value = 1; count = 1; @@ -166,21 +166,21 @@ class CfgWeapons { type = 201; }; }; - class GVAR(bloodIV_500): GVAR(bloodIV) { + class ACE_bloodIV_500: ACE_bloodIV { displayName = $STR_ACE_MEDICAL_BLOOD_IV_500; class ItemInfo: InventoryItem_Base_F { mass = 5; type = 201; }; }; - class GVAR(bloodIV_250): GVAR(bloodIV) { + class ACE_bloodIV_250: ACE_bloodIV { displayName = $STR_ACE_MEDICAL_BLOOD_IV_250; class ItemInfo: InventoryItem_Base_F { mass = 2.5; type = 201; }; }; - class GVAR(salineIV): ItemCore { + class ACE_salineIV: ItemCore { scope = 2; value = 1; count = 1; @@ -193,21 +193,21 @@ class CfgWeapons { type = 201; }; }; - class GVAR(salineIV_500): GVAR(salineIV) { + class ACE_salineIV_500: ACE_salineIV { displayName = $STR_ACE_MEDICAL_SALINE_IV_500; class ItemInfo: InventoryItem_Base_F { mass = 2.5; type = 201; }; }; - class GVAR(salineIV_250): GVAR(salineIV) { + class ACE_salineIV_250: ACE_salineIV { displayName = $STR_ACE_MEDICAL_SALINE_IV_250; class ItemInfo: InventoryItem_Base_F { mass = 2.5; type = 201; }; }; - class GVAR(quikclot): ItemCore { + class ACE_quikclot: ItemCore { scope = 2; value = 1; count = 1; @@ -221,7 +221,7 @@ class CfgWeapons { type = 201; }; }; - class GVAR(personalAidKit): ItemCore { + class ACE_personalAidKit: ItemCore { scope = 2; value = 1; count = 1; @@ -236,19 +236,19 @@ class CfgWeapons { type = 201; }; }; - class GVAR(surgicalKit): ItemCore { + class ACE_surgicalKit: ItemCore { scope=2; displayName= $STR_ACE_MEDICAL_SURGICALKIT_DISPLAY; model = QUOTE(PATHTOF(data\surgical_kit.p3d)); picture = QUOTE(PATHTOF(ui\items\surgicalKit.paa)); descriptionShort = $STR_ACE_MEDICAL_SURGICALKIT_DESC_SHORT; descriptionUse = $STR_ACE_MEDICAL_SURGICALKIT_DESC_USE; - class ItemInfo: InventoryItem_Base_F { + class ItemInfo: InventoryItem_Base_F { mass = 5; type = 201; }; }; - class GVAR(bodyBag): ItemCore { + class ACE_bodyBag: ItemCore { scope=2; displayName= $STR_ACE_MEDICAL_BODYBAG_DISPLAY; model = QUOTE(PATHTOF(data\bodybagItem.p3d)); diff --git a/addons/medical/XEH_postInit.sqf b/addons/medical/XEH_postInit.sqf index d23a02225f..ee73d28318 100644 --- a/addons/medical/XEH_postInit.sqf +++ b/addons/medical/XEH_postInit.sqf @@ -12,6 +12,7 @@ GVAR(heartBeatSounds_Slow) = ["ACE_heartbeat_slow_1", "ACE_heartbeat_slow_2"]; ["Medical_treatmentCompleted", FUNC(onTreatmentCompleted)] call ace_common_fnc_addEventHandler; ["medical_propagateWound", FUNC(onPropagateWound)] call ace_common_fnc_addEventHandler; ["medical_woundUpdateRequest", FUNC(onWoundUpdateRequest)] call ace_common_fnc_addEventHandler; +["interactMenuClosed", {[objNull, false] call FUNC(displayPatientInformation); }] call ace_common_fnc_addEventHandler; // Initialize all effects _fnc_createEffect = { @@ -217,7 +218,7 @@ if (isNil QGVAR(level)) then { }, 0, []] call CBA_fnc_addPerFrameHandler; // broadcast injuries to JIP clients in a MP session -if (isMultiplayer) then { +if (isMultiplayer and GVAR(level) >= 2) then { [QGVAR(onPlayerConnected), "onPlayerConnected", { if (isNil QGVAR(InjuredCollection)) then { GVAR(InjuredCollection) = []; diff --git a/addons/medical/XEH_preInit.sqf b/addons/medical/XEH_preInit.sqf index c6ddbf0783..bc63a65135 100644 --- a/addons/medical/XEH_preInit.sqf +++ b/addons/medical/XEH_preInit.sqf @@ -16,8 +16,10 @@ PREP(addToInjuredCollection); PREP(addToLog); PREP(addToTriageCard); PREP(addUnconsciousCondition); +PREP(addUnloadPatientActions); PREP(canAccessMedicalEquipment); PREP(canTreat); +PREP(canTreatCached); PREP(determineIfFatal); PREP(getBloodLoss); PREP(getBloodPressure); @@ -46,6 +48,7 @@ PREP(init); PREP(isInMedicalFacility); PREP(isMedic); PREP(isMedicalVehicle); +PREP(itemCheck); PREP(onMedicationUsage); PREP(onWoundUpdateRequest); PREP(onPropagateWound); @@ -79,6 +82,8 @@ PREP(treatmentTourniquetLocal); PREP(useItem); PREP(useItems); PREP(displayPatientInformation); +PREP(displayTriageCard); +PREP(dropDownTriageCard); PREP(moduleMedicalSettings); PREP(moduleAssignMedicRoles); PREP(moduleAssignMedicalVehicle); diff --git a/addons/medical/config.cpp b/addons/medical/config.cpp index 3e8aaa8d55..ab0f83fa9e 100644 --- a/addons/medical/config.cpp +++ b/addons/medical/config.cpp @@ -2,8 +2,8 @@ class CfgPatches { class ADDON { - units[] = {QGVAR(fieldDressingItem), QGVAR(packingBandageItem), QGVAR(elasticBandageItem), QGVAR(tourniquetItem), QGVAR(morphineItem), QGVAR(atropineItem), QGVAR(epinephrineItem), QGVAR(plasmaIVItem), QGVAR(bloodIVItem), QGVAR(salineIVItem), QGVAR(quikclotItem), QGVAR(personalAidKitItem), QGVAR(surgicalKitItem), QGVAR(bodyBagItem)}; - weapons[] = {QGVAR(fieldDressing), QGVAR(packingBandage), QGVAR(elasticBandage), QGVAR(tourniquet), QGVAR(morphine), QGVAR(atropine), QGVAR(epinephrine), QGVAR(plasmaIV), QGVAR(plasmaIV_500), QGVAR(plasmaIV_250), QGVAR(bloodIV), QGVAR(bloodIV_500), QGVAR(bloodIV_250), QGVAR(salineIV), QGVAR(salineIV_500), QGVAR(salineIV_250), QGVAR(quikclot), QGVAR(personalAidKit), QGVAR(surgicalKit), QGVAR(bodyBag)}; + units[] = {"ACE_medicalSupplyCrate", "ACE_fieldDressingItem", "ACE_packingBandageItem", "ACE_elasticBandageItem", "ACE_tourniquetItem", "ACE_morphineItem", "ACE_atropineItem", "ACE_epinephrineItem", "ACE_plasmaIVItem", "ACE_bloodIVItem", "ACE_salineIVItem", "ACE_quikclotItem", "ACE_personalAidKitItem", "ACE_surgicalKitItem", "ACE_bodyBagItem"}; + weapons[] = {"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_tourniquet", "ACE_morphine", "ACE_atropine", "ACE_epinephrine", "ACE_plasmaIV", "ACE_plasmaIV_500", "ACE_plasmaIV_250", "ACE_bloodIV", "ACE_bloodIV_500", "ACE_bloodIV_250", "ACE_salineIV", "ACE_salineIV_500", "ACE_salineIV_250", "ACE_quikclot", "ACE_personalAidKit", "ACE_surgicalKit", "ACE_bodyBag"}; requiredVersion = REQUIRED_VERSION; requiredAddons[] = {ace_common, ace_interaction}; author[] = {"Glowbal", "KoffienFlummi"}; @@ -20,3 +20,4 @@ class CfgPatches { #include "ACE_Medical_Treatments.hpp" #include "ACE_Settings.hpp" #include "UI\RscTitles.hpp" +#include "UI\triagecard.hpp" diff --git a/addons/medical/functions/fnc_actionRemoveTourniquet.sqf b/addons/medical/functions/fnc_actionRemoveTourniquet.sqf index 2944c2f6e2..75d7b67daa 100644 --- a/addons/medical/functions/fnc_actionRemoveTourniquet.sqf +++ b/addons/medical/functions/fnc_actionRemoveTourniquet.sqf @@ -36,6 +36,6 @@ _tourniquets set[_part, 0]; _target setvariable [QGVAR(tourniquets), _tourniquets, true]; // Adding the tourniquet item to the caller -_caller addItem QGVAR(tourniquet); +_caller addItem "ACE_tourniquet"; // "AinvPknlMstpSlayWrflDnon_medic diff --git a/addons/medical/functions/fnc_addUnloadPatientActions.sqf b/addons/medical/functions/fnc_addUnloadPatientActions.sqf new file mode 100644 index 0000000000..3a96c0b089 --- /dev/null +++ b/addons/medical/functions/fnc_addUnloadPatientActions.sqf @@ -0,0 +1,44 @@ +/* + * Author: CAA-Picard + * Create one unload action per unconscious passenger + * + * Argument: + * 0: Vehicle + * 1: Player + * 3: Parameters + * + * Return value: + * Children actions + * + * Public: No + */ +#include "script_component.hpp" + +EXPLODE_3_PVT(_this,_vehicle,_player,_parameters); + +private ["_actions"]; +_actions = []; + +{ + _unit = _x; + if (_unit != _player && {(alive _unit) && {_unit getVariable ["ACE_isUnconscious", false]}}) then { + _actions pushBack + [ + [ + str(_unit), + [_unit, true] call EFUNC(common,getName), + "", + {[_player, (_this select 2) select 0] call FUNC(actionUnloadUnit);}, + {true}, + {}, + [_unit] + ] call EFUNC(interact_menu,createAction), + [], + _unit + ]; + }; +} forEach crew _vehicle; + +systemChat str(count _actions); + +_actions diff --git a/addons/medical/functions/fnc_canTreat.sqf b/addons/medical/functions/fnc_canTreat.sqf index 0c48222977..6a49652301 100644 --- a/addons/medical/functions/fnc_canTreat.sqf +++ b/addons/medical/functions/fnc_canTreat.sqf @@ -39,19 +39,16 @@ if (count _items > 0 && {!([_caller, _target, _items] call FUNC(hasItems))}) exi _locations = getArray (_config >> "treatmentLocations"); _return = true; -if (isText (_config >> "Condition")) then { - _condition = getText(_config >> "condition"); - if (_condition != "") then { - if (isnil _condition) then { - _condition = compile _condition; - } else { - _condition = missionNamespace getvariable _condition; - }; - if (typeName _condition == "BOOL") then { - _return = _condition; - } else { - _return = [_caller, _target, _selectionName, _className] call _condition; - }; +if (getText (_config >> "condition") != "") then { + if (isnil _condition) then { + _condition = compile _condition; + } else { + _condition = missionNamespace getvariable _condition; + }; + if (typeName _condition == "BOOL") then { + _return = _condition; + } else { + _return = [_caller, _target, _selectionName, _className] call _condition; }; }; if (!_return) exitwith {false}; diff --git a/addons/medical/functions/fnc_canTreatCached.sqf b/addons/medical/functions/fnc_canTreatCached.sqf new file mode 100644 index 0000000000..34d753b119 --- /dev/null +++ b/addons/medical/functions/fnc_canTreatCached.sqf @@ -0,0 +1,22 @@ +/* + * Author: Glowbal + * Cached Check if the treatment action can be performed. + * + * Arguments: + * 0: The caller + * 1: The target + * 2: Selection name + * 3: ACE_Medical_Treatments Classname + * + * ReturnValue: + * Can Treat + * + * Public: No + */ + +#include "script_component.hpp" + +#define MAX_DURATION_CACHE 2 + +// parameters, function, namespace, uid +[_this, DFUNC(canTreat), _this select 0, format[QGVAR(canTreat_%1_%2), _this select 2, _this select 3], MAX_DURATION_CACHE, "clearConditionCaches"] call EFUNC(common,cachedCall); diff --git a/addons/medical/functions/fnc_displayPatientInformation.sqf b/addons/medical/functions/fnc_displayPatientInformation.sqf index 36a1e39511..0387547720 100644 --- a/addons/medical/functions/fnc_displayPatientInformation.sqf +++ b/addons/medical/functions/fnc_displayPatientInformation.sqf @@ -75,9 +75,17 @@ if (_show) then { }; }foreach _openWounds; } else { - // TODO handle basic medical colors for body part selections here - + { + _selectionBloodLoss set [_forEachIndex, _target getHitPointDamage _x]; + if (_target getHitPointDamage _x > 0.1) then { + // @todo localize + _allInjuryTexts pushBack format ["%1 %2", + ["Lightly wounded", "Heavily wounded"] select (_target getHitPointDamage _x > 0.5), + ["head", "torso", "left arm", "right arm", "left leg", "right leg"] select _forEachIndex + ]; + }; + } forEach ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"]; }; // Handle the body image coloring diff --git a/addons/medical/functions/fnc_displayTriageCard.sqf b/addons/medical/functions/fnc_displayTriageCard.sqf new file mode 100644 index 0000000000..95e6713d9a --- /dev/null +++ b/addons/medical/functions/fnc_displayTriageCard.sqf @@ -0,0 +1,78 @@ +/* + * Author: Glowbal + * Display triage card for a unit + * + * Arguments: + * 0: The unit + * + * Return Value: + * nil + * + * Public: Yes + */ + +#include "script_component.hpp" + +private ["_target", "_show"]; +_target = _this select 0; +_show = if (count _this > 1) then {_this select 1} else {true}; +GVAR(currentSelectedSelectionN) = if (count _this > 2) then {_this select 2} else {0}; + +GVAR(TriageCardTarget) = if (_show) then {_target} else {ObjNull}; + +if (_show) then { + //("ACE_MedicalTriageCard" call BIS_fnc_rscLayer) cutRsc [QGVAR(triageCard),"PLAIN"]; + createDialog QGVAR(triageCard); + + [{ + private ["_target", "_display", "_alphaLevel", "_damaged", "_availableSelections", "_openWounds", "_selectionBloodLoss", "_red", "_green", "_blue", "_alphaLevel", "_allInjuryTexts", "_lbCtrl", "_genericMessages"]; + _target = (_this select 0) select 0; + if (GVAR(TriageCardTarget) != _target) exitwith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + }; + + disableSerialization; + _display = uiNamespace getvariable QGVAR(triageCard); + if (isnil "_display") exitwith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + }; + + _triageCardTexts = []; + + // TODO fill the lb with the appropiate information for the patient + _lbCtrl = (_display displayCtrl 200); + lbClear _lbCtrl; + + _log = _target getvariable ["myVariableTESTKOEAKJR", []]; + { + // [_message,_moment,_type, _arguments] + _message = _x select 0; + _moment = _x select 1; + _arguments = _x select 3; + if (isLocalized _message) then { + _message = localize _message; + }; + + { + if (typeName _x == "STRING" && {isLocalized _x}) then { + _arguments set [_foreachIndex, localize _x]; + }; + }foreach _arguments; + _message = format([_message] + _arguments); + _lbCtrl lbAdd format["%1 %2", _moment, _message]; + }foreach _log; + + if (count _triageCardTexts == 0) then { + _lbCtrl lbAdd "No entries on this triage card.."; + }; + + _triageStatus = [_target] call FUNC(getTriageStatus); + (_display displayCtrl 2000) ctrlSetText (_triageStatus select 0); + (_display displayCtrl 2000) ctrlSetBackgroundColor (_triageStatus select 2); + + }, 0, [_target]] call CBA_fnc_addPerFrameHandler; + +} else { + //("ACE_MedicalTriageCard" call BIS_fnc_rscLayer) cutText ["","PLAIN"]; + closeDialog 7010; +}; diff --git a/addons/medical/functions/fnc_dropDownTriageCard.sqf b/addons/medical/functions/fnc_dropDownTriageCard.sqf new file mode 100644 index 0000000000..5e763822db --- /dev/null +++ b/addons/medical/functions/fnc_dropDownTriageCard.sqf @@ -0,0 +1,32 @@ +/* + * Author: Glowbal + * Display triage card for a unit + * + * Arguments: + * 0: The unit + * + * Return Value: + * nil + * + * Public: Yes + */ + +#include "script_component.hpp" + +private ["_show"]; +_show = _this select 0; +disableSerialization; + +_display = uiNamespace getvariable QGVAR(triageCard); +if (isnil "_display") exitwith {}; + +_pos = [0,0,0,0]; +if (_show) then { + _pos = ctrlPosition (_display displayCtrl 2001); +}; +for "_idc" from 2002 to 2006 step 1 do { + _pos set [1, (_pos select 1) + (_pos select 3)]; + _ctrl = (_display displayCtrl _idc); + _ctrl ctrlSetPosition _pos; + _ctrl ctrlCommit 0; +}; diff --git a/addons/medical/functions/fnc_handleDamage_advanced.sqf b/addons/medical/functions/fnc_handleDamage_advanced.sqf index 0158608067..8d4f14315a 100644 --- a/addons/medical/functions/fnc_handleDamage_advanced.sqf +++ b/addons/medical/functions/fnc_handleDamage_advanced.sqf @@ -45,15 +45,16 @@ _unit setvariable [QGVAR(bodyPartStatus), _damageBodyParts, true]; [_unit, _selectionName, _newDamage, _typeOfProjectile, _typeOfDamage] call FUNC(handleDamage_wounds); -if (GVAR(enableAirway)) then { - [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_airway); -}; -if (GVAR(enableFractures)) then { - [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_fractures); -}; -if (GVAR(enableInternalBleeding)) then { - [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_internalInjuries); -}; +// TODO Disabled until implemented fully +//if (GVAR(enableAirway)) then { +// [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_airway); +//}; +//if (GVAR(enableFractures)) then { +// [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_fractures); +//}; +//if (GVAR(enableInternalBleeding)) then { +// [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_internalInjuries); +//}; if (alive _unit && {!(_unit getvariable ["ACE_isUnconscious", false])}) then { [_unit, _newDamage] call FUNC(reactionToDamage); diff --git a/addons/medical/functions/fnc_handleDamage_basic.sqf b/addons/medical/functions/fnc_handleDamage_basic.sqf index f31c9f186d..600101e7eb 100644 --- a/addons/medical/functions/fnc_handleDamage_basic.sqf +++ b/addons/medical/functions/fnc_handleDamage_basic.sqf @@ -112,8 +112,20 @@ if (_selection == "") then { }; -// Assign orphan structural damage to torso; -// @todo +// Assign orphan structural damage to torso +[{ + private ["_unit", "_damagesum"]; + _unit = _this select 0; + _damagesum = (_unit getHitPointDamage "HitHead") + + (_unit getHitPointDamage "HitBody") + + (_unit getHitPointDamage "HitLeftArm") + + (_unit getHitPointDamage "HitRightArm") + + (_unit getHitPointDamage "HitLeftLeg") + + (_unit getHitPointDamage "HitRightLeg"); + if (_damagesum < 0.06 and damage _unit > 0.06 and alive _unit) then { + _unit setHitPointDamage ["HitBody", damage _unit]; + }; +}, [_unit], 2, 0.1] call EFUNC(common,waitAndExecute); if (_selection == "") then { @@ -137,7 +149,7 @@ if (_legdamage >= LEGDAMAGETRESHOLD1) then { } else { if (_unit getHitPointDamage "HitLegs" != 0) then {_unit setHitPointDamage ["HitLegs", 0]}; }; -// @ŧodo: force prone for completely fucked up legs. +// @todo: force prone for completely fucked up legs. // Arm Damage @@ -171,9 +183,8 @@ if (_selection == "" and _damageReturn < 1 and !(_unit getVariable [QGVAR(isUnconscious), False] )) then { - // random chance to kill AI instead of knocking them out - if (_unit getVariable [QGVAR(allowUnconscious), ([_unit] call EFUNC(common,isPlayer)) or random 1 > 0.5]) then { - hint "unconscious"; // @todo + if (_unit getVariable [QGVAR(allowUnconscious), ([_unit] call EFUNC(common,isPlayer)) or random 1 > 0.3]) then { + [_unit, true] call FUNC(setUnconscious); } else { _damageReturn = 1; }; diff --git a/addons/medical/functions/fnc_handleDamage_fractures.sqf b/addons/medical/functions/fnc_handleDamage_fractures.sqf index 0a22365044..31fa1c8873 100644 --- a/addons/medical/functions/fnc_handleDamage_fractures.sqf +++ b/addons/medical/functions/fnc_handleDamage_fractures.sqf @@ -70,5 +70,5 @@ if (_amountOfDamage > 0.05) then { _fractureID = (_fractures select (_amountOf - 1) select 0) + 1; }; _fractures pushback [_fractureID, _fractureType, _bodyPartn, 1 /* percentage treated */]; - _unit setvariable [GVAR(fractures), _fractures, true]; -}; \ No newline at end of file + _unit setvariable [QGVAR(fractures), _fractures, true]; +}; diff --git a/addons/medical/functions/fnc_handleUnitVitals.sqf b/addons/medical/functions/fnc_handleUnitVitals.sqf index e7c55d5d08..68bd98a153 100644 --- a/addons/medical/functions/fnc_handleUnitVitals.sqf +++ b/addons/medical/functions/fnc_handleUnitVitals.sqf @@ -16,6 +16,11 @@ private ["_unit", "_heartRate","_bloodPressure","_bloodVolume","_painStatus", "_lastTimeValuesSynced", "_syncValues"]; _unit = _this select 0; +_interval = time - (_unit getVariable [QGVAR(lastMomentVitalsHandled), 0]); +_unit setVariable [QGVAR(lastMomentVitalsHandled), time]; + +if (_interval == 0) exitWith {}; + _lastTimeValuesSynced = _unit getvariable [QGVAR(lastMomentValuesSynced), 0]; _syncValues = time - _lastTimeValuesSynced >= (10 + floor(random(10))); if (_syncValues) then { @@ -60,40 +65,64 @@ if (_painStatus > 0) then { }; }; +if (GVAR(level) == 1) then { + // reduce pain + if (_unit getVariable [QGVAR(pain), 0] > 0) then { + _unit setVariable [QGVAR(pain), ((_unit getVariable QGVAR(pain)) - 0.001 * _interval) max 0, _syncValues]; + }; -if (_bloodVolume < 30) exitwith { - [_unit] call FUNC(setDead); -}; + // reduce painkillers + if (_unit getVariable [QGVAR(morphine), 0] > 0) then { + _unit setVariable [QGVAR(morphine), ((_unit getVariable QGVAR(morphine)) - 0.0015 * _interval) max 0, _syncValues]; + }; -if ([_unit] call EFUNC(common,isAwake)) then { - if (_bloodVolume < 60) then { - if (random(1) > 0.9) then { - [_unit] call FUNC(setUnconscious); + // bleeding + _blood = _unit getVariable [QGVAR(bloodVolume), 100]; + _blood = (_blood - 0.4 * (damage _unit) * _interval) max 0; + if (_blood != (_unit getVariable [QGVAR(bloodVolume), 100])) then { + _unit setVariable [QGVAR(bloodVolume), _blood, _syncValues]; + if (_blood <= 35 and !(_unit getVariable [QGVAR(isUnconscious), false])) then { + [_unit, true] call FUNC(setUnconscious); + }; + if (_blood == 0) then { + [_unit] call FUNC(setDead); }; }; }; // handle advanced medical, with vitals if (GVAR(level) >= 2) then { + if (_bloodVolume < 30) exitwith { + [_unit] call FUNC(setDead); + }; + + if ([_unit] call EFUNC(common,isAwake)) then { + if (_bloodVolume < 60) then { + if (random(1) > 0.9) then { + [_unit] call FUNC(setUnconscious); + }; + }; + }; // Set the vitals - _heartRate = (_unit getvariable [QGVAR(heartRate), 0]) + ([_unit] call FUNC(getHeartRateChange)); + _heartRate = (_unit getvariable [QGVAR(heartRate), 0]) + ([_unit] call FUNC(getHeartRateChange)) * _interval; _unit setvariable [QGVAR(heartRate), _heartRate, _syncValues]; _bloodPressure = [_unit] call FUNC(getBloodPressure); _unit setvariable [QGVAR(bloodPressure), _bloodPressure, _syncValues]; + // TODO Disabled until implemented fully // Handle airway - if (GVAR(setting_allowAirwayInjuries)) then { + /*if (GVAR(setting_allowAirwayInjuries)) then { _airwayStatus = _unit getvariable [QGVAR(airwayStatus), 100]; if (((_unit getvariable [QGVAR(airwayOccluded), false]) || (_unit getvariable [QGVAR(airwayCollapsed), false])) && !((_unit getvariable [QGVAR(airwaySecured), false]))) then { if (_airwayStatus >= 0.5) then { - _unit setvariable [QGVAR(airwayStatus), _airwayStatus - 0.5, _syncValues]; + _unit setvariable [QGVAR(airwayStatus), _airwayStatus - 0.5 * _interval, _syncValues]; }; } else { if !((_unit getvariable [QGVAR(airwayOccluded), false]) || (_unit getvariable [QGVAR(airwayCollapsed), false])) then { if (_airwayStatus < 100) then { - _unit setvariable [QGVAR(airwayStatus), (_airwayStatus + 1.5) min 100, _syncValues]; + _unit setvariable [QGVAR(airwayStatus), (_airwayStatus + 1.5 * _interval) min 100, _syncValues]; }; }; }; @@ -103,12 +132,11 @@ if (GVAR(level) >= 2) then { [_unit, true] call FUNC(setDead); }; }; - }; + };*/ // Check vitals for medical status // TODO check for in revive state instead of variable - // TODO Implement cardiac arrest. - _bloodPressureL = _bloodPressure select 0; + _bloodPressureL = _bloodPressure select 0; _bloodPressureH = _bloodPressure select 1; if (!(_unit getvariable [QGVAR(inCardiacArrest),false])) then { diff --git a/addons/medical/functions/fnc_hasItem.sqf b/addons/medical/functions/fnc_hasItem.sqf index d02abb9187..551d532ae4 100644 --- a/addons/medical/functions/fnc_hasItem.sqf +++ b/addons/medical/functions/fnc_hasItem.sqf @@ -32,7 +32,7 @@ if ([_medic, _item] call EFUNC(common,hasItem)) exitwith { }; _return = false; -if ([vehicle _medic] call FUNC(isMedicalVehicle) && {(vehicle _medic != _medic)}) then { +if ((vehicle _medic != _medic) && {[vehicle _medic] call FUNC(isMedicalVehicle)}) then { _crew = crew vehicle _medic; { if ([_medic, _x] call FUNC(canAccessMedicalEquipment) && {([_x, _item] call EFUNC(common,hasItem))}) exitwith { diff --git a/addons/medical/functions/fnc_init.sqf b/addons/medical/functions/fnc_init.sqf index c58cccedb4..dfd27cdd6f 100644 --- a/addons/medical/functions/fnc_init.sqf +++ b/addons/medical/functions/fnc_init.sqf @@ -74,3 +74,8 @@ _logs = _unit getvariable [QGVAR(allLogs), []]; _unit setvariable [_x, nil, true]; } foreach _logs; _unit setvariable [QGVAR(allLogs), [], true]; + +// items +[{ + _this call FUNC(itemCheck); +}, [_unit], 0.5, 0.1] call EFUNC(common,waitAndExecute); diff --git a/addons/medical/functions/fnc_isInMedicalVehicle.sqf b/addons/medical/functions/fnc_isInMedicalVehicle.sqf new file mode 100644 index 0000000000..e610a5cf3f --- /dev/null +++ b/addons/medical/functions/fnc_isInMedicalVehicle.sqf @@ -0,0 +1,23 @@ +/* + * Author: KoffeinFlummi + * Checks if a unit is in a medical vehicle. + * + * Arguments: + * 0: unit to be checked + * + * Return Value: + * Is unit in medical vehicle? + * + * Public: Yes + */ + +private ["_unit", "_vehicle"]; + +_unit = _this select 0; +_vehicle = vehicle _unit; + +if (_unit == _vehicle) exitWith {false}; +if (_unit in [driver _vehicle, gunner _vehicle, commander _vehicle]) exitWith {false}; + +// @todo: variable names standard? +_vehicle getVariable [QGVAR(isMedic), getNumber (configFile >> "CfgVehicles" >> typeOf _vehicle >> "attendant") == 1] diff --git a/addons/medical/functions/fnc_isMedic.sqf b/addons/medical/functions/fnc_isMedic.sqf index d3ece4c8b0..cc07948f4b 100644 --- a/addons/medical/functions/fnc_isMedic.sqf +++ b/addons/medical/functions/fnc_isMedic.sqf @@ -1,5 +1,5 @@ /* - * Author: Glowbal + * Author: Glowbal, KoffeinFlummi * Check if a unit is any medical class * * Arguments: @@ -18,18 +18,7 @@ private ["_unit","_class","_return"]; _unit = _this select 0; _medicN = if (count _this > 1) then {_this select 1} else {1}; -_return = false; -if (GVAR(medicSetting) >= 1) then { - _class = _unit getvariable [QGVAR(medicClass), 0]; - if (GVAR(medicSetting) == 1) then { - _return = _class > 0; - } else { - if (_class >= _medicN) then { - _return = true; - }; - }; -} else { - _return = true; -}; +_class = _unit getVariable [QGVAR(medicClass), + getNumber (configFile >> "CfgVehicles" >> typeOf _unit >> "attendant")]; -_return; +_class >= _medicN min GVAR(medicSetting) diff --git a/addons/medical/functions/fnc_itemCheck.sqf b/addons/medical/functions/fnc_itemCheck.sqf new file mode 100644 index 0000000000..c903417dfc --- /dev/null +++ b/addons/medical/functions/fnc_itemCheck.sqf @@ -0,0 +1,51 @@ +/* + * Author: KoffeinFlummi + * Replaces vanilla items with ACE ones. + * + * Arguments: + * 0: The unit + * + * ReturnValue: + * nil + * + * Public: Yes + */ + +#include "script_component.hpp" + +private ["_unit"]; +_unit = _this select 0; + +while {({_x == "FirstAidKit"} count items _unit) > 0} do { + _unit removeItem "FirstAidKit"; + if (GVAR(level) >= 2) then { + _unit addItem "ACE_fieldDressing"; + _unit addItem "ACE_packingBandage"; + _unit addItem "ACE_morphine"; + _unit addItem "ACE_tourniquet"; + } else { + _unit addItem "ACE_fieldDressing"; + _unit addItem "ACE_fieldDressing"; + _unit addItem "ACE_morphine"; + }; +}; + +while {({_x == "Medikit"} count items _unit) > 0} do { + _unit removeItem "Medikit"; + if (GVAR(level) >= 2) then { + _unit addItemToBackpack "ACE_fieldDressing"; + _unit addItemToBackpack "ACE_packingBandage"; + _unit addItemToBackpack "ACE_packingBandage"; + _unit addItemToBackpack "ACE_epinephrine"; + _unit addItemToBackpack "ACE_morphine"; + _unit addItemToBackpack "ACE_salineIV_250"; + _unit addItemToBackpack "ACE_tourniquet"; + } else { + _unit addItemToBackpack "ACE_epinephrine"; + _unit addItemToBackpack "ACE_epinephrine"; + _unit addItemToBackpack "ACE_epinephrine"; + _unit addItemToBackpack "ACE_epinephrine"; + _unit addItemToBackpack "ACE_bloodIV"; + _unit addItemToBackpack "ACE_bloodIV"; + }; +}; diff --git a/addons/medical/functions/fnc_onPropagateWound.sqf b/addons/medical/functions/fnc_onPropagateWound.sqf index 762afa762c..934899eac4 100644 --- a/addons/medical/functions/fnc_onPropagateWound.sqf +++ b/addons/medical/functions/fnc_onPropagateWound.sqf @@ -33,5 +33,5 @@ if (!local _unit) then { if (!_exists) then { _openWounds pushback _injury; }; - _unit setvariable [GVAR(openWounds), _openWounds]; + _unit setvariable [QGVAR(openWounds), _openWounds]; }; diff --git a/addons/medical/functions/fnc_setHitPointDamage.sqf b/addons/medical/functions/fnc_setHitPointDamage.sqf index 473852b159..a9505b2150 100644 --- a/addons/medical/functions/fnc_setHitPointDamage.sqf +++ b/addons/medical/functions/fnc_setHitPointDamage.sqf @@ -1,6 +1,6 @@ /* * Author: KoffeinFlummi - * My very own setHitPointDamage since BIS's one is buggy when affecting a remote unit. + * My very own setHitPointDamage since BIS' one is buggy when affecting a remote unit. * It also doesn't change the overall damage. This does. * * Arguments: @@ -16,6 +16,10 @@ */ #include "script_component.hpp" +#define LEGDAMAGETRESHOLD1 1 +#define LEGDAMAGETRESHOLD2 1.7 +#define ARMDAMAGETRESHOLD1 1 +#define ARMDAMAGETRESHOLD2 1.7 private ["_unit", "_selection", "_damage", "_selections", "_damages", "_damageOld", "_damageSumOld", "_damageNew", "_damageSumNew", "_damageFinal"]; @@ -76,3 +80,22 @@ _unit setDamage _damageNew; _damageFinal = (_damages select _forEachIndex); _unit setHitPointDamage [_x, _damageFinal]; } forEach _selections; + +// Leg Damage +_legdamage = (_unit getHitPointDamage "HitLeftLeg") + (_unit getHitPointDamage "HitRightLeg"); +if (_legdamage >= LEGDAMAGETRESHOLD1) then { + if (_unit getHitPointDamage "HitLegs" != 1) then {_unit setHitPointDamage ["HitLegs", 1]}; +} else { + if (_unit getHitPointDamage "HitLegs" != 0) then {_unit setHitPointDamage ["HitLegs", 0]}; +}; +// @ŧodo: force prone for completely fucked up legs. + + +// Arm Damage +_armdamage = (_unit getHitPointDamage "HitLeftArm") + (_unit getHitPointDamage "HitRightArm"); +if (_armdamage >= ARMDAMAGETRESHOLD1) then { + if (_unit getHitPointDamage "HitHands" != 1) then {_unit setHitPointDamage ["HitHands", 1]}; +} else { + if (_unit getHitPointDamage "HitHands" != 0) then {_unit setHitPointDamage ["HitHands", 0]}; +}; +// @todo: Drop weapon for full damage. diff --git a/addons/medical/functions/fnc_setUnconscious.sqf b/addons/medical/functions/fnc_setUnconscious.sqf index 890f4d2787..e27d7f21f7 100644 --- a/addons/medical/functions/fnc_setUnconscious.sqf +++ b/addons/medical/functions/fnc_setUnconscious.sqf @@ -35,6 +35,12 @@ if (!local _unit) exitwith { _unit setvariable ["ACE_isUnconscious", true, true]; _unit setUnconscious true; +// @todo: mute player? +if (_unit == ACE_player) then { + if (visibleMap) then {openMap false}; + closeDialog 0; +}; + // If a unit has the launcher out, it will sometimes start selecting the primairy weapon while unconscious, // therefor we force it to select the primairy weapon before going unconscious if ((vehicle _unit) isKindOf "StaticWeapon") then { diff --git a/addons/medical/functions/fnc_treatmentBasic_bandage.sqf b/addons/medical/functions/fnc_treatmentBasic_bandage.sqf index 39b910d6e4..4b07e989aa 100644 --- a/addons/medical/functions/fnc_treatmentBasic_bandage.sqf +++ b/addons/medical/functions/fnc_treatmentBasic_bandage.sqf @@ -32,6 +32,4 @@ if (_selection == "all") then { _damage = ((_target getHitPointDamage _point) - BANDAGEHEAL) max 0; [_target, _point, _damage] call FUNC(setHitPointDamage); - - // @todo: leg/arm damage - in setHitPointDamage? }; diff --git a/addons/medical/functions/fnc_treatmentBasic_epipen.sqf b/addons/medical/functions/fnc_treatmentBasic_epipen.sqf index e616327673..644e98c390 100644 --- a/addons/medical/functions/fnc_treatmentBasic_epipen.sqf +++ b/addons/medical/functions/fnc_treatmentBasic_epipen.sqf @@ -15,7 +15,6 @@ */ #include "script_component.hpp" -#define BLOODBAGHEAL 70 private ["_caller", "_target","_className"]; _caller = _this select 0; diff --git a/addons/medical/functions/fnc_treatmentBasic_morphine.sqf b/addons/medical/functions/fnc_treatmentBasic_morphine.sqf index 30c87b6f05..d8d793d0bc 100644 --- a/addons/medical/functions/fnc_treatmentBasic_morphine.sqf +++ b/addons/medical/functions/fnc_treatmentBasic_morphine.sqf @@ -23,11 +23,9 @@ _target = _this select 1; _className = _this select 3; // reduce pain, pain sensitivity -_morphine = (_target getVariable [QGVAR(morphine), 0] + MORPHINEHEAL) min 1; +_morphine = ((_target getVariable [QGVAR(morphine), 0]) + MORPHINEHEAL) min 1; _target setVariable [QGVAR(morphine), _morphine, true]; _pain = ((_target getVariable [QGVAR(pain), 0]) - MORPHINEHEAL) max 0; _target setVariable [QGVAR(pain), _pain, true]; // @todo overdose - -// @todo pain, painkiller reduction diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml index 6b63aaa416..79bd7df1eb 100644 --- a/addons/medical/stringtable.xml +++ b/addons/medical/stringtable.xml @@ -1,73 +1,243 @@ + + + Inject Morphine + Morphin injizieren + Inyectar Morfina + Wstrzyknij morfinę + Aplikovat Morfin + Ввести морфин + Morphine + Morfium + Injetar Morfina + Inietta Morfina + + + Inject Epinephrine + Epinephrine injizieren + Inyectar Epinefrina + Wtrzyknij adrenalinę + Aplikovat Adrenalin + Ввести андреналил + Adrénaline + Adrenalin + Injetar Epinefrina + Inietta Epinefrina + + + Transfuse Blood + Bluttransfusion + Transfundir sangre + Przetocz krew + Transfúze krve + Перелить кровь + Transfusion + Infúzió + Transfundir Sangue + Effettua Trasfusione + + + Bandage + Verbinden + Venda + Bandaż + Obvázat + Pansement + Benda + Kötözés + Atadura + Перевязать + + + Bandage Head + Kopf verbinden + Vendar la cabeza + Bandażuj głowę + Obvázat hlavu + Перевязать голову + Pansement Tête + Fej kötözése + Atar Cabeça + Benda la testa + + + Bandage Torso + Torso verbinden + Vendar el torso + Bandażuj tors + Obvázat hruď + Перевязать торс + Pansement Torse + Felsőtest kötözése + Atar Tronco + Benda il torso + + + Bandage Left Arm + Arm links verbinden + Vendar el brazo izquierdo + Bandażuj lewe ramię + Obvázat levou ruku + Перевязать левую руку + Pansement Bras Gauche + Bal kar kötözése + Atar Braço Esquerdo + Benda il braccio sinistro + + + Bandage Right Arm + Arm rechts verbinden + Vendar el brazo derecho + Bandażuj prawe ramię + Obvázat pravou ruku + Перевязать правую руку + Pansement Bras Droit + Jobb kar kötözése + Atar Braço Direito + Benda il braccio destro + + + Bandage Left Leg + Bein links verbinden + Vendar la pierna izquierda + Bandażuj lewą nogę + Obvázat levou nohu + Перевязать левую ногу + Pansement Jambe Gauche + Bal láb kötözése + Atar Perna Esquerda + Benda la gamba sinistra + + + Bandage Right Leg + Bein rechts verbinden + Vendar la pierna derecha + Bandażuj prawą nogę + Obvázat pravou nohu + Перевязать правую ногу + Pansement Jambe Droite + Jobb láb kötözése + Atar Perna Direita + Benda la gamba destra + + + Injecting Morphine ... + Morphin injizieren ... + Inyectando Morfina ... + Wstrzykiwanie morfiny ... + Aplikuju Morfin ... + Введение морфина... + Injection de Morphine... + Morfium beadása... + Injetando Morfina ... + Inietto la morfina ... + + + Injecting Epinephrine ... + Epinephrine injizieren ... + Inyectando Epinefrina ... + Wstrzykiwanie adrenaliny ... + Aplikuju Adrenalin ... + Введение андреналина + Injection d'Adrénaline ... + Adrenalin beadása... + Injetando Epinefrina ... + Inietto l'epinefrina ... + + + Transfusing Blood ... + Bluttransfusion ... + Realizando transfusión ... + Przetaczanie krwi ... + Probíhá transfúze krve ... + Переливание крови... + Transfusion Sanguine ... + Infúzió... + Transfundindo Sangue ... + Effettuo la trasfusione ... + + + Bandaging ... + Verbinden ... + Vendando ... + Bandażowanie ... + Obvazuji ... + Pansement ... + Sto applicando la benda ... + Bekötözés... + Atando ... + Перевязывание.... + + - Minor + Minor - Delayed + Delayed - Immediate + Immediate - Deceased + Deceased - None + None - Normal breathing + Normal breathing Дыхание в норме Respiración normal Respiration Normale Normalny oddech - No breathing + No breathing Дыхания нет No respira Apnée Brak oddechu - Difficult breathing + Difficult breathing Дыхание затруднено Dificultad para respirar Difficultée Respiratoire Trudności z oddychaniem - Almost no breathing + Almost no breathing Дыхания почти нет Casi sin respirar Respiration Faible Prawie brak oddechu - Bleeding + Bleeding Кровотечение Sangrando Seignement Krwawienie zewnętrzne - In Pain + In Pain Испытывает боль Con Dolor A De La Douleur W bólu - Lost a lot of Blood + Lost a lot of Blood Большая кровопотеря Mucha Sangre perdida A Perdu Bcp de Sang Stracił dużo krwi - Tourniquet [CAT] + Tourniquet [CAT] Жгут Torniquete [CAT] Garot [CAT] @@ -76,487 +246,484 @@ - Bandage (Basic) + Bandage (Basic) Повязка (обычная) Vendaje (Básico) Bandage (Standard) Bandaż (jałowy) - Used to cover a wound + Used to cover a wound Для перевязки ран Utilizado para cubrir una herida Utilisé Pour Couvrir Une Blessure Używany w celu przykrycia i ochrony miejsca zranienia - A dressing, that is a particular material used to cover a wound, which is applied over the wound once bleeding has been stemmed. + A dressing, that is a particular material used to cover a wound, which is applied over the wound once bleeding has been stemmed. Повязка, накладываемая поверх раны после остановки кровотечения. Un apósito, material específico utilizado para cubrir una herida, se aplica sobre la herida una vez ha dejado de sangrar. C'est un bandage, qui est fait d'un matériel spécial utiliser pour couvrir une blessure, qui peut etre appliquer des que le seignement as ete stopper. Opatrunek materiałowy, używany do przykrywania ran, zakładany na ranę po zatamowaniu krwawienia. - Packing Bandage + Packing Bandage Тампонирующая повязка Vendaje Compresivo Bandage Mèche Bandaż (uciskowy) - Used to pack medium to large wounds and stem the bleeding + Used to pack medium to large wounds and stem the bleeding Для тампонирования ран среднего и большого размера и остановки кровотечения. Se utiliza para vendar heridas medianas y grandes y detener el sangrado Utiliser pour remplire la cavité créé dans une blessure moyenne et grande. Używany w celu opatrywania średnich i dużych ran oraz tamowania krwawienia. - A bandage used to pack the wound to stem bleeding and facilitate wound healing. Packing a wound is an option in large polytrauma injuries. + A bandage used to pack the wound to stem bleeding and facilitate wound healing. Packing a wound is an option in large polytrauma injuries. Повязка для тампонирования раны, остановки кровотечения и лучшего заживления. При тяжелых сочетанных ранениях возможно тампонирование раны. Se utiliza para detener la hemorragia de una herida y favorecer su cicatrización. Se usa en grandes lesiones o politraumatismos. Un bandage servent a etre inseré dans les blessure pour éponger le seignement et faciliter la guerrison. Ce bandage est une option pour soigner les lession de politrauma. Opatrunek stosowany w celu zatrzymania krwawienia i osłony większych ran. - Bandage (Elastic) + Bandage (Elastic) Повязка (давящая) Vendaje (Elástico) Bandage (Élastique) Bandaż (elastyczny) - Bandage kit, Elastic + Bandage kit, Elastic Давящая повязка Vendaje (Elástico) Bandage Compressif Élastique Zestaw bandaży elastycznych. - + Ce bandage peut etre utiliser pour compresser la plaie afin de ralentire le seignement et assurer la tenue du bandage lors de mouvment. Elastyczna opaska podtrzymująca opatrunek oraz usztywniająca okolice stawów. Brinda una compresión uniforme y ofrece soporte extra a una zona lesionada - Tourniquet (CAT) + Tourniquet (CAT) Жгут Torniquete (CAT) Garot (CAT) Staza (typ. CAT) - Slows down blood loss when bleeding + Slows down blood loss when bleeding Уменьшает кровопотерю при кровотечении. Reduce la velocidad de pérdida de sangre Ralentit le seignement Zmniejsza ubytek krwi z kończyn w przypadku krwawienia. - A constricting device used to compress venous and arterial circulation in effect inhibiting or slowing blood flow and therefore decreasing loss of blood. + A constricting device used to compress venous and arterial circulation in effect inhibiting or slowing blood flow and therefore decreasing loss of blood. Жгут используется для прижатия сосудов, приводящего к остановке или значительному уменьшению кровотечения и сокращению кровопотери. Dispositivo utilizado para eliminar el pulso distal y de ese modo controlar la pérdida de sangre Un appareil servent a compresser les artères et veines afin de reduire la perte de sang. Opaska zaciskowa CAT służy do tamowanie krwotoków w sytuacji zranienia kończyn z masywnym krwawieniem tętniczym lub żylnym. - Morphine auto-injector + Morphine auto-injector Морфин в автоматическом шприце Morfina auto-inyectable Auto-injecteur de Morphine Autostrzykawka z morfiną - Used to combat moderate to severe pain experiences + Used to combat moderate to severe pain experiences Для снятия средних и сильных болевых ощущений. Usado para combatir los estados dolorosos moderados a severos Utiliser pour contrer les douleurs modéré à severes. Morfina. Ma silne działanie przeciwbólowe. - An analgesic used to combat moderate to severe pain experiences. + An analgesic used to combat moderate to severe pain experiences. Анальгетик для снятия средних и сильных болевых ощущений. Analgésico usado para combatir los estados dolorosos de moderado a severo. Un Analgésique puissant servant a contrer les douleur modéré a severe. Organiczny związek chemiczny z grupy alkaloidów. Ma silne działanie przeciwbólowe. - Atropin auto-injector + Atropin auto-injector Атропин в автоматическом шприце Atropina auto-inyectable Auto-injecteur d'Atropine Autostrzykawka AtroPen - Used in NBC scenarios + Used in NBC scenarios Применяется для защиты от ОМП Usado en escenarios NBQ Utiliser en cas d'attaque CBRN Atropina. Stosowana jako lek rozkurczowy i środek rozszerzający źrenice. - A drug used by the Military in NBC scenarios. + A drug used by the Military in NBC scenarios. Препарат, используемый в войсках для защиты от оружия массового поражения. Medicamento usado por Militares en escenarios NBQ Médicament utilisé par l'armée en cas d'attaque CBRN Atropina. Stosowana jako lek rozkurczowy i środek rozszerzający źrenice. Środek stosowany w przypadku zagrożeń NBC. - Epinephrine auto-injector + Epinephrine auto-injector Адреналин в автоматическом шприце Epinefrina auto-inyectable Auto-injecteur d'épinéphrine Autostrzykawka EpiPen - Increase heart rate and counter effects given by allergic reactions + Increase heart rate and counter effects given by allergic reactions Стимулирует работу сердца и купирует аллергические реакции. Aumenta la frecuencia cardiaca y contraresta los efectos de las reacciones alérgicas Augmente la Fréquance cadiaque et contré les effet d'une reaction Anaphylactique Adrenalina. Zwiększa puls i przeciwdziała efektom wywołanym przez reakcje alergiczne - A drug that works on a sympathetic response to dilate the bronchi, increase heart rate and counter such effects given by allergic reactions (anaphylaxis). Used in sudden cardiac arrest scenarios with decreasing positive outcomes. + A drug that works on a sympathetic response to dilate the bronchi, increase heart rate and counter such effects given by allergic reactions (anaphylaxis). Used in sudden cardiac arrest scenarios with decreasing positive outcomes. Препарат, вызывающий симпатическую реакцию, приводящую к расширению бронхов, увеличению частоты сердечных сокращений и купированию аллергических реакций (анафилактического шока). Применяется при остановке сердца с уменьшением вероятности благоприятного исхода. Medicamento que dilata los bronquios, aumenta la frecuencia cardiaca y contrarresta los efectos de las reacciones alérgicas (anafilaxis). Se utiliza en caso de paros cardiacos repentinos. Un medicament qui fonctione sur le systeme sympatique créan une dilatation des bronches, augmente la fréquance cardiaque et contre les effet d'une reaction alergique (anaphylaxie). Utiliser lors d'arret cardio-respiratoire pour augmenté les chances retrouver un ryhtme. EpiPen z adrenaliną ma działanie sympatykomimetyczne, tj. pobudza receptory alfa- i beta-adrenergiczne. Pobudzenie układu współczulnego prowadzi do zwiększenia częstotliwości pracy serca, zwiększenia pojemności wyrzutowej serca i przyśpieszenia krążenia wieńcowego. Pobudzenie oskrzelowych receptorów beta-adrenergicznych wywołuje rozkurcz mięśni gładkich oskrzeli, co w efekcie zmniejsza towarzyszące oddychaniu świsty i duszności. - Plasma IV (1000ml) + Plasma IV (1000ml) Плазма для в/в вливания (1000 мл) Plasma Intravenoso (1000ml) Plasma Sanguin IV (1000ml) Osocze IV (1000ml) - A volume-expanding blood supplement. + A volume-expanding blood supplement. Дополнительный препарат, применяемый при возмещении объема крови. Suplemento para expandir el volumen sanguíneo. Supplement visant a remplacer les volume sanguin Składnik krwi, używany do zwiększenia jej objętości. - A volume-expanding blood supplement. + A volume-expanding blood supplement. Дополнительный препарат, применяемый при возмещении объема крови. Suplemento para expandir el volumen sanguíneo. Supplement visant a remplacer le volume sanguin et remplace les plaquettes. Składnik krwi, używany do zwiększenia jej objętości. - Plasma IV (500ml) + Plasma IV (500ml) Плазма для в/в вливания (500 мл) Plasma Intravenoso (500ml) Plasma Sanguin IV (500ml) Osocze IV (500ml) - Plasma IV (250ml) + Plasma IV (250ml) Плазма для в/в вливания (250 мл) Plasma Intravenoso (250ml) Plasma Sanguin (250ml) Osocze IV (250ml) - Blood IV (1000ml) + Blood IV (1000ml) Кровь для переливания (1000 мл) Sangre Intravenosa (1000ml) Cullot Sanguin IV (1000ml) Krew IV (1000ml) - Blood IV, for restoring a patients blood (keep cold) + Blood IV, for restoring a patients blood (keep cold) Пакет крови для возмещения объема потерянной крови (хранить в холодильнике) Sangre Intravenosa, para restarurar el volumen sanguíneo (mantener frío) Cullot Sanguin IV, pour remplacer le volume sanguin (garder Réfrigeré) Krew IV, używana do uzupełnienia krwi u pacjenta, trzymać w warunkach chłodniczych - O Negative infusion blood used in strict and rare events to replenish blood supply usually conducted in the transport phase of medical care. + O Negative infusion blood used in strict and rare events to replenish blood supply usually conducted in the transport phase of medical care. Кровь I группы, резус-отрицательная, применяется по жизненным показаниям для возмещения объема потерянной крови на догоспитальном этапе оказания медицинской помощи. Cullot Sanguin O- ,utiliser seulement lors de perte sanguine majeur afin de remplacer le volume sanguin perdu. Habituelment utiliser lors du transport ou dans un etablisement de soin. Krew 0 Rh-, używana w rzadkich i szczególnych przypadkach do uzupełnienia krwi u pacjenta, zazwyczaj w trakcie fazie transportu rannej osoby do szpitala. Utilice sólo durante gran pérdida de sangre para reemplazar el volumen de sangre perdido. Uso habitual durante el transporte de heridos. - Blood IV (500ml) + Blood IV (500ml) Кровь для переливания (500 мл) Sangre Intravenosa (500ml) Cullot Sanguin IV (500ml) Krew IV (500ml) - Blood IV (250ml) + Blood IV (250ml) Кровь для переливания (250 мл) Sangre Intravenosa (250ml) Cullot Sanguin IV (250ml) Krew IV (250ml) - Saline IV (1000ml) + Saline IV (1000ml) Физраствор для в/в вливания (1000 мл) Solución Salina Intravenosa (1000ml) solution Saline 0.9% IV (1000ml) Solanka 0,9% IV (1000ml) - Saline IV, for restoring a patients blood + Saline IV, for restoring a patients blood Пакет физраствора для возмещения объема потерянной крови Solución Salina Intravenosa, para restaurar el volumen sanguíneo Solution Saline 0.9% IV, pour retablir temporairement la tention arteriel Solanka 0,9%, podawana dożylnie (IV), używana w celu uzupełnienia krwi u pacjenta - A medical volume-replenishing agent introduced into the blood system through an IV infusion. + A medical volume-replenishing agent introduced into the blood system through an IV infusion. Пакет физиологического раствора для возмещения объема потерянной крови путем внутривенного вливания. Suero fisiológico inoculado al torrente sanguíneo de forma intravenosa. Un remplacment temporaire pour rétablir la tention artériel lors de perte sanguine, étant ajouter par intraveineuse Używany w medycynie w formie płynu infuzyjnego jako środek nawadniający i uzupełniający niedobór elektrolitów, podawany dożylnie (IV). - Saline IV (500ml) + Saline IV (500ml) Физраствор для в/в вливания (500 мл) Solución Salina Intravenosa (500ml) Solution Saline 0.9% IV (500ml) Solanka 0,9% IV (500ml) - Saline IV (250ml) + Saline IV (250ml) Физраствор для в/в вливания (250 мл) Solución Salina Intravenosa (250ml) Solution Saline 0.9% IV (250ml) Solanka 0,9% IV (250ml) - Basic Field Dressing (QuikClot) + Basic Field Dressing (QuikClot) Первичный перевязочный пакет (QuikClot) Vendaje Básico (Coagulante) Bandage Regulier (Coagulant) Opatrunek QuikClot - QuikClot bandage + QuikClot bandage Гемостатический пакет QuikClot Venda Coagulante Bandage coagulant Podstawowy opatrunek stosowany na rany - + Un bandage servant a coaguler les seignements mineur à moyen. Proszkowy opatrunek adsorbcyjny przeznaczony do tamowania zagrażających życiu krwawień średniej i dużej intensywności. Vendaje Hemostático con coagulante que detiene el sangrado. - Personal Aid Kit + Personal Aid Kit Аптечка Kit de Soporte Vital Avanzado Équipement de support Vitale Apteczka osobista - Includes various treatment kit needed for stitching or advanced treatment + Includes various treatment kit needed for stitching or advanced treatment Содержит различные материалы и инструменты для зашивания ран и оказания специальной медпомощи. Incluye material médico para tratamientos avanzados Inclue du matériel medical pour les traitement avancé, tel les point de suture. Zestaw środków medycznych do opatrywania ran i dodatkowego leczenia po-urazowego - + - Surgical Kit + Surgical Kit Хирургический набор Kit Quirúrgico - Surgical Kit for in field advanced medical treatment + Surgical Kit for in field advanced medical treatment Набор для хирургической помощи в полевых условиях Kit Quirúrgico para el tratamiento avanzado en el campo de batalla - Surgical Kit for in field advanced medical treatment + Surgical Kit for in field advanced medical treatment Набор для хирургической помощи в полевых условиях Kit Quirúrgico para el tratamiento avanzado en el campo de batalla - Bodybag + Bodybag Мешок для трупов Bolsa para cadáveres - A bodybag for dead bodies + A bodybag for dead bodies Мешок для упаковки трупов Bolsa para cadáveres - A bodybag for dead bodies + A bodybag for dead bodies Мешок для упаковки трупов Bolsa para cadáveres - Blood Pressure + Blood Pressure Артериальное давление Presión Arterial - Checking Blood Pressure.. + Checking Blood Pressure.. Проверка артериального давления... Comprobando Presión Arterial... - You checked %1 + You checked %1 Вы осмотрели раненого %1 Examinando a %1 - You find a blood pressure of %2/%3 + You find a blood pressure of %2/%3 Артериальное давление %2/%3 La Presión Arterial es %2/%3 - You find a low blood pressure + You find a low blood pressure Давление низкое La Presión Arterial es baja - You find a normal blood pressure + You find a normal blood pressure Давление нормальное La Presión Arterial es normal - You find a high blood pressure + You find a high blood pressure Давление высокое La Presión Arterial es alta - You find no blood pressure + You find no blood pressure Давления нет No hay Presión Arterial - You fail to find a blood pressure + You fail to find a blood pressure Артериальное давление не определяется No puedes encontrar Presión Arterial - Pulse + Pulse Пульс Pulso - Checking Heart Rate.. + Checking Heart Rate.. Проверка пульса... Comprobando Pulso... - You checked %1 + You checked %1 Вы осмотрели раненого %1 Examinando a %1 - You find a Heart Rate of %2 + You find a Heart Rate of %2 Пульс %2 уд./мин. El Pulso es %2 - You find a weak Heart Rate + You find a weak Heart Rate Пульс слабый El Pulso es débil - You find a strong Heart Rate + You find a strong Heart Rate Пульс учащенный El Pulso está acelerado - You find a normal Heart Rate + You find a normal Heart Rate Пульс в норме El Pulso es bueno - You find no Heart Rate + You find no Heart Rate Пульс не прощупывается No tiene Pulso - Response + Response Реакция Reacciona - You check response of patient + You check response of patient Вы проверяете реакцию раненого Compruebas si el paciente reacciona - %1 is responsive + %1 is responsive %1 реагирует на раздражители %1 ha reaccionado - - %1 is not responsive + %1 is not responsive %1 не реагирует %1 no reacciona - You checked %1 + You checked %1 Вы осмотрели раненого %1 Examinas a %1 - - Bandaging - Перевязка... - Vendando - - Bandaged + Bandaged Повязка наложена Vendado - You bandage %1 (%2) + You bandage %1 (%2) Вы перевязали раненого %1 (%2) Aplicas vendaje a %1 en %2 - %1 is bandaging you + %1 is bandaging you %1 перевязывает вас %1 te está vendando - You start stitching injures from %1 (%2) + You start stitching injures from %1 (%2) Вы зашиваете ранения от %1 (%2) Estás suturando heridas de %1 en %2 - Stitching + Stitching Наложение швов Suturando - You treat the airway of %1 + You treat the airway of %1 Вы интубируете раненого %1 Estás intubando a %1 - Airway + Airway Дыхательные пути Vías Aéreas - %1 is treating your airway + %1 is treating your airway %1 проводит вам интубацию %1 te está intubando + + Unload patient >> + - + diff --git a/addons/medical/ui/icons/autoInjector.paa b/addons/medical/ui/icons/autoInjector.paa new file mode 100644 index 0000000000..f1707d2b82 Binary files /dev/null and b/addons/medical/ui/icons/autoInjector.paa differ diff --git a/addons/medical/ui/icons/bandage.paa b/addons/medical/ui/icons/bandage.paa new file mode 100644 index 0000000000..e8de331ae3 Binary files /dev/null and b/addons/medical/ui/icons/bandage.paa differ diff --git a/addons/medical/ui/icons/bodybag.paa b/addons/medical/ui/icons/bodybag.paa new file mode 100644 index 0000000000..ec35ad0796 Binary files /dev/null and b/addons/medical/ui/icons/bodybag.paa differ diff --git a/addons/medical/ui/icons/iv.paa b/addons/medical/ui/icons/iv.paa new file mode 100644 index 0000000000..ef7048dfd1 Binary files /dev/null and b/addons/medical/ui/icons/iv.paa differ diff --git a/addons/medical/ui/icons/medical_cross.paa b/addons/medical/ui/icons/medical_cross.paa new file mode 100644 index 0000000000..656ebc000b Binary files /dev/null and b/addons/medical/ui/icons/medical_cross.paa differ diff --git a/addons/medical/ui/icons/packingBandage.paa b/addons/medical/ui/icons/packingBandage.paa new file mode 100644 index 0000000000..0fb1a3650c Binary files /dev/null and b/addons/medical/ui/icons/packingBandage.paa differ diff --git a/addons/medical/ui/icons/surgicalKit.paa b/addons/medical/ui/icons/surgicalKit.paa new file mode 100644 index 0000000000..212c56c78c Binary files /dev/null and b/addons/medical/ui/icons/surgicalKit.paa differ diff --git a/addons/medical/ui/icons/tourniquet.paa b/addons/medical/ui/icons/tourniquet.paa new file mode 100644 index 0000000000..6497420e54 Binary files /dev/null and b/addons/medical/ui/icons/tourniquet.paa differ diff --git a/addons/medical/ui/icons/triageCard.paa b/addons/medical/ui/icons/triageCard.paa new file mode 100644 index 0000000000..0a1865fc9f Binary files /dev/null and b/addons/medical/ui/icons/triageCard.paa differ diff --git a/addons/medical/ui/triage_card_corner_l.paa b/addons/medical/ui/triage_card_corner_l.paa new file mode 100644 index 0000000000..a713f43e2d Binary files /dev/null and b/addons/medical/ui/triage_card_corner_l.paa differ diff --git a/addons/medical/ui/triage_card_corner_r.paa b/addons/medical/ui/triage_card_corner_r.paa new file mode 100644 index 0000000000..5d095321b9 Binary files /dev/null and b/addons/medical/ui/triage_card_corner_r.paa differ diff --git a/addons/medical/ui/triagecard.hpp b/addons/medical/ui/triagecard.hpp new file mode 100644 index 0000000000..f1b98f1e2d --- /dev/null +++ b/addons/medical/ui/triagecard.hpp @@ -0,0 +1,191 @@ +class ACE_gui_buttonBase; + +class GVAR(triageCard) { + idd = 7010; + movingenable = 0; + onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QUOTE(GVAR(triageCard))), _this select 0)]); + onUnload = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QUOTE(GVAR(triageCard))), nil)]); + class controlsBackground { + class Background: ACE_gui_backgroundBase { + idc = -1; + type = CT_STATIC; + x = "10 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "15 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "19 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + style = ST_LEFT + ST_SHADOW; + font = "PuristaMedium"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + colorText[] = {0.0, 0.0, 0.0, 1}; + colorBackground[] = {1,1,1,1}; + text = ""; + }; + class cornor_top_l: ACE_gui_backgroundBase { + idc = -1; + x = "10 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "5 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "5 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + font = "PuristaMedium"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + colorText[] = {1,1,0,1}; + colorBackground[] = {0,0,0,0}; + text = QUOTE(PATHTOF(ui\triage_card_corner_l.paa)); + }; + class cornor_top_r: cornor_top_l { + x = "20 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + text = QUOTE(PATHTOF(ui\triage_card_corner_r.paa)); + }; + + class TriageCardLabel { + idc = 199; + type = CT_STATIC; + x = "14.25 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "5 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "7.5 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "0.7 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)"; + style = 0x02 + 0x100; // ST_LEFT + ST_SHADOW + font = "PuristaMedium"; + colorText[] = {0,0,0,1}; + colorBackground[] = {0,0,0,0}; + text = "TRIAGE CARD"; + }; + class TriageList: ACE_gui_listBoxBase { + idc = 200; + x = "11 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "6 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "13 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "13 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)"; + rowHeight = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)"; + colorBackground[] = {0, 0, 0, 0}; + colorText[] = {0,0,0, 1.0}; + colorScrollbar[] = {0.95, 0.95, 0.95, 0}; + colorSelect[] = {0.0, 0.0, 0.0, 1}; + colorSelect2[] = {0.0, 0.0, 0.0, 1}; + colorSelectBackground[] = {0, 0, 0, 0.0}; + colorSelectBackground2[] = {0.0, 0.0, 0.0, 0.0}; + }; + class TriageTextBottom: TriageCardLabel { + idc = 2000; + x = "10 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "20 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "15 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "1.1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + style = 0x02; + colorText[] = {1, 1, 1.0, 1}; + colorBackground[] = {0,0.0,0.0,0.7}; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + text = ""; + }; + class selectTriageStatus: ACE_gui_buttonBase { + idc = 2001; + x = "10 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "20 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "15 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "1.1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + style = 0x02; + size = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1.4)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + animTextureNormal = "#(argb,8,8,3)color(0,0,0,0.0)"; + animTextureDisabled = "#(argb,8,8,3)color(0,0,0,0.0)"; + animTextureOver = "#(argb,8,8,3)color(0,0,0,0.0)"; + animTextureFocused = "#(argb,8,8,3)color(0,0,0,0.0)"; + animTexturePressed = "#(argb,8,8,3)color(0,0,0,0.0)"; + animTextureDefault = "#(argb,8,8,3)color(0,0,0,0.0)"; + action = QUOTE([true] call FUNC(dropDownTriageCard);); + text = ""; + }; + class selectTriageStatusNone: selectTriageStatus { + idc = 2002; + x = 0; + y = 0; + w = 0; + h = 0; + text = $STR_ACE_MEDICAL_TRIAGE_STATUS_NONE; + style = 0x02; + size = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + animTextureNormal = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureDisabled = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureOver = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureFocused = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTexturePressed = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureDefault = "#(argb,8,8,3)color(0,0,0,0.9)"; + action = QUOTE([false] call FUNC(dropDownTriageCard); GVAR(TriageCardTarget) setvariable [ARR_3('ACE_medical_triageLevel',0,true)];); + }; + class selectTriageStatusMinor: selectTriageStatus { + idc = 2003; + x = 0; + y = 0; + w = 0; + h = 0; + text = $STR_ACE_MEDICAL_TRIAGE_STATUS_MINOR; + style = 0x02; + size = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + animTextureNormal = "#(argb,8,8,3)color(0,0.5,0,0.9)"; + animTextureDisabled = "#(argb,8,8,3)color(0,0.5,0,0.9)"; + animTextureOver = "#(argb,8,8,3)color(0,0.5,0,0.9)"; + animTextureFocused = "#(argb,8,8,3)color(0,0.5,0,0.9)"; + animTexturePressed = "#(argb,8,8,3)color(0,0.5,0,0.9)"; + animTextureDefault = "#(argb,8,8,3)color(0,0.5,0,0.9)"; + action = QUOTE([false] call FUNC(dropDownTriageCard); GVAR(TriageCardTarget) setvariable [ARR_3('ACE_medical_triageLevel',1,true)];); + }; + class selectTriageStatusDelayed: selectTriageStatus { + idc = 2004; + x = 0; + y = 0; + w = 0; + h = 0; + text = $STR_ACE_MEDICAL_TRIAGE_STATUS_DELAYED; + style = 0x02; + size = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + animTextureNormal = "#(argb,8,8,3)color(0.77,0.51,0.08,0.9)"; + animTextureDisabled = "#(argb,8,8,3)color(0.77,0.51,0.08,0.9)"; + animTextureOver = "#(argb,8,8,3)color(0.77,0.51,0.08,0.9)"; + animTextureFocused = "#(argb,8,8,3)color(0.77,0.51,0.08,0.9)"; + animTexturePressed = "#(argb,8,8,3)color(0.77,0.51,0.08,0.9)"; + animTextureDefault = "#(argb,8,8,3)color(0.77,0.51,0.08,0.9)"; + action = QUOTE([false] call FUNC(dropDownTriageCard); GVAR(TriageCardTarget) setvariable [ARR_3('ACE_medical_triageLevel',2,true)];); + }; + class selectTriageStatusImmediate: selectTriageStatus { + idc = 2005; + x = 0; + y = 0; + w = 0; + h = 0; + text = $STR_ACE_MEDICAL_TRIAGE_STATUS_IMMEDIATE; + style = 0x02; + size = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + animTextureNormal = "#(argb,8,8,3)color(1,0.2,0.2,0.9)"; + animTextureDisabled = "#(argb,8,8,3)color(1,0.2,0.2,0.9)"; + animTextureOver = "#(argb,8,8,3)color(1,0.2,0.2,0.9)"; + animTextureFocused = "#(argb,8,8,3)color(1,0.2,0.2,0.9)"; + animTexturePressed = "#(argb,8,8,3)color(1,0.2,0.2,0.9)"; + animTextureDefault = "#(argb,8,8,3)color(1,0.2,0.2,0.9)"; + action = QUOTE([false] call FUNC(dropDownTriageCard); GVAR(TriageCardTarget) setvariable [ARR_3('ACE_medical_triageLevel', 3, true)];); + }; + class selectTriageStatusDeceased: selectTriageStatus { + idc = 2006; + x = 0; + y = 0; + w = 0; + h = 0; + text = $STR_ACE_MEDICAL_TRIAGE_STATUS_DECEASED; + style = 0x02; + size = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 1)"; + animTextureNormal = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureDisabled = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureOver = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureFocused = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTexturePressed = "#(argb,8,8,3)color(0,0,0,0.9)"; + animTextureDefault = "#(argb,8,8,3)color(0,0,0,0.9)"; + action = QUOTE([false] call FUNC(dropDownTriageCard); GVAR(TriageCardTarget) setvariable [ARR_3('ACE_medical_triageLevel', 4, true)];); + }; + }; +}; \ No newline at end of file diff --git a/addons/movement/XEH_postInit.sqf b/addons/movement/XEH_postInit.sqf index 9d2d48ce74..310b689e15 100644 --- a/addons/movement/XEH_postInit.sqf +++ b/addons/movement/XEH_postInit.sqf @@ -21,7 +21,7 @@ ["ACE3", QGVAR(climb), localize "STR_ACE_Movement_Climb", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if (ACE_player != (vehicle ACE_player)) exitWith {false}; diff --git a/addons/nametags/XEH_postInit.sqf b/addons/nametags/XEH_postInit.sqf index 4d9a1341d7..47a176b1dd 100644 --- a/addons/nametags/XEH_postInit.sqf +++ b/addons/nametags/XEH_postInit.sqf @@ -10,7 +10,7 @@ if (!hasInterface) exitWith {}; ["ACE3", QGVAR(showNameTags), localize "STR_ACE_NameTags_ShowNames", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Statement GVAR(ShowNamesTime) = time; diff --git a/addons/nightvision/XEH_postInitClient.sqf b/addons/nightvision/XEH_postInitClient.sqf index 65d6e8c45f..9d64baecb3 100644 --- a/addons/nightvision/XEH_postInitClient.sqf +++ b/addons/nightvision/XEH_postInitClient.sqf @@ -40,7 +40,7 @@ GVAR(ppEffectMuzzleFlash) ppEffectCommit 0; ["ACE3", QGVAR(IncreaseNVGBrightness), localize "STR_ACE_NightVision_IncreaseNVGBrightness", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if ((currentVisionMode _player != 1)) exitWith {false}; @@ -54,7 +54,7 @@ GVAR(ppEffectMuzzleFlash) ppEffectCommit 0; ["ACE3", QGVAR(DecreaseNVGBrightness), localize "STR_ACE_NightVision_DecreaseNVGBrightness", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if ((currentVisionMode _player != 1)) exitWith {false}; diff --git a/addons/overheating/XEH_postInit.sqf b/addons/overheating/XEH_postInit.sqf index 57b02b101e..4755b9c869 100644 --- a/addons/overheating/XEH_postInit.sqf +++ b/addons/overheating/XEH_postInit.sqf @@ -7,7 +7,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(unjamWeapon), localize "STR_ACE_Overheating_UnjamWeapon", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon) && {currentWeapon ACE_player in (ACE_player getVariable [QGVAR(jammedWeapons), []])} diff --git a/addons/parachute/XEH_postInit.sqf b/addons/parachute/XEH_postInit.sqf index 35efab12a9..ead4b33943 100644 --- a/addons/parachute/XEH_postInit.sqf +++ b/addons/parachute/XEH_postInit.sqf @@ -19,7 +19,7 @@ if (!hasInterface) exitWith {}; ["ACE3", QGVAR(showAltimeter), localize "STR_ACE_Parachute_showAltimeter", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; if (!('ACE_Altimeter' in assignedItems ace_player)) exitWith {false}; if (!(missionNamespace getVariable [QGVAR(AltimeterActive), false])) then { [ace_player] call FUNC(showAltimeter); diff --git a/addons/reload/XEH_postInit.sqf b/addons/reload/XEH_postInit.sqf index 6751348532..b3ca31cd5d 100644 --- a/addons/reload/XEH_postInit.sqf +++ b/addons/reload/XEH_postInit.sqf @@ -7,7 +7,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(checkAmmo), localize "STR_ACE_Reload_checkAmmo", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon) || {(vehicle ACE_player) isKindOf 'StaticWeapon'}) exitWith {false}; diff --git a/addons/reload/functions/fnc_checkAmmo.sqf b/addons/reload/functions/fnc_checkAmmo.sqf index 7c24ff1ff3..2ab656fe47 100644 --- a/addons/reload/functions/fnc_checkAmmo.sqf +++ b/addons/reload/functions/fnc_checkAmmo.sqf @@ -31,6 +31,10 @@ if (count _this > 1) then { }; }; -_unit playActionNow "Gear"; +if (_unit == _target) then { + _unit playActionNow "Gear"; +} else { + _unit playActionNow "PutDown"; +}; [FUNC(displayAmmo), [_target], 1, 0.1] call EFUNC(common,waitAndExecute); diff --git a/addons/respawn/functions/fnc_showFriendlyFireMessage.sqf b/addons/respawn/functions/fnc_showFriendlyFireMessage.sqf index 7d1b374252..1fdd10da4e 100644 --- a/addons/respawn/functions/fnc_showFriendlyFireMessage.sqf +++ b/addons/respawn/functions/fnc_showFriendlyFireMessage.sqf @@ -25,8 +25,6 @@ _killer = _this select 1; if (_unit != _killer && side group _unit in [side group ACE_player, civilian] && {side group _killer == side group ACE_player}) then { systemChat format ["%1 was killed by %2", [_unit] call EFUNC(common,getName), [_killer] call EFUNC(common,getName)]; - // Raise custom event. @todo: remove - [_unit, "killedByFriendly", [_unit, _killer]] call EFUNC(common,callCustomEventHandlers); // Raise ACE globalEvent ["killedByFriendly", [_unit, _killer]] call EFUNC(common,globalEvent); }; diff --git a/addons/resting/XEH_postInit.sqf b/addons/resting/XEH_postInit.sqf index 9251c7663f..ec80100523 100644 --- a/addons/resting/XEH_postInit.sqf +++ b/addons/resting/XEH_postInit.sqf @@ -7,7 +7,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(RestWeapon), localize "STR_ACE_Resting_RestWeapon", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon) && {inputAction 'reloadMagazine' == 0} && diff --git a/addons/safemode/XEH_postInit.sqf b/addons/safemode/XEH_postInit.sqf index 9508843e25..6754038bd1 100644 --- a/addons/safemode/XEH_postInit.sqf +++ b/addons/safemode/XEH_postInit.sqf @@ -9,7 +9,7 @@ ["ACE3", QGVAR(safeMode), localize "STR_ACE_SafeMode_SafeMode", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; diff --git a/addons/scopes/XEH_postInit.sqf b/addons/scopes/XEH_postInit.sqf index 6f8fae1a1b..6d4485e1b0 100644 --- a/addons/scopes/XEH_postInit.sqf +++ b/addons/scopes/XEH_postInit.sqf @@ -36,7 +36,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(AdjustUp), localize "STR_ACE_Scopes_AdjustUp", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific [ACE_player] call FUNC(inventoryCheck); if !([ACE_player, 0, 0.1] call FUNC(canAdjustScope)) exitWith {false}; @@ -51,7 +51,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(AdjustDown), localize "STR_ACE_Scopes_AdjustDown", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific [ACE_player] call FUNC(inventoryCheck); if !([ACE_player, 0, -0.1] call FUNC(canAdjustScope)) exitWith {false}; @@ -66,7 +66,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(AdjustLeft), localize "STR_ACE_Scopes_AdjustLeft", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific [ACE_player] call FUNC(inventoryCheck); if !([ACE_player, -0.1, 0] call FUNC(canAdjustScope)) exitWith {false}; @@ -81,7 +81,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(AdjustRight), localize "STR_ACE_Scopes_AdjustRight", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific [ACE_player] call FUNC(inventoryCheck); if !([ACE_player, 0.1, 0] call FUNC(canAdjustScope)) exitWith {false}; diff --git a/addons/smallarms/$PBOPREFIX$ b/addons/smallarms/$PBOPREFIX$ index 9d0480659e..9d177151a4 100644 --- a/addons/smallarms/$PBOPREFIX$ +++ b/addons/smallarms/$PBOPREFIX$ @@ -1 +1 @@ -z\ace\addons\switchunits \ No newline at end of file +z\ace\addons\smallarms \ No newline at end of file diff --git a/addons/vector/initKeybinds.sqf b/addons/vector/initKeybinds.sqf index 1ce79d79eb..1e186f36ca 100644 --- a/addons/vector/initKeybinds.sqf +++ b/addons/vector/initKeybinds.sqf @@ -3,7 +3,7 @@ ["ACE3", QGVAR(AzimuthKey), localize "STR_ACE_Vector_AzimuthKey", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(currentWeapon ACE_player == "ACE_Vector" && {ACE_player == cameraOn} && {cameraView == "GUNNER"}) exitWith {false}; @@ -20,7 +20,7 @@ GVAR(isDownStateKey1) = false; // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Statement ["azimuth"] call FUNC(onKeyUp); @@ -32,7 +32,7 @@ ["ACE3", QGVAR(DistanceKey), localize "STR_ACE_Vector_DistanceKey", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(currentWeapon ACE_player == "ACE_Vector" && {ACE_player == cameraOn} && {cameraView == "GUNNER"}) exitWith {false}; @@ -49,7 +49,7 @@ GVAR(isDownStateKey2) = false; // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Statement ["distance"] call FUNC(onKeyUp); diff --git a/addons/vehiclelock/CfgEventHandlers.hpp b/addons/vehiclelock/CfgEventHandlers.hpp index b928bc2de6..cf704d000c 100644 --- a/addons/vehiclelock/CfgEventHandlers.hpp +++ b/addons/vehiclelock/CfgEventHandlers.hpp @@ -3,3 +3,15 @@ class Extended_PreInit_EventHandlers { init = QUOTE(call COMPILE_FILE(XEH_preInit)); }; }; +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_postInit)); + }; +}; +class Extended_InventoryOpened_EventHandlers { + class CAManBase { + class ADDON { + clientInventoryOpened = QUOTE(_this call FUNC(onOpenInventory);); + }; + }; +}; diff --git a/addons/vehiclelock/CfgMagazines.hpp b/addons/vehiclelock/CfgMagazines.hpp index 198c617509..100df8065b 100644 --- a/addons/vehiclelock/CfgMagazines.hpp +++ b/addons/vehiclelock/CfgMagazines.hpp @@ -1,9 +1,10 @@ class CfgMagazines { - class CA_Magazine; - class ACE_key_customKeyMagazine: CA_Magazine { - picture = QUOTE(PATHTOF(ui\keyBlack.paa)); - displayName = "ACE Vehicle Key"; //!!!CANNONT be localized!!!, because it is used as part of the magazineDetail string - descriptionShort = "$STR_ACE_Vehicle_Item_Custom_Description"; - count = 1; - }; + class CA_Magazine; + class ACE_key_customKeyMagazine: CA_Magazine { + picture = QUOTE(PATHTOF(ui\keyBlack.paa)); + displayName = "ACE Vehicle Key"; //!!!CANNOT be localized!!!: because it is used as part of the magazineDetail string + descriptionShort = "$STR_ACE_Vehicle_Item_Custom_Description"; + count = 1; + mass = 0; + }; }; diff --git a/addons/vehiclelock/CfgVehicles.hpp b/addons/vehiclelock/CfgVehicles.hpp index 5be796c126..1a7da461ca 100644 --- a/addons/vehiclelock/CfgVehicles.hpp +++ b/addons/vehiclelock/CfgVehicles.hpp @@ -1,102 +1,107 @@ #define MACRO_LOCK_ACTIONS \ - class ACE_MainActions { \ - class ACE_unlockVehicle { \ - displayName = "$STR_ACE_Vehicle_Action_UnLock"; \ - distance = 4; \ - condition = QUOTE(([ARR_2(_player, _target)] call FUNC(hasKeyForVehicle)) && {(locked _target) in [ARR_2(2,3)]}); \ - statement = QUOTE([ARR_3('SetVehicleLock', [_target], [ARR_2(_target,false)])] call EFUNC(common,targetEvent)); \ - showDisabled = 0; \ - priority = 0.3; \ - icon = QUOTE(PATHTOF(ui\key_menuIcon_ca.paa)); \ - }; \ - class ACE_lockVehicle { \ - displayName = "$STR_ACE_Vehicle_Action_Lock"; \ - distance = 4; \ - condition = QUOTE(([ARR_2(_player, _target)] call FUNC(hasKeyForVehicle)) && {(locked _target) in [ARR_2(0,1)]}); \ - statement = QUOTE([ARR_3('SetVehicleLock', [_target], [ARR_2(_target,true)])] call EFUNC(common,targetEvent)); \ - showDisabled = 0; \ - priority = 0.2; \ - icon = QUOTE(PATHTOF(ui\key_menuIcon_ca.paa)); \ - }; \ - class ACE_lockpickVehicle { \ - displayName = "$STR_ACE_Vehicle_Action_Lockpick"; \ - distance = 4; \ - condition = QUOTE([ARR_3(_player, _target, 'canLockpick')] call FUNC(lockpick)); \ - statement = QUOTE([ARR_3(_player, _target, 'startLockpick')] call FUNC(lockpick)); \ - showDisabled = 0; \ - priority = 0.1; \ - }; \ - }; + class ACE_MainActions { \ + class ACE_unlockVehicle { \ + displayName = "$STR_ACE_Vehicle_Action_UnLock"; \ + distance = 4; \ + condition = QUOTE(([ARR_2(_player, _target)] call FUNC(hasKeyForVehicle)) && {(locked _target) in [ARR_2(2,3)]}); \ + statement = QUOTE([ARR_3('VehicleLock_SetVehicleLock', [_target], [ARR_2(_target,false)])] call EFUNC(common,targetEvent)); \ + showDisabled = 0; \ + priority = 0.3; \ + icon = QUOTE(PATHTOF(ui\key_menuIcon_ca.paa)); \ + }; \ + class ACE_lockVehicle { \ + displayName = "$STR_ACE_Vehicle_Action_Lock"; \ + distance = 4; \ + condition = QUOTE(([ARR_2(_player, _target)] call FUNC(hasKeyForVehicle)) && {(locked _target) in [ARR_2(0,1)]}); \ + statement = QUOTE([ARR_3('VehicleLock_SetVehicleLock', [_target], [ARR_2(_target,true)])] call EFUNC(common,targetEvent)); \ + showDisabled = 0; \ + priority = 0.2; \ + icon = QUOTE(PATHTOF(ui\key_menuIcon_ca.paa)); \ + }; \ + class ACE_lockpickVehicle { \ + displayName = "$STR_ACE_Vehicle_Action_Lockpick"; \ + distance = 4; \ + condition = QUOTE([ARR_3(_player, _target, 'canLockpick')] call FUNC(lockpick)); \ + statement = QUOTE([ARR_3(_player, _target, 'startLockpick')] call FUNC(lockpick)); \ + showDisabled = 0; \ + priority = 0.1; \ + }; \ + }; class CfgVehicles { - class LandVehicle; - class Car: LandVehicle { - class ACE_Actions { - MACRO_LOCK_ACTIONS - }; - }; - class Tank: LandVehicle { - class ACE_Actions { - MACRO_LOCK_ACTIONS - }; - }; - class Air; - class Helicopter: Air { - class ACE_Actions { - MACRO_LOCK_ACTIONS - }; - }; - - class Logic; - class Module_F: Logic { - class ArgumentsBaseUnits {}; - class ModuleDescription {}; - }; - class ACE_VehicleLock_ModuleSetup: Module_F { - author = "$STR_ACE_Common_ACETeam"; - category = "ACE"; - displayName = "Vehicle Lock Setup"; - function = "ACE_VehicleLock_fnc_moduleInit"; - scope = 2; - isGlobal = 1; - icon = QUOTE(PATHTOF(ui\IconLock_ca.paa)); - functionPriority = 0; - class Arguments { - class SetLockState { - displayName = "Set Lock State"; // Argument label - description = "Set lock state for all vehicles on map at start"; // Tooltip description - typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" - class values { - class None {name = "As Is"; value = 0; default = 1;}; - class Side {name = "Locked"; value = 1;}; - class Unique {name = "Unlocked"; value = 2;}; + class LandVehicle; + class Car: LandVehicle { + class ACE_Actions { + MACRO_LOCK_ACTIONS }; - }; - class LockpickStrength { - displayName = "Global Lockpick Strength"; - description = "Global Time to lockpick (in seconds). Default: 10"; - typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" - defaultValue = "10"; // Default text filled in the input box - }; }; - class ModuleDescription: ModuleDescription { - description = "Settings for lockpick strength and initial vehicle lock state. Removes ambiguous lock states.
Source: vehiclelock.pbo"; + class Tank: LandVehicle { + class ACE_Actions { + MACRO_LOCK_ACTIONS + }; + }; + class Air; + class Helicopter: Air { + class ACE_Actions { + MACRO_LOCK_ACTIONS + }; }; - }; - class ACE_VehicleLock_ModuleSyncedAssign: Module_F { - author = "$STR_ACE_Common_ACETeam"; - category = "ACE"; - displayName = "Vehicle Key Assign"; - function = "ACE_VehicleLock_fnc_moduleSync"; - scope = 2; - isGlobal = 1; - icon = QUOTE(PATHTOF(ui\IconLock_ca.paa)); - functionPriority = 0; - class Arguments {}; - class ModuleDescription: ModuleDescription { - description = "Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start.
Source: vehiclelock.pbo"; - sync[] = {"AnyPlayer", "AnyVehicle"}; + class Logic; + class Module_F: Logic { + class ModuleDescription {}; + }; + class ACE_VehicleLock_ModuleSetup: Module_F { + author = "$STR_ACE_Common_ACETeam"; + category = "ACE"; + displayName = "Vehicle Lock Setup"; + function = QUOTE(DFUNC(moduleInit)); + scope = 2; + isGlobal = 0; + icon = QUOTE(PATHTOF(ui\IconLock_ca.paa)); + functionPriority = 0; + class Arguments { + class LockVehicleInventory { + displayName = "Lock Vehicle Inventory"; + description = "Locks the inventory of locked vehicles"; + typeName = "BOOL"; + defaultValue = 0; + }; + class SetLockState { + displayName = "Set Lock State"; // Argument label + description = "Set lock state for all vehicles on map at start"; // Tooltip description + typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" + class values { + class None {name = "As Is"; value = 0; default = 1;}; + class Side {name = "Locked"; value = 1;}; + class Unique {name = "Unlocked"; value = 2;}; + }; + }; + class DefaultLockpickStrength { + displayName = "Default Lockpick Strength"; + description = "Default Time to lockpick (in seconds). Default: 10"; + typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" + defaultValue = "10"; // Default text filled in the input box + }; + }; + class ModuleDescription: ModuleDescription { + description = "Settings for lockpick strength and initial vehicle lock state. Removes ambiguous lock states.
Source: vehiclelock.pbo"; + }; + }; + + class ACE_VehicleLock_ModuleSyncedAssign: Module_F { + author = "$STR_ACE_Common_ACETeam"; + category = "ACE"; + displayName = "Vehicle Key Assign"; + function = QUOTE(DFUNC(moduleSync)); + scope = 2; + isGlobal = 0; + icon = QUOTE(PATHTOF(ui\IconLock_ca.paa)); + functionPriority = 0; + class Arguments {}; + class ModuleDescription: ModuleDescription { + description = "Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start.
Source: vehiclelock.pbo"; + sync[] = {"AnyPlayer", "AnyVehicle"}; + }; }; - }; }; diff --git a/addons/vehiclelock/CfgWeapons.hpp b/addons/vehiclelock/CfgWeapons.hpp index 157fb4bf60..4b20de15d7 100644 --- a/addons/vehiclelock/CfgWeapons.hpp +++ b/addons/vehiclelock/CfgWeapons.hpp @@ -1,41 +1,41 @@ class CfgWeapons { - class InventoryItem_Base_F; - class ACE_ItemCore; + class InventoryItem_Base_F; + class ACE_ItemCore; - class ACE_key_master: ACE_ItemCore { - author = "$STR_ACE_Common_ACETeam"; - displayName = "Vehicle Key: Master"; - descriptionShort = "$STR_ACE_Vehicle_Item_Master_Description"; - model = "\A3\weapons_F\ammo\mag_univ.p3d"; - picture = QUOTE(PATHTOF(ui\keyBlack.paa)); - scope = 2; - class ItemInfo: InventoryItem_Base_F { - mass = 0.1; - }; - }; - class ACE_key_lockpick: ACE_key_master { - displayName = "Lockpick"; - descriptionShort = "$STR_ACE_Vehicle_Item_Lockpick_Description"; - picture = QUOTE(PATHTOF(ui\lockpick.paa)); - }; - class ACE_key_west: ACE_key_master { - displayName = "Vehicle Key: West"; - descriptionShort = "$STR_ACE_Vehicle_Item_West_Description"; - picture = QUOTE(PATHTOF(ui\keyBlue.paa)); - }; - class ACE_key_east: ACE_key_master { - displayName = "Vehicle Key: East"; - descriptionShort = "$STR_ACE_Vehicle_Item_East_Description"; - picture = QUOTE(PATHTOF(ui\keyRed.paa)); - }; - class ACE_key_indp: ACE_key_master { - displayName = "Vehicle Key: Independent"; - descriptionShort = "$STR_ACE_Vehicle_Item_Indp_Description"; - picture = QUOTE(PATHTOF(ui\keyPurple.paa)); - }; - class ACE_key_civ: ACE_key_master { - displayName = "Vehicle Key: Civilian"; - descriptionShort = "$STR_ACE_Vehicle_Item_Civ_Description"; - picture = QUOTE(PATHTOF(ui\keyGreen.paa)); - }; + class ACE_key_master: ACE_ItemCore { + author = "$STR_ACE_Common_ACETeam"; + displayName = "Vehicle Key: Master"; + descriptionShort = "$STR_ACE_Vehicle_Item_Master_Description"; + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QUOTE(PATHTOF(ui\keyBlack.paa)); + scope = 2; + class ItemInfo: InventoryItem_Base_F { + mass = 0; + }; + }; + class ACE_key_lockpick: ACE_key_master { + displayName = "Lockpick"; + descriptionShort = "$STR_ACE_Vehicle_Item_Lockpick_Description"; + picture = QUOTE(PATHTOF(ui\lockpick.paa)); + }; + class ACE_key_west: ACE_key_master { + displayName = "Vehicle Key: West"; + descriptionShort = "$STR_ACE_Vehicle_Item_West_Description"; + picture = QUOTE(PATHTOF(ui\keyBlue.paa)); + }; + class ACE_key_east: ACE_key_master { + displayName = "Vehicle Key: East"; + descriptionShort = "$STR_ACE_Vehicle_Item_East_Description"; + picture = QUOTE(PATHTOF(ui\keyRed.paa)); + }; + class ACE_key_indp: ACE_key_master { + displayName = "Vehicle Key: Independent"; + descriptionShort = "$STR_ACE_Vehicle_Item_Indp_Description"; + picture = QUOTE(PATHTOF(ui\keyPurple.paa)); + }; + class ACE_key_civ: ACE_key_master { + displayName = "Vehicle Key: Civilian"; + descriptionShort = "$STR_ACE_Vehicle_Item_Civ_Description"; + picture = QUOTE(PATHTOF(ui\keyGreen.paa)); + }; }; diff --git a/addons/vehiclelock/XEH_postInit.sqf b/addons/vehiclelock/XEH_postInit.sqf new file mode 100644 index 0000000000..c635de2bd3 --- /dev/null +++ b/addons/vehiclelock/XEH_postInit.sqf @@ -0,0 +1,5 @@ +#include "script_component.hpp" + +//Add Event Handlers +["VehicleLock_SetupCustomKey", {_this call FUNC(serverSetupCustomKeyEH)}] call EFUNC(common,addEventHandler); +["VehicleLock_SetVehicleLock", {_this call FUNC(setVehicleLockEH)}] call EFUNC(common,addEventHandler); diff --git a/addons/vehiclelock/XEH_preInit.sqf b/addons/vehiclelock/XEH_preInit.sqf index 80d1d6335f..bdab28fc75 100644 --- a/addons/vehiclelock/XEH_preInit.sqf +++ b/addons/vehiclelock/XEH_preInit.sqf @@ -8,11 +8,8 @@ PREP(hasKeyForVehicle); PREP(lockpick); PREP(moduleInit); PREP(moduleSync); +PREP(onOpenInventory); PREP(serverSetupCustomKeyEH); PREP(setVehicleLockEH); -//Add Event Handlers -["SetupCustomKey", {_this call FUNC(serverSetupCustomKeyEH)}] call EFUNC(common,addEventHandler); -["SetVehicleLock", {_this call FUNC(setVehicleLockEH)}] call EFUNC(common,addEventHandler); - ADDON = true; diff --git a/addons/vehiclelock/config.cpp b/addons/vehiclelock/config.cpp index 9031987315..700e27b3cb 100644 --- a/addons/vehiclelock/config.cpp +++ b/addons/vehiclelock/config.cpp @@ -17,6 +17,10 @@ class ACE_Settings { value = 10; typeName = "SCALAR"; }; + class GVAR(LockVehicleInventory) { + value = 0; + typeName = "BOOL"; + }; }; #include "CfgEventHandlers.hpp" diff --git a/addons/vehiclelock/functions/fnc_addKeyForVehicle.sqf b/addons/vehiclelock/functions/fnc_addKeyForVehicle.sqf index c64a0f890d..d683073286 100644 --- a/addons/vehiclelock/functions/fnc_addKeyForVehicle.sqf +++ b/addons/vehiclelock/functions/fnc_addKeyForVehicle.sqf @@ -1,45 +1,40 @@ /* - Name: ACE_VehicleLock_fnc_addKeyForVehicle - - Author: Pabst Mirror - - Description: - Adds a key to a unit that will open a vehicle - - Parameters: - 0: OBJECT - unit - 1: OBJECT - vehicle - 2: BOOL - custom key (true: custom key (magazine) - false: side key (item)) - - Returns: - Nothing - - Example: - [bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle; -*/ - + * Author: PabstMirror + * Adds a key to a unit that will open a vehicle + * Note: has global effects for Unit (will add items to remote unit) + * + * Arguments: + * 0: Unit + * 1: Vehicle + * 2: custom key (true: custom key (magazine) - false: side key (item)) + * + * Return Value: + * None + * + * Example: + * [ACE_player, car, true] call ACE_VehicleLock_fnc_addKeyForVehicle + * + * Public: Yes + */ #include "script_component.hpp" -private ["_unit","_veh","_useCustom","_previousMags","_newMags","_keyMagazine","_keyName"]; +private ["_previousMags","_newMags","_keyMagazine","_keyName"]; -_unit = [_this, 0, objNull, [objNull]] call bis_fnc_param; -_veh = [_this, 1, objNull, [objNull]] call bis_fnc_param; -_useCustom = [_this, 2, false, [false]] call bis_fnc_param; +PARAMS_3(_unit,_veh,_useCustom); -if (isNull _unit) exitWith {["addKeyForVehicleClient: null unit"] call BIS_fnc_error;}; -if (isNull _veh) exitWith {["addKeyForVehicleClient: null vehicle"] call BIS_fnc_error;}; +if (isNull _unit) exitWith {ERROR("null unit");}; +if (isNull _veh) exitWith {ERROR("null vehicle");}; if (_useCustom) then { - _previousMags = magazinesDetail _unit; - _unit addMagazine ["ACE_key_customKeyMagazine", 1]; - _newMags = (magazinesDetail _unit) - _previousMags; - if ((count _newMags) == 0) exitWith { - ["ACE_VehicleLock_fnc_addKeyForVehicle: failed to add magazine (inventory full?)"] call BIS_fnc_error; - }; - _keyMagazine = _newMags select 0; - TRACE_2("setting up key on server",_veh,_keyMagazine); - ["SetupCustomKey", [_veh, _keyMagazine]] call EFUNC(common,serverEvent); + _previousMags = magazinesDetail _unit; + _unit addMagazine ["ACE_key_customKeyMagazine", 1]; //addMagazine array has global effects + _newMags = (magazinesDetail _unit) - _previousMags; + if ((count _newMags) == 0) exitWith {ERROR("failed to add magazine (inventory full?)");}; + _keyMagazine = _newMags select 0; + TRACE_2("setting up key on server",_veh,_keyMagazine); + //Have the server run add the key to the vehicle's key array: + ["VehicleLock_SetupCustomKey", [_veh, _keyMagazine]] call EFUNC(common,serverEvent); } else { - _keyName = [_veh] call FUNC(getVehicleSideKey); - _unit addItem _keyName; + _keyName = [_veh] call FUNC(getVehicleSideKey); + _unit addItem _keyName; //addItem has global effects }; diff --git a/addons/vehiclelock/functions/fnc_getVehicleSideKey.sqf b/addons/vehiclelock/functions/fnc_getVehicleSideKey.sqf index 819c13c332..999f471ac3 100644 --- a/addons/vehiclelock/functions/fnc_getVehicleSideKey.sqf +++ b/addons/vehiclelock/functions/fnc_getVehicleSideKey.sqf @@ -1,27 +1,25 @@ /* -Name: ACE_VehicleLock_fnc_getVehicleSideKey - -Author: Pabst Mirror - -Description: - Returns the side specifc key for a vehicle - -Parameters: - 0: OBJECT - vehicle - -Returns: - STRING - Key Classname - -Example: - [tank1] call ACE_VehicleLock_fnc_getVehicleSideKey; -*/ - + * Author: PabstMirror + * Returns the side specifc key for a vehicle + * + * Arguments: + * 0: Vehicle + * + * Return Value: + * The vehicle's side key classname + * + * Example: + * [tank1] call ACE_VehicleLock_fnc_getVehicleSideKey; + * + * Public: No + */ #include "script_component.hpp" -private ["_veh","_vehConfigSide","_vehSide","_returnValue"]; +private ["_vehConfigSide","_vehSide","_returnValue"]; -_veh = [_this, 0, objNull, [objNull]] call bis_fnc_param; -if (isNull _veh) exitWith {["ACE_VehicleLock_fnc_getVehicleSideKey: null vehicle"] call BIS_fnc_error; ""}; +PARAMS_1(_veh); + +if (isNull _veh) exitWith {ERROR("null vehicle"); "error"}; _vehConfigSide = [_veh, true] call BIS_fnc_objectSide; _vehSide = _veh getVariable [QGVAR(lockSide), _vehConfigSide]; @@ -32,7 +30,7 @@ switch (_vehSide) do { case (west): {_returnValue = "ACE_key_west"}; case (east): {_returnValue = "ACE_key_east"}; case (resistance): {_returnValue = "ACE_key_indp"}; -case (civilian): {_returnValue = "ACE_key_civ"}; + default {_returnValue = "ACE_key_civ"}; }; _returnValue diff --git a/addons/vehiclelock/functions/fnc_hasKeyForVehicle.sqf b/addons/vehiclelock/functions/fnc_hasKeyForVehicle.sqf index a1c899edad..779f4a363e 100644 --- a/addons/vehiclelock/functions/fnc_hasKeyForVehicle.sqf +++ b/addons/vehiclelock/functions/fnc_hasKeyForVehicle.sqf @@ -1,31 +1,27 @@ /* -Name: ACE_VehicleLock_fnc_hasKeyForVehicle - -Author: Pabst Mirror - -Description: - Returns if user has a valid key for the vehicle - -Parameters: - 0: OBJECT - unit - 1: OBJECT - vehicle - -Returns: - BOOL - unit has key for vehicle - -Example: - [bob, car] call ACE_VehicleLock_fnc_hasKeyForVehicle; -*/ - + * Author: PabstMirror + * Returns if user has a valid key for the vehicle + * + * Arguments: + * 0: Unit + * 1: Vehicle + * + * Return Value: + * unit has key for vehicle + * + * Example: + * [bob, car] call ACE_VehicleLock_fnc_hasKeyForVehicle; + * + * Public: No + */ #include "script_component.hpp" -private ["_unit","_veh","_returnValue","_sideKeyName","_customKeys"]; +private ["_returnValue","_sideKeyName","_customKeys"]; -_unit = [_this, 0, objNull, [objNull]] call bis_fnc_param; -_veh = [_this, 1, objNull, [objNull]] call bis_fnc_param; +PARAMS_2(_unit,_veh); -if (isNull _unit) exitWith {["ACE_VehicleLock_fnc_hasKeyForVehicle: null unit"] call BIS_fnc_error; false}; -if (isNull _veh) exitWith {["ACE_VehicleLock_fnc_hasKeyForVehicle: null vehicle"] call BIS_fnc_error; false}; +if (isNull _unit) exitWith {ERROR("null unit"); false}; +if (isNull _veh) exitWith {ERROR("null vehicle"); false}; _returnValue = false; @@ -39,7 +35,7 @@ if (_sideKeyName in (items _unit)) then {_returnValue = true}; //Check custom keys _customKeys = _veh getVariable [QGVAR(customKeys), []]; { - if (_x in (magazinesDetail _unit)) then {_returnValue = true;}; + if (_x in (magazinesDetail _unit)) then {_returnValue = true;}; } forEach _customKeys; _returnValue diff --git a/addons/vehiclelock/functions/fnc_lockpick.sqf b/addons/vehiclelock/functions/fnc_lockpick.sqf index c6a6369515..4fee354824 100644 --- a/addons/vehiclelock/functions/fnc_lockpick.sqf +++ b/addons/vehiclelock/functions/fnc_lockpick.sqf @@ -1,79 +1,66 @@ /* -Name: ACE_VehicleLock_fnc_lockpick - -Author: Pabst Mirror - -Description: - Handles lockpick functionality from action menu. - -Parameters: - 0: OBJECT - unit - 1: OBJECT - vehicle - 2: STRING - function type - "canLockpick": returns BOOL if lockpick is possible - "startLockpick": starts the process - "finishLockpick": on completions, opens the lock - -Returns: - BOOL - -Example: - [ACE_player, ACE_Interaction_Target, 'canLockpick'] call ACE_VehicleLock_fnc_lockpick -*/ - + * Author: PabstMirror + * Handles lockpick functionality. Three different functions: + * "canLockpick": returns BOOL if lockpick is possible + * "startLockpick": starts the process + * "finishLockpick": on completions, opens the lock + * + * Arguments: + * 0: Unit (player) + * 1: Vehicle + * 2: Function Type + * + * Return Value: + * "canLockpick" + * + * Example: + * [ACE_player, ACE_Interaction_Target, 'canLockpick'] call ACE_VehicleLock_fnc_lockpick + * + * Public: No + */ #include "script_component.hpp" -private ["_unit","_veh","_funcType","_vehLockpickStrenth","_returnValue", "_condition"]; +private ["_vehLockpickStrenth","_condition","_returnValue"]; -_unit = [_this, 0, objNull, [objNull]] call bis_fnc_param; -_veh = [_this, 1, objNull, [objNull]] call bis_fnc_param; -_funcType = [_this, 2, "", [""]] call bis_fnc_param; +PARAMS_3(_unit,_veh,_funcType); -if (isNull _unit) exitWith { - ["ACE_VehicleLock_fnc_lockpick: null unit"] call BIS_fnc_error; - false -}; -if (isNull _veh) exitWith { - ["ACE_VehicleLock_fnc_lockpick: null vehicle"] call BIS_fnc_error; - false -}; +if (isNull _unit) exitWith {ERROR("null unit"); false}; +if (isNull _veh) exitWith {ERROR("null vehicle"); false}; //need lockpick item -if (!("ACE_key_lockpick" in (items _unit))) exitWith { - false -}; +if (!("ACE_key_lockpick" in (items _unit))) exitWith {false}; _vehLockpickStrenth = _veh getVariable[QGVAR(lockpickStrength), GVAR(DefaultLockpickStrength)]; -if (typeName _vehLockpickStrenth != "SCALAR") exitWith { - ["ACE_VehicleLock_fnc_lockpick: 'ACE_vehicleLock_LockpickStrength' invalid: (%1)", _veh] call BIS_fnc_error; - false -}; +if (typeName _vehLockpickStrenth != "SCALAR") exitWith {ERROR("ACE_vehicleLock_LockpickStrength invalid"); false}; //-1 indicates unpickable lock -if (_vehLockpickStrenth < 0) exitWith { - false +if (_vehLockpickStrenth < 0) exitWith {false}; + +//Condition check for progressBar +_condition = { + PARAMS_1(_args); + EXPLODE_2_PVT(_args,_unit,_veh); + ((_unit distance _veh) < 5) && {(speed _veh) < 0.1} }; +if (!([[_unit, _veh]] call _condition)) exitWith {false}; + _returnValue = false; - switch (true) do { case (_funcType == "canLockpick"): { - _returnValue = true; - }; -case (_funcType == "startLockpick"): { - _condition = { - PARAMS_1(_args); - EXPLODE_2_PVT(_args,_unit,_veh); - ([_unit, objNull, []] call EFUNC(common,canInteractWith)) && ((_unit distance _veh) < 5) && ((speed _veh) < 1) + _returnValue = true; + }; +case (_funcType == "startLockpick"): { + [_vehLockpickStrenth, [_unit, _veh, "finishLockpick"], {(_this select 0) call FUNC(lockpick)}, {}, (localize "STR_ACE_Vehicle_Action_LockpickInUse"), _condition] call EFUNC(common,progressBar); + _returnValue = true; }; - [_vehLockpickStrenth, [_unit, _veh, "finishLockpick"], {(_this select 0) call FUNC(lockpick)}, {}, (localize "STR_ACE_Vehicle_Action_LockpickInUse"), _condition] call EFUNC(common,progressBar); - }; case (_funcType == "finishLockpick"): { - ["SetVehicleLock", [_veh], [_veh, false]] call EFUNC(common,targetEvent); - }; - default { - ["ACE_VehicleLock_fnc_lockpick: bad function type"] call BIS_fnc_error; - }; + ["VehicleLock_SetVehicleLock", [_veh], [_veh, false]] call EFUNC(common,targetEvent); + _returnValue = true; + }; + default { + ERROR("bad function type"); + }; }; -_returnValue; +_returnValue diff --git a/addons/vehiclelock/functions/fnc_moduleInit.sqf b/addons/vehiclelock/functions/fnc_moduleInit.sqf index a344185ab0..c26e8aacbd 100644 --- a/addons/vehiclelock/functions/fnc_moduleInit.sqf +++ b/addons/vehiclelock/functions/fnc_moduleInit.sqf @@ -1,22 +1,20 @@ /* -Name: ACE_VehicleLock_fnc_moduleInit - -Author: Pabst Mirror - -Description: - Function for setup module. Sets default lockpick strength, auto handout keys, and default lock state. - -Parameters: - 0: OBJECT - logic - 1: ignored - 2: BOOL - Module Activated -Returns: - Nothing - -Example: - called from module -*/ - + * Author: PabstMirror + * Function for setup module. Sets default lockpick strength and default lock state. + * + * Arguments: + * 0: The Module Logic Object + * 1: synced objects + * 2: Activated + * + * Return Value: + * None + * + * Example: + * [fromModule] call ACE_VehicleLock_fnc_hasKeyForVehicle; + * + * Public: No + */ #include "script_component.hpp" private ["_sideKeysAssignment", "_setLockState", "_lock"]; @@ -24,28 +22,28 @@ private ["_sideKeysAssignment", "_setLockState", "_lock"]; PARAMS_3(_logic,_syncedUnits,_activated); if (!_activated) exitWith {WARNING("Vehicle Lock Init Module - placed but not active");}; +if (!isServer) exitWith {}; + +//Set the GVAR for default lockpick strength +[_logic, QGVAR(DefaultLockpickStrength), "DefaultLockpickStrength"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(LockVehicleInventory), "LockVehicleInventory"] call EFUNC(common,readSettingFromModule); -_sideKeysAssignment = _logic getVariable["SideKeysAssignment", 0]; _setLockState = _logic getVariable["SetLockState", 0]; - -if (isServer) then { - [_logic, QGVAR(DefaultLockpickStrength), "LockpickStrength"] call EFUNC(common,readSettingFromModule); -}; - -//Run at mission start (anyone besides JIPs) -if (isServer || {player == player}) then { - { - if ((local _x) && {(_x isKindOf "Car") || (_x isKindOf "Tank") || (_x isKindOf "Helicopter")}) then { - //set lock state (eliminates the ambigious 1-"Default" and 3-"Locked for Player" states) - _lock = switch (_setLockState) do { - case (0): {(locked _x) in [2, 3]}; - case (1):{true}; - case (2):{false}; - }; - if (((_lock) && {(locked _x) != 2}) || {(!_lock) && {(locked _x) != 0}}) then { - TRACE_3("Setting Lock State", _lock, (typeOf _x), _x); - ["SetVehicleLock", [_x, _lock]] call EFUNC(common,localEvent); - }; - }; - } forEach vehicles; -}; +[{ + PARAMS_1(_setLockState); + { + if ((_x isKindOf "Car") || {_x isKindOf "Tank"} || {_x isKindOf "Helicopter"}) then { + //set lock state (eliminates the ambigious 1-"Default" and 3-"Locked for Player" states) + _lock = switch (_setLockState) do { + case (0): {(locked _x) in [2, 3]}; + case (1):{true}; + case (2):{false}; + }; + if (((_lock) && {(locked _x) != 2}) || {(!_lock) && {(locked _x) != 0}}) then { + TRACE_3("Setting Lock State", _lock, (typeOf _x), _x); + ["VehicleLock_SetVehicleLock", [_x], [_x, _lock]] call EFUNC(common,targetEvent); + }; + }; + } forEach vehicles; + //Delay call until mission start (so everyone has the eventHandler's installed) +}, [_setLockState], 0.25, 0.25] call EFUNC(common,waitAndExecute); diff --git a/addons/vehiclelock/functions/fnc_moduleSync.sqf b/addons/vehiclelock/functions/fnc_moduleSync.sqf index 60c23c5195..feed42e3ab 100644 --- a/addons/vehiclelock/functions/fnc_moduleSync.sqf +++ b/addons/vehiclelock/functions/fnc_moduleSync.sqf @@ -1,22 +1,20 @@ /* -Name: ACE_VehicleLock_fnc_moduleSync - -Author: Pabst Mirror - -Description: - Function for sync module. Assigns keys for all synced vehicles to any players that are synced. - -Parameters: - 0: OBJECT - logic - 1: ARRAY - synced objects (only objects at mission start, so JIP without AI won't be present) - -Returns: - Nothing - -Example: - called from module -*/ - + * Author: PabstMirror + * Function for sync module. Assigns keys for all synced vehicles to any players that are synced. + * + * Arguments: + * 0: The Module Logic Object + * 1: synced objects + * 2: Activated + * + * Return Value: + * None + * + * Example: + * [fromModule] call ACE_VehicleLock_fnc_moduleSync; + * + * Public: No + */ #include "script_component.hpp" PARAMS_3(_logic,_syncedObjects,_activated); @@ -24,29 +22,28 @@ PARAMS_3(_logic,_syncedObjects,_activated); if !(_activated) exitWith {WARNING("Vehicle Lock Sync Module - placed but not active");}; if (!isServer) exitWith {}; -_addKeyAfterGearAssign = { - private ["_syncedObjects", "_listOfVehicles"]; - _syncedObjects = _this select 0; - _listOfVehicles = []; - { - if ((_x isKindOf "Car") || (_x isKindOf "Tank") || (_x isKindOf "Helicopter")) then { - _listOfVehicles pushBack _x; +[{ + private ["_listOfVehicles"]; + PARAMS_1(_syncedObjects); + _listOfVehicles = []; + { + if ((_x isKindOf "Car") || (_x isKindOf "Tank") || (_x isKindOf "Helicopter")) then { + _listOfVehicles pushBack _x; + }; + } forEach _syncedObjects; + + if ((count _listOfVehicles) == 0) exitWith { //Verbose error for mission makers (only shows on server) + ["ACE_VehicleLock_fnc_moduleSync: no vehicles synced"] call BIS_fnc_error; }; - } forEach _syncedObjects; - if ((count _listOfVehicles) == 0) exitWith { //Verbose error for mission makers - ["ACE_VehicleLock_fnc_moduleSync: no vehicles synced"] call BIS_fnc_error; - }; + { + _unit = _x; + if (_unit isKindOf "CAManBase") then { + { + [_unit, _x, true] call FUNC(addKeyForVehicle); + } forEach _listOfVehicles; + }; + } forEach _syncedObjects; - { - _unit = _x; - if (_unit isKindOf "CAManBase") then { - { - [_unit, _x, true] call FUNC(addKeyForVehicle); - } forEach _listOfVehicles; - }; - } forEach _syncedObjects; -}; - -//Wait to add keys until various gear assigns have finished (~5 seconds) -[_addKeyAfterGearAssign, [_syncedObjects], 5, 1] call EFUNC(common,waitAndExecute); + //Wait to add keys until various gear assigns have finished (~5 seconds) +}, [_syncedObjects], 5, 1] call EFUNC(common,waitAndExecute); diff --git a/addons/vehiclelock/functions/fnc_onOpenInventory.sqf b/addons/vehiclelock/functions/fnc_onOpenInventory.sqf new file mode 100644 index 0000000000..55fee28cc6 --- /dev/null +++ b/addons/vehiclelock/functions/fnc_onOpenInventory.sqf @@ -0,0 +1,40 @@ +/* + * Author: PabstMirror + * Handles the inventory opening. + * + * Arguments: + * 0: Unit + * 1: Container + * + * Return Value: + * Handeled + * + * Example: + * [player, car] call ACE_VehicleLock_fnc_onOpenInventory; + * + * Public: No + */ +#include "script_component.hpp" + +PARAMS_2(_unit,_container); + +//Only check for player: +if (_unit != ace_player) exitWith {false}; + +_handeled = false; + +if (GVAR(LockVehicleInventory) && //if setting not enabled + {(vehicle ace_player) == ace_player} && //Player dismounted + {(_container isKindOf "Car") || (_container isKindOf "Tank") || (_container isKindOf "Helicopter")} && //container is a lockable veh + {(locked _container) in [2,3]} && //Vehicle is locked + {!([ace_player, _container] call FUNC(hasKeyForVehicle))} //player doesn't have key + ) then { + //Give feedback that vehicle is locked + playSound "ACE_Sound_Click"; + //don't open the vehicles inventory + _handeled = true; + //Just opens a dummy groundContainer + ACE_player action ["Gear", objNull]; +}; + +_handeled diff --git a/addons/vehiclelock/functions/fnc_serverSetupCustomKeyEH.sqf b/addons/vehiclelock/functions/fnc_serverSetupCustomKeyEH.sqf index f9a420841e..9d8a396e31 100644 --- a/addons/vehiclelock/functions/fnc_serverSetupCustomKeyEH.sqf +++ b/addons/vehiclelock/functions/fnc_serverSetupCustomKeyEH.sqf @@ -1,22 +1,19 @@ - /* - Name: ACE_VehicleLock_fnc_serverSetupCustomKeyEH - - Author: Pabst Mirror - - Description: - Adds a key (magazineDetail name) to approved keys for a vehicle - - Parameters: - 0: OBJECT - vehicle - 1: STRING - Magazine Name - - Returns: - Nothing - - Example: - [tank1, "someMagainze [id xx:yy]"] call ACE_VehicleLock_fnc_serverSetupCustomKeyEH; -*/ - +/* + * Author: PabstMirror + * On the server: Adds a key (magazineDetail name) to approved keys for a vehicle. + * + * Arguments: + * 0: Vehicle + * 1: Magazine Name + * + * Return Value: + * None + * + * Example: + * [tank1, "someMagainze [id xx:yy]"] call ACE_VehicleLock_fnc_serverSetupCustomKeyEH + * + * Public: Yes + */ #include "script_component.hpp" private ["_currentKeys"]; @@ -24,6 +21,7 @@ private ["_currentKeys"]; PARAMS_2(_veh,_key); if (!isServer) exitWith {ERROR("only run on server");}; +if (isNull _veh) exitWith {ERROR("null vehicle");}; if (_key == "") exitWith {ERROR("empty key string");}; _currentKeys = _veh getVariable [QGVAR(customKeys), []]; diff --git a/addons/vehiclelock/functions/fnc_setVehicleLockEH.sqf b/addons/vehiclelock/functions/fnc_setVehicleLockEH.sqf index 7aaa9b154c..cb51cb27a8 100644 --- a/addons/vehiclelock/functions/fnc_setVehicleLockEH.sqf +++ b/addons/vehiclelock/functions/fnc_setVehicleLockEH.sqf @@ -1,33 +1,25 @@ /* - Name: ACE_VehicleLock_fnc_setVehicleLockEH - - Author: Pabst Mirror - - Description: - Sets a vehicle lock state because of a "SetVehicleLock" event - - Parameters: - 0: OBJECT - vehicle - 1: BOOL - new lock state - - Returns: - Nothing - - Example: - [tank1, false] call ACE_VehicleLock_fnc_setVehicleLockEH; -*/ - + * Author: PabstMirror + * Sets a vehicle lock state because of a "VehicleLock_SetVehicleLock" event + * + * Arguments: + * 0: Vehicle + * 1: New lock state + * + * Return Value: + * None + * + * Example: + * [tank1, false] call ACE_VehicleLock_fnc_setVehicleLockEH; + * + * Public: Yes + */ #include "script_component.hpp" -private ["_veh","_isLocked","_lockNumber"]; +private ["_lockNumber"]; -_veh = [_this, 0, objNull, [objNull]] call bis_fnc_param; -_isLocked = [_this, 1, false, [false]] call bis_fnc_param; +PARAMS_2(_veh,_isLocked); _lockNumber = if (_isLocked) then {2} else {0}; - TRACE_2("Setting Lock State", _veh, _lockNumber); - _veh lock _lockNumber; - -// _veh setVariable ["ACE_LockedInventory", _isLocked, true]; //todo inventory lock diff --git a/addons/vehiclelock/readme.md b/addons/vehiclelock/readme.md index a1bd223a52..dc013145aa 100644 --- a/addons/vehiclelock/readme.md +++ b/addons/vehiclelock/readme.md @@ -5,8 +5,8 @@ Adds keys as an item, to lock and unlock vehicles. Primary target would be role play or TVT, but has uses in all game types, even co-ops (e.g.: DAC AI will steal unlocked vehicles) Two key modes (can be used together): -Simple Side based keys (e.g. "ACE_key_west" works on any hunter) -Custom keys (one key will only open a specific vehicle and nothing else) +* Simple Side based keys (e.g. "ACE_key_west" works on any [WEST] vehicle like the M-ATV//hunter) +* Custom keys (one key will only open a specific vehicle and nothing else) #### Items Added: @@ -18,24 +18,20 @@ Custom keys (one key will only open a specific vehicle and nothing else) `ACE_key_civ` #### Magazine added: -`ACE_key_customKeyMagazine` (should never be manualy added, needs to be 'programed' to work on a vehicle) +`ACE_key_customKeyMagazine` (should never be manualy added, needs to be "programed" to work on a vehicle, see `ACE_VehicleLock_fnc_addKeyForVehicle`) ## For Mission Makers: #### Modules: -* Vehicle Lock Setup - Settings for lockpick strength and initial vehicle lock state. -* Vehicle Key Assign - Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. - -#### Global Variable: -* `ACE_VehicleLock_DefaultLockpickStrength` - Time in seconds to lock pick globaly, can also set per-vehicle (-1 would disable) +* Vehicle Lock Setup - Settings for locking inventory of locked vehicles, default lockpick time, and initial vehicle lock state. +* Vehicle Key Assign - Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Will NOT work for JIP units. #### Vehicle setVariables: * `ACE_VehicleLock_lockSide` - SIDE: overrides a vehicle's side, allows indfor to use little-bird's with indp keys * `ACE_vehicleLock_lockpickStrength` - NUMBER: secons, determines how long lockpicking with take, overrides ACE_VehicleLock_DefaultLockpickStrength -* `ACE_VehicleLock_customKeys` - ARRAY: array of strings of magazinesDetails, use the following function to modify -`[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` -will add a `ACE_magazine_customKey` to bob and program it to work on car1 +#### Public Functions: +`[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` - will add a `ACE_magazine_customKey` to bob and program it to work on car1 ## Maintainers diff --git a/addons/vehicles/XEH_postInit.sqf b/addons/vehicles/XEH_postInit.sqf index 316e539572..7b1a0c575e 100644 --- a/addons/vehicles/XEH_postInit.sqf +++ b/addons/vehicles/XEH_postInit.sqf @@ -7,7 +7,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(speedLimiter), localize "STR_ACE_SpeedLimiter", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player == driver vehicle ACE_player && {vehicle ACE_player isKindOf 'Car' || diff --git a/addons/weaponselect/XEH_postInit.sqf b/addons/weaponselect/XEH_postInit.sqf index 6160448d56..14c4f1aa51 100644 --- a/addons/weaponselect/XEH_postInit.sqf +++ b/addons/weaponselect/XEH_postInit.sqf @@ -7,7 +7,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectPistol), localize "STR_ACE_WeaponSelect_SelectPistol", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -21,7 +21,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectRifle), localize "STR_ACE_WeaponSelect_SelectRifle", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -35,7 +35,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectRifleMuzzle), localize "STR_ACE_WeaponSelect_SelectRifleMuzzle", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -49,7 +49,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectLauncher), localize "STR_ACE_WeaponSelect_SelectLauncher", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -63,7 +63,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectBinocular), localize "STR_ACE_WeaponSelect_SelectBinocular", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -77,7 +77,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectGrenadeFrag), localize "STR_ACE_WeaponSelect_SelectGrenadeFrag", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -91,7 +91,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectGrenadeOther), localize "STR_ACE_WeaponSelect_SelectGrenadeOther", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -105,7 +105,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(HolsterWeapon), localize "STR_ACE_WeaponSelect_HolsterWeapon", { // Conditions: canInteract - if !([ACE_player, objNull, ["isNotEscorting"]] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false}; @@ -119,7 +119,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(EngineOn), localize "STR_ACE_WeaponSelect_EngineOn", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player != vehicle ACE_player && {ACE_player == driver vehicle ACE_player} && {!isEngineOn vehicle ACE_player}) exitWith {false}; @@ -133,7 +133,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(EngineOff), localize "STR_ACE_WeaponSelect_EngineOff", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player != vehicle ACE_player && {ACE_player == driver vehicle ACE_player} && {isEngineOn vehicle ACE_player}) exitWith {false}; @@ -147,7 +147,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectMainGun), localize "STR_ACE_WeaponSelect_SelectMainGun", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player != vehicle ACE_player) exitWith {false}; @@ -161,7 +161,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectMachineGun), localize "STR_ACE_WeaponSelect_SelectMachineGun", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player != vehicle ACE_player) exitWith {false}; @@ -175,7 +175,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(SelectMissiles), localize "STR_ACE_WeaponSelect_SelectMissiles", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player != vehicle ACE_player) exitWith {false}; @@ -189,7 +189,7 @@ if !(hasInterface) exitWith {}; ["ACE3", QGVAR(FireSmokeLauncher), localize "STR_ACE_WeaponSelect_FireSmokeLauncher", { // Conditions: canInteract - if !([ACE_player, objNull, []] call EGVAR(common,canInteractWith)) exitWith {false}; + if !([ACE_player, objNull, []] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: specific if !(ACE_player != vehicle ACE_player && {ACE_player == commander vehicle ACE_player}) exitWith {false}; diff --git a/tools/ace_build_tool/pabstFrankensteinBuilder.py b/tools/ace_build_tool/pabstFrankensteinBuilder.py new file mode 100644 index 0000000000..eb35f1c7e5 --- /dev/null +++ b/tools/ace_build_tool/pabstFrankensteinBuilder.py @@ -0,0 +1,776 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : + +# make.py +# An Arma 3 addon build system + +############################################################################### + +# The MIT License (MIT) + +# Copyright (c) 2013-2014 Ryan Schultz + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +############################################################################### + +__version__ = "0.3dev" + +import sys + +if sys.version_info[0] == 2: + print("Python 3 is required.") + sys.exit(1) + +import os +import os.path +import shutil +import platform +import glob +import subprocess +import hashlib +import configparser +import json +import traceback + +if sys.platform == "win32": + import winreg + +############################################################################### +# http://akiscode.com/articles/sha-1directoryhash.shtml +# Copyright (c) 2009 Stephen Akiki +# MIT License (Means you can do whatever you want with this) +# See http://www.opensource.org/licenses/mit-license.php +# Error Codes: +# -1 -> Directory does not exist +# -2 -> General error (see stack traceback) +def get_directory_hash(directory): + directory_hash = hashlib.sha1() + if not os.path.exists (directory): + return -1 + + try: + for root, dirs, files in os.walk(directory): + for names in files: + path = os.path.join(root, names) + try: + f = open(path, 'rb') + except: + # You can't open the file for some reason + f.close() + continue + + while 1: + # Read file in as little chunks + buf = f.read(4096) + if not buf: break + new = hashlib.sha1(buf) + directory_hash.update(new.digest()) + f.close() + + except: + # Print the stack traceback + traceback.print_exc() + return -2 + + return directory_hash.hexdigest() + +# Copyright (c) André Burgaud +# http://www.burgaud.com/bring-colors-to-the-windows-console-with-python/ +if sys.platform == "win32": + from ctypes import windll, Structure, c_short, c_ushort, byref + + SHORT = c_short + WORD = c_ushort + + class COORD(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("X", SHORT), + ("Y", SHORT)] + + class SMALL_RECT(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("Left", SHORT), + ("Top", SHORT), + ("Right", SHORT), + ("Bottom", SHORT)] + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", WORD), + ("srWindow", SMALL_RECT), + ("dwMaximumWindowSize", COORD)] + + # winbase.h + STD_INPUT_HANDLE = -10 + STD_OUTPUT_HANDLE = -11 + STD_ERROR_HANDLE = -12 + + # wincon.h + FOREGROUND_BLACK = 0x0000 + FOREGROUND_BLUE = 0x0001 + FOREGROUND_GREEN = 0x0002 + FOREGROUND_CYAN = 0x0003 + FOREGROUND_RED = 0x0004 + FOREGROUND_MAGENTA = 0x0005 + FOREGROUND_YELLOW = 0x0006 + FOREGROUND_GREY = 0x0007 + FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified. + + BACKGROUND_BLACK = 0x0000 + BACKGROUND_BLUE = 0x0010 + BACKGROUND_GREEN = 0x0020 + BACKGROUND_CYAN = 0x0030 + BACKGROUND_RED = 0x0040 + BACKGROUND_MAGENTA = 0x0050 + BACKGROUND_YELLOW = 0x0060 + BACKGROUND_GREY = 0x0070 + BACKGROUND_INTENSITY = 0x0080 # background color is intensified. + + stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) + SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + + def get_text_attr(): + """Returns the character attributes (colors) of the console screen + buffer.""" + csbi = CONSOLE_SCREEN_BUFFER_INFO() + GetConsoleScreenBufferInfo(stdout_handle, byref(csbi)) + return csbi.wAttributes + + def set_text_attr(color): + """Sets the character attributes (colors) of the console screen + buffer. Color is a combination of foreground and background color, + foreground and background intensity.""" + SetConsoleTextAttribute(stdout_handle, color) +############################################################################### + +def find_bi_tools(work_drive): + """Find BI tools.""" + + reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) + try: + k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools") + arma3tools_path = winreg.QueryValueEx(k, "path")[0] + winreg.CloseKey(k) + except: + raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") + + addonbuilder_path = os.path.join(arma3tools_path, "AddonBuilder", "AddonBuilder.exe") + dssignfile_path = os.path.join(arma3tools_path, "DSSignFile", "DSSignFile.exe") + dscreatekey_path = os.path.join(arma3tools_path, "DSSignFile", "DSCreateKey.exe") + + if os.path.isfile(addonbuilder_path) and os.path.isfile(dssignfile_path) and os.path.isfile(dscreatekey_path): + return [addonbuilder_path, dssignfile_path, dscreatekey_path] + else: + raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") + +def find_depbo_tools(): + """Use registry entries to find DePBO-based tools.""" + + reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) + try: + k = winreg.OpenKey(reg, r"Software\Mikero\pboProject") + try: + pboproject_path = winreg.QueryValueEx(k, "exe")[0] + winreg.CloseKey(k) + print("Found pboproject.") + except: + print_error("ERROR: Could not find pboProject.") + + k = winreg.OpenKey(reg, r"Software\Mikero\rapify") + try: + rapify_path = winreg.QueryValueEx(k, "exe")[0] + winreg.CloseKey(k) + print("Found rapify.") + except: + print_error("Could not find rapify.") + + k = winreg.OpenKey(reg, r"Software\Mikero\MakePbo") + try: + makepbo_path = winreg.QueryValueEx(k, "exe")[0] + winreg.CloseKey(k) + print("Found makepbo.") + except: + print_error("Could not find makepbo.") + except: + raise Exception("BadDePBO", "DePBO tools not installed correctly") + + #Strip any quotations from the path due to a MikeRo tool bug which leaves a trailing space in some of its registry paths. + return [pboproject_path.strip('"'),rapify_path.strip('"'),makepbo_path.strip('"')] + +def color(color): + """Set the color. Works on Win32 and normal terminals.""" + if sys.platform == "win32": + if color == "green": + set_text_attr(FOREGROUND_GREEN | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) + elif color == "red": + set_text_attr(FOREGROUND_RED | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) + elif color == "blue": + set_text_attr(FOREGROUND_BLUE | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) + elif color == "reset": + set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070) + elif color == "grey": + set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070) + else : + if color == "green": + sys.stdout.write('\033[92m') + elif color == "red": + sys.stdout.write('\033[91m') + elif color == "blue": + sys.stdout.write('\033[94m') + elif color == "reset": + sys.stdout.write('\033[0m') + +def print_error(msg): + color("red") + print ("ERROR: " + msg) + color("reset") + +def print_green(msg): + color("green") + print(msg) + color("reset") + +def print_blue(msg): + color("blue") + print(msg) + color("reset") + +def print_yellow(msg): + color("yellow") + print(msg) + color("reset") + +############################################################################### + +def main(argv): + """Build an Arma addon suite in a directory from rules in a make.cfg file.""" + print_blue(("\nmake.py for Arma, v" + __version__)) + + if sys.platform != "win32": + print_error("Non-Windows platform (Cygwin?). Please re-run from cmd.") + sys.exit(1) + + reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) + try: + k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools") + arma3tools_path = winreg.QueryValueEx(k, "path")[0] + winreg.CloseKey(k) + except: + raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") + + # Default behaviors + test = False # Copy to Arma 3 directory? + arg_modules = False # Only build modules on command line? + make_release = False # Make zip file from the release? + release_version = 0 # Version of release + use_pboproject = True # Default to pboProject build tool + make_target = "DEFAULT" # Which section in make.cfg to use for the build + new_key = False # Make a new key and use it to sign? + quiet = False # Suppress output from build tool? + + # Parse arguments + if "help" in argv or "-h" in argv or "--help" in argv: + print (""" +make.py [help] [test] [force] [key ] [target ] [release ] + [module name] [module name] [...] + +test -- Copy result to Arma 3. +release -- Make archive with . +force -- Ignore cache and build all. +target -- Use rules in make.cfg under heading [] rather than + default [Make] +key -- Use key in working directory with to sign. If it does not + exist, create key. +quiet -- Suppress command line output from build tool. + +If module names are specified, only those modules will be built. + +Examples: + make.py force test + Build all modules (ignoring cache) and copy the mod folder to the Arma 3 + directory. + make.py mymodule_gun + Only build the module named 'mymodule_gun'. + make.py force key MyNewKey release 1.0 + Build all modules (ignoring cache), sign them with NewKey, and pack them + into a zip file for release with version 1.0. + + +If a file called $NOBIN$ is found in the module directory, that module will not be binarized. + +See the make.cfg file for additional build options. +""") + sys.exit(0) + + if "force" in argv: + argv.remove("force") + force_build = True + else: + force_build = False + + if "test" in argv: + test = True + argv.remove("test") + + if "release" in argv: + make_release = True + release_version = argv[argv.index("release") + 1] + argv.remove(release_version) + argv.remove("release") + + if "target" in argv: + make_target = argv[argv.index("target") + 1] + argv.remove("target") + argv.remove(make_target) + force_build = True + + if "key" in argv: + new_key = True + key_name = argv[argv.index("key") + 1] + argv.remove("key") + argv.remove(key_name) + + if "quiet" in argv: + quiet = True + argv.remove("quiet") + + # Get the directory the make script is in. + make_root = os.path.dirname(os.path.realpath(__file__)) + make_root_parent = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) + os.chdir(make_root) + + cfg = configparser.ConfigParser(); + try: + cfg.read(os.path.join(make_root, "make.cfg")) + + # Project name (with @ symbol) + project = cfg.get(make_target, "project", fallback="@"+os.path.basename(os.getcwd())) + + # Private key path + key = cfg.get(make_target, "key", fallback=None) + + # Project prefix (folder path) + prefix = cfg.get(make_target, "prefix", fallback="") + + # Should we autodetect modules on a complete build? + module_autodetect = cfg.getboolean(make_target, "module_autodetect", fallback=True) + + # Manual list of modules to build for a complete build + modules = cfg.get(make_target, "modules", fallback=None) + # Parse it out + if modules: + modules = [x.strip() for x in modules.split(',')] + else: + modules = [] + + # List of directories to ignore when detecting + ignore = [x.strip() for x in cfg.get(make_target, "ignore", fallback="release").split(',')] + + # BI Tools work drive on Windows + work_drive = cfg.get(make_target, "work_drive", fallback="P:\\") + + # Which build tool should we use? + build_tool = "pboproject" + + # Release/build directory, relative to script dir + release_dir = cfg.get(make_target, "release_dir", fallback="release") + + # Project PBO file prefix (files are renamed to prefix_name.pbo) + pbo_name_prefix = cfg.get(make_target, "pbo_name_prefix", fallback=None) + + # Project module Root + module_root_parent = os.path.abspath(os.path.join(os.path.join(work_drive, prefix), os.pardir)) + module_root = cfg.get(make_target, "module_root", fallback=os.path.join(make_root_parent, "addons")) + print_green ("module_root: " + module_root) + if (os.path.isdir(module_root)): + os.chdir(module_root) + else: + print_error ("Directory " + module_root + " does not exist.") + sys.exit() + + except: + raise + print_error("Could not parse make.cfg.") + sys.exit(1) + + + + # See if we have been given specific modules to build from command line. + if len(argv) > 1 and not make_release: + arg_modules = True + modules = argv[1:] + + # Find the tools we need. + try: + tools = find_bi_tools(work_drive) + addonbuilder = tools[0] + dssignfile = tools[1] + dscreatekey = tools[2] + + except: + print_error("Arma 3 Tools are not installed correctly or the P: drive has not been created.") + sys.exit(1) + + if build_tool == "pboproject": + try: + depbo_tools = find_depbo_tools() + pboproject = depbo_tools[0] + rapifyTool = depbo_tools[1] + makepboTool = depbo_tools[2] + except: + raise + print_error("Could not find dePBO tools. Download the needed tools from: https://dev.withsix.com/projects/mikero-pbodll/files") + sys.exit(1) + + # Try to open and deserialize build cache file. + try: + cache = {} + with open(os.path.join(make_root, "make.cache"), 'r') as f: + cache_raw = f.read() + + cache = json.loads(cache_raw) + + except: + print ("No cache found.") + cache = {} + + # Get list of subdirs in make root. + dirs = next(os.walk(module_root))[1] + + # Autodetect what directories to build. + if module_autodetect and not arg_modules: + modules = [] + for path in dirs: + # Any dir that has a config.cpp in its root is an addon to build. + config_path = os.path.join(path, 'config.cpp') + if os.path.isfile(config_path) and not path in ignore: + modules.append(path) + + # Make the key specified from command line if necessary. + if new_key: + if not os.path.isfile(os.path.join(module_root, key_name + ".biprivatekey")): + print_green("\nRequested key does not exist.") + ret = subprocess.call([dscreatekey, key_name]) # Created in make_root + if ret == 0: + print_blue("Created: " + os.path.join(module_root, key_name + ".biprivatekey")) + else: + print_error("Failed to create key!") + + try: + print_blue("Copying public key to release directory.") + + try: + os.makedirs(os.path.join(module_root, release_dir, "Keys")) + except: + pass + + shutil.copyfile(os.path.join(module_root, key_name + ".bikey"), os.path.join(module_root, release_dir, "Keys", key_name + ".bikey")) + + except: + raise + print_error("Could not copy key to release directory.") + + else: + print_green("\nNOTE: Using key " + os.path.join(module_root, key_name + ".biprivatekey")) + + key = os.path.join(module_root, key_name + ".biprivatekey") + + + # For each module, prep files and then build. + for module in modules: + print_green("\nMaking " + module + "-"*max(1, (60-len(module)))) + + # Cache check + if module in cache: + old_sha = cache[module] + else: + old_sha = "" + + # Hash the module + new_sha = get_directory_hash(os.path.join(module_root, module)) + + # Check if it needs rebuilt + # print ("Hash:", new_sha) + if old_sha == new_sha: + if not force_build: + print("Module has not changed.") + # Skip everything else + continue + + # Only do this if the project isn't stored directly on the work drive. + # Split the path at the drive name and see if they are on the same drive (usually P:) + if os.path.splitdrive(module_root)[0] != os.path.splitdrive(work_drive)[0]: + try: + # Remove old work drive version (ignore errors) + shutil.rmtree(os.path.join(work_drive, prefix, module), True) + + # Copy module to the work drive + shutil.copytree(module, os.path.join(work_drive, prefix, module)) + + except: + raise + print_error("ERROR: Could not copy module to work drive. Does the module exist?") + input("Press Enter to continue...") + print("Resuming build...") + continue + else: + print("WARNING: Module is stored on work drive (" + work_drive + ").") + + try: + # Remove the old pbo, key, and log + old = os.path.join(module_root, release_dir, project, "Addons", module) + "*" + files = glob.glob(old) + for f in files: + os.remove(f) + + if pbo_name_prefix: + old = os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix+module) + "*" + files = glob.glob(old) + for f in files: + os.remove(f) + except: + raise + print_error("ERROR: Could not copy module to work drive. Does the module exist?") + input("Press Enter to continue...") + print("Resuming build...") + continue + + # Build the module into a pbo + print_blue("Building: " + os.path.join(work_drive, prefix, module)) + print_blue("Destination: " + os.path.join(module_root, release_dir, project, "Addons")) + + # Make destination folder (if needed) + try: + os.makedirs(os.path.join(module_root, release_dir, project, "Addons")) + except: + pass + + # Run build tool + build_successful = False + if build_tool == "pboproject": + try: + #PABST: Convert config (run the macro'd config.cpp through CfgConvert twice to produce a de-macro'd cpp that pboProject can read without fucking up: + os.chdir("P:\\CfgConvert") + shutil.copyfile(os.path.join(work_drive, prefix, module, "config.cpp"), os.path.join(work_drive, prefix, module, "config.backup")) + print_green("\Pabst (double converting):" + "cfgConvertGUI.exe " + os.path.join(work_drive, prefix, module, "config.cpp")) + ret = subprocess.call(["cfgConvertGUI.exe", os.path.join(work_drive, prefix, module, "config.cpp")]) + ret = subprocess.call(["cfgConvertGUI.exe", os.path.join(work_drive, prefix, module, "config.bin")]) + + # Call pboProject + os.chdir("P:\\") + + if os.path.isfile(os.path.join(work_drive, prefix, module, "$NOBIN$")): + print_green("$NOBIN$ Found. Proceeding with non-binarizing!") + cmd = [makepboTool, "-P","-A","-L","-N","-G", os.path.join(work_drive, prefix, module),os.path.join(module_root, release_dir, project,"Addons")] + + else: + cmd = [pboproject, "-P", os.path.join(work_drive, prefix, module), "+Engine=Arma3", "-S","+Noisy", "+X", "+Clean", "+Mod="+os.path.join(module_root, release_dir, project), "-Key"] + + color("grey") + if quiet: + devnull = open(os.devnull, 'w') + ret = subprocess.call(cmd, stdout=devnull) + devnull.close() + else: + ret = subprocess.call(cmd) + color("reset") + + if ret == 0: + print_green("pboProject return code == " + str(ret)) + # Prettyprefix rename the PBO if requested. + if pbo_name_prefix: + try: + os.rename(os.path.join(module_root, release_dir, project, "Addons", module+".pbo"), os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix+module+".pbo")) + except: + raise + print_error("Could not rename built PBO with prefix.") + # Sign result + if key: + print("Signing with " + key + ".") + if pbo_name_prefix: + ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix + module + ".pbo")]) + else: + ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "Addons", module + ".pbo")]) + + if ret == 0: + build_successful = True + else: + build_successful = True + + if not build_successful: + print_error("pboProject return code == " + str(ret)) + print_error("Module not successfully built/signed.") + #input("Press Enter to continue...") + print ("Resuming build...") + continue + + #PABST: cleanup config BS (you could comment this out to see the "de-macroed" cpp + print_green("\Pabst (restoring): " + os.path.join(work_drive, prefix, module, "config.cpp")) + os.remove(os.path.join(work_drive, prefix, module, "config.cpp")) + os.remove(os.path.join(work_drive, prefix, module, "config.bin")) + os.rename(os.path.join(work_drive, prefix, module, "config.backup"), os.path.join(work_drive, prefix, module, "config.cpp")) + + # Back to the root + os.chdir(module_root) + + except: + raise + print_error("Could not run Addon Builder.") + input("Press Enter to continue...") + print ("Resuming build...") + continue + + elif build_tool== "addonbuilder": + # Detect $NOBIN$ and do not binarize if found. + if os.path.isfile(os.path.join(work_drive, prefix, module, "$NOBIN$")): + do_binarize = False + print("$NOBIN$ file found in module, packing only.") + else: + do_binarize = True + try: + # Call AddonBuilder + os.chdir("P:\\") + + cmd = [addonbuilder, os.path.join(work_drive, prefix, module), os.path.join(make_root, release_dir, project, "Addons"), "-clear", "-project="+work_drive] + if not do_binarize: + cmd.append("-packonly") + + if quiet: + previousDirectory = os.getcwd() + os.chdir(arma3tools_path) + devnull = open(os.devnull, 'w') + ret = subprocess.call(cmd, stdout=devnull) + devnull.close() + os.chdir(previousDirectory) + else: + previousDirectory = os.getcwd() + os.chdir(arma3tools_path) + print_error("Current directory - " + os.getcwd()) + ret = subprocess.call(cmd) + os.chdir(previousDirectory) + print_error("Current directory - " + os.getcwd()) + color("reset") + print_green("completed") + # Prettyprefix rename the PBO if requested. + if pbo_name_prefix: + try: + os.rename(os.path.join(make_root, release_dir, project, "Addons", module+".pbo"), os.path.join(make_root, release_dir, project, "Addons", pbo_name_prefix+module+".pbo")) + except: + raise + print_error("Could not rename built PBO with prefix.") + + if ret == 0: + # Sign result + if key: + print("Signing with " + key + ".") + if pbo_name_prefix: + ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "Addons", pbo_name_prefix + module + ".pbo")]) + else: + ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "Addons", module + ".pbo")]) + + if ret == 0: + build_successful = True + else: + build_successful = True + + if not build_successful: + print_error("Module not successfully built.") + + # Back to the root + os.chdir(make_root) + + except: + raise + print_error("Could not run Addon Builder.") + input("Press Enter to continue...") + print ("Resuming build...") + continue + + else: + print_error("Unknown build_tool " + build_tool + "!") + + # Update the hash for a successfully built module + if build_successful: + cache[module] = new_sha + + # Done building all modules! + + # Write out the cache state + cache_out = json.dumps(cache) + with open(os.path.join(make_root, "make.cache"), 'w') as f: + f.write(cache_out) + + # Delete the pboproject temp files if building a release. + if make_release and build_tool == "pboproject": + try: + shutil.rmtree(os.path.join(module_root, release_dir, project, "temp"), True) + except: + print_error("ERROR: Could not delete pboProject temp files.") + + print_green("\nDone.") + + # Make release + if make_release: + print_blue("\nMaking release: " + project + "-" + release_version + ".zip") + + try: + # Delete all log files + for root, dirs, files in os.walk(os.path.join(module_root, release_dir, project, "Addons")): + for currentFile in files: + if currentFile.lower().endswith("log"): + os.remove(os.path.join(root, currentFile)) + + # Create a zip with the contents of release/ in it + shutil.make_archive(project + "-" + release_version, "zip", os.path.join(module_root, release_dir)) + except: + raise + print_error("Could not make release.") + + # Copy to Arma 3 folder for testing + if test: + print_blue("\nCopying to Arma 3.") + + if sys.platform == "win32": + reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + k = winreg.OpenKey(reg, r"SOFTWARE\Wow6432Node\Bohemia Interactive\Arma 3") + a3_path = winreg.EnumValue(k, 1)[1] + winreg.CloseKey(k) + except: + print_error("Could not find Arma 3's directory in the registry.") + else: + a3_path = cygwin_a3path + + if os.path.exists(a3_path): + try: + shutil.rmtree(os.path.join(a3_path, project), True) + shutil.copytree(os.path.join(module_root, release_dir, project), os.path.join(a3_path, project)) + except: + print_error("Could not copy files. Is Arma 3 running?") + +if __name__ == "__main__": + main(sys.argv) +input("Press Enter to continue...") \ No newline at end of file