From 4cb8671d52b1dafcaa3de1e58da78c2657d905a8 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Wed, 7 Jan 2026 00:09:08 -0600 Subject: [PATCH 01/23] smoke: new component --- .hemtt/launch.toml | 9 +- addons/smoke/$PBOPREFIX$ | 1 + addons/smoke/ACE_Arsenal_Stats.hpp | 20 +++ addons/smoke/CfgEventHandlers.hpp | 15 +++ addons/smoke/CfgGlasses.hpp | 53 ++++++++ addons/smoke/XEH_PREP.hpp | 2 + addons/smoke/XEH_postInit.sqf | 22 ++++ addons/smoke/XEH_preInit.sqf | 11 ++ addons/smoke/XEH_preStart.sqf | 2 + addons/smoke/config.cpp | 16 +++ addons/smoke/functions/fnc_isInSmoke.sqf | 28 +++++ addons/smoke/functions/fnc_pfh.sqf | 58 +++++++++ addons/smoke/initSettings.inc.sqf | 46 +++++++ addons/smoke/script_component.hpp | 17 +++ addons/smoke/stringtable.xml | 149 +++++++++++++++++++++++ 15 files changed, 447 insertions(+), 2 deletions(-) create mode 100644 addons/smoke/$PBOPREFIX$ create mode 100644 addons/smoke/ACE_Arsenal_Stats.hpp create mode 100644 addons/smoke/CfgEventHandlers.hpp create mode 100644 addons/smoke/CfgGlasses.hpp create mode 100644 addons/smoke/XEH_PREP.hpp create mode 100644 addons/smoke/XEH_postInit.sqf create mode 100644 addons/smoke/XEH_preInit.sqf create mode 100644 addons/smoke/XEH_preStart.sqf create mode 100644 addons/smoke/config.cpp create mode 100644 addons/smoke/functions/fnc_isInSmoke.sqf create mode 100644 addons/smoke/functions/fnc_pfh.sqf create mode 100644 addons/smoke/initSettings.inc.sqf create mode 100644 addons/smoke/script_component.hpp create mode 100644 addons/smoke/stringtable.xml diff --git a/.hemtt/launch.toml b/.hemtt/launch.toml index ff6bdadd3b9..638df8bfac9 100644 --- a/.hemtt/launch.toml +++ b/.hemtt/launch.toml @@ -3,6 +3,12 @@ workshop = [ "450814997", # CBA_A3 ] +[adt] +extends = "default" +workshop = [ + "3499977893", # ADT +] + [rhs] extends = "default" workshop = [ @@ -27,10 +33,9 @@ workshop = [ ] [wardrobe] -extends = "default" +extends = "adt" mission = "Wardrobe.VR" workshop = [ - "3499977893", # Advanced Developer Tools "1779063631", # ZEN # "751965892", # ACRE # "623475643", # eden enhanced diff --git a/addons/smoke/$PBOPREFIX$ b/addons/smoke/$PBOPREFIX$ new file mode 100644 index 00000000000..830debaa3c8 --- /dev/null +++ b/addons/smoke/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\smoke diff --git a/addons/smoke/ACE_Arsenal_Stats.hpp b/addons/smoke/ACE_Arsenal_Stats.hpp new file mode 100644 index 00000000000..e31618ec3ef --- /dev/null +++ b/addons/smoke/ACE_Arsenal_Stats.hpp @@ -0,0 +1,20 @@ +class EGVAR(arsenal,stats) { + class statBase; + class GVAR(breathing_protection): statBase { + scope = 2; + displayName = CSTRING(statBreatingProtection); + showBar = 1; + condition = QUOTE(getNumber (_this select 1 >> QQGVAR(Breathing_Protection)) > 0); + barStatement = QUOTE(getNumber (_this select 1 >> QQGVAR(Breathing_Protection))); + tabs[] = {{7}, {}}; + }; + + class GVAR(eyes_protection): statBase { + scope = 2; + displayName = CSTRING(statEyesProtection); + showBar = 1; + condition = QUOTE(getNumber (_this select 1 >> QQGVAR(Eyes_Protection)) > 0); + barStatement = QUOTE(getNumber (_this select 1 >> QQGVAR(Eyes_Protection))); + tabs[] = {{7}, {}}; + }; +}; diff --git a/addons/smoke/CfgEventHandlers.hpp b/addons/smoke/CfgEventHandlers.hpp new file mode 100644 index 00000000000..e90bed419e7 --- /dev/null +++ b/addons/smoke/CfgEventHandlers.hpp @@ -0,0 +1,15 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preStart)); + }; +}; +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + }; +}; +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_postInit)); + }; +}; diff --git a/addons/smoke/CfgGlasses.hpp b/addons/smoke/CfgGlasses.hpp new file mode 100644 index 00000000000..d7ee9a1f65d --- /dev/null +++ b/addons/smoke/CfgGlasses.hpp @@ -0,0 +1,53 @@ +class CfgGlasses { + class None; + + class G_AirPurifyingRespirator_01_base_F: None { + GVAR(Eyes_Protection) = 1; + GVAR(Breathing_Protection) = 1; + }; + + class G_Balaclava_blk: None { + GVAR(Breathing_Protection) = 0.2; + }; + class G_Balaclava_combat: G_Balaclava_blk { + GVAR(Eyes_Protection) = 1; + }; + class G_Balaclava_lowprofile: G_Balaclava_blk { + GVAR(Eyes_Protection) = 1; + }; + + class G_Combat: None { + GVAR(Eyes_Protection) = 1; + }; + class G_Lowprofile: None { + GVAR(Eyes_Protection) = 1; + }; + + class G_RegulatorMask_base_F: None { + GVAR(Eyes_Protection) = 1; + GVAR(Breathing_Protection) = 1; + }; + + class G_Respirator_base_F: None { + GVAR(Breathing_Protection) = 0.8; + }; + + class G_EyeProtectors_base_F: None { + GVAR(Eyes_Protection) = 0.2; + }; + + class G_Balaclava_TI_blk_F: None { + GVAR(Breathing_Protection) = 0.4; + }; + class G_Balaclava_TI_G_blk_F: G_Balaclava_TI_blk_F { + GVAR(Eyes_Protection) = 1; + }; + class G_Balaclava_TI_tna_F; + class G_Balaclava_TI_G_tna_F: G_Balaclava_TI_tna_F { + GVAR(Eyes_Protection) = 1; + }; + + class G_Blindfold_01_base_F: None { + GVAR(Eyes_Protection) = 0.6; + }; +}; diff --git a/addons/smoke/XEH_PREP.hpp b/addons/smoke/XEH_PREP.hpp new file mode 100644 index 00000000000..120eca9de92 --- /dev/null +++ b/addons/smoke/XEH_PREP.hpp @@ -0,0 +1,2 @@ +PREP(isInSmoke); +PREP(pfh); diff --git a/addons/smoke/XEH_postInit.sqf b/addons/smoke/XEH_postInit.sqf new file mode 100644 index 00000000000..2c6d1125a17 --- /dev/null +++ b/addons/smoke/XEH_postInit.sqf @@ -0,0 +1,22 @@ +#include "script_component.hpp" + +GVAR(ppHandleDynamicBlur) = ppEffectCreate ["DynamicBlur", 400]; +GVAR(ppHandleColorCorrections) = ppEffectCreate ["ColorCorrections", 1500]; +GVAR(ppHandleDynamicBlur) ppEffectEnable GVAR(enabled); +GVAR(ppHandleColorCorrections) ppEffectEnable GVAR(enabled); + +if (GVAR(enabled)) then { + GVAR(pfh) = [{ + [ace_player] call FUNC(pfh); + }] call CBA_fnc_addPerFrameHandler; +}; + +["loadout", { + params ["_unit"]; + if !(local _unit) exitWith {}; + private _config = configFile >> "CfgGlasses" >> goggles _unit; + private _breathing = getNumber (_config >> QGVAR(Breathing_Protection)); + _unit setVariable [QGVAR(breathingProtection), _breathing, true]; + private _eyes = getNumber (_config >> QGVAR(Eyes_Protection)); + _unit setVariable [QGVAR(eyesProtection), _eyes, true]; +}, true] call CBA_fnc_addPlayerEventHandler; diff --git a/addons/smoke/XEH_preInit.sqf b/addons/smoke/XEH_preInit.sqf new file mode 100644 index 00000000000..55d80be45e4 --- /dev/null +++ b/addons/smoke/XEH_preInit.sqf @@ -0,0 +1,11 @@ +#include "script_component.hpp" + +ADDON = false; + +#include "XEH_PREP.hpp" + +#include "initSettings.inc.sqf" + +GVAR(pfh) = -1; + +ADDON = true; diff --git a/addons/smoke/XEH_preStart.sqf b/addons/smoke/XEH_preStart.sqf new file mode 100644 index 00000000000..a51262a37b9 --- /dev/null +++ b/addons/smoke/XEH_preStart.sqf @@ -0,0 +1,2 @@ +#include "script_component.hpp" +#include "XEH_PREP.hpp" diff --git a/addons/smoke/config.cpp b/addons/smoke/config.cpp new file mode 100644 index 00000000000..2cfc94ad4a3 --- /dev/null +++ b/addons/smoke/config.cpp @@ -0,0 +1,16 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = QUOTE(COMPONENT); + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_main"}; + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgGlasses.hpp" +#include "ACE_Arsenal_Stats.hpp" diff --git a/addons/smoke/functions/fnc_isInSmoke.sqf b/addons/smoke/functions/fnc_isInSmoke.sqf new file mode 100644 index 00000000000..83e11e97489 --- /dev/null +++ b/addons/smoke/functions/fnc_isInSmoke.sqf @@ -0,0 +1,28 @@ +#include "..\script_component.hpp" + +params ["_unit"]; + +private _coverage = 0; + +private _eyePos = eyePos _unit; +private _positions = [ + [_eyePos, _eyePos vectorAdd [5, 0, 0], _unit], + [_eyePos, _eyePos vectorAdd [-5, 0, 0], _unit], + [_eyePos, _eyePos vectorAdd [0, 5, 0], _unit], + [_eyePos, _eyePos vectorAdd [0, -5, 0], _unit] +]; + +{ + private _intersect = lineIntersectsSurfaces _x; + if (_intersect isNotEqualTo []) then { + _x set [1, _intersect select 0 select 0]; + }; + // Check visibility can return 0 for really close surfaces + if ((_x#0) distance (_x#1) < 0.05) then { + _coverage = _coverage + 1; + } else { + _coverage = _coverage + ([objNull, "VIEW"] checkVisibility [_x#0, _x#1]); + }; +} forEach _positions; + +_coverage < ((count _positions) / 2) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf new file mode 100644 index 00000000000..dba5f9fcf09 --- /dev/null +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -0,0 +1,58 @@ +#include "..\script_component.hpp" + +params ["_unit"]; + +private _isInSmoke = [_unit] call FUNC(isInSmoke); + +private _change = (if (_isInSmoke) then { + 0.175 * GVAR(effectFactor) +} else { + -0.04 * GVAR(recoveryFactor) +}) * diag_deltaTime; + +// Eyes +private _levelEyes = _unit getVariable [QGVAR(eyesLevel), 0]; +private _newLevelEyes = _levelEyes + _change; +_newLevelEyes = _newLevelEyes min 1; +_newLevelEyes = _newLevelEyes max 0; + +private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), false]; +if (_eyesProtect != 0) then { + _levelEyes = _levelEyes * (1 - _eyesProtect); +}; +_unit setVariable [QGVAR(eyesLevel), _levelEyes, true]; + +private _dynamicBlurValue = linearConversion [0.2, 1, _levelEyes, 0, 0.8, true]; +private _colorCorrectionsValue = linearConversion [0.2, 1, _levelEyes, 1, 0.6, true]; + +if (_unit == ace_player) then { + GVAR(ppHandleDynamicBlur) ppEffectAdjust [_dynamicBlurValue]; + GVAR(ppHandleColorCorrections) ppEffectAdjust [1,1,0,[0,0,0,0],[0.8, 0.8, 0.8, _colorCorrectionsValue],[1,1,1,0]]; + + GVAR(ppHandleDynamicBlur) ppEffectCommit 0; + GVAR(ppHandleColorCorrections) ppEffectCommit 0; +}; + +// Breathing +private _levelBreathing = _unit getVariable [QGVAR(breathingLevel), 0]; +private _newLevelBreathing = _levelBreathing + _change; +_newLevelBreathing = _newLevelBreathing min 1; +_newLevelBreathing = _newLevelBreathing max 0; + +private _breathProtect = _unit getVariable [QGVAR(breathingProtection), false]; +if (_breathProtect != 0) then { + _levelBreathing = _levelBreathing * (1 - _breathProtect); +}; +_unit setVariable [QGVAR(breathingLevel), _levelBreathing, true]; + +private _breathingEffectiveness = linearConversion [0.2, 1, _levelBreathing, 1, 0.6, true]; +if !(isNil "ace_medical_vitals_fnc_addSpO2DutyFactor") then { + [ADDON, _breathingEffectiveness] call ace_medical_vitals_fnc_addSpO2DutyFactor; +}; + +// Event +private _smoked = _unit getVariable [QGVAR(smoked), false]; +if (_isInSmoke != _smoked) then { + [QGVAR(smoked), _isInSmoke] call CBA_fnc_localEvent; +}; +_unit setVariable [QGVAR(smoked), _isInSmoke, true]; diff --git a/addons/smoke/initSettings.inc.sqf b/addons/smoke/initSettings.inc.sqf new file mode 100644 index 00000000000..9d326ac5d21 --- /dev/null +++ b/addons/smoke/initSettings.inc.sqf @@ -0,0 +1,46 @@ +private _category = format ["ACE %1", localize LSTRING(DisplayName)]; + +[ + QGVAR(enabled), "CHECKBOX", + [LSTRING(enabled_DisplayName), LSTRING(enabled_Description)], + _category, + true, + 1, + { + [QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged); + GVAR(ppHandleDynamicBlur) ppEffectEnable _this; + GVAR(ppHandleColorCorrections) ppEffectEnable _this; + if (_this) then { + if (GVAR(pfh) == -1) then { + GVAR(pfh) = [{ + [ace_player] call FUNC(pfh); + }] call CBA_fnc_addPerFrameHandler; + }; + } else { + if (GVAR(pfh) != -1) then { + [GVAR(pfh)] call CBA_fnc_removePerFrameHandler; + GVAR(pfh) = -1; + }; + }; + } +] call CBA_fnc_addSetting; + +[ + QGVAR(effectFactor), "SLIDER", + [LSTRING(effectFactor_DisplayName), LSTRING(effectFactor_Description)], + _category, + [0, 1, 0.5, 0.1], + 1, + {[QGVAR(effectFactor), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_fnc_addSetting; + +[ + QGVAR(recoveryFactor), "SLIDER", + [LSTRING(recoveryFactor_DisplayName), LSTRING(recoveryFactor_Description)], + _category, + [0, 1, 0.5, 0.1], + 1, + {[QGVAR(recoveryFactor), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_fnc_addSetting; diff --git a/addons/smoke/script_component.hpp b/addons/smoke/script_component.hpp new file mode 100644 index 00000000000..e9deb0896dd --- /dev/null +++ b/addons/smoke/script_component.hpp @@ -0,0 +1,17 @@ +#define COMPONENT smoke +#define COMPONENT_BEAUTIFIED Smoke +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_SMOKE + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_SMOKE + #define DEBUG_SETTINGS DEBUG_SETTINGS_SMOKE +#endif + +#include "\z\ace\addons\main\script_macros.hpp" diff --git a/addons/smoke/stringtable.xml b/addons/smoke/stringtable.xml new file mode 100644 index 00000000000..e0706fbbc53 --- /dev/null +++ b/addons/smoke/stringtable.xml @@ -0,0 +1,149 @@ + + + + + Smoke Effects + Kouřové efekty + Effets de fumée + Efectos de humo + Effetti del fumo + Efekty dymu + Efeitos de Fumaça + Эффекты дыма + Rauch Effekte + 연기 효과 + 煙エフェクト + 烟雾效果 + 烟雾效果 + Ефекти диму + + + Adjusts the rate of smoke effect. Lower values increase the duration that can be spent in smoke. + Upravuje rychlost kouřového efektu. Nižší hodnoty prodlužují dobu, kterou lze strávit v kouři. + Modifie la vitesse de l'effet de fumée. Des valeurs plus basses augmentent la durée pendant laquelle on peut rester dans la fumée. + Ajusta la velocidad del efecto de humo. Los valores más bajos aumentan la duración que se puede pasar en el humo. + Regola la velocità dell'effetto fumo. Valori più bassi aumentano la durata che si può trascorrere nel fumo. + Dostosowuje szybkość efektu dymu. Niższe wartości zwiększają czas, jaki można spędzić w dymie. + Ajusta a taxa do efeito de fumaça. Valores mais baixos aumentam a duração que pode ser passada na fumaça. + Регулирует скорость эффекта дыма. Более низкие значения увеличивают продолжительность пребывания в дыму. + Passt die Geschwindigkeit des Raucheffekts an. Niedrigere Werte erhöhen die Dauer, die man im Rauch verbringen kann. + 연기 효과의 속도를 조정합니다. 낮은 값은 연기 속에서 보낼 수 있는 시간을 늘립니다. + 煙エフェクトの速度を調整します。値が低いほど、煙の中で過ごせる時間が長くなります。 + 调整烟雾效果的速率。较低的值会增加在烟雾中停留的时间。 + 调整烟雾效果的速率。较低的值会增加在烟雾中停留的时间。 + Регулює швидкість ефекту диму. Нижчі значення збільшують тривалість перебування в диму. + + + Effect Factor + Faktor efektu + Facteur d'effet + Factor de efecto + Fattore di effetto + Czynnik efektu + Fator de Efeito + Коэффициент эффекта + Effekt Faktor + 효과 계수 + エフェクトファクター + 效果系数 + 效果系数 + Фактор ефекту + + + Enable / Disable Smoke Effects + Povolit / Zakázat kouřové efekty + Activer / Désactiver les effets de fumée + Activar / Desactivar los efectos de humo + Abilita / Disabilita gli effetti del fumo + Włącz / Wyłącz efekty dymu + Ativar / Desativar Efeitos de Fumaça + Включить / Выключить эффекты дыма + Rauch Effekte Ein- / Ausschalten + 연기 효과 활성화 / 비활성화 + 煙エフェクトの有効化 / 無効化 + 启用 / 禁用 烟雾效果 + 启用 / 禁用 烟雾效果 + Увімкнути / Вимкнути ефекти диму + + + Enabled + Povoleno + Activé + Activada + Abilitata + Włączone + Ativado + Включена + Aktiv + 활성화 + 有効化 + 啟用 + 启用 + Увімкнено + + + Adjusts the rate of recovery from smoke effects. Higher values increase the rate of recovery after leaving smoke. + Upravuje rychlost zotavení z kouřových efektů. Vyšší hodnoty zvyšují rychlost zotavení po opuštění kouře. + Modifie la vitesse de récupération des effets de fumée. Des valeurs plus élevées augmentent la vitesse de récupération après avoir quitté la fumée. + Ajusta la velocidad de recuperación de los efectos del humo. Los valores más altos aumentan la velocidad de recuperación después de salir del humo. + Regola la velocità di recupero dagli effetti del fumo. Valori più alti aumentano la velocità di recupero dopo aver lasciato il fumo. + Dostosowuje szybkość regeneracji po efektach dymu. Wyższe wartości zwiększają szybkość regeneracji po opuszczeniu dymu. + Ajusta a taxa de recuperação dos efeitos da fumaça. Valores mais altos aumentam a taxa de recuperação após sair da fumaça. + Регулирует скорость восстановления от эффектов дыма. Более высокие значения увеличивают скорость восстановления после выхода из дыма. + Passt die Erholungsgeschwindigkeit von Raucheffekten an. Höhere Werte erhöhen die Erholungsrate nach dem Verlassen des Rauchs. + 연기 효과에서 회복 속도를 조정합니다. 높은 값은 연기를 떠난 후 회복 속도를 증가시킵니다. + 煙エフェクトからの回復速度を調整します。値が高いほど、煙から離れた後の回復速度が速くなります。 + 调整从烟雾效果中恢复的速率。较高的值会增加离开烟雾后的恢复速率。 + 调整从烟雾效果中恢复的速率。较高的值会增加离开烟雾后的恢复速率。 + Регулює швидкість відновлення від ефектів диму. Вищі значення збільшують швидкість відновлення після виходу з диму. + + + Recovery Factor + Faktor zotavení + Facteur de récupération + Factor de recuperación + Fattore di recupero + Czynnik regeneracji + Fator de Recuperação + Коэффициент восстановления + Erholungsfaktor + 회복 계수 + 回復ファクター + 恢复系数 + 恢复系数 + Фактор відновлення + + + Breathing Protection + Ochrana dýchání + Protection respiratoire + Protección respiratoria + Protezione respiratoria + Ochrona oddychania + Proteção Respiratória + Защита дыхания + Atemschutz + 호흡 보호 + 呼吸保護 + 呼吸保护 + 呼吸保护 + Захист дихання + + + Eye Protection + Ochrana očí + Protection des yeux + Protección ocular + Protezione degli occhi + Ochrona oczu + Proteção Ocular + Защита глаз + Augenschutz + 눈 보호 + 目の保護 + 眼睛保护 + 眼睛保护 + Захист очей + + + From 307aa65f6d1298172e4cfa9462c52fb3379474b0 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Wed, 7 Jan 2026 00:17:29 -0600 Subject: [PATCH 02/23] headers --- addons/smoke/functions/fnc_isInSmoke.sqf | 15 +++++++++++++++ addons/smoke/functions/fnc_pfh.sqf | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/addons/smoke/functions/fnc_isInSmoke.sqf b/addons/smoke/functions/fnc_isInSmoke.sqf index 83e11e97489..1a6b99843da 100644 --- a/addons/smoke/functions/fnc_isInSmoke.sqf +++ b/addons/smoke/functions/fnc_isInSmoke.sqf @@ -1,4 +1,19 @@ #include "..\script_component.hpp" +/* + * Author: BrettMayson + * Check if a unit is in smoke (or any thick particle effect that has `blockAIVisibility`) + * + * Arguments: + * 0: Unit + * + * Return Value: + * Is the unit in smoke? + * + * Example: + * [player] call ace_smoke_fnc_isInSmoke + * + * Public: Yes + */ params ["_unit"]; diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index dba5f9fcf09..623404fb935 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -1,4 +1,21 @@ #include "..\script_component.hpp" +/* + * Author: BrettMayson + * Per Frame Handler that updates smoke effects on units + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [{ + * [player] call ace_smoke_fnc_pfh + * }] call CBA_fnc_addPerFrameHandler + * + * Public: No + */ params ["_unit"]; From c4ea58b9b0c2cb0d8f1afc4d7803ff386d32e8ff Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Wed, 7 Jan 2026 00:26:10 -0600 Subject: [PATCH 03/23] Apply suggestions from code review Co-authored-by: PabstMirror --- addons/smoke/functions/fnc_pfh.sqf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 623404fb935..a1bb55361b8 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -33,7 +33,7 @@ private _newLevelEyes = _levelEyes + _change; _newLevelEyes = _newLevelEyes min 1; _newLevelEyes = _newLevelEyes max 0; -private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), false]; +private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), 0]; if (_eyesProtect != 0) then { _levelEyes = _levelEyes * (1 - _eyesProtect); }; @@ -64,7 +64,7 @@ _unit setVariable [QGVAR(breathingLevel), _levelBreathing, true]; private _breathingEffectiveness = linearConversion [0.2, 1, _levelBreathing, 1, 0.6, true]; if !(isNil "ace_medical_vitals_fnc_addSpO2DutyFactor") then { - [ADDON, _breathingEffectiveness] call ace_medical_vitals_fnc_addSpO2DutyFactor; + [QUOTE(ADDON), _breathingEffectiveness] call ace_medical_vitals_fnc_addSpO2DutyFactor; }; // Event From e9e58b4983e4bac1c0f168135bda932515debe0d Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Wed, 7 Jan 2026 00:26:33 -0600 Subject: [PATCH 04/23] Apply suggestion from @PabstMirror Co-authored-by: PabstMirror --- addons/smoke/functions/fnc_pfh.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index a1bb55361b8..fb2bf475de2 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -37,7 +37,7 @@ private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), 0]; if (_eyesProtect != 0) then { _levelEyes = _levelEyes * (1 - _eyesProtect); }; -_unit setVariable [QGVAR(eyesLevel), _levelEyes, true]; +_unit setVariable [QGVAR(eyesLevel), _levelEyes]; private _dynamicBlurValue = linearConversion [0.2, 1, _levelEyes, 0, 0.8, true]; private _colorCorrectionsValue = linearConversion [0.2, 1, _levelEyes, 1, 0.6, true]; From 7dcb19e3103d9c50e94e7a4cb1b842f1b3d40f1b Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Wed, 7 Jan 2026 00:41:31 -0600 Subject: [PATCH 05/23] compat: aegis --- .hemtt/launch.toml | 9 ++++ .../compat_aegis_smoke/CfgGlasses.hpp | 41 +++++++++++++++++++ .../compat_aegis_smoke/config.cpp | 24 +++++++++++ .../compat_aegis_smoke/script_component.hpp | 3 ++ addons/smoke/functions/fnc_pfh.sqf | 2 +- 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 addons/compat_aegis/compat_aegis_smoke/CfgGlasses.hpp create mode 100644 addons/compat_aegis/compat_aegis_smoke/config.cpp create mode 100644 addons/compat_aegis/compat_aegis_smoke/script_component.hpp diff --git a/.hemtt/launch.toml b/.hemtt/launch.toml index 638df8bfac9..c9d92022d75 100644 --- a/.hemtt/launch.toml +++ b/.hemtt/launch.toml @@ -32,6 +32,15 @@ workshop = [ "1369691841", # Community Factions Project ] +[aegis] +extends = "default" +workshop = [ + "949252631", # Aegis +] +dlc = [ + "ws", # Western Sahara +] + [wardrobe] extends = "adt" mission = "Wardrobe.VR" diff --git a/addons/compat_aegis/compat_aegis_smoke/CfgGlasses.hpp b/addons/compat_aegis/compat_aegis_smoke/CfgGlasses.hpp new file mode 100644 index 00000000000..86bb1af563b --- /dev/null +++ b/addons/compat_aegis/compat_aegis_smoke/CfgGlasses.hpp @@ -0,0 +1,41 @@ +class CfgGlasses { + class None; + + class G_Combat_Goggles_blk_F: None { + ace_smoke_eyes_protection = 1; + }; + + class G_Balaclava_light_blk_F: None { + ace_smoke_breathing_protection = 0.4; + }; + class G_Balaclava_light_G_blk_F: G_Balaclava_light_blk_F { + ace_smoke_eyes_protection = 1; + }; + class G_Balaclava_light_eaf_F; + class G_Balaclava_light_G_eaf_F: G_Balaclava_light_eaf_F { + ace_smoke_eyes_protection = 1; + }; + class G_Balaclava_light_mtp_F; + class G_Balaclava_light_G_mtp_F: G_Balaclava_light_mtp_F { + ace_smoke_eyes_protection = 1; + }; + class G_Balaclava_light_tropic_F; + class G_Balaclava_light_G_tropic_F: G_Balaclava_light_tropic_F { + ace_smoke_eyes_protection = 1; + }; + class G_Balaclava_light_wdl_F; + class G_Balaclava_light_G_wdl_F: G_Balaclava_light_wdl_F { + ace_smoke_eyes_protection = 1; + }; + + class G_Balaclava_TI_blk_F: None { + ace_smoke_breathing_protection = 0.4; + }; + class G_Balaclava_TI_G_blk_F: G_Balaclava_TI_blk_F { + ace_smoke_eyes_protection = 1; + }; + class G_Balaclava_TI_tna_F; + class G_Balaclava_TI_G_tna_F: G_Balaclava_TI_tna_F { + ace_smoke_eyes_protection = 1; + }; +}; diff --git a/addons/compat_aegis/compat_aegis_smoke/config.cpp b/addons/compat_aegis/compat_aegis_smoke/config.cpp new file mode 100644 index 00000000000..be9c09f88c5 --- /dev/null +++ b/addons/compat_aegis/compat_aegis_smoke/config.cpp @@ -0,0 +1,24 @@ +#include "script_component.hpp" + +class CfgPatches { + class SUBADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { + "A3_Aegis_Characters_F_Aegis_Facewear", + "ace_smoke", + }; + skipWhenMissingDependencies = 1; + author = ECSTRING(common,ACETeam); + authors[] = {"BrettMayson"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + + // this prevents any patched class from requiring this addon + addonRootClass = "A3_Characters_F"; + }; +}; + +#include "CfgGlasses.hpp" diff --git a/addons/compat_aegis/compat_aegis_smoke/script_component.hpp b/addons/compat_aegis/compat_aegis_smoke/script_component.hpp new file mode 100644 index 00000000000..cafc3b0288d --- /dev/null +++ b/addons/compat_aegis/compat_aegis_smoke/script_component.hpp @@ -0,0 +1,3 @@ +#define SUBCOMPONENT smoke +#define SUBCOMPONENT_BEAUTIFIED Smoke +#include "..\script_component.hpp" diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index fb2bf475de2..83b29621ae3 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -60,7 +60,7 @@ private _breathProtect = _unit getVariable [QGVAR(breathingProtection), false]; if (_breathProtect != 0) then { _levelBreathing = _levelBreathing * (1 - _breathProtect); }; -_unit setVariable [QGVAR(breathingLevel), _levelBreathing, true]; +_unit setVariable [QGVAR(breathingLevel), _levelBreathing]; private _breathingEffectiveness = linearConversion [0.2, 1, _levelBreathing, 1, 0.6, true]; if !(isNil "ace_medical_vitals_fnc_addSpO2DutyFactor") then { From 8a958b5f0a8cff16de55e1c4a115d7b272af107b Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Wed, 7 Jan 2026 01:02:01 -0600 Subject: [PATCH 06/23] compat: cup --- .../compat_cup_smoke/CfgGlasses.hpp | 80 +++++++++++++++++++ .../compat_cup_smoke/config.cpp | 23 ++++++ .../compat_cup_smoke/script_component.hpp | 3 + 3 files changed, 106 insertions(+) create mode 100644 addons/compat_cup_units/compat_cup_smoke/CfgGlasses.hpp create mode 100644 addons/compat_cup_units/compat_cup_smoke/config.cpp create mode 100644 addons/compat_cup_units/compat_cup_smoke/script_component.hpp diff --git a/addons/compat_cup_units/compat_cup_smoke/CfgGlasses.hpp b/addons/compat_cup_units/compat_cup_smoke/CfgGlasses.hpp new file mode 100644 index 00000000000..3b9c71bf637 --- /dev/null +++ b/addons/compat_cup_units/compat_cup_smoke/CfgGlasses.hpp @@ -0,0 +1,80 @@ +#define PROTECT(var1,eyes,breathing) class var1: None { \ + ace_smoke_eyes_protection = eyes; \ + ace_smoke_breathing_protection = breathing; \ +} + +class CfgGlasses { + class None; + + class CUP_RUS_Balaclava_blk: None { + ace_smoke_breathing_protection = 0.4; + }; + + class CUP_G_Ratnik_Balaclava_base: None { + ace_smoke_breathing_protection = 0.4; + }; + + PROTECT(CUP_G_ESS_BLK_Dark,1,0); + PROTECT(CUP_G_ESS_BLK_Ember,1,0); + PROTECT(CUP_G_ESS_BLK,1,0); + PROTECT(CUP_G_ESS_CBR_Dark,1,0); + PROTECT(CUP_G_ESS_CBR_Ember,1,0); + PROTECT(CUP_G_ESS_CBR,1,0); + PROTECT(CUP_G_ESS_RGR_Dark,1,0); + PROTECT(CUP_G_ESS_RGR_Ember,1,0); + PROTECT(CUP_G_ESS_RGR,1,0); + PROTECT(CUP_G_ESS_KHK_Dark,1,0); + PROTECT(CUP_G_ESS_KHK_Ember,1,0); + PROTECT(CUP_G_ESS_KHK,1,0); + PROTECT(CUP_G_ESS_BLK_Facewrap_Black,1,0.4); + PROTECT(CUP_G_ESS_RGR_Facewrap_Ranger,1,0.4); + PROTECT(CUP_G_ESS_CBR_Facewrap_Red,1,0.4); + PROTECT(CUP_G_ESS_RGR_Facewrap_Skull,1,0.4); + PROTECT(CUP_G_ESS_KHK_Facewrap_Tan,1,0.4); + PROTECT(CUP_G_ESS_RGR_Facewrap_Tropical,1,0.4); + PROTECT(CUP_G_ESS_KHK_Facewrap_White,1,0.4); + PROTECT(CUP_G_ESS_BLK_Facewrap_Black_GPS,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Blk,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Grn,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Red,1,0); + PROTECT(CUP_G_ESS_KHK_Scarf_Tan,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_White,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Face_Blk,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Face_Grn,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Face_Red,1,0.4); + PROTECT(CUP_G_ESS_KHK_Scarf_Face_Tan,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Face_White,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Blk_Beard,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Blk_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Grn_Beard,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Grn_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Red_Beard,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Red_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_KHK_Scarf_Tan_Beard,1,0); + PROTECT(CUP_G_ESS_KHK_Scarf_Tan_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_White_Beard,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_White_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Grn_GPS,1,0); + PROTECT(CUP_G_ESS_KHK_Scarf_Tan_GPS,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_White_GPS,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Face_Grn_GPS,1,0.4); + PROTECT(CUP_G_ESS_KHK_Scarf_Face_Tan_GPS,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Face_White_GPS,1,0.4); + PROTECT(CUP_G_ESS_BLK_Scarf_Grn_GPS_Beard,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_Grn_GPS_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_KHK_Scarf_Tan_GPS_Beard,1,0); + PROTECT(CUP_G_ESS_KHK_Scarf_Tan_GPS_Beard_Blonde,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_White_GPS_Beard,1,0); + PROTECT(CUP_G_ESS_BLK_Scarf_White_GPS_Beard_Blonde,1,0); + PROTECT(CUP_G_PMC_Facewrap_Black_Glasses_Dark_Headset,0,0.4); + PROTECT(CUP_G_PMC_Facewrap_Black_Glasses_Dark,0,0.4); + PROTECT(CUP_PMC_Facewrap_Black,0,0.4); + PROTECT(CUP_G_PMC_Facewrap_Tan_Glasses_Dark_Headset,0,0.4); + PROTECT(CUP_G_PMC_Facewrap_Tropical_Glasses_Dark_Headset,0,0.4); + PROTECT(CUP_G_PMC_Facewrap_Winter_Glasses_Dark_Headset,0,0.4); + PROTECT(CUP_G_Scarf_Face_Blk,0,0.4); + PROTECT(CUP_G_Scarf_Face_Grn,0,0.4); + PROTECT(CUP_G_Scarf_Face_Red,0,0.4); + PROTECT(CUP_G_Scarf_Face_Tan,0,0.4); + PROTECT(CUP_G_Scarf_Face_White,0,0.4); +}; diff --git a/addons/compat_cup_units/compat_cup_smoke/config.cpp b/addons/compat_cup_units/compat_cup_smoke/config.cpp new file mode 100644 index 00000000000..6f833154da5 --- /dev/null +++ b/addons/compat_cup_units/compat_cup_smoke/config.cpp @@ -0,0 +1,23 @@ +#include "script_component.hpp" + +class CfgPatches { + class SUBADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { + "ace_smoke", + "CUP_Creatures_Military_RussiaModern_Headgear", + "CUP_Creatures_Military_USArmy", + }; + skipWhenMissingDependencies = 1; + author = ECSTRING(common,ACETeam); + authors[] = {"BrettMayson"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + addonRootClass = QUOTE(ADDON); + }; +}; + +#include "CfgGlasses.hpp" diff --git a/addons/compat_cup_units/compat_cup_smoke/script_component.hpp b/addons/compat_cup_units/compat_cup_smoke/script_component.hpp new file mode 100644 index 00000000000..cafc3b0288d --- /dev/null +++ b/addons/compat_cup_units/compat_cup_smoke/script_component.hpp @@ -0,0 +1,3 @@ +#define SUBCOMPONENT smoke +#define SUBCOMPONENT_BEAUTIFIED Smoke +#include "..\script_component.hpp" From 838ab185cb4507047f7c022f4ecbf6f1208cb7fb Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Fri, 9 Jan 2026 15:52:53 -0600 Subject: [PATCH 07/23] fix default breathing protection --- addons/smoke/functions/fnc_pfh.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 83b29621ae3..3e34156fbf4 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -56,7 +56,7 @@ private _newLevelBreathing = _levelBreathing + _change; _newLevelBreathing = _newLevelBreathing min 1; _newLevelBreathing = _newLevelBreathing max 0; -private _breathProtect = _unit getVariable [QGVAR(breathingProtection), false]; +private _breathProtect = _unit getVariable [QGVAR(breathingProtection), 0]; if (_breathProtect != 0) then { _levelBreathing = _levelBreathing * (1 - _breathProtect); }; From 1fbd5cd7b710d199ee649fd6237380b543a751fb Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Fri, 9 Jan 2026 17:59:59 -0600 Subject: [PATCH 08/23] fix var assignment --- addons/smoke/functions/fnc_pfh.sqf | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 3e34156fbf4..3e2dcece300 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -32,6 +32,7 @@ private _levelEyes = _unit getVariable [QGVAR(eyesLevel), 0]; private _newLevelEyes = _levelEyes + _change; _newLevelEyes = _newLevelEyes min 1; _newLevelEyes = _newLevelEyes max 0; +_levelEyes = _newLevelEyes; private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), 0]; if (_eyesProtect != 0) then { From 28bdebc599d0d29b8915d9d693b54e222753ef51 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Fri, 9 Jan 2026 18:56:39 -0600 Subject: [PATCH 09/23] use 500 --- addons/smoke/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/smoke/XEH_postInit.sqf b/addons/smoke/XEH_postInit.sqf index 2c6d1125a17..2c2dd5d5e28 100644 --- a/addons/smoke/XEH_postInit.sqf +++ b/addons/smoke/XEH_postInit.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" -GVAR(ppHandleDynamicBlur) = ppEffectCreate ["DynamicBlur", 400]; +GVAR(ppHandleDynamicBlur) = ppEffectCreate ["DynamicBlur", 500]; GVAR(ppHandleColorCorrections) = ppEffectCreate ["ColorCorrections", 1500]; GVAR(ppHandleDynamicBlur) ppEffectEnable GVAR(enabled); GVAR(ppHandleColorCorrections) ppEffectEnable GVAR(enabled); From db09e41d9122661d4921b6337a7e174287e1a90c Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 10 Jan 2026 09:03:15 -0600 Subject: [PATCH 10/23] compat: ws --- .../compat_ws/compat_ws_smoke/CfgWeapons.hpp | 11 ++++++ addons/compat_ws/compat_ws_smoke/config.cpp | 24 +++++++++++++ .../compat_ws_smoke/script_component.hpp | 3 ++ addons/hearing/stringtable.xml | 34 +++++++++---------- addons/smoke/ACE_Arsenal_Stats.hpp | 4 +-- addons/smoke/CfgWeapons.hpp | 17 ++++++++++ addons/smoke/config.cpp | 3 +- 7 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 addons/compat_ws/compat_ws_smoke/CfgWeapons.hpp create mode 100644 addons/compat_ws/compat_ws_smoke/config.cpp create mode 100644 addons/compat_ws/compat_ws_smoke/script_component.hpp create mode 100644 addons/smoke/CfgWeapons.hpp diff --git a/addons/compat_ws/compat_ws_smoke/CfgWeapons.hpp b/addons/compat_ws/compat_ws_smoke/CfgWeapons.hpp new file mode 100644 index 00000000000..2a3303d8713 --- /dev/null +++ b/addons/compat_ws/compat_ws_smoke/CfgWeapons.hpp @@ -0,0 +1,11 @@ +class CfgWeapons { + class lxWS_H_turban_01_black; + class lxWS_H_turban_03_black: lxWS_H_turban_01_black { + ace_smoke_breathing_protection = 0.4; + }; + + class H_Shemag_khk; + class H_turban_02_mask_black_lxws: H_Shemag_khk { + ace_smoke_breathing_protection = 0.4; + }; +}; diff --git a/addons/compat_ws/compat_ws_smoke/config.cpp b/addons/compat_ws/compat_ws_smoke/config.cpp new file mode 100644 index 00000000000..61a8c70dfcc --- /dev/null +++ b/addons/compat_ws/compat_ws_smoke/config.cpp @@ -0,0 +1,24 @@ +#include "script_component.hpp" + +class CfgPatches { + class SUBADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { + "data_f_lxWS_Loadorder", + "ace_smoke", + }; + skipWhenMissingDependencies = 1; + author = ECSTRING(common,ACETeam); + authors[] = {"BrettMayson"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + + // this prevents any patched class from requiring this addon + addonRootClass = "A3_Characters_F"; + }; +}; + +#include "CfgWeapons.hpp" diff --git a/addons/compat_ws/compat_ws_smoke/script_component.hpp b/addons/compat_ws/compat_ws_smoke/script_component.hpp new file mode 100644 index 00000000000..cafc3b0288d --- /dev/null +++ b/addons/compat_ws/compat_ws_smoke/script_component.hpp @@ -0,0 +1,3 @@ +#define SUBCOMPONENT smoke +#define SUBCOMPONENT_BEAUTIFIED Smoke +#include "..\script_component.hpp" diff --git a/addons/hearing/stringtable.xml b/addons/hearing/stringtable.xml index 9eab8e109cb..3ced27a2450 100644 --- a/addons/hearing/stringtable.xml +++ b/addons/hearing/stringtable.xml @@ -491,36 +491,36 @@ ЕЛЕКТРОННИЙ - Volume muffling - Snížení hlasitosti - Atténuation du volume - Atenuación de volumen - Attenuazione del volume - Tłumienie głośności - Abafamento de Volume - Глушение звука + Volume Muffling + Snížení Hlasitosti + Atténuation Du Volume + Atenuación De Volumen + Attenuazione Del Volume + Tłumienie Głośności + Abafamento De Volume + Глушение Звука Lautstärkedämpfung 소리 차음도 音量の抑制 進低音量 降低音量 - Глушіння звуку + Глушіння Звуку - Hearing protection - Ochrana sluchu - Protection auditive - Protección auditiva - Protezione uditiva - Ochrona słuchu + Hearing Protection + Ochrana Sluchu + Protection Auditive + Protección Auditiva + Protezione Uditiva + Ochrona Słuchu Proteção Auditiva - Защита слуха + Защита Слуха Gehörschutz 청력 보호 聴覚保護 聽力保護 听力保护 - Захист слуху + Захист Слуху Volume when unconscious. diff --git a/addons/smoke/ACE_Arsenal_Stats.hpp b/addons/smoke/ACE_Arsenal_Stats.hpp index e31618ec3ef..313b9f6ee11 100644 --- a/addons/smoke/ACE_Arsenal_Stats.hpp +++ b/addons/smoke/ACE_Arsenal_Stats.hpp @@ -6,7 +6,7 @@ class EGVAR(arsenal,stats) { showBar = 1; condition = QUOTE(getNumber (_this select 1 >> QQGVAR(Breathing_Protection)) > 0); barStatement = QUOTE(getNumber (_this select 1 >> QQGVAR(Breathing_Protection))); - tabs[] = {{7}, {}}; + tabs[] = {{6,7}, {}}; }; class GVAR(eyes_protection): statBase { @@ -15,6 +15,6 @@ class EGVAR(arsenal,stats) { showBar = 1; condition = QUOTE(getNumber (_this select 1 >> QQGVAR(Eyes_Protection)) > 0); barStatement = QUOTE(getNumber (_this select 1 >> QQGVAR(Eyes_Protection))); - tabs[] = {{7}, {}}; + tabs[] = {{6,7}, {}}; }; }; diff --git a/addons/smoke/CfgWeapons.hpp b/addons/smoke/CfgWeapons.hpp new file mode 100644 index 00000000000..74fc3494864 --- /dev/null +++ b/addons/smoke/CfgWeapons.hpp @@ -0,0 +1,17 @@ +class CfgWeapons { + class H_HelmetB; + class H_HelmetO_ViperSP_hex_F: H_HelmetB { + GVAR(Eyes_Protection) = 1; + }; + + class H_PilotHelmetFighter_B: H_HelmetB { + GVAR(Breathing_Protection) = 1; + GVAR(Eyes_Protection) = 1; + }; + + class H_HelmetB_camo; + class H_RacingHelmet_1_F: H_HelmetB_camo { + GVAR(Breathing_Protection) = 0.3; + GVAR(Eyes_Protection) = 0.7; + }; +}; diff --git a/addons/smoke/config.cpp b/addons/smoke/config.cpp index 2cfc94ad4a3..c1c121c6fd7 100644 --- a/addons/smoke/config.cpp +++ b/addons/smoke/config.cpp @@ -11,6 +11,7 @@ class CfgPatches { }; }; +#include "ACE_Arsenal_Stats.hpp" #include "CfgEventHandlers.hpp" #include "CfgGlasses.hpp" -#include "ACE_Arsenal_Stats.hpp" +#include "CfgWeapons.hpp" From c7a5c5fe347cdc7d58acf0ddee1ac496858e5bec Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sun, 11 Jan 2026 11:36:24 -0600 Subject: [PATCH 11/23] don't check inside vehicles --- addons/smoke/functions/fnc_isInSmoke.sqf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/smoke/functions/fnc_isInSmoke.sqf b/addons/smoke/functions/fnc_isInSmoke.sqf index 1a6b99843da..183d356a3dc 100644 --- a/addons/smoke/functions/fnc_isInSmoke.sqf +++ b/addons/smoke/functions/fnc_isInSmoke.sqf @@ -17,6 +17,8 @@ params ["_unit"]; +if (!isNull objectParent _unit) exitWith { false }; + private _coverage = 0; private _eyePos = eyePos _unit; From 1fd6f2c524e7ec52455e2a3dea9f8227a583e0c5 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Sat, 24 Jan 2026 22:23:43 -0600 Subject: [PATCH 12/23] Apply suggestions from code review Co-authored-by: PabstMirror --- addons/smoke/XEH_postInit.sqf | 1 + addons/smoke/functions/fnc_pfh.sqf | 1 + addons/smoke/initSettings.inc.sqf | 1 + 3 files changed, 3 insertions(+) diff --git a/addons/smoke/XEH_postInit.sqf b/addons/smoke/XEH_postInit.sqf index 2c2dd5d5e28..903e1303a27 100644 --- a/addons/smoke/XEH_postInit.sqf +++ b/addons/smoke/XEH_postInit.sqf @@ -1,5 +1,6 @@ #include "script_component.hpp" +if (!hasInterface) exitWith {}; GVAR(ppHandleDynamicBlur) = ppEffectCreate ["DynamicBlur", 500]; GVAR(ppHandleColorCorrections) = ppEffectCreate ["ColorCorrections", 1500]; GVAR(ppHandleDynamicBlur) ppEffectEnable GVAR(enabled); diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 3e2dcece300..9fe96d9b43c 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -56,6 +56,7 @@ private _levelBreathing = _unit getVariable [QGVAR(breathingLevel), 0]; private _newLevelBreathing = _levelBreathing + _change; _newLevelBreathing = _newLevelBreathing min 1; _newLevelBreathing = _newLevelBreathing max 0; +_levelBreathing = _newLevelBreathing; private _breathProtect = _unit getVariable [QGVAR(breathingProtection), 0]; if (_breathProtect != 0) then { diff --git a/addons/smoke/initSettings.inc.sqf b/addons/smoke/initSettings.inc.sqf index 9d326ac5d21..4dbbf669e29 100644 --- a/addons/smoke/initSettings.inc.sqf +++ b/addons/smoke/initSettings.inc.sqf @@ -8,6 +8,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)]; 1, { [QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged); + if (!hasInterface) exitwith {}; GVAR(ppHandleDynamicBlur) ppEffectEnable _this; GVAR(ppHandleColorCorrections) ppEffectEnable _this; if (_this) then { From 2a6019880c9f0e1397449c9b931ba9971349eba5 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 24 Jan 2026 22:24:32 -0600 Subject: [PATCH 13/23] don't seVariable every run --- addons/smoke/functions/fnc_pfh.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 9fe96d9b43c..fbc6f7e8ddc 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -72,6 +72,6 @@ if !(isNil "ace_medical_vitals_fnc_addSpO2DutyFactor") then { // Event private _smoked = _unit getVariable [QGVAR(smoked), false]; if (_isInSmoke != _smoked) then { + _unit setVariable [QGVAR(smoked), _isInSmoke, true]; [QGVAR(smoked), _isInSmoke] call CBA_fnc_localEvent; }; -_unit setVariable [QGVAR(smoked), _isInSmoke, true]; From 3ad61024af8f6bff369884bd5175773cab74cefc Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 24 Jan 2026 23:04:01 -0600 Subject: [PATCH 14/23] reduce pfh frequency, fix detection in tight spaces --- .hemtt/launch.toml | 1 + addons/smoke/functions/fnc_isInSmoke.sqf | 14 ++++++-------- addons/smoke/functions/fnc_pfh.sqf | 2 +- addons/smoke/initSettings.inc.sqf | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.hemtt/launch.toml b/.hemtt/launch.toml index c9d92022d75..a9ab6cb5614 100644 --- a/.hemtt/launch.toml +++ b/.hemtt/launch.toml @@ -1,6 +1,7 @@ [default] workshop = [ "450814997", # CBA_A3 + "synixe:@bozcaada", ] [adt] diff --git a/addons/smoke/functions/fnc_isInSmoke.sqf b/addons/smoke/functions/fnc_isInSmoke.sqf index 183d356a3dc..e18cca21b74 100644 --- a/addons/smoke/functions/fnc_isInSmoke.sqf +++ b/addons/smoke/functions/fnc_isInSmoke.sqf @@ -17,8 +17,6 @@ params ["_unit"]; -if (!isNull objectParent _unit) exitWith { false }; - private _coverage = 0; private _eyePos = eyePos _unit; @@ -32,14 +30,14 @@ private _positions = [ { private _intersect = lineIntersectsSurfaces _x; if (_intersect isNotEqualTo []) then { - _x set [1, _intersect select 0 select 0]; + _x set [1, _intersect select 0]; + } else { + _x set [1, [_x#1,0,objNull]]; }; - // Check visibility can return 0 for really close surfaces - if ((_x#0) distance (_x#1) < 0.05) then { + if ((_x#0) distance (_x#1#0) < 0.1) then { _coverage = _coverage + 1; } else { - _coverage = _coverage + ([objNull, "VIEW"] checkVisibility [_x#0, _x#1]); + _coverage = _coverage + ([objectParent _unit, "VIEW", _x#1#2] checkVisibility [_x#0, _x#1#0]); }; } forEach _positions; - -_coverage < ((count _positions) / 2) +_coverage < ((count _positions) / 3) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index fbc6f7e8ddc..9246a9980e5 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -64,8 +64,8 @@ if (_breathProtect != 0) then { }; _unit setVariable [QGVAR(breathingLevel), _levelBreathing]; -private _breathingEffectiveness = linearConversion [0.2, 1, _levelBreathing, 1, 0.6, true]; if !(isNil "ace_medical_vitals_fnc_addSpO2DutyFactor") then { + private _breathingEffectiveness = linearConversion [0.2, 1, _levelBreathing, 1, 0.6, true]; [QUOTE(ADDON), _breathingEffectiveness] call ace_medical_vitals_fnc_addSpO2DutyFactor; }; diff --git a/addons/smoke/initSettings.inc.sqf b/addons/smoke/initSettings.inc.sqf index 4dbbf669e29..8add4331b27 100644 --- a/addons/smoke/initSettings.inc.sqf +++ b/addons/smoke/initSettings.inc.sqf @@ -8,14 +8,14 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)]; 1, { [QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged); - if (!hasInterface) exitwith {}; + if (!hasInterface) exitWith {}; GVAR(ppHandleDynamicBlur) ppEffectEnable _this; GVAR(ppHandleColorCorrections) ppEffectEnable _this; if (_this) then { if (GVAR(pfh) == -1) then { GVAR(pfh) = [{ [ace_player] call FUNC(pfh); - }] call CBA_fnc_addPerFrameHandler; + }, 0.25] call CBA_fnc_addPerFrameHandler; }; } else { if (GVAR(pfh) != -1) then { From 7ff70cc459286139db33770a2230b694df66747a Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 24 Jan 2026 23:05:05 -0600 Subject: [PATCH 15/23] 5 times per second --- addons/smoke/initSettings.inc.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/smoke/initSettings.inc.sqf b/addons/smoke/initSettings.inc.sqf index 8add4331b27..9a6139689ef 100644 --- a/addons/smoke/initSettings.inc.sqf +++ b/addons/smoke/initSettings.inc.sqf @@ -15,7 +15,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)]; if (GVAR(pfh) == -1) then { GVAR(pfh) = [{ [ace_player] call FUNC(pfh); - }, 0.25] call CBA_fnc_addPerFrameHandler; + }, 0.2] call CBA_fnc_addPerFrameHandler; }; } else { if (GVAR(pfh) != -1) then { From 729c5a40c95f8a78dd641194038831b7dc894656 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 24 Jan 2026 23:07:29 -0600 Subject: [PATCH 16/23] don't apply in tanks --- addons/smoke/functions/fnc_pfh.sqf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 9246a9980e5..7f18233574e 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -19,6 +19,9 @@ params ["_unit"]; +private _vehicle = objectParent _unit; +if (!isNull _vehicle && {_vehicle isKindOf "Tank"}) exitWith {}; + private _isInSmoke = [_unit] call FUNC(isInSmoke); private _change = (if (_isInSmoke) then { From 9d2633490d35c24f4558380fc27beca26b6db66b Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Mon, 2 Feb 2026 01:01:17 -0600 Subject: [PATCH 17/23] better vehicle handling --- .hemtt/launch.toml | 12 +++-- .../functions/fnc_addSpO2DutyFactor.sqf | 6 ++- addons/smoke/XEH_PREP.hpp | 2 + addons/smoke/XEH_preInit.sqf | 2 + addons/smoke/functions/fnc_isOpenSeat.sqf | 47 +++++++++++++++++++ addons/smoke/functions/fnc_isOpenVehicle.sqf | 38 +++++++++++++++ addons/smoke/functions/fnc_pfh.sqf | 11 ++++- 7 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 addons/smoke/functions/fnc_isOpenSeat.sqf create mode 100644 addons/smoke/functions/fnc_isOpenVehicle.sqf diff --git a/.hemtt/launch.toml b/.hemtt/launch.toml index a9ab6cb5614..22ca0704a1d 100644 --- a/.hemtt/launch.toml +++ b/.hemtt/launch.toml @@ -1,7 +1,6 @@ [default] workshop = [ "450814997", # CBA_A3 - "synixe:@bozcaada", ] [adt] @@ -10,6 +9,12 @@ workshop = [ "3499977893", # ADT ] +[zen] +extends = "default" +workshop = [ + "1779063631", # ZEN +] + [rhs] extends = "default" workshop = [ @@ -48,15 +53,14 @@ mission = "Wardrobe.VR" workshop = [ "1779063631", # ZEN # "751965892", # ACRE -# "623475643", # eden enhanced +# "623475643", # 3den Enhanced ] [sogns] -extends = "default" +extends = "adt" dlc = ["vn"] workshop = [ "623475643", # 3den Enhanced - "3499977893", # Advanced Developer Tools "3083451905", # S.O.G. Nickel Steel "1779063631", # Zeus Enhanced ] diff --git a/addons/medical_vitals/functions/fnc_addSpO2DutyFactor.sqf b/addons/medical_vitals/functions/fnc_addSpO2DutyFactor.sqf index 0c85ae3fa55..69573b9dff9 100644 --- a/addons/medical_vitals/functions/fnc_addSpO2DutyFactor.sqf +++ b/addons/medical_vitals/functions/fnc_addSpO2DutyFactor.sqf @@ -16,6 +16,10 @@ * Public: No */ params [["_id", "", [""]], ["_factor", 1, [0, {}]]]; -if (_id == "" || {_factor isEqualTo 1}) exitWith {}; +if (_id == "") exitWith {}; + +if (_factor isEqualTo 1) exitWith { + [_id] call FUNC(removeSpO2DutyFactor); +}; GVAR(spo2DutyList) set [_id, _factor]; diff --git a/addons/smoke/XEH_PREP.hpp b/addons/smoke/XEH_PREP.hpp index 120eca9de92..059e0c6264b 100644 --- a/addons/smoke/XEH_PREP.hpp +++ b/addons/smoke/XEH_PREP.hpp @@ -1,2 +1,4 @@ PREP(isInSmoke); +PREP(isOpenVehicle); +PREP(isOpenSeat); PREP(pfh); diff --git a/addons/smoke/XEH_preInit.sqf b/addons/smoke/XEH_preInit.sqf index 55d80be45e4..61eb91c6dc1 100644 --- a/addons/smoke/XEH_preInit.sqf +++ b/addons/smoke/XEH_preInit.sqf @@ -7,5 +7,7 @@ ADDON = false; #include "initSettings.inc.sqf" GVAR(pfh) = -1; +GVAR(openVehicleCache) = createHashMap; +GVAR(openSeatCache) = createHashMap; ADDON = true; diff --git a/addons/smoke/functions/fnc_isOpenSeat.sqf b/addons/smoke/functions/fnc_isOpenSeat.sqf new file mode 100644 index 00000000000..7b43c2f927c --- /dev/null +++ b/addons/smoke/functions/fnc_isOpenSeat.sqf @@ -0,0 +1,47 @@ +#include "..\script_component.hpp" +/* + * Author: BrettMayson + * Check if a seat is open and thus susceptible to smoke entering + * + * Arguments: + * 0: Vehicle + * 1: Unit + * + * Return Value: + * Is the seat open? + * + * Example: + * [_vehicle, _unit] call ace_smoke_fnc_isOpenSeat + * + * Public: Yes + */ + +params [ + ["_vehicle", objNull, [objNull]], + ["_unit", objNull, [objNull]] +]; + +if (_vehicle isEqualTo objNull || _unit isEqualTo objNull) exitWith { true }; + +private _class = typeOf _vehicle; +private _index = _vehicle getCargoIndex _unit; + +private _open = -1; +if (_class in GVAR(openSeatCache)) then { + private _cache = GVAR(openSeatCache) get _class; + if (_index in _cache) then { + _open = _cache get _index; + }; +}; +if (_open isNotEqualTo -1) exitWith { _open }; + +if ([_vehicle] call FUNC(isOpenVehicle)) exitWith { true }; + +private _eyePos = eyePos _unit; +private _intersect = lineIntersectsSurfaces [_eyePos, _eyePos vectorAdd [0, 0, 1], _unit]; +private _open = _intersect isEqualTo []; + +private _cache = GVAR(openSeatCache) getOrDefaultCall [_class, { createHashMap }, true]; +_cache set [_index, _open]; + +_open diff --git a/addons/smoke/functions/fnc_isOpenVehicle.sqf b/addons/smoke/functions/fnc_isOpenVehicle.sqf new file mode 100644 index 00000000000..9b9516c26f8 --- /dev/null +++ b/addons/smoke/functions/fnc_isOpenVehicle.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" +/* + * Author: BrettMayson + * Check if a vehicle is open and thus susceptible to smoke entering + * + * Arguments: + * 0: Vehicle + * + * Return Value: + * Is the vehicle open? + * + * Example: + * [vehicle player] call ace_smoke_fnc_isOpenVehicle + * + * Public: Yes + */ + +params [ + ["_vehicle", objNull, [objNull]] +]; + +if (_vehicle isEqualTo objNull) exitWith { true }; + +private _class = typeOf _vehicle; + +if (_class in GVAR(openVehicleCache)) exitWith { GVAR(openVehicleCache) get _class }; + +private _attentuation = getText(configFile >> "CfgVehicles" >> _class >> "attenuationEffectType"); +if (_attentuation == "") exitWith { true }; + +private _attenuation = configFile >> "AttenuationEffects" >> _attentuation; +private _open = [0,1] findIf { + private _equalizer = getArray(_attenuation >> format ["Equalizer%1", _x] >> "gain"); + _equalizer isEqualTo [1,1,1,1] +} != -1; + +GVAR(openVehicleCache) set [_class, _open]; +_open diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 7f18233574e..4f92bb932c5 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -20,9 +20,16 @@ params ["_unit"]; private _vehicle = objectParent _unit; -if (!isNull _vehicle && {_vehicle isKindOf "Tank"}) exitWith {}; -private _isInSmoke = [_unit] call FUNC(isInSmoke); +private _isInSmoke = if (!isNull _vehicle) then { + if ([_vehicle, _unit] call FUNC(isOpenSeat)) then { + [_unit] call FUNC(isInSmoke) + } else { + false + } +} else { + [_unit] call FUNC(isInSmoke) +}; private _change = (if (_isInSmoke) then { 0.175 * GVAR(effectFactor) From f6cb4584e32c0f385ae8e84f22dd25c0ebbbf4b7 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Mon, 2 Feb 2026 01:05:12 -0600 Subject: [PATCH 18/23] full protection allows recovery --- addons/smoke/functions/fnc_pfh.sqf | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 4f92bb932c5..39a62e872b1 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -39,13 +39,19 @@ private _change = (if (_isInSmoke) then { // Eyes private _levelEyes = _unit getVariable [QGVAR(eyesLevel), 0]; -private _newLevelEyes = _levelEyes + _change; +private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), 0]; + +private _eyesChange = _change; +if (_eyesProtect == 1 && _isInSmoke) then { + _eyesChange = -0.04 * GVAR(recoveryFactor) * diag_deltaTime; +}; + +private _newLevelEyes = _levelEyes + _eyesChange; _newLevelEyes = _newLevelEyes min 1; _newLevelEyes = _newLevelEyes max 0; _levelEyes = _newLevelEyes; -private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), 0]; -if (_eyesProtect != 0) then { +if (_eyesProtect != 0 && _eyesProtect != 1) then { _levelEyes = _levelEyes * (1 - _eyesProtect); }; _unit setVariable [QGVAR(eyesLevel), _levelEyes]; @@ -63,13 +69,19 @@ if (_unit == ace_player) then { // Breathing private _levelBreathing = _unit getVariable [QGVAR(breathingLevel), 0]; -private _newLevelBreathing = _levelBreathing + _change; +private _breathProtect = _unit getVariable [QGVAR(breathingProtection), 0]; + +private _breathChange = _change; +if (_breathProtect == 1 && _isInSmoke) then { + _breathChange = -0.04 * GVAR(recoveryFactor) * diag_deltaTime; +}; + +private _newLevelBreathing = _levelBreathing + _breathChange; _newLevelBreathing = _newLevelBreathing min 1; _newLevelBreathing = _newLevelBreathing max 0; _levelBreathing = _newLevelBreathing; -private _breathProtect = _unit getVariable [QGVAR(breathingProtection), 0]; -if (_breathProtect != 0) then { +if (_breathProtect != 0 && _breathProtect != 1) then { _levelBreathing = _levelBreathing * (1 - _breathProtect); }; _unit setVariable [QGVAR(breathingLevel), _levelBreathing]; From dc53019b9cba676b62b1dea8f6b5c41a6f8d2b86 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Mon, 2 Feb 2026 01:43:36 -0600 Subject: [PATCH 19/23] reuse code, various tweaks --- addons/smoke/XEH_postInit.sqf | 6 -- addons/smoke/functions/fnc_isInSmoke.sqf | 6 +- addons/smoke/functions/fnc_isOpenSeat.sqf | 2 +- addons/smoke/functions/fnc_pfh.sqf | 73 +++++++++-------------- addons/smoke/initSettings.inc.sqf | 6 +- addons/smoke/script_component.hpp | 2 + 6 files changed, 39 insertions(+), 56 deletions(-) diff --git a/addons/smoke/XEH_postInit.sqf b/addons/smoke/XEH_postInit.sqf index 903e1303a27..4fa37ee6348 100644 --- a/addons/smoke/XEH_postInit.sqf +++ b/addons/smoke/XEH_postInit.sqf @@ -6,12 +6,6 @@ GVAR(ppHandleColorCorrections) = ppEffectCreate ["ColorCorrections", 1500]; GVAR(ppHandleDynamicBlur) ppEffectEnable GVAR(enabled); GVAR(ppHandleColorCorrections) ppEffectEnable GVAR(enabled); -if (GVAR(enabled)) then { - GVAR(pfh) = [{ - [ace_player] call FUNC(pfh); - }] call CBA_fnc_addPerFrameHandler; -}; - ["loadout", { params ["_unit"]; if !(local _unit) exitWith {}; diff --git a/addons/smoke/functions/fnc_isInSmoke.sqf b/addons/smoke/functions/fnc_isInSmoke.sqf index e18cca21b74..d9d9fc09860 100644 --- a/addons/smoke/functions/fnc_isInSmoke.sqf +++ b/addons/smoke/functions/fnc_isInSmoke.sqf @@ -15,7 +15,11 @@ * Public: Yes */ -params ["_unit"]; +params [["_unit", objNull, [objNull]]]; + +private _vehicle = objectParent _unit; + +if (!isNull _vehicle && {!([_vehicle, _unit] call FUNC(isOpenSeat))}) exitWith { false }; private _coverage = 0; diff --git a/addons/smoke/functions/fnc_isOpenSeat.sqf b/addons/smoke/functions/fnc_isOpenSeat.sqf index 7b43c2f927c..4eabdd14812 100644 --- a/addons/smoke/functions/fnc_isOpenSeat.sqf +++ b/addons/smoke/functions/fnc_isOpenSeat.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: BrettMayson - * Check if a seat is open and thus susceptible to smoke entering + * Check if a seat is open and thus susceptible to smoke entering, may not be accurate for vehicles with top coverings * * Arguments: * 0: Vehicle diff --git a/addons/smoke/functions/fnc_pfh.sqf b/addons/smoke/functions/fnc_pfh.sqf index 39a62e872b1..8ceb3c72e78 100644 --- a/addons/smoke/functions/fnc_pfh.sqf +++ b/addons/smoke/functions/fnc_pfh.sqf @@ -19,71 +19,54 @@ params ["_unit"]; -private _vehicle = objectParent _unit; +if (isGamePaused) exitWith {}; -private _isInSmoke = if (!isNull _vehicle) then { - if ([_vehicle, _unit] call FUNC(isOpenSeat)) then { - [_unit] call FUNC(isInSmoke) - } else { - false - } -} else { - [_unit] call FUNC(isInSmoke) -}; +#define EFFECT_RATE 0.3 +#define RECOVERY_RATE -0.075 + +private _isInSmoke = [_unit] call FUNC(isInSmoke); private _change = (if (_isInSmoke) then { - 0.175 * GVAR(effectFactor) + EFFECT_RATE * GVAR(effectFactor) } else { - -0.04 * GVAR(recoveryFactor) -}) * diag_deltaTime; + RECOVERY_RATE * GVAR(recoveryFactor) +}) * diag_deltaTime * (1 / PFH_INTERVAL); + +private _fnc_updateLevel = { + params ["_level", "_protect"]; + private _innerChange = if (_protect == 1 && _isInSmoke) then { + RECOVERY_RATE * GVAR(recoveryFactor) * diag_deltaTime * (1 / PFH_INTERVAL) + } else { + _change + }; + private _newLevel = (_level + _innerChange) min 1 max 0; + if (_protect != 0 && _protect != 1) then { + _newLevel = _newLevel * (1 - _protect); + }; + _newLevel +}; // Eyes private _levelEyes = _unit getVariable [QGVAR(eyesLevel), 0]; private _eyesProtect = _unit getVariable [QGVAR(eyesProtection), 0]; - -private _eyesChange = _change; -if (_eyesProtect == 1 && _isInSmoke) then { - _eyesChange = -0.04 * GVAR(recoveryFactor) * diag_deltaTime; -}; - -private _newLevelEyes = _levelEyes + _eyesChange; -_newLevelEyes = _newLevelEyes min 1; -_newLevelEyes = _newLevelEyes max 0; -_levelEyes = _newLevelEyes; - -if (_eyesProtect != 0 && _eyesProtect != 1) then { - _levelEyes = _levelEyes * (1 - _eyesProtect); -}; +_levelEyes = [_levelEyes, _eyesProtect] call _fnc_updateLevel; _unit setVariable [QGVAR(eyesLevel), _levelEyes]; -private _dynamicBlurValue = linearConversion [0.2, 1, _levelEyes, 0, 0.8, true]; -private _colorCorrectionsValue = linearConversion [0.2, 1, _levelEyes, 1, 0.6, true]; +private _dynamicBlurValue = linearConversion [0.05, 1, _levelEyes, 0, 0.8, true]; +private _colorCorrectionsValue = linearConversion [0.05, 1, _levelEyes, 1, 0.6, true]; if (_unit == ace_player) then { GVAR(ppHandleDynamicBlur) ppEffectAdjust [_dynamicBlurValue]; GVAR(ppHandleColorCorrections) ppEffectAdjust [1,1,0,[0,0,0,0],[0.8, 0.8, 0.8, _colorCorrectionsValue],[1,1,1,0]]; - GVAR(ppHandleDynamicBlur) ppEffectCommit 0; - GVAR(ppHandleColorCorrections) ppEffectCommit 0; + GVAR(ppHandleDynamicBlur) ppEffectCommit PFH_INTERVAL; + GVAR(ppHandleColorCorrections) ppEffectCommit PFH_INTERVAL; }; // Breathing private _levelBreathing = _unit getVariable [QGVAR(breathingLevel), 0]; private _breathProtect = _unit getVariable [QGVAR(breathingProtection), 0]; - -private _breathChange = _change; -if (_breathProtect == 1 && _isInSmoke) then { - _breathChange = -0.04 * GVAR(recoveryFactor) * diag_deltaTime; -}; - -private _newLevelBreathing = _levelBreathing + _breathChange; -_newLevelBreathing = _newLevelBreathing min 1; -_newLevelBreathing = _newLevelBreathing max 0; -_levelBreathing = _newLevelBreathing; - -if (_breathProtect != 0 && _breathProtect != 1) then { - _levelBreathing = _levelBreathing * (1 - _breathProtect); -}; +_levelBreathing = [_levelBreathing, _breathProtect] call _fnc_updateLevel; _unit setVariable [QGVAR(breathingLevel), _levelBreathing]; if !(isNil "ace_medical_vitals_fnc_addSpO2DutyFactor") then { diff --git a/addons/smoke/initSettings.inc.sqf b/addons/smoke/initSettings.inc.sqf index 9a6139689ef..5ca5a3be275 100644 --- a/addons/smoke/initSettings.inc.sqf +++ b/addons/smoke/initSettings.inc.sqf @@ -15,7 +15,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)]; if (GVAR(pfh) == -1) then { GVAR(pfh) = [{ [ace_player] call FUNC(pfh); - }, 0.2] call CBA_fnc_addPerFrameHandler; + }, PFH_INTERVAL] call CBA_fnc_addPerFrameHandler; }; } else { if (GVAR(pfh) != -1) then { @@ -30,7 +30,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)]; QGVAR(effectFactor), "SLIDER", [LSTRING(effectFactor_DisplayName), LSTRING(effectFactor_Description)], _category, - [0, 1, 0.5, 0.1], + [0, 1, 0.5, 0, true], 1, {[QGVAR(effectFactor), _this] call EFUNC(common,cbaSettings_settingChanged)}, true // Needs mission restart @@ -40,7 +40,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)]; QGVAR(recoveryFactor), "SLIDER", [LSTRING(recoveryFactor_DisplayName), LSTRING(recoveryFactor_Description)], _category, - [0, 1, 0.5, 0.1], + [0, 1, 0.5, 0, true], 1, {[QGVAR(recoveryFactor), _this] call EFUNC(common,cbaSettings_settingChanged)}, true // Needs mission restart diff --git a/addons/smoke/script_component.hpp b/addons/smoke/script_component.hpp index e9deb0896dd..1e984dacf00 100644 --- a/addons/smoke/script_component.hpp +++ b/addons/smoke/script_component.hpp @@ -15,3 +15,5 @@ #endif #include "\z\ace\addons\main\script_macros.hpp" + +#define PFH_INTERVAL 0.2 From 33001b15d2f8fa68858f34b73210e03f0afb0ee5 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Mon, 2 Feb 2026 02:36:26 -0600 Subject: [PATCH 20/23] improve vehicle logic --- addons/smoke/CfgVehicles.hpp | 47 ++++++++++++++++++++ addons/smoke/config.cpp | 1 + addons/smoke/functions/fnc_isOpenSeat.sqf | 29 ++++++++++-- addons/smoke/functions/fnc_isOpenVehicle.sqf | 8 ++-- 4 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 addons/smoke/CfgVehicles.hpp diff --git a/addons/smoke/CfgVehicles.hpp b/addons/smoke/CfgVehicles.hpp new file mode 100644 index 00000000000..7bbaf058fc3 --- /dev/null +++ b/addons/smoke/CfgVehicles.hpp @@ -0,0 +1,47 @@ +class CfgVehicles { + class Truck_01_base_F; + class B_Truck_01_transport_F: Truck_01_base_F { + ace_smoke_seats[] = { + {0}, // Driver is enclosed + {1, 1}, // Gunners are exposed + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + }; + }; + + class Heli_Transport_04_base_F; + class O_Heli_Transport_04_bench_F: Heli_Transport_04_base_F { + ace_smoke_seats[] = { + {0}, // Pilot is enclosed + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, // Crew is enclosed, passengers are exposed + }; + }; + + class Car_F; + class Offroad_01_base_F: Car_F { + ace_smoke_seats[] = {1}; // All seats are exposed + }; + class Hatchback_01_base_F: Car_F { + ace_smoke_seats[] = {1}; + }; + class SUV_01_base_F: Car_F { + ace_smoke_seats[] = {1}; + }; + class Van_01_base_F: Car_F { + ace_smoke_seats[] = {1}; + }; + class Van_02_base_F: Car_F { + ace_smoke_seats[] = {1}; + }; + class Tractor_01_base_F: Car_F { + ace_smoke_seats[] = {1}; + }; + + class Truck_02_base_F; + class C_Truck_02_covered_F: Truck_02_base_F { + ace_smoke_seats[] = { + {0}, // Driver is enclosed + {1, 1}, // Gunners are exposed + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + }; + }; +}; diff --git a/addons/smoke/config.cpp b/addons/smoke/config.cpp index c1c121c6fd7..bfe59b1f77e 100644 --- a/addons/smoke/config.cpp +++ b/addons/smoke/config.cpp @@ -14,4 +14,5 @@ class CfgPatches { #include "ACE_Arsenal_Stats.hpp" #include "CfgEventHandlers.hpp" #include "CfgGlasses.hpp" +#include "CfgVehicles.hpp" #include "CfgWeapons.hpp" diff --git a/addons/smoke/functions/fnc_isOpenSeat.sqf b/addons/smoke/functions/fnc_isOpenSeat.sqf index 4eabdd14812..c082b97af2b 100644 --- a/addons/smoke/functions/fnc_isOpenSeat.sqf +++ b/addons/smoke/functions/fnc_isOpenSeat.sqf @@ -23,18 +23,39 @@ params [ if (_vehicle isEqualTo objNull || _unit isEqualTo objNull) exitWith { true }; +if (isTurnedOut _unit) exitWith { true }; + private _class = typeOf _vehicle; -private _index = _vehicle getCargoIndex _unit; + +private _key = _vehicle unitTurret _unit; +if (count _key >= 1) then { + _key = [_key select 0]; +} else { + _key = [-2, _vehicle getCargoIndex _unit]; +}; private _open = -1; if (_class in GVAR(openSeatCache)) then { private _cache = GVAR(openSeatCache) get _class; - if (_index in _cache) then { - _open = _cache get _index; + if (_key in _cache) then { + _open = _cache get _key; }; }; if (_open isNotEqualTo -1) exitWith { _open }; +private _config = getArray (configOf _vehicle >> QGVAR(seats)); +if (_config isNotEqualTo []) exitWith { + if (typeName _config == "SCALAR") exitWith { _config == 1 }; + private _path = switch (_key select 0) do { + case -2: { [2, _key select 1] }; // cargo + case -1: { [0, 0] }; // driver + default { [1, _key select 0] }; // turret + }; + private _subConfig = _config select (_path select 0); + if (typeName _subConfig == "SCALAR") exitWith { _subConfig == 1 }; + _subConfig select (_path select 1) == 1 +}; + if ([_vehicle] call FUNC(isOpenVehicle)) exitWith { true }; private _eyePos = eyePos _unit; @@ -42,6 +63,6 @@ private _intersect = lineIntersectsSurfaces [_eyePos, _eyePos vectorAdd [0, 0, 1 private _open = _intersect isEqualTo []; private _cache = GVAR(openSeatCache) getOrDefaultCall [_class, { createHashMap }, true]; -_cache set [_index, _open]; +_cache set [_key, _open]; _open diff --git a/addons/smoke/functions/fnc_isOpenVehicle.sqf b/addons/smoke/functions/fnc_isOpenVehicle.sqf index 9b9516c26f8..4f214fec75c 100644 --- a/addons/smoke/functions/fnc_isOpenVehicle.sqf +++ b/addons/smoke/functions/fnc_isOpenVehicle.sqf @@ -25,10 +25,12 @@ private _class = typeOf _vehicle; if (_class in GVAR(openVehicleCache)) exitWith { GVAR(openVehicleCache) get _class }; -private _attentuation = getText(configFile >> "CfgVehicles" >> _class >> "attenuationEffectType"); -if (_attentuation == "") exitWith { true }; +private _attenuation = getText(configFile >> "CfgVehicles" >> _class >> "attenuationEffectType"); +if (_attenuation == "") exitWith { true }; +// It's marked as being open, but most helis are at least mostly enclosed +if (_attenuation == "HeliAttenuation") exitWith { false }; -private _attenuation = configFile >> "AttenuationEffects" >> _attentuation; +private _attenuation = configFile >> "AttenuationEffects" >> _attenuation; private _open = [0,1] findIf { private _equalizer = getArray(_attenuation >> format ["Equalizer%1", _x] >> "gain"); _equalizer isEqualTo [1,1,1,1] From 7399a22638cf26a49e565489db41e605497ab885 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Tue, 3 Feb 2026 07:31:16 -0600 Subject: [PATCH 21/23] change helicopter config --- addons/smoke/CfgVehicles.hpp | 20 ++++++++++++++++++++ addons/smoke/functions/fnc_isOpenSeat.sqf | 10 +++------- addons/smoke/functions/fnc_isOpenVehicle.sqf | 2 -- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/addons/smoke/CfgVehicles.hpp b/addons/smoke/CfgVehicles.hpp index 7bbaf058fc3..a19a9caa88b 100644 --- a/addons/smoke/CfgVehicles.hpp +++ b/addons/smoke/CfgVehicles.hpp @@ -16,6 +16,26 @@ class CfgVehicles { }; }; + class Heli_light_03_base_F; + class Heli_light_03_unarmed_base_F: Heli_light_03_base_F { + ace_smoke_seats[] = {0}; // All seats are enclosed + }; + + class Heli_Light_02_base_F; + class Heli_Light_02_dynamicLoadout_base_F: Heli_Light_02_base_F { + ace_smoke_seats[] = {0}; // All seats are enclosed + }; + + class Heli_Attack_01_base_F; + class Heli_Attack_01_dynamicLoadout_base_F: Heli_Attack_01_base_F { + ace_smoke_seats[] = {0}; // All seats are enclosed + }; + + class Helicopter_Base_H; + class Heli_Transport_02_base_F: Helicopter_Base_H { + ace_smoke_seats[] = {0}; // All seats are enclosed + }; + class Car_F; class Offroad_01_base_F: Car_F { ace_smoke_seats[] = {1}; // All seats are exposed diff --git a/addons/smoke/functions/fnc_isOpenSeat.sqf b/addons/smoke/functions/fnc_isOpenSeat.sqf index c082b97af2b..4ece98fb72c 100644 --- a/addons/smoke/functions/fnc_isOpenSeat.sqf +++ b/addons/smoke/functions/fnc_isOpenSeat.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: BrettMayson - * Check if a seat is open and thus susceptible to smoke entering, may not be accurate for vehicles with top coverings + * Check if a seat is open and thus susceptible to smoke entering * * Arguments: * 0: Vehicle @@ -58,11 +58,7 @@ if (_config isNotEqualTo []) exitWith { if ([_vehicle] call FUNC(isOpenVehicle)) exitWith { true }; -private _eyePos = eyePos _unit; -private _intersect = lineIntersectsSurfaces [_eyePos, _eyePos vectorAdd [0, 0, 1], _unit]; -private _open = _intersect isEqualTo []; - private _cache = GVAR(openSeatCache) getOrDefaultCall [_class, { createHashMap }, true]; -_cache set [_key, _open]; +_cache set [_key, true]; -_open +true diff --git a/addons/smoke/functions/fnc_isOpenVehicle.sqf b/addons/smoke/functions/fnc_isOpenVehicle.sqf index 4f214fec75c..5c8e1ca3e43 100644 --- a/addons/smoke/functions/fnc_isOpenVehicle.sqf +++ b/addons/smoke/functions/fnc_isOpenVehicle.sqf @@ -27,8 +27,6 @@ if (_class in GVAR(openVehicleCache)) exitWith { GVAR(openVehicleCache) get _cla private _attenuation = getText(configFile >> "CfgVehicles" >> _class >> "attenuationEffectType"); if (_attenuation == "") exitWith { true }; -// It's marked as being open, but most helis are at least mostly enclosed -if (_attenuation == "HeliAttenuation") exitWith { false }; private _attenuation = configFile >> "AttenuationEffects" >> _attenuation; private _open = [0,1] findIf { From 276a58407aa1eaff19c622965a9df014275edd4f Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Tue, 3 Feb 2026 07:35:56 -0600 Subject: [PATCH 22/23] add back sky check --- addons/smoke/functions/fnc_isOpenSeat.sqf | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/smoke/functions/fnc_isOpenSeat.sqf b/addons/smoke/functions/fnc_isOpenSeat.sqf index 4ece98fb72c..c082b97af2b 100644 --- a/addons/smoke/functions/fnc_isOpenSeat.sqf +++ b/addons/smoke/functions/fnc_isOpenSeat.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: BrettMayson - * Check if a seat is open and thus susceptible to smoke entering + * Check if a seat is open and thus susceptible to smoke entering, may not be accurate for vehicles with top coverings * * Arguments: * 0: Vehicle @@ -58,7 +58,11 @@ if (_config isNotEqualTo []) exitWith { if ([_vehicle] call FUNC(isOpenVehicle)) exitWith { true }; +private _eyePos = eyePos _unit; +private _intersect = lineIntersectsSurfaces [_eyePos, _eyePos vectorAdd [0, 0, 1], _unit]; +private _open = _intersect isEqualTo []; + private _cache = GVAR(openSeatCache) getOrDefaultCall [_class, { createHashMap }, true]; -_cache set [_key, true]; +_cache set [_key, _open]; -true +_open From 98feb6be5809c6755f7fdfc515be363a30990628 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Tue, 3 Feb 2026 17:13:33 -0600 Subject: [PATCH 23/23] Update addons/smoke/functions/fnc_isOpenSeat.sqf Co-authored-by: PabstMirror --- addons/smoke/functions/fnc_isOpenSeat.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/smoke/functions/fnc_isOpenSeat.sqf b/addons/smoke/functions/fnc_isOpenSeat.sqf index c082b97af2b..23ce4941775 100644 --- a/addons/smoke/functions/fnc_isOpenSeat.sqf +++ b/addons/smoke/functions/fnc_isOpenSeat.sqf @@ -60,7 +60,7 @@ if ([_vehicle] call FUNC(isOpenVehicle)) exitWith { true }; private _eyePos = eyePos _unit; private _intersect = lineIntersectsSurfaces [_eyePos, _eyePos vectorAdd [0, 0, 1], _unit]; -private _open = _intersect isEqualTo []; +private _open = (_intersect findIf { _x#2 == _vehicle }) == -1; // No intersection with vehicle roof private _cache = GVAR(openSeatCache) getOrDefaultCall [_class, { createHashMap }, true]; _cache set [_key, _open];