1
0
mirror of https://github.com/acemod/ACE3.git synced 2024-08-30 18:23:18 +00:00

Merge branch 'acemod:master' into Event-hanlder-replacement

This commit is contained in:
lambdatiger 2024-08-14 11:22:28 -05:00 committed by GitHub
commit 66fce29708
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
233 changed files with 4281 additions and 1210 deletions
addons
advanced_ballistics
arsenal
atragmx
attach/functions
captives
chemlights
common
compat_aegis
compat_cup_weapons
compat_cup_weapons_csw
compat_cup_weapons_explosives
compat_gm/compat_gm_explosives
compat_rhs_afrf3
compat_rhs_gref3/compat_rhs_gref3_explosives
compat_rhs_saf3/compat_rhs_saf3_explosives
compat_rhs_usf3
compat_sog
compat_spe/compat_spe_explosives
cookoff/functions
csw
explosives
fastroping
field_rations
hearing
hitreactions
interact_menu
interaction
irlight
kestrel4500
medical_ai
medical_damage

@ -24,22 +24,6 @@ if (!hasInterface) exitWith {};
// Register Perframe Handler
[LINKFUNC(handleFirePFH), GVAR(simulationInterval)] call CBA_fnc_addPerFrameHandler;
//Add warnings for missing compat PBOs (only if AB is on)
{
_x params ["_modPBO", "_compatPBO"];
if ([_modPBO] call EFUNC(common,isModLoaded) && {!([_compatPBO] call EFUNC(common,isModLoaded))}) then {
WARNING_2("Weapon Mod [%1] missing ace compat pbo [%2] (from @ace\optionals)",_modPBO,_compatPBO);
};
} forEach [
["RH_acc","ace_compat_rh_acc"],
["RH_de_cfg","ace_compat_rh_de"],
["RH_m4_cfg","ace_compat_rh_m4"],
["RH_PDW","ace_compat_rh_pdw"],
["RKSL_PMII","ace_compat_rksl_pm_ii"],
["iansky_opt","ace_compat_sma3_iansky"],
["R3F_Armes","ace_compat_r3f"]
];
}] call CBA_fnc_addEventHandler;
#ifdef DEBUG_MODE_FULL

@ -5,7 +5,9 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)];
[LSTRING(enabled_DisplayName), LSTRING(enabled_Description)],
_category,
false,
1
1,
{[QGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_fnc_addSetting;
[
@ -45,5 +47,7 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)];
[LSTRING(simulationInterval_DisplayName), LSTRING(simulationInterval_Description)],
_category,
[0, 0.2, 0.05, 2],
1
1,
{[QGVAR(simulationInterval), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_fnc_addSetting;

@ -78,6 +78,7 @@ PREP(removeStat);
PREP(removeVirtualItems);
PREP(renameDefaultLoadout);
PREP(replaceUniqueItemsLoadout);
PREP(saveLoadout);
PREP(scanConfig);
PREP(showItem);
PREP(sortPanel);

@ -0,0 +1,37 @@
#include "..\script_component.hpp"
/*
* Author: DartRuffian
* Saves a given loadout to the client's profile.
*
* Arguments:
* 0: Name of loadout <STRING>
* 1: CBA extended loadout or getUnitLoadout array <ARRAY>
* 2: Replace existing loadout <BOOL> (default: false)
*
* Return Value:
* True if loadout was saved, otherwise false <BOOL>
*
* Example:
* ["Current Loadout", getUnitLoadout ACE_player] call ace_arsenal_fnc_saveLoadout
*
* Public: Yes
*/
params [["_name", "", [""]], ["_loadout", [], [[]]], ["_replaceExisting", false, [false]]];
if (_name == "" || {_loadout isEqualTo []}) exitWith { false };
private _loadouts = profileNamespace getVariable [QGVAR(saved_loadouts), []];
private _loadoutIndex = _loadouts findIf {(_x#0) == _name};
// If a loadout with same name already exists and no overwriting enabled, quit
if (!_replaceExisting && {_loadoutIndex != -1}) exitWith { false };
if (_loadoutIndex == -1) then {
_loadouts pushBack [_name, _loadout];
} else {
_loadouts set [_loadoutIndex, [_name, _loadout]];
};
profileNamespace setVariable [QGVAR(saved_loadouts), _loadouts];
true

@ -6,7 +6,7 @@ class CfgPatches {
units[] = {"ACE_Item_ATragMX"};
weapons[] = {"ACE_ATragMX"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ACE_Advanced_Ballistics", "ACE_common", "ACE_weather"};
requiredAddons[] = {"ace_advanced_ballistics", "ace_common", "ace_weather"};
author = ECSTRING(common,ACETeam);
authors[] = {"Ruthberg"};
url = ECSTRING(main,URL);

@ -50,8 +50,8 @@ if (_unit == _attachToVehicle) then { //Self Attachment
} else {
GVAR(placeAction) = PLACE_WAITING;
[_unit, "forceWalk", "ACE_Attach", true] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", "ACE_Attach", true] call EFUNC(common,statusEffect_set);
[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
[{[localize LSTRING(PlaceAction), ""] call EFUNC(interaction,showMouseHint)}, []] call CBA_fnc_execNextFrame;
_unit setVariable [QGVAR(placeActionEH), [_unit, "DefaultAction", {true}, {GVAR(placeAction) = PLACE_APPROVE;}] call EFUNC(common,AddActionEventHandler)];
@ -88,8 +88,8 @@ if (_unit == _attachToVehicle) then { //Self Attachment
{!([_attachToVehicle, _unit, _itemClassname] call FUNC(canAttach))}) then {
[_idPFH] call CBA_fnc_removePerFrameHandler;
[_unit, "forceWalk", "ACE_Attach", false] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", "ACE_Attach", false] call EFUNC(common,statusEffect_set);
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
[] call EFUNC(interaction,hideMouseHint);
[_unit, "DefaultAction", (_unit getVariable [QGVAR(placeActionEH), -1])] call EFUNC(common,removeActionEventHandler);
_unit removeAction _actionID;

@ -40,12 +40,12 @@ if (_respawn > 3) then {
if (_unit getVariable [QGVAR(isHandcuffed), false]) then {
[_unit, false] call FUNC(setHandcuffed);
};
[_unit, "setCaptive", QGVAR(Handcuffed), false] call EFUNC(common,statusEffect_set);
[_unit, "setCaptive", QGVAR(handcuffed), false] call EFUNC(common,statusEffect_set);
if (_unit getVariable [QGVAR(isSurrendering), false]) then {
[_unit, false] call FUNC(setSurrendered);
};
[_unit, "setCaptive", QGVAR(Surrendered), false] call EFUNC(common,statusEffect_set);
[_unit, "setCaptive", QGVAR(surrendered), false] call EFUNC(common,statusEffect_set);
if (_unit getVariable [QGVAR(isEscorting), false]) then {
_unit setVariable [QGVAR(isEscorting), false, true];

@ -41,8 +41,8 @@ if ((_unit getVariable [QGVAR(isHandcuffed), false]) isEqualTo _state) exitWith
if (_state) then {
_unit setVariable [QGVAR(isHandcuffed), true, true];
[_unit, "setCaptive", QGVAR(Handcuffed), true] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(Handcuffed), true] call EFUNC(common,statusEffect_set);
[_unit, "setCaptive", QGVAR(handcuffed), true] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(handcuffed), true] call EFUNC(common,statusEffect_set);
if (_unit getVariable [QGVAR(isSurrendering), false]) then { //If surrendering, stop
[_unit, false] call FUNC(setSurrendered);
@ -82,8 +82,8 @@ if (_state) then {
}, [_unit], 0.01] call CBA_fnc_waitAndExecute;
} else {
_unit setVariable [QGVAR(isHandcuffed), false, true];
[_unit, "setCaptive", QGVAR(Handcuffed), false] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(Handcuffed), false] call EFUNC(common,statusEffect_set);
[_unit, "setCaptive", QGVAR(handcuffed), false] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(handcuffed), false] call EFUNC(common,statusEffect_set);
//remove AnimChanged EH
private _animChangedEHID = _unit getVariable [QGVAR(handcuffAnimEHID), -1];

@ -44,8 +44,8 @@ if (_state) then {
_unit setVariable [QGVAR(isSurrendering), true, true];
[_unit, "setCaptive", QGVAR(Surrendered), true] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(Surrendered), true] call EFUNC(common,statusEffect_set);
[_unit, "setCaptive", QGVAR(surrendered), true] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(surrendered), true] call EFUNC(common,statusEffect_set);
if (_unit == ACE_player) then {
["captive", [false, false, false, false, false, false, false, false, false, true]] call EFUNC(common,showHud);
@ -71,8 +71,8 @@ if (_state) then {
}, [_unit], 0.01] call CBA_fnc_waitAndExecute;
} else {
_unit setVariable [QGVAR(isSurrendering), false, true];
[_unit, "setCaptive", QGVAR(Surrendered), false] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(Surrendered), false] call EFUNC(common,statusEffect_set);
[_unit, "setCaptive", QGVAR(surrendered), false] call EFUNC(common,statusEffect_set);
[_unit, "blockRadio", QGVAR(surrendered), false] call EFUNC(common,statusEffect_set);
//remove AnimChanged EH
private _animChangedEHID = _unit getVariable [QGVAR(surrenderAnimEHID), -1];

@ -158,6 +158,7 @@
<Japanese>目隠しを外す</Japanese>
<Russian>Снять повязку с глаз</Russian>
<Spanish>Quitar vendas de los ojos</Spanish>
<Portuguese>Remover a venda</Portuguese>
</Key>
<Key ID="STR_ACE_Captives_CableTie">
<English>Cable Tie</English>

@ -3,6 +3,7 @@
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {"ACE_Box_Chemlights","ACE_Item_Chemlight_Shield","ACE_Item_Chemlight_Shield_Green","ACE_Item_Chemlight_Shield_Red","ACE_Item_Chemlight_Shield_Blue","ACE_Item_Chemlight_Shield_Yellow","ACE_Item_Chemlight_Shield_Orange","ACE_Item_Chemlight_Shield_White","ModuleChemlightOrange","ModuleChemlightWhite","ModuleChemlightHiRed","ModuleChemlightHiYellow","ModuleChemlightHiWhite","ModuleChemlightHiBlue","ModuleChemlightHiGreen","ModuleChemlightUltraHiOrange"};
weapons[] = {"ACE_Chemlight_Shield", "ACE_Chemlight_Shield_Green","ACE_Chemlight_Shield_Red","ACE_Chemlight_Shield_Blue","ACE_Chemlight_Shield_Yellow","ACE_Chemlight_Shield_Orange","ACE_Chemlight_Shield_White"};
requiredVersion = REQUIRED_VERSION;

@ -1,4 +1,5 @@
#define COMPONENT chemlights
#define COMPONENT_BEAUTIFIED Chemlights
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL

@ -178,6 +178,7 @@ PREP(setupLocalUnitsHandler);
PREP(setVariableJIP);
PREP(setVariablePublic);
PREP(setVolume);
PREP(setWeaponLightLaserState);
PREP(showHud);
PREP(statusEffect_addType);
PREP(statusEffect_get);

@ -19,16 +19,16 @@
//Status Effect EHs:
[QGVAR(setStatusEffect), LINKFUNC(statusEffect_set)] call CBA_fnc_addEventHandler;
["forceWalk", false, ["ace_advanced_fatigue", "ACE_SwitchUnits", "ACE_Attach", "ace_dragging", "ACE_Explosives", "ACE_Ladder", "ACE_Sandbag", "ACE_refuel", "ACE_rearm", "ACE_Trenches", "ace_medical_fracture"]] call FUNC(statusEffect_addType);
["blockSprint", false, ["ace_advanced_fatigue", "ace_dragging", "ace_medical_fracture"]] call FUNC(statusEffect_addType);
["setCaptive", true, [QEGVAR(captives,Handcuffed), QEGVAR(captives,Surrendered)]] call FUNC(statusEffect_addType);
["blockDamage", false, ["fixCollision", "ACE_cargo"]] call FUNC(statusEffect_addType);
["blockEngine", false, ["ACE_Refuel"]] call FUNC(statusEffect_addType);
["blockThrow", false, ["ACE_Attach", "ACE_concertina_wire", "ace_dragging", "ACE_Explosives", "ACE_Ladder", "ACE_rearm", "ACE_refuel", "ACE_Sandbag", "ACE_Trenches", "ACE_tripod"]] call FUNC(statusEffect_addType);
["forceWalk", false, ["ace_advanced_fatigue", "ace_attach", "ace_dragging", "ace_explosives", QEGVAR(medical,fracture), "ace_rearm", "ace_refuel", "ace_sandbag", "ace_switchunits", "ace_tacticalladder", "ace_trenches"]] call FUNC(statusEffect_addType);
["blockSprint", false, ["ace_advanced_fatigue", "ace_dragging", QEGVAR(medical,fracture)]] call FUNC(statusEffect_addType);
["setCaptive", true, [QEGVAR(captives,handcuffed), QEGVAR(captives,surrendered)]] call FUNC(statusEffect_addType);
["blockDamage", false, ["fixCollision", "ace_cargo"]] call FUNC(statusEffect_addType);
["blockEngine", false, ["ace_refuel"]] call FUNC(statusEffect_addType);
["blockThrow", false, ["ace_attach", "ace_concertina_wire", "ace_dragging", "ace_explosives", "ace_rearm", "ace_refuel", "ace_sandbag", "ace_tacticalladder", "ace_trenches", "ace_tripod"]] call FUNC(statusEffect_addType);
["setHidden", true, ["ace_unconscious"]] call FUNC(statusEffect_addType);
["blockRadio", false, [QEGVAR(captives,Handcuffed), QEGVAR(captives,Surrendered), "ace_unconscious"]] call FUNC(statusEffect_addType);
["blockRadio", false, [QEGVAR(captives,handcuffed), QEGVAR(captives,surrendered), "ace_unconscious"]] call FUNC(statusEffect_addType);
["blockSpeaking", false, ["ace_unconscious"]] call FUNC(statusEffect_addType);
["disableWeaponAssembly", false, ["ace_common", "ace_common_lockVehicle", "ace_csw"]] call FUNC(statusEffect_addType);
["disableWeaponAssembly", false, ["ace_common", QGVAR(lockVehicle), "ace_csw"]] call FUNC(statusEffect_addType);
["lockInventory", true, [], true] call FUNC(statusEffect_addType);
[QGVAR(forceWalk), {
@ -216,6 +216,7 @@ if (isServer) then {
[QGVAR(setVectorDirAndUp), {(_this select 0) setVectorDirAndUp (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(addWeaponItem), {(_this select 0) addWeaponItem [(_this select 1), (_this select 2)]}] call CBA_fnc_addEventHandler;
[QGVAR(removeMagazinesTurret), {(_this select 0) removeMagazinesTurret [_this select 1, _this select 2]}] call CBA_fnc_addEventHandler;
[QGVAR(triggerAmmo), {triggerAmmo _this}] call CBA_fnc_addEventHandler;
[QGVAR(setVanillaHitPointDamage), {
params ["_object", "_hitPointAnddamage"];

@ -12,6 +12,8 @@ GVAR(showHudHash) = createHashMap;
GVAR(vehicleIconCache) = createHashMap; // for getVehicleIcon
GVAR(wheelSelections) = createHashMap;
GVAR(InteractionConditions) = createHashMap;
GVAR(blockItemReplacement) = false;
// Cache for FUNC(isModLoaded)

@ -15,3 +15,25 @@ uiNamespace setVariable [QGVAR(addonCache), createHashMap];
// Cache for FUNC(getConfigName)
uiNamespace setVariable [QGVAR(configNames), createHashMap];
//Add warnings for missing compat PBOs
GVAR(isModLoadedCache) = createHashMap;
{
_x params ["_modPBO", "_compatPBO"];
if ([_modPBO] call FUNC(isModLoaded) && {!([_compatPBO] call FUNC(isModLoaded))}) then {
WARNING_2("Weapon Mod [%1] missing ace compat pbo [%2]",_modPBO,_compatPBO);
};
} forEach [
["CUP_Creatures_People_LoadOrder","ace_compat_cup_units"],
["CUP_Vehicles_LoadOrder","ace_compat_cup_vehicles"],
["CUP_Weapons_LoadOrder","ace_compat_cup_weapons"],
["r3f_armes_c","ace_compat_r3f"],
["RF_Data_Loadorder","ace_compat_rf"],
["RH_acc","ace_compat_rh_acc"],
["RH_de_cfg","ace_compat_rh_de"],
["RH_m4_cfg","ace_compat_rh_m4"],
["RH_PDW","ace_compat_rh_pdw"],
["RKSL_PMII","ace_compat_rksl_pm_ii"],
["iansky_opt","ace_compat_sma3_iansky"],
["R3F_Armes","ace_compat_r3f"]
];

@ -19,17 +19,4 @@
params ["_conditionName", "_conditionFunc"];
_conditionName = toLowerANSI _conditionName;
private _conditions = missionNamespace getVariable [QGVAR(InteractionConditions), [[],[]]];
_conditions params ["_conditionNames", "_conditionFuncs"];
private _index = _conditionNames find _conditionName;
if (_index == -1) then {
_index = count _conditionNames;
};
_conditionNames set [_index, _conditionName];
_conditionFuncs set [_index, _conditionFunc];
GVAR(InteractionConditions) = _conditions;
GVAR(InteractionConditions) set [_conditionName, _conditionFunc];

@ -27,15 +27,11 @@ private _owner = _target getVariable [QGVAR(owner), objNull];
if (!isNull _owner && {_unit != _owner}) exitWith {false};
// check general conditions
private _conditions = missionNamespace getVariable [QGVAR(InteractionConditions), [[],[]]];
_conditions params ["_conditionNames", "_conditionFuncs"];
private _canInteract = true;
{
if (!(_x in _exceptions) && {!([_unit, _target] call (_conditionFuncs select _forEachIndex))}) exitWith {
if (!(_x in _exceptions) && {!([_unit, _target] call _y)}) exitWith {
_canInteract = false;
};
} forEach _conditionNames;
} forEach GVAR(InteractionConditions);
_canInteract

@ -1,6 +1,6 @@
#include "..\script_component.hpp"
/*
* Author: commy2
* Author: commy2, johnb43
* Get the muzzles of a weapon.
*
* Arguments:
@ -10,19 +10,30 @@
* All weapon muzzles <ARRAY>
*
* Example:
* ["gun"] call ace_common_fnc_getWeaponMuzzles
* "arifle_AK12_F" call ace_common_fnc_getWeaponMuzzles
*
* Public: Yes
*/
params [["_weapon", "", [""]]];
private _muzzles = getArray (configFile >> "CfgWeapons" >> _weapon >> "muzzles");
private _config = configFile >> "CfgWeapons" >> _weapon;
if (!isClass _config) exitWith {
[] // return
};
private _muzzles = [];
// Get config case muzzle names
{
if (_x == "this") then {
_muzzles set [_forEachIndex, configName (configFile >> "CfgWeapons" >> _weapon)];
_muzzles pushBack (configName _config);
} else {
if (isClass (_config >> _x)) then {
_muzzles pushBack (configName (_config >> _x));
};
};
} forEach _muzzles;
} forEach getArray (_config >> "muzzles");
_muzzles
_muzzles // return

@ -18,16 +18,4 @@
params ["_conditionName"];
_conditionName = toLowerANSI _conditionName;
private _conditions = missionNamespace getVariable [QGVAR(InteractionConditions), [[],[]]];
_conditions params ["_conditionNames", "_conditionFuncs"];
private _index = _conditionNames find _conditionName;
if (_index == -1) exitWith {};
_conditionNames deleteAt _index;
_conditionFuncs deleteAt _index;
GVAR(InteractionConditions) = _conditions;
GVAR(InteractionConditions) deleteAt _conditionName;

@ -0,0 +1,59 @@
#include "..\script_component.hpp"
/*
* Author: johnb43
* Toggles the unit's current weapon's light & laser.
* API for persistent lasers. Doesn't work on AI, as they have their own logic.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Weapon light/laser state <BOOL> (default: false)
*
* Return Value:
* None
*
* Example:
* [player, true] call ace_common_fnc_setWeaponLightLaserState
*
* Public: Yes
*/
params [["_unit", objNull, [objNull]], ["_state", false, [false]]];
if (!local _unit || {!alive _unit} || {!(_unit call FUNC(isPlayer))}) exitWith {};
if !(_unit call CBA_fnc_canUseWeapon) exitWith {};
private _currentWeapon = currentWeapon _unit;
// Exit if unit has no weapon selected
if (_currentWeapon == "") exitWith {};
private _weaponIndex = [_unit, _currentWeapon] call FUNC(getWeaponIndex);
// Ignore binoculars
if (_weaponIndex == -1) exitWith {};
_unit setVariable [QGVAR(laserEnabled_) + str _weaponIndex, _state];
// Turn off light/laser (switching between weapons can leave previous weapon laser on)
action ["GunLightOff", _unit];
action ["IRLaserOff", _unit];
// Light/laser is off, don't need to do anything more
if (!_state) exitWith {};
// Turn laser on next frame (if weapon hasn't changed)
[{
params ["_unit", "_currentWeapon"];
private _weaponState = (weaponState _unit) select [0, 3];
if (_weaponState select 0 != _currentWeapon) exitWith {};
action ["GunLightOn", _unit];
action ["IRLaserOn", _unit];
_unit selectWeapon _weaponState;
}, [_unit, _currentWeapon]] call CBA_fnc_execNextFrame;
nil

@ -2,26 +2,31 @@
/*
* Author: PabstMirror
* Switch attachment from one mode to another - based on CBA_accessory_fnc_switchAttachment
* ToDo: Port this to CBA?
*
* Arguments:
* 0: Unit <OBJECT>
* 1: From <STRING>
* 2: To <STRING>
* 1: Weapon (String or CBA-Weapon-Index (not ace's getWeaponIndex)) <STRING|NUMBER>
* 2: From <STRING>
* 3: To <STRING>
*
* Return Value:
* None
*
* Example:
* [player, "ACE_DBAL_A3_Green_VP", "ACE_DBAL_A3_Green"] call ace_common_fnc_switchAttachmentMode
* [player, 0, "ACE_DBAL_A3_Green_VP", "ACE_DBAL_A3_Green"] call ace_common_fnc_switchAttachmentMode
*
* Public: No
*/
params ["_unit", "_currItem", "_switchItem"];
TRACE_3("switchAttachmentMode",_unit,_currItem,_switchItem);
switch (currentWeapon _unit) do {
case (""): {};
params ["_unit", "_weapon", "_currItem", "_switchItem"];
TRACE_4("switchAttachmentMode",_unit,_weapon,_currItem,_switchItem);
if (_weapon isEqualTo "") exitWith {};
private _exit = _unit != ACE_player;
switch (_weapon) do {
case 0;
case (primaryWeapon _unit): {
private _currWeaponType = 0;
_unit removePrimaryWeaponItem _currItem;
@ -31,6 +36,7 @@ switch (currentWeapon _unit) do {
["CBA_attachmentSwitched", _this] call CBA_fnc_localEvent;
}, [_unit, _currItem, _switchItem, _currWeaponType]] call CBA_fnc_execNextFrame;
};
case 1;
case (handgunWeapon _unit): {
private _currWeaponType = 1;
_unit removeHandgunItem _currItem;
@ -40,6 +46,7 @@ switch (currentWeapon _unit) do {
["CBA_attachmentSwitched", _this] call CBA_fnc_localEvent;
}, [_unit, _currItem, _switchItem, _currWeaponType]] call CBA_fnc_execNextFrame;
};
case 2;
case (secondaryWeapon _unit): {
private _currWeaponType = 2;
_unit removeSecondaryWeaponItem _currItem;
@ -49,13 +56,18 @@ switch (currentWeapon _unit) do {
["CBA_attachmentSwitched", _this] call CBA_fnc_localEvent;
}, [_unit, _currItem, _switchItem, _currWeaponType]] call CBA_fnc_execNextFrame;
};
default {
ERROR_1("bad weapon - %1",_this);
_exit = true;
};
};
if (_exit) exitWith {}; // Don't notify if the unit isn't the local player or if an invalid weapon was passed
private _configSwitchItem = configfile >> "CfgWeapons" >> _switchItem;
private _switchItemHintText = getText (_configSwitchItem >> "MRT_SwitchItemHintText");
private _switchItemHintImage = getText (_configSwitchItem >> "picture");
if (_switchItemHintText isNotEqualTo "") then {
playSound "click";
if (_switchItemHintText != "") then {
[[_switchItemHintImage, 2.0], [_switchItemHintText], true] call CBA_fnc_notify;
};
if (_unit == ACE_player) then {
playSound "click";
};

@ -1,6 +1,6 @@
#include "..\script_component.hpp"
/*
* Author: Dystopian
* Author: Dystopian, johnb43
* Controls persistent laser state.
*
* Arguments:
@ -17,51 +17,87 @@
params ["_enabled"];
if (!hasInterface) exitwith {};
// Reset state
{
ACE_player setVariable [QGVAR(laserEnabled_) + str _x, nil];
} forEach [0, 1, 2];
if (!_enabled) exitWith {
if (isNil QGVAR(laserKeyDownEH)) exitWith {};
["KeyDown", GVAR(laserKeyDownEH)] call CBA_fnc_removeDisplayHandler;
removeUserActionEventHandler ["headlights", "Activate", GVAR(laserKeyDownEH)];
["loadout", GVAR(laserLoadoutEH)] call CBA_fnc_removePlayerEventHandler;
["turret", GVAR(laserTurretEH)] call CBA_fnc_removePlayerEventHandler;
["vehicle", GVAR(laserVehicleEH)] call CBA_fnc_removePlayerEventHandler;
["weapon", GVAR(laserWeaponEH)] call CBA_fnc_removePlayerEventHandler;
GVAR(laserKeyDownEH) = nil;
GVAR(laserLoadoutEH) = nil;
GVAR(laserTurretEH) = nil;
GVAR(laserVehicleEH) = nil;
GVAR(laserWeaponEH) = nil;
};
GVAR(laserKeyDownEH) = ["KeyDown", {
if !((_this select 1) in actionKeys "headlights") exitWith {false};
private _weapon = currentWeapon ACE_player;
[
{
params ["_weapon", "_laserWasEnabled"];
private _laserEnabled = ACE_player isIRLaserOn _weapon || {ACE_player isFlashlightOn _weapon};
if (_laserEnabled && {_laserWasEnabled} || {!_laserEnabled && {!_laserWasEnabled}}) exitWith {};
private _weaponIndex = [ACE_player, _weapon] call FUNC(getWeaponIndex);
ACE_player setVariable [QGVAR(laserEnabled_) + str _weaponIndex, [nil, true] select _laserEnabled];
},
[_weapon, ACE_player isIRLaserOn _weapon || {ACE_player isFlashlightOn _weapon}]
] call CBA_fnc_execNextFrame;
false
}] call CBA_fnc_addDisplayHandler;
private _fnc_getLightLaserState = {
private _currentWeapon = currentWeapon ACE_player;
private _laserEH = {
if (sunOrMoon == 1) exitWith {};
params ["_player"];
private _weaponIndex = [_player, currentWeapon _player] call FUNC(getWeaponIndex);
if (
!(_player getVariable [QGVAR(laserEnabled_) + str _weaponIndex, false])
|| {_weaponIndex > 0 && {"" != primaryWeapon _player}} // Arma switches to primary weapon if exists
|| {!(_player call CBA_fnc_canUseWeapon)} // ignore in vehicle except FFV
) exitWith {};
[
// wait for weapon in "ready to fire" direction
{0.01 > getCameraViewDirection _this vectorDistance (_this weaponDirection currentWeapon _this)},
{{_this action [_x, _this]} forEach ["GunLightOn", "IRLaserOn"]},
_player,
3,
{{_this action [_x, _this]} forEach ["GunLightOn", "IRLaserOn"]}
] call CBA_fnc_waitUntilAndExecute;
if (_currentWeapon == "") exitWith {};
// Ignore in vehicle except FFV
if !(ACE_player call CBA_fnc_canUseWeapon) exitWith {};
private _weaponIndex = [ACE_player, _currentWeapon] call FUNC(getWeaponIndex);
if (_weaponIndex == -1) exitWith {};
// Light/laser state only changes in the next frame
// However, as by default changing attachment modes is CTRL + L, the vanilla EH triggers when lights are bound to L (even despite CBA intercepting keystroke)
// Therefore, add an extra frame of delay, after which the previous laser state will have been restored
[{
ACE_player setVariable [
QGVAR(laserEnabled_) + str (_this select 1),
ACE_player isIRLaserOn (_this select 0) || {ACE_player isFlashlightOn (_this select 0)}
];
}, [_currentWeapon, _weaponIndex], 2] call CBA_fnc_execAfterNFrames;
};
GVAR(laserLoadoutEH) = ["loadout", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserTurretEH) = ["turret", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserVehicleEH) = ["vehicle", _laserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserWeaponEH) = ["weapon", _laserEH] call CBA_fnc_addPlayerEventHandler;
// Get current weapon light/laser state
call _fnc_getLightLaserState;
// Update state every time it's changed
GVAR(laserKeyDownEH) = addUserActionEventHandler ["headlights", "Activate", _fnc_getLightLaserState];
// Dropping weapons, as well as switching light/laser attachments turns off lights/lasers
GVAR(lastWeapons) = (getUnitLoadout ACE_player) select [0, 3];
// Monitor weapon addition/removal here
GVAR(laserLoadoutEH) = ["loadout", {
params ["_unit", "_loadout"];
private _weapons = _loadout select [0, 3];
if (_weapons isEqualTo GVAR(lastWeapons)) exitWith {};
GVAR(lastWeapons) = _weapons;
[
_unit,
_unit getVariable [QGVAR(laserEnabled_) + str ([_unit, currentWeapon _unit] call FUNC(getWeaponIndex)), false]
] call FUNC(setWeaponLightLaserState);
}] call CBA_fnc_addPlayerEventHandler;
private _fnc_switchPersistentLaserEH = {
params ["_unit"];
[
_unit,
_unit getVariable [QGVAR(laserEnabled_) + str ([_unit, currentWeapon _unit] call FUNC(getWeaponIndex)), false]
] call FUNC(setWeaponLightLaserState);
};
GVAR(laserTurretEH) = ["turret", _fnc_switchPersistentLaserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserVehicleEH) = ["vehicle", _fnc_switchPersistentLaserEH] call CBA_fnc_addPlayerEventHandler;
GVAR(laserWeaponEH) = ["weapon", _fnc_switchPersistentLaserEH] call CBA_fnc_addPlayerEventHandler;

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

@ -0,0 +1,82 @@
class CfgVehicles {
class Tank;
class Tank_F: Tank {
class Turrets {
class MainTurret;
};
};
class MBT_01_base_F: Tank_F {
class Turrets: Turrets {
class MainTurret: MainTurret {
// Overwrite the changes Aegis makes for the .338 coax MG on the Slammer/Merkava
// The idea is:
// 1) keep it as realistic as possible
// 2) easier to overwrite something with skipWhenMissingDependencies than to not overwrite something if another mod is loaded
weapons[] = {"cannon_120mm", "ACE_LMG_coax_MAG58_mem3"}; // Base 1.82: "cannon_120mm","LMG_coax"
magazines[] = {
"24Rnd_120mm_APFSDS_shells_Tracer_Red",
"12Rnd_120mm_HE_shells_Tracer_Red",
"12Rnd_120mm_HEAT_MP_T_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"4Rnd_120mm_LG_cannon_missiles" // Aegis adds laser-guided munitions
};
};
};
};
class B_MBT_01_base_F: MBT_01_base_F {};
class B_MBT_01_cannon_F: B_MBT_01_base_F {};
class B_MBT_01_TUSK_F: B_MBT_01_cannon_F {
class Turrets: Turrets {
class MainTurret: MainTurret {
weapons[] = {"cannon_120mm", "ACE_LMG_coax_MAG58_mem3"}; // Base 1.82: "cannon_120mm","LMG_coax"
magazines[] = {
"24Rnd_120mm_APFSDS_shells_Tracer_Red",
"12Rnd_120mm_HE_shells_Tracer_Red",
"12Rnd_120mm_HEAT_MP_T_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"200Rnd_762x51_Belt_Red",
"4Rnd_120mm_LG_cannon_missiles" // Aegis adds laser-guided munitions
};
};
};
};
};

@ -0,0 +1,18 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_vehicles", "A3_Aegis_Armor_F_Aegis_MBT_01"};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgVehicles.hpp"

@ -0,0 +1,5 @@
#define COMPONENT compat_aegis
#define COMPONENT_BEAUTIFIED Aegis Compatibility
#include "\z\ace\addons\main\script_mod.hpp"
#include "\z\ace\addons\main\script_macros.hpp"

@ -65,7 +65,7 @@ class CfgVehicles {
class ace_csw {
enabled = 1;
proxyWeapon = "CUP_proxy_DSHKM";
magazineLocation = "_target selectionPosition 'magazine'";
magazineLocation = "_target selectionPosition 'otocvez'";
disassembleWeapon = "CUP_DSHKM_carry";
disassembleTurret = "ace_csw_kordTripod";
desiredAmmo = 100;
@ -119,7 +119,7 @@ class CfgVehicles {
class ace_csw {
enabled = 1;
proxyWeapon = "CUP_proxy_MK19";
magazineLocation = "_target selectionPosition 'magazine'";
magazineLocation = "_target selectionPosition 'otochlaven'";
disassembleWeapon = "CUP_MK19_carry";
disassembleTurret = "ace_csw_m3TripodLow";
desiredAmmo = 48;
@ -165,7 +165,7 @@ class CfgVehicles {
class ace_csw {
enabled = 1;
proxyWeapon = "CUP_proxy_SPG9";
magazineLocation = "_target selectionPosition 'otochlaven'";
magazineLocation = "_target selectionPosition 'handle'";
disassembleWeapon = "CUP_SPG9_carry";
disassembleTurret = "ace_csw_spg9Tripod";
desiredAmmo = 1;

@ -9,6 +9,7 @@
<German>[CSW] AGS30 Gurt</German>
<Spanish>[CSW] Cinta de AGS30</Spanish>
<Italian>[CSW] Nastro AGS30</Italian>
<Portuguese>[CSW] Cinto de AGS30</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_MK19_displayName">
<English>[CSW] MK19 Belt</English>
@ -18,6 +19,7 @@
<German>[CSW] MK19 Gurt</German>
<Spanish>[CSW] Cinta de MK19</Spanish>
<Italian>[CSW] Nastro MK19</Italian>
<Portuguese>[CSW] Cinto de MK19</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_TOW_displayName">
<English>[CSW] TOW Tube</English>
@ -27,6 +29,7 @@
<German>[CSW] TOW Rohr</German>
<Spanish>[CSW] Tubo de TOW</Spanish>
<Italian>[CSW] Tubo TOW</Italian>
<Portuguese>[CSW] Tubo de TOW</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_TOW2_displayName">
<English>[CSW] TOW2 Tube</English>
@ -36,6 +39,7 @@
<German>[CSW] TOW2 Rohr</German>
<Spanish>[CSW] Tubo de TOW2</Spanish>
<Italian>[CSW] Tubo TOW2</Italian>
<Portuguese>[CSW] Tubo de TOW2</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_PG9_displayName">
<English>[CSW] PG-9 Round</English>
@ -45,6 +49,7 @@
<German>[CSW] PG-9 Rakete</German>
<Spanish>[CSW] Carga de PG-9</Spanish>
<Italian>[CSW] Razzo PG-9</Italian>
<Portuguese>[CSW] Cartucho PG-9</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_OG9_displayName">
<English>[CSW] OG-9 Round</English>
@ -54,6 +59,7 @@
<German>[CSW] OG-9 Rakete</German>
<Spanish>[CSW] Carga de OG-9</Spanish>
<Italian>[CSW] Razzo OG-9</Italian>
<Portuguese>[CSW] Cartucho OG-9</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_M1HE_displayName">
<English>[CSW] M1 HE</English>
@ -74,6 +80,7 @@
<German>[CSW] M84 Rauch</German>
<Spanish>[CSW] Humo M84</Spanish>
<Italian>[CSW] M84 Fumogeno</Italian>
<Portuguese>[CSW] M84 Fumígeno</Portuguese>
</Key>
<Key ID="STR_ACE_Compat_CUP_Weapons_CSW_mag_M60A2_displayName">
<English>[CSW] M60A2 WP</English>

@ -4,18 +4,18 @@ class CfgAmmo {
hit = 3000;
indirectHit = 3000;
indirectHitRange = 5;
ace_explosives_explodeOnDefuse = 0.02;
EGVAR(explosives,explodeOnDefuse) = 0.02;
};
class CUP_PipeBomb_Ammo: PipeBombBase {
hit = 3000;
indirectHit = 3000;
indirectHitRange = 5;
ace_explosives_explodeOnDefuse = 0.02;
EGVAR(explosives,explodeOnDefuse) = 0.02;
};
class CUP_Mine_Ammo;
class CUP_IED_V1_Ammo: CUP_Mine_Ammo {
ace_explosives_explodeOnDefuse = 0.06;
EGVAR(explosives,explodeOnDefuse) = 0.06;
triggerWhenDestroyed = 1;
};
};

@ -2,9 +2,9 @@ class CfgMagazines {
class CA_Magazine;
class CUP_TimeBomb_M: CA_Magazine {
scope = 1;
ace_explosives_placeable = 1;
EGVAR(explosives,placeable) = 1;
useAction = 0;
ace_explosives_setupObject = "ACE_PipeBomb_place_CUP";
EGVAR(explosives,setupObject) = "ACE_PipeBomb_place_CUP";
class ACE_Triggers {
SupportedTriggers[] = {"Timer", "Command", "MK16_Transmitter", "DeadmanSwitch", "Cellphone"};
class Timer {
@ -16,9 +16,9 @@ class CfgMagazines {
};
};
class CUP_Mine_M: CUP_TimeBomb_M {
ace_explosives_placeable = 1;
EGVAR(explosives,placeable) = 1;
useAction = 0;
ace_explosives_setupObject = "ACE_Mine_place_CUP";
EGVAR(explosives,setupObject) = "ACE_Mine_place_CUP";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -27,9 +27,9 @@ class CfgMagazines {
};
};
class CUP_MineE_M: CUP_TimeBomb_M {
ace_explosives_placeable = 1;
EGVAR(explosives,placeable) = 1;
useAction = 0;
ace_explosives_setupObject = "ACE_MineE_place_CUP";
EGVAR(explosives,setupObject) = "ACE_MineE_place_CUP";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -39,20 +39,20 @@ class CfgMagazines {
};
class CUP_IED_V1_M: CUP_Mine_M {
ace_explosives_placeable = 1;
EGVAR(explosives,placeable) = 1;
useAction = 0;
ace_explosives_setupObject = "ACE_IED_V1_place_CUP";
EGVAR(explosives,setupObject) = "ACE_IED_V1_place_CUP";
class ACE_Triggers {
SupportedTriggers[] = {"Timer", "Command", "MK16_Transmitter", "DeadmanSwitch", "Cellphone", "PressurePlate"};
};
};
class CUP_IED_V2_M: CUP_IED_V1_M {
useAction = 0;
ace_explosives_setupObject = "ACE_IED_V2_place_CUP";
EGVAR(explosives,setupObject) = "ACE_IED_V2_place_CUP";
};
class CUP_IED_V3_M: CUP_IED_V1_M {
useAction = 0;
ace_explosives_setupObject = "ACE_IED_V3_place_CUP";
EGVAR(explosives,setupObject) = "ACE_IED_V3_place_CUP";
class ACE_Triggers {
SupportedTriggers[] = {"Timer", "Command", "MK16_Transmitter", "DeadmanSwitch", "Cellphone", "PressurePlate"};
class Timer {
@ -77,7 +77,7 @@ class CfgMagazines {
};
class CUP_IED_V4_M: CUP_IED_V1_M {
useAction = 0;
ace_explosives_setupObject = "ACE_IED_V4_place_CUP";
EGVAR(explosives,setupObject) = "ACE_IED_V4_place_CUP";
class ACE_Triggers {
SupportedTriggers[] = {"Timer", "Command", "MK16_Transmitter", "DeadmanSwitch", "Cellphone", "PressurePlate"};
class Timer {

@ -1,32 +1,31 @@
class CfgVehicles {
class ACE_Explosives_Place;
class ACE_PipeBomb_place_CUP: ACE_Explosives_Place {
displayName = "Satchel Charge";
displayName = "$STR_CUP_dn_PipeBomb";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_Satchel.p3d";
ace_explosives_offset[] = {0, 0, 0};
};
class ACE_Mine_place_CUP: ACE_Explosives_Place {
displayName = "AT-15 Anti-Tank Mine";
displayName = "$STR_CUP_dn_Mine";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_AT15.p3d";
ace_explosives_offset[] = {0, 0, 0};
};
class ACE_MineE_place_CUP: ACE_Explosives_Place {
displayName = "TM46 Anti-Tank Mine";
displayName = "$STR_CUP_dn_MineE";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_TM46.p3d";
ace_explosives_offset[] = {0, 0, 0};
};
class ACE_IED_V1_place_CUP: ACE_Explosives_Place {
displayName = "IED";
displayName = "$STR_A3_CfgVehicles_IEDUrbanSmall_F";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_IED_V1.p3d";
ace_explosives_offset[] = {0, 0, 0};
};
class ACE_IED_V2_place_CUP: ACE_IED_V1_place_CUP {
displayName = "$STR_A3_CfgVehicles_IEDUrbanBig_F";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_IED_V2.p3d";
};
class ACE_IED_V3_place_CUP: ACE_IED_V1_place_CUP {
displayName = "$STR_A3_CfgVehicles_IEDLandSmall_F";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_IED_V3.p3d";
};
class ACE_IED_V4_place_CUP: ACE_IED_V1_place_CUP {
displayName = "$STR_A3_CfgVehicles_IEDLandBig_F";
model = "\CUP\Weapons\CUP_Weapons_Put\CUP_IED_V4.p3d";
};
};

@ -2,7 +2,6 @@ class CfgMagazines {
// Explosives
class gm_explosive_petn_charge_base;
class gm_explosive_petn_charge: gm_explosive_petn_charge_base {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) =QEGVAR(explosives,Place_gm_explosive_petn);
useAction = 0;
@ -21,7 +20,6 @@ class CfgMagazines {
class gm_explosive_plnp_charge_base;
class gm_explosive_plnp_charge: gm_explosive_plnp_charge_base {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) =QEGVAR(explosives,Place_gm_explosive_plnp);
useAction = 0;

@ -1,5 +1,7 @@
#include "script_component.hpp"
if !(["ace_nametags"] call EFUNC(common,isModLoaded)) exitWith {};
private _russianRankIcons = [
QPATHTOEF(nametags,UI\icons_russia\private_gs.paa),
QPATHTOEF(nametags,UI\icons_russia\corporal_gs.paa),

@ -6,4 +6,12 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
// Disable RHS' wheel replacement mechanic
if (["ace_repair"] call EFUNC(common,isModLoaded)) then {
RHS_Retread_Enabled = false;
rhs_btr70_EnableRetread = false;
rhs_TypeTirePressure = 1;
RHS_BTR_Effects_Init = true;
};
ADDON = true;

@ -42,7 +42,6 @@ class CfgMagazines {
};
class rhs_ec75_mag: ATMine_Range_Mag {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,SetupObject) = QEGVAR(explosives,Place_rhs_ec75);
useAction = 0;
class ACE_Triggers {
@ -133,7 +132,6 @@ class CfgMagazines {
};
class rhs_mine_ozm72_c_mag: rhs_mine_ozm72_a_mag {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,SetupObject) = QEGVAR(explosives,Place_rhs_mine_ozm72_c);
useAction = 0;
class ACE_Triggers {

@ -0,0 +1,123 @@
class CfgVehicles {
class Wheeled_APC_F;
class rhs_btr_base: Wheeled_APC_F {
class EGVAR(interaction,anims) {
class wheel_1_unhide {
positions[] = {{-0.8, -1.7, 0}};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
class wheel_2_unhide {
positions[] = {{0.35, -2.9, -0.1}};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhs_btr70_vmf: rhs_btr_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class wheel_1_unhide: wheel_1_unhide {
positions[] = {{-1.2, -2.6, 0.2}};
};
class wheel_2_unhide: wheel_2_unhide {
positions[] = {{-0.3, -3.8, 0}};
};
};
};
class rhs_btr70_msv: rhs_btr70_vmf {};
class rhs_btr80_msv: rhs_btr70_msv {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class wheel_1_unhide: wheel_1_unhide {
positions[] = {{-1, -2.5, 0.6}};
};
class wheel_2_unhide: wheel_2_unhide {
enabled = 0;
};
};
};
class Truck_F;
class rhs_truck: Truck_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class RHS_Ural_BaseTurret: Truck_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhs_zil131_base: Truck_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhs_kraz255_base;
class rhs_kraz255b1_base: rhs_kraz255_base {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class O_Truck_02_covered_F;
class rhs_kamaz5350: O_Truck_02_covered_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class MRAP_02_base_F;
class rhs_tigr_base: MRAP_02_base_F {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class Offroad_01_base_f;
class RHS_UAZ_Base: Offroad_01_base_f {
class EGVAR(interaction,anims) {
class spare_hide {
selections[] = {"spare"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
};

@ -0,0 +1,21 @@
#include "script_component.hpp"
class CfgPatches {
class SUBADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"rhs_main_loadorder",
"ace_repair"
};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"Dystopian", "johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgVehicles.hpp"

@ -0,0 +1,3 @@
#define SUBCOMPONENT repair
#define SUBCOMPONENT_BEAUTIFIED Repair
#include "..\script_component.hpp"

@ -1,83 +1,83 @@
class CfgAmmo {
class APERSMine_Range_Ammo;
class rhs_mine_a200_bz_ammo: APERSMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.035};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.035};
};
class rhs_mine_a200_dz35_ammo: rhs_mine_a200_bz_ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.02};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.02};
};
class rhs_mine_glasmine43_hz_ammo: APERSMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.015};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.015};
};
class rhs_mine_glasmine43_bz_ammo: rhs_mine_glasmine43_hz_ammo {
ace_minedetector_detectable = 0;
EGVAR(minedetector,detectable) = 0;
};
class rhs_mine_bounding_trigger_base;
class rhs_mine_m2a3b_press_ammo: rhs_mine_bounding_trigger_base {
ace_explosives_defuseObjectPosition[] = {0, 0.046, 0.02};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0.046, 0.02};
};
class rhs_mine_m2a3b_trip_ammo: rhs_mine_m2a3b_press_ammo {
ace_explosives_defuseObjectPosition[] = {0, 0.046, 0.055};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0.046, 0.055};
};
class rhs_mine_M3_pressure_ammo: APERSMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.015};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.015};
};
class rhs_mine_M3_tripwire_ammo: rhs_mine_M3_pressure_ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.055};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.055};
};
class ATMine_Range_Ammo;
class rhs_mine_TM43_ammo: ATMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.072};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.072};
};
class rhs_mine_M7A2_ammo: APERSMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.067};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.067};
};
class rhs_mine_Mk2_pressure_ammo: APERSMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.02};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.02};
};
class rhs_mine_Mk2_tripwire_ammo: rhs_mine_Mk2_pressure_ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.055};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.055};
};
class APERSBoundingMine_Range_Ammo;
class rhs_mine_smine35_press_ammo: APERSBoundingMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.03};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.03};
};
class rhs_mine_smine35_trip_ammo: rhs_mine_bounding_trigger_base {
ace_explosives_defuseObjectPosition[] = {0, 0, 0.04};
EGVAR(explosives,defuseObjectPosition)[] = {0, 0, 0.04};
};
class rhs_mine_smine44_trip_ammo: rhs_mine_smine35_trip_ammo {
ace_explosives_defuseObjectPosition[] = {-0.03, 0, 0.015};
EGVAR(explosives,defuseObjectPosition)[] = {-0.03, 0, 0.015};
};
class rhs_mine_smine44_press_ammo: APERSBoundingMine_Range_Ammo {
ace_explosives_defuseObjectPosition[] = {-0.02, 0, 0.02};
EGVAR(explosives,defuseObjectPosition)[] = {-0.02, 0, 0.02};
};
class APERSTripMine_Wire_Ammo;
class rhs_mine_stockmine43_2m_ammo: APERSTripMine_Wire_Ammo {
ace_explosives_defuseObjectPosition[] = {-1, 0, 0.25};
EGVAR(explosives,defuseObjectPosition)[] = {-1, 0, 0.25};
};
class rhs_mine_stockmine43_4m_ammo: rhs_mine_stockmine43_2m_ammo {
ace_explosives_defuseObjectPosition[] = {-2, 0, 0.25};
EGVAR(explosives,defuseObjectPosition)[] = {-2, 0, 0.25};
};
class DemoCharge_Remote_Ammo;
class rhs_charge_M2tet_x2_ammo: DemoCharge_Remote_Ammo {
ace_explosives_defuseObjectPosition[] = {0.095, 0, 0.055};
EGVAR(explosives,defuseObjectPosition)[] = {0.095, 0, 0.055};
};
};

@ -1,7 +1,7 @@
class CfgMagazines {
class APERSMine_Range_Mag;
class rhs_mine_a200_bz_mag: APERSMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_a200_bz";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_a200_bz";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -11,7 +11,7 @@ class CfgMagazines {
};
class rhs_mine_a200_dz35_mag: rhs_mine_a200_bz_mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_a200_dz35";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_a200_dz35";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -21,7 +21,7 @@ class CfgMagazines {
};
class rhs_mine_glasmine43_hz_mag: APERSMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_glasmine43_hz";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_glasmine43_hz";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -31,12 +31,12 @@ class CfgMagazines {
};
class rhs_mine_glasmine43_bz_mag: rhs_mine_glasmine43_hz_mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_glasmine43_bz";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_glasmine43_bz";
};
class APERSBoundingMine_Range_Mag;
class rhs_mine_m2a3b_press_mag: APERSBoundingMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_m2a3b_press";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_m2a3b_press";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -46,7 +46,7 @@ class CfgMagazines {
};
class rhs_mine_m2a3b_trip_mag: rhs_mine_m2a3b_press_mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_m2a3b_trip";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_m2a3b_trip";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -56,7 +56,7 @@ class CfgMagazines {
};
class rhs_mine_m3_pressure_mag: APERSMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_m3_pressure";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_m3_pressure";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -67,7 +67,7 @@ class CfgMagazines {
class APERSTripMine_Wire_Mag;
class rhs_mine_M3_tripwire_mag: APERSTripMine_Wire_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_M3_tripwire";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_M3_tripwire";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -78,7 +78,7 @@ class CfgMagazines {
class ATMine_Range_Mag;
class rhs_mine_TM43_mag: ATMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_TM43";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_TM43";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -88,7 +88,7 @@ class CfgMagazines {
};
class rhs_mine_M7A2_mag: APERSMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_M7A2";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_M7A2";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -98,7 +98,7 @@ class CfgMagazines {
};
class rhs_mine_mk2_pressure_mag: APERSMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_mk2_pressure";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_mk2_pressure";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -108,7 +108,7 @@ class CfgMagazines {
};
class rhs_mine_Mk2_tripwire_mag: APERSTripMine_Wire_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_Mk2_tripwire";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_Mk2_tripwire";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -118,7 +118,7 @@ class CfgMagazines {
};
class rhs_mine_smine35_press_mag: APERSBoundingMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_smine35_press";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_smine35_press";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -128,7 +128,7 @@ class CfgMagazines {
};
class rhs_mine_smine35_trip_mag: rhs_mine_smine35_press_mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_smine35_trip";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_smine35_trip";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -138,7 +138,7 @@ class CfgMagazines {
};
class rhs_mine_smine44_trip_mag: APERSBoundingMine_Range_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_smine44_trip";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_smine44_trip";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -148,7 +148,7 @@ class CfgMagazines {
};
class rhs_mine_smine44_press_mag: rhs_mine_smine44_trip_mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_smine44_press";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_smine44_press";
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -158,7 +158,7 @@ class CfgMagazines {
};
class rhs_mine_stockmine43_2m_mag: APERSTripMine_Wire_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_stockmine43_2m";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_stockmine43_2m";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -168,7 +168,7 @@ class CfgMagazines {
};
class rhs_mine_stockmine43_4m_mag: rhs_mine_stockmine43_2m_mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_mine_stockmine43_4m";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_mine_stockmine43_4m";
class ACE_Triggers {
SupportedTriggers[] = {"Tripwire"};
class Tripwire {
@ -179,7 +179,7 @@ class CfgMagazines {
class DemoCharge_Remote_Mag;
class rhs_charge_M2tet_x2_mag: DemoCharge_Remote_Mag {
ace_explosives_SetupObject = "ACE_Explosives_Place_rhs_charge_M2tet_x2";
EGVAR(explosives,setupObject) = "ACE_Explosives_Place_rhs_charge_M2tet_x2";
class ACE_Triggers {
SupportedTriggers[] = {"Timer", "Command", "MK16_Transmitter", "DeadmanSwitch"};
class Timer {

@ -51,7 +51,6 @@ class CfgMagazines {
class CA_Magazine;
class rhssaf_tm100_mag: CA_Magazine {
useAction = 0;
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) = QEGVAR(explosives,Place_rhssaf_tm100);
class ACE_Triggers {

@ -43,8 +43,7 @@ class CfgVehicles {
EGVAR(refuel,fuelCapacity) = 302;
};
class Truck_F;
class Truck_01_base_F: Truck_F {};
class Truck_01_base_F;
class rhsusf_fmtv_base: Truck_01_base_F {
EGVAR(refuel,fuelCapacity) = 219;
};
@ -55,8 +54,7 @@ class CfgVehicles {
EGVAR(refuel,fuelCargo) = 900; // 45 jerrycans
};
class rhsusf_HEMTT_A4_base: Truck_01_base_F {};
class rhsusf_M977A4_usarmy_wd: rhsusf_HEMTT_A4_base {};
class rhsusf_M977A4_usarmy_wd;
class rhsusf_M977A4_AMMO_usarmy_wd: rhsusf_M977A4_usarmy_wd {
EGVAR(rearm,defaultSupply) = 1200;
};

@ -1,7 +1,6 @@
class CfgMagazines {
class CA_Magazine;
class rhsusf_m112_mag: CA_Magazine {
EGVAR(explosives,delayTime) = 1;
EGVAR(explosives,placeable) = 1;
EGVAR(explosives,setupObject) = QEGVAR(explosives,Place_rhsusf_explosive_m112);
useAction = 0;

@ -0,0 +1,52 @@
class CfgVehicles {
class rhsusf_stryker_base;
class rhsusf_stryker_m1126_base: rhsusf_stryker_base {
class EGVAR(interaction,anims) {
class Hide_FCans {
positions[] = {{-0.7, -3, -0.4}};
items[] = {"Land_CanisterFuel_F", "Land_CanisterFuel_F"};
name = ECSTRING(refuel,TakeFuelCanister);
text = ECSTRING(refuel,TakeFuelCanisterAction);
};
};
};
class rhsusf_stryker_m1127_base: rhsusf_stryker_m1126_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_FCans: Hide_FCans {
positions[] = {{-0.5, -3, -0.4}};
};
};
};
class rhsusf_stryker_m1126_m2_base: rhsusf_stryker_m1126_base {};
class rhsusf_stryker_m1132_m2_base: rhsusf_stryker_m1126_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_FCans: Hide_FCans {
positions[] = {{-1, -4, -0.4}};
};
};
};
class rhsusf_stryker_m1134_base: rhsusf_stryker_m1132_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_FCans: Hide_FCans {
positions[] = {{-0.7, -3, -0.7}};
};
};
};
class rhsusf_m1a2tank_base;
class rhsusf_m1a2sep2_base: rhsusf_m1a2tank_base {
class EGVAR(interaction,anims) {
class fuelcans_hide {
// Rotate interactions with turret rotation
positions[] = {
"[0.23, -0.6, 0] vectorAdd ([[1.1, -3.6, 0.6], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)",
"[0.23, -0.6, 0] vectorAdd ([[-1.1, -3.6, 0.6], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)"
};
items[] = {"Land_CanisterFuel_F", "Land_CanisterFuel_F"};
name = ECSTRING(refuel,TakeFuelCanister);
text = ECSTRING(refuel,TakeFuelCanisterAction);
};
};
};
};

@ -21,3 +21,4 @@ class CfgPatches {
};
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"

@ -0,0 +1,126 @@
class CfgVehicles {
class Truck_01_base_F;
class rhsusf_fmtv_base: Truck_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {{1, 1.4, 0}};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_M1078A1P2_fmtv_usarmy: rhsusf_fmtv_base {};
class rhsusf_M1078A1P2_B_fmtv_usarmy: rhsusf_M1078A1P2_fmtv_usarmy {};
class rhsusf_M1078A1P2_B_M2_fmtv_usarmy: rhsusf_M1078A1P2_B_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.4, -0.5}};
};
};
};
class rhsusf_M1078A1R_SOV_M2_D_fmtv_socom: rhsusf_M1078A1P2_B_M2_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1, -0.5}};
};
};
};
class rhsusf_M1083A1P2_fmtv_usarmy: rhsusf_M1078A1P2_fmtv_usarmy {};
class rhsusf_M1083A1P2_B_fmtv_usarmy: rhsusf_M1083A1P2_fmtv_usarmy {};
class rhsusf_M1083A1P2_B_M2_fmtv_usarmy: rhsusf_M1083A1P2_B_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.4, -0.5}};
};
};
};
class rhsusf_M1084A1P2_fmtv_usarmy: rhsusf_M1083A1P2_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.8, 0}};
};
};
};
class rhsusf_M1084A1P2_B_M2_fmtv_usarmy: rhsusf_M1083A1P2_B_M2_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 1.8, -0.5}};
};
};
};
class rhsusf_M1085A1P2_B_Medical_fmtv_usarmy: rhsusf_M1083A1P2_B_fmtv_usarmy {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class hide_spare: hide_spare {
positions[] = {{1, 6.1, 0}};
};
};
};
class rhsusf_HEMTT_A4_base: Truck_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {"_target selectionPosition 'sparewheel' vectorAdd [0.6, 0.6, -0.4]"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class MRAP_01_base_F;
class rhsusf_m1151_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {"_target selectionPosition 'sparewheel' vectorAdd [-0.465, 0, 0]"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
// Don't inherit, as it's easier for the trenches compat
class rhsusf_M1165A1_GMV_SAG2_base: rhsusf_m1151_base {
class EGVAR(interaction,anims) {
class hide_spare {
positions[] = {"_target selectionPosition 'sparewheel_gmv' vectorAdd [0, -0.44, 0]"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_rg33_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
selections[] = {"sparewheel"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_M1239_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
selections[] = {"sparewheel"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
class rhsusf_MATV_base: MRAP_01_base_F {
class EGVAR(interaction,anims) {
class hide_spare {
selections[] = {"sparewheel"};
items[] = {"ACE_Wheel"};
name = ECSTRING(repair,RemoveWheel);
text = ECSTRING(repair,RemovingWheel);
};
};
};
};

@ -0,0 +1,23 @@
#include "script_component.hpp"
class CfgPatches {
class SUBADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"rhsusf_main_loadorder",
"ace_repair"
};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
addonRootClass = QUOTE(ADDON);
};
};
#include "CfgVehicles.hpp"

@ -0,0 +1,3 @@
#define SUBCOMPONENT repair
#define SUBCOMPONENT_BEAUTIFIED Repair
#include "..\script_component.hpp"

@ -0,0 +1,48 @@
class CfgVehicles {
class rhsusf_stryker_base;
class rhsusf_stryker_m1126_base: rhsusf_stryker_base {
class EGVAR(interaction,anims) {
class Hide_PioKit {
positions[] = {{-1, -2.2, -0.5}};
items[] = {"ACE_EntrenchingTool"};
name = ECSTRING(trenches,EntrenchingToolName);
text = ECSTRING(trenches,EntrenchingToolName);
};
};
};
class rhsusf_stryker_m1127_base: rhsusf_stryker_m1126_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_PioKit: Hide_PioKit {
positions[] = {{-0.8, -2.2, -0.5}};
};
};
};
class rhsusf_stryker_m1126_m2_base: rhsusf_stryker_m1126_base {};
class rhsusf_stryker_m1132_m2_base: rhsusf_stryker_m1126_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_PioKit: Hide_PioKit {
positions[] = {{-1.3, -3.3, -0.5}};
};
};
};
class rhsusf_stryker_m1134_base: rhsusf_stryker_m1132_m2_base {
class EGVAR(interaction,anims): EGVAR(interaction,anims) {
class Hide_PioKit: Hide_PioKit {
positions[] = {{-1, -2.2, -0.8}};
};
};
};
class rhsusf_m1151_base;
class rhsusf_M1165A1_GMV_SAG2_base: rhsusf_m1151_base {
class EGVAR(interaction,anims) {
class tools_hide {
positions[] = {{0.365, 1.5, -0.4}};
items[] = {"ACE_EntrenchingTool"};
name = ECSTRING(trenches,EntrenchingToolName);
text = ECSTRING(trenches,EntrenchingToolName);
};
};
};
};

@ -0,0 +1,23 @@
#include "script_component.hpp"
class CfgPatches {
class SUBADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"rhsusf_main_loadorder",
"ace_trenches"
};
skipWhenMissingDependencies = 1;
author = ECSTRING(common,ACETeam);
authors[] = {"johnb43"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
addonRootClass = QUOTE(ADDON);
};
};
#include "CfgVehicles.hpp"

@ -0,0 +1,3 @@
#define SUBCOMPONENT trenches
#define SUBCOMPONENT_BEAUTIFIED Trenches
#include "..\script_component.hpp"

@ -2,7 +2,7 @@ class ACE_CSW_Groups {
// --- Gun Turrets -------------------------------------------------------------
class ace_csw_100Rnd_127x99_mag {
class EGVAR(csw,100Rnd_127x99_mag) {
vn_m2_v_100_mag = 1;
};

@ -1,7 +1,6 @@
class CfgMagazines {
class SPE_Mine_Magazine;
class SPE_US_TNT_4pound_mag: SPE_Mine_Magazine {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) = QEXPLOSIVES_PLACE(4LBTNT);
useAction = 0;
@ -19,7 +18,6 @@ class CfgMagazines {
};
class SPE_US_TNT_half_pound_mag: SPE_Mine_Magazine {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) = QEXPLOSIVES_PLACE(halfLBTNT);
useAction = 0;
@ -37,7 +35,6 @@ class CfgMagazines {
};
class SPE_US_Bangalore_mag: SPE_Mine_Magazine {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) = QEXPLOSIVES_PLACE(bangalore);
useAction = 0;
@ -55,7 +52,6 @@ class CfgMagazines {
};
class SPE_Ladung_Small_MINE_mag: SPE_Mine_Magazine {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) = QEXPLOSIVES_PLACE(smallLadung);
useAction = 0;
@ -73,7 +69,6 @@ class CfgMagazines {
};
class SPE_Ladung_Big_MINE_mag: SPE_Mine_Magazine {
EGVAR(explosives,DelayTime) = 1;
EGVAR(explosives,Placeable) = 1;
EGVAR(explosives,SetupObject) = QEXPLOSIVES_PLACE(bigLadung);
useAction = 0;

@ -91,7 +91,7 @@ private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname;
private _ammo = getText (_configMagazine >> "ammo");
private _configAmmo = configFile >> "CfgAmmo" >> _ammo;
private _simType = toLower getText (_configAmmo >> "simulation");
private _simType = toLowerANSI getText (_configAmmo >> "simulation");
private _speed = linearConversion [0, 1, random 1, 1, 20, true];
private _effect2pos = _object selectionPosition "destructionEffect2";
@ -100,7 +100,7 @@ private _fnc_spawnProjectile = {
// If the magazines are inside of the cargo (inventory), don't let their projectiles escape the interior of the vehicle
if (!_spawnProjectile) exitWith {};
params ["_object", "_ammo", "_speed", "_flyAway"];
params ["_flyAway"];
private _spawnPos = _object modelToWorld [-0.2 + random 0.4, -0.2 + random 0.4, random 3];
@ -117,7 +117,7 @@ private _fnc_spawnProjectile = {
_projectile setVectorDir _vectorVelocity;
_projectile setVelocity _vectorVelocity;
} else {
_projectile setDamage 1;
triggerAmmo _projectile;
};
};
@ -126,14 +126,14 @@ switch (_simType) do {
[QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent;
if (random 1 < 0.6) then {
[_object, _ammo, _speed, true] call _fnc_spawnProjectile;
true call _fnc_spawnProjectile;
};
};
case "shotshell": {
[QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent;
if (random 1 < 0.15) then {
[_object, _ammo, _speed, true] call _fnc_spawnProjectile;
true call _fnc_spawnProjectile;
};
};
case "shotgrenade": {
@ -141,7 +141,7 @@ switch (_simType) do {
_speed = 0;
};
[_object, _ammo, _speed, random 1 < 0.5] call _fnc_spawnProjectile;
(random 1 < 0.5) call _fnc_spawnProjectile;
};
case "shotrocket";
case "shotmissile";
@ -149,7 +149,7 @@ switch (_simType) do {
if (random 1 < 0.1) then {
[QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent;
[_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile;
(random 1 < 0.3) call _fnc_spawnProjectile;
} else {
createVehicle ["ACE_ammoExplosionLarge", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"];
};
@ -157,22 +157,13 @@ switch (_simType) do {
case "shotdirectionalbomb";
case "shotmine": {
if (random 1 < 0.5) then {
// Not all explosives detonate on destruction, some have scripted alternatives
if (getNumber (_configAmmo >> "triggerWhenDestroyed") != 1) then {
_ammo = getText (_configAmmo >> QEGVAR(explosives,explosive));
};
// If a scripted alternative doesn't exist use generic explosion
if (_ammo != "") then {
[_object, _ammo, 0, false] call _fnc_spawnProjectile;
} else {
createVehicle ["SmallSecondary", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"];
};
// _speed should be 0, but as it doesn't fly away, no need to set _speed
false call _fnc_spawnProjectile;
};
};
case "shotilluminating": {
if (random 1 < 0.15) then {
[_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile;
(random 1 < 0.3) call _fnc_spawnProjectile;
};
};
};

@ -52,7 +52,7 @@ private _ammo = "";
_x params ["_magazine", "_count"];
if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then {
_ammoToDetonate pushBack [_magazine, _count, false];
_ammoToDetonate pushBack [_magazine, _count, random 1 < 0.5];
_totalAmmo = _totalAmmo + _count;
};
} forEach (magazinesAmmoCargo _object);

@ -58,6 +58,7 @@ class CfgMagazines {
class GVAR(20Rnd_20mm_G_belt): 40Rnd_20mm_G_belt {
author = ECSTRING(common,ACETeam);
displayName = CSTRING(GMGBelt_displayName);
descriptionShort = CSTRING(GMGBelt_descriptionShort);
model = "\A3\Structures_F_EPB\Items\Military\Ammobox_rounds_F.p3d";
picture = QPATHTOF(UI\ammoBox_50bmg_ca.paa);
type = 256;

@ -672,6 +672,22 @@
<Russian>[CSW] Лента 20-мм гранат для ст. гранатомёта</Russian>
<Korean>[CSW] 20mm 고속유탄발사기 탄띠</Korean>
</Key>
<Key ID="STR_ACE_CSW_GMGBelt_descriptionShort">
<English>Caliber: 20 mm&lt;br/&gt;Rounds: 20&lt;br /&gt;Used in: Grenade Launcher</English>
<Chinese>口徑20 mm&lt;br/&gt;個數20&lt;br /&gt;用於:榴彈發射器</Chinese>
<French>Calibre : 20 mm&lt;br/&gt;Munitions : 20&lt;br /&gt;Application : lance-grenades</French>
<Spanish>Calibre: 20 mm&lt;br/&gt;Cargas: 20&lt;br /&gt;Se usa en: lanzagranadas</Spanish>
<Italian>Calibro: 20 mm&lt;br/&gt;Munizioni: 20&lt;br /&gt;Si usa in: lanciagranate</Italian>
<Polish>Kaliber: 20 mm&lt;br/&gt;Naboje: 20&lt;br /&gt;Używane w: granatniku</Polish>
<Russian>Калибр: 20 мм&lt;br/&gt;Кол-во: 20&lt;br /&gt;Применение: гранатомет</Russian>
<German>Kaliber: 20 mm&lt;br/&gt;Patronen: 20&lt;br /&gt;Eingesetzt von: Granatenwerfer</German>
<Czech>Ráže: 20 mm&lt;br/&gt;Munice: 20&lt;br /&gt;Použití: Granátomet</Czech>
<Portuguese>Calibre: 20 mm&lt;br/&gt;Balas: 20&lt;br /&gt;Uso em: Lança-granadas</Portuguese>
<Korean>구경: 20mm&lt;br /&gt;탄 수: 20&lt;br /&gt;사용 가능: 유탄발사기</Korean>
<Chinesesimp>口径20 毫米&lt;br/&gt;容弹量20&lt;br /&gt;用于:枪榴弹发射器</Chinesesimp>
<Japanese>口径20 mm &lt;br/&gt;弾薬20&lt;br /&gt;使用:グレネードランチャー</Japanese>
<Turkish>Kalibre: 20 mm&lt;br/&gt;Mermi: 20&lt;br /&gt;Kullanıldığı Yer: Bombaatar</Turkish>
</Key>
<Key ID="STR_ACE_CSW_m3Tripod_displayName">
<English>M3 Tripod</English>
<Spanish>Trípode M3</Spanish>

@ -28,7 +28,6 @@ class CfgAmmo {
class DirectionalBombBase;
class ClaymoreDirectionalMine_Remote_Ammo: DirectionalBombBase {
GVAR(magazine) = "ClaymoreDirectionalMine_Remote_Mag";
GVAR(Explosive) = "ClaymoreDirectionalMine_Remote_Ammo_Scripted";
GVAR(size) = 0;
GVAR(defuseObjectPosition)[] = {0, 0, 0.038};
soundActivation[] = {"", 0, 0, 0};
@ -92,7 +91,6 @@ class CfgAmmo {
class PipeBombBase;
class DemoCharge_Remote_Ammo: PipeBombBase {
GVAR(magazine) = "DemoCharge_Remote_Mag";
GVAR(Explosive) = "DemoCharge_Remote_Ammo_Scripted"; // can probably remove as base ammo now has triggerWhenDestroyed
GVAR(size) = 0;
GVAR(defuseObjectPosition)[] = {0.07, 0, 0.055};
soundActivation[] = {"", 0, 0, 0};
@ -103,7 +101,6 @@ class CfgAmmo {
};
class SatchelCharge_Remote_Ammo: PipeBombBase {
GVAR(magazine) = "SatchelCharge_Remote_Mag";
GVAR(Explosive) = "SatchelCharge_Remote_Ammo_Scripted"; // can probably remove as base ammo now has triggerWhenDestroyed
GVAR(size) = 0;
GVAR(defuseObjectPosition)[] = {0.1, 0.1, 0.05};
soundActivation[] = {"", 0, 0, 0};
@ -171,7 +168,6 @@ class CfgAmmo {
// Orange DLC:
class APERSMineDispenser_Ammo: PipeBombBase {
GVAR(magazine) = "APERSMineDispenser_Mag";
GVAR(Explosive) = "APERSMineDispenser_Ammo_Scripted"; // triggerWhenDestroyed = 1;
GVAR(size) = 0;
GVAR(defuseObjectPosition)[] = {0.0, -0.05, 0.15};
};

@ -4,7 +4,6 @@ class CfgMagazines {
GVAR(Placeable) = 1;
useAction = 0;
GVAR(SetupObject) = "ACE_Explosives_Place_ATMine"; // CfgVehicle class for setup object.
GVAR(DelayTime) = 2.5;
class ACE_Triggers {
SupportedTriggers[] = {"PressurePlate"};
class PressurePlate {
@ -50,7 +49,6 @@ class CfgMagazines {
GVAR(Placeable) = 1;
useAction = 0;
GVAR(SetupObject) = "ACE_Explosives_Place_Claymore";
GVAR(DelayTime) = 1.5;
class ACE_Triggers {
SupportedTriggers[] = {"Command", "MK16_Transmitter"};
class Command {
@ -64,7 +62,6 @@ class CfgMagazines {
GVAR(Placeable) = 1;
useAction = 0;
GVAR(SetupObject) = "ACE_Explosives_Place_SatchelCharge";
GVAR(DelayTime) = 1;
class ACE_Triggers {
SupportedTriggers[] = {"Timer", "Command", "MK16_Transmitter", "DeadmanSwitch"};
class Timer {

@ -106,7 +106,7 @@ class CfgVehicles {
};
class ACE_Explosives_Place_DemoCharge: ACE_Explosives_Place {
displayName = "Demo Charge";
displayName = "$STR_A3_cfgMagazines_DemoCharge0";
model = "\A3\Weapons_F\explosives\c4_charge_small_d";
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -115,15 +115,15 @@ class CfgVehicles {
};
};
class ACE_Explosives_Place_APERSBoundingMine: ACE_Explosives_Place {
displayName = "APERS Bounding Mine";
displayName = "$STR_A3_cfgMagazines_BouncingMineRangeMagazine0";
model = "\A3\Weapons_F\explosives\mine_AP_bouncing";
};
class ACE_Explosives_Place_APERSMine: ACE_Explosives_Place {
displayName = "APERS Mine";
displayName = "$STR_A3_cfgMagazines_ClassicMineRangeMagazine0";
model = "\A3\Weapons_F\explosives\mine_ap";
};
class ACE_Explosives_Place_APERSTripwireMine: ACE_Explosives_Place {
displayName = "APERS Tripwire Mine";
displayName = "$STR_A3_cfgMagazines_ClassicMineWireMagazine0";
model = "\A3\Weapons_F\explosives\mine_AP_tripwire";
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -133,12 +133,12 @@ class CfgVehicles {
};
class ACE_Explosives_Place_ATMine: ACE_Explosives_Place {
displayName = "AT Mine";
displayName = "$STR_A3_CfgMagazines_Mine0";
model = "\A3\Weapons_f\Explosives\mine_at";
};
class ACE_Explosives_Place_Claymore: ACE_Explosives_Place {
displayName = "Claymore";
displayName = "$STR_A3_cfgMagazines_DirectionalMineRemoteMagazine0";
model = "\A3\Weapons_F\explosives\mine_AP_miniclaymore";
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -148,7 +148,7 @@ class CfgVehicles {
};
class ACE_Explosives_Place_SatchelCharge: ACE_Explosives_Place {
displayName = "Satchel Charge";
displayName = "$STR_A3_cfgMagazines_PipeBomb0";
model = "\A3\Weapons_F\Explosives\satchel";
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -159,7 +159,7 @@ class CfgVehicles {
// Orange DLC:
class ACE_Explosives_Place_APERSMineDispenser: ACE_Explosives_Place {
displayName = "APERSMineDispenser";
displayName = "$STR_A3_CfgMagazines_APERSMineDispenser_Mag0";
model = "\A3\Weapons_F_Orange\Explosives\APERSmineDispenser";
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -168,7 +168,7 @@ class CfgVehicles {
};
};
class ACE_Explosives_Place_TrainingMine: ACE_Explosives_Place {
displayName = "TrainingMine";
displayName = "$STR_A3_CfgMagazines_TrainingMine_Mag0";
model = "\A3\Weapons_F_Orange\Explosives\TrainingMine_F";
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -179,28 +179,28 @@ class CfgVehicles {
class ACE_Explosives_Place_SLAM: ACE_Explosives_Place {
displayName = "SLAM";
displayName = "$STR_A3_cfgMagazines_DirectionalMineRangeMagazine0";
model = "\A3\Weapons_F\Explosives\mine_SLAM_directional";
};
// IEDs
class ACE_Explosives_Place_IEDUrbanBig: ACE_Explosives_Place {
displayName = "IED Urban Big";
displayName = "$STR_A3_CfgVehicles_IEDUrbanBig_F";
model = "\A3\Weapons_F\Explosives\IED_urban_big";
};
class ACE_Explosives_Place_IEDLandBig: ACE_Explosives_Place {
displayName = "IED Land Big";
displayName = "$STR_A3_CfgVehicles_IEDLandBig_F";
model = "\A3\Weapons_F\Explosives\IED_land_big";
};
class ACE_Explosives_Place_IEDUrbanSmall: ACE_Explosives_Place {
displayName = "IED Urban Small";
displayName = "$STR_A3_CfgVehicles_IEDUrbanSmall_F";
model = "\A3\Weapons_F\Explosives\IED_urban_small";
};
class ACE_Explosives_Place_IEDLandSmall: ACE_Explosives_Place {
displayName = "IED Land Small";
displayName = "$STR_A3_CfgVehicles_IEDLandSmall_F";
model = "\A3\Weapons_F\Explosives\IED_land_small";
};

@ -42,7 +42,7 @@ if (isServer) then {
params ["_explosive"];
TRACE_1("exploding",_explosive);
if (!isNull _explosive) then {
_explosive setDamage 1;
[QEGVAR(common,triggerAmmo), _explosive, _explosive] call CBA_fnc_targetEvent;
};
}, _explosive, _delay] call CBA_fnc_waitAndExecute;
}] call CBA_fnc_addEventHandler;

@ -29,8 +29,8 @@ if (!isClass (configFile >> "CfgVehicles" >> _setupObjectClass)) exitWith {ERROR
private _p3dModel = getText (configFile >> "CfgVehicles" >> _setupObjectClass >> "model");
if (_p3dModel == "") exitWith {ERROR("No Model");}; //"" - will crash game!
[_unit, "forceWalk", "ACE_Explosives", true] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", "ACE_Explosives", true] call EFUNC(common,statusEffect_set);
[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
//Show mouse buttons:
[localize LSTRING(PlaceAction), localize LSTRING(CancelAction), localize LSTRING(ScrollAction)] call EFUNC(interaction,showMouseHint);
@ -149,8 +149,8 @@ GVAR(TweakedAngle) = 0;
[_pfID] call CBA_fnc_removePerFrameHandler;
GVAR(pfeh_running) = false;
[_unit, "forceWalk", "ACE_Explosives", false] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", "ACE_Explosives", false] call EFUNC(common,statusEffect_set);
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
[_unit, "blockThrow", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
[] call EFUNC(interaction,hideMouseHint);
[_unit, "DefaultAction", (_unit getVariable [QGVAR(placeActionEH), -1])] call EFUNC(common,removeActionEventHandler);
[_unit, "zoomtemp", (_unit getVariable [QGVAR(cancelActionEH), -1])] call EFUNC(common,removeActionEventHandler);

@ -134,7 +134,7 @@
<Spanish>Equipa el helicoptero seleccionado con un Sistema de Inserción/Extracción Rápida por Cuerda</Spanish>
<Italian>Equipaggia l'elicottero selezionato con il Fast Rope Insertion Extraction System</Italian>
<Czech>Vybavit vybraný vrtulník systémem Fast Rope Insertion Extraction (FRIES)</Czech>
<Portuguese>Equipa um helicóptero selecionado com um sistema de Fast Rope Insertion Extraction System</Portuguese>
<Portuguese>Equipa o helicóptero selecionado com um Sistema de Inserção/Extração Rápida por Corda</Portuguese>
<Russian>Снаряжает выбранный вертолет оборудованием для спуска десанта по канатам</Russian>
<Japanese>選択されたヘリコプターで Fast Rope Insertion Extraction System を使えるようにします。</Japanese>
<Korean>선택된 헬리콥터에 패스트로프 투입 및 탈출 시스템을 장착합니다.</Korean>
@ -298,6 +298,7 @@
<German>Schnelles-Abseilen</German>
<Italian>Fast Rope</Italian>
<Korean>패스트로프</Korean>
<Portuguese>Descida rápida pela corda</Portuguese>
</Key>
<Key ID="STR_ACE_Fastroping_setting_requireRopeItems_displayName">
<English>Require rope item to deploy</English>

@ -4,9 +4,9 @@
[ELSTRING(common,Enabled), LSTRING(Enabled_Description)],
LSTRING(DisplayName),
false,
true,
{},
true // Needs restart
1,
{[QXGVAR(enabled), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_fnc_addSetting;
[

@ -1,6 +1,6 @@
PREP(addEarPlugs);
PREP(earRinging);
PREP(explosionNear);
PREP(explosion);
PREP(firedNear);
PREP(getAmmoLoudness);
PREP(handleRespawn);

@ -35,6 +35,7 @@ GVAR(lastPlayerVehicle) = objNull;
// Spawn volume updating process
[LINKFUNC(updateVolume), 1, false] call CBA_fnc_addPerFrameHandler;
[QGVAR(explosion), LINKFUNC(explosion)] call CBA_fnc_addEventHandler;
[QGVAR(updateVolume), LINKFUNC(updateVolume)] call CBA_fnc_addEventHandler;
// Update veh attunation when player veh changes
@ -71,12 +72,7 @@ GVAR(lastPlayerVehicle) = objNull;
private _firedEH = _oldPlayer getVariable [QGVAR(firedEH), -1];
_oldPlayer removeEventHandler ["FiredNear", _firedEH];
_oldPlayer setVariable [QGVAR(firedEH), nil];
private _explosionEH = _oldPlayer getVariable [QGVAR(explosionEH), -1];
_oldPlayer removeEventHandler ["Explosion", _explosionEH];
_oldPlayer setVariable [QGVAR(explosionEH), nil];
TRACE_3("removed unit eh",_oldPlayer,_firedEH,_explosionEH);
TRACE_2("removed unit eh",_oldPlayer,_firedEH);
};
// Don't add a new EH if the unit respawned
if ((_player getVariable [QGVAR(firedEH), -1]) == -1) then {
@ -86,11 +82,7 @@ GVAR(lastPlayerVehicle) = objNull;
private _firedEH = _player addEventHandler ["FiredNear", {call FUNC(firedNear)}];
_player setVariable [QGVAR(firedEH), _firedEH];
private _explosionEH = _player addEventHandler ["Explosion", {call FUNC(explosionNear)}];
_player setVariable [QGVAR(explosionEH), _explosionEH];
TRACE_3("added unit eh",_player,_firedEH,_explosionEH);
TRACE_2("added unit eh",_player,_firedEH);
};
GVAR(deafnessDV) = 0;
@ -100,6 +92,17 @@ GVAR(lastPlayerVehicle) = objNull;
call FUNC(updateHearingProtection);
}, true] call CBA_fnc_addPlayerEventHandler;
addMissionEventHandler ["ProjectileCreated", {
params ["_projectile"];
if (!local _projectile) exitWith {};
// Rockets only explode on local clients
_projectile addEventHandler ["Explode", {
[QGVAR(explosion), _this] call CBA_fnc_globalEvent;
}];
}];
// Update protection on possible helmet change
["loadout", LINKFUNC(updateHearingProtection), false] call CBA_fnc_addPlayerEventHandler;
}] call CBA_fnc_addEventHandler;

@ -0,0 +1,55 @@
#include "..\script_component.hpp"
/*
* Author: johnb43
* Handles deafness due to explosions going off near the player.
*
* Arguments:
* 0: Projectile <OBJECT>
* 1: Explosion position ASL <ARRAY>
* 2: Velocity <ARRAY> (unused)
*
* Return Value:
* None
*
* Example:
* [_projectile, [0, 0, 0], [0, 0, 0]] call ace_hearing_fnc_explosion
*
* Public: No
*/
// Ignore spectators, curators and alike
if ((getNumber (configOf ACE_player >> "isPlayableLogic")) == 1) exitWith {};
params ["_projectile", "_pos"];
// Don't allow for distances under 1
private _distance = ((eyePos ACE_player) vectorDistance _pos) max 1;
// Fast exit if explosion far away
if (_distance > 100) exitWith {
TRACE_1("too far away",_distance);
};
private _ammoConfig = configOf _projectile;
private _explosive = getNumber (_ammoConfig >> "explosive");
private _vehAttenuation = [GVAR(playerVehAttenuation), 1] select (isNull objectParent ACE_player || {isTurnedOut ACE_player});
TRACE_5("",typeOf _projectile,_distance,_explosive,_audibleFire,_vehAttenuation);
(if (isArray (_ammoConfig >> "soundHit1")) then {
getArray (_ammoConfig >> "soundHit1")
} else {
getArray (_ammoConfig >> "soundHit")
}) params ["", ["_volume", 1], "", ["_maxDistance", 1500]];
if (_distance > _maxDistance) exitWith {
TRACE_2("too far away",_distance,_maxDistance);
};
private _strength = _vehAttenuation * _explosive * _volume * _maxDistance / _distance^2;
TRACE_2("strength",_volume,_strength);
// Call immediately, as it will get picked up later by the update thread anyway
_strength call FUNC(earRinging);

@ -1,26 +0,0 @@
#include "..\script_component.hpp"
/*
* Author: KoffeinFlummi, commy2, Ruthberg
* Handles deafness due to explosions going off near the player.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Damage inflicted to the unit <NUMBER>
*
* Return Value:
* None
*
* Example:
* [clientExplosionEvent] call ace_hearing_fnc_explosionNear
*
* Public: No
*/
params ["_unit", "_damage"];
TRACE_2("explosion near player",_unit,_damage);
private _strength = (0 max _damage) * 30;
// Call immediately, as it will get picked up later by the update thread anyway
_strength call FUNC(earRinging);

@ -372,6 +372,7 @@
<French>Mettre/enlever les bouchons</French>
<German>Ohrstöpsel einsetzen/herausnehmen</German>
<Spanish>Poner/quitar tapones</Spanish>
<Portuguese>Colocar/retirar protetores auriculares</Portuguese>
</Key>
<Key ID="STR_ACE_Hearing_heavyWeaponUnits">
<English>Only units with heavy weapons</English>
@ -382,6 +383,7 @@
<Spanish>Sólo unidades con armas pesadas</Spanish>
<Italian>Solo a unità con armi pesanti</Italian>
<Korean>중화기를 가진 유닛만 해당</Korean>
<Portuguese>Apenas unidades com armas pesadas</Portuguese>
</Key>
</Package>
</Project>

@ -24,6 +24,7 @@
<Korean>플레이어가 무기를 떨굴 확률 (팔 피격)</Korean>
<German>Spieler Wahrscheinlichkeit, die Waffe fallen zu lassen (Arm Treffer)</German>
<Italian>Probabilità dei giocatori di far cadere l'arma (colpo al braccio)</Italian>
<Portuguese>Probabilidade do jogador de largar a arma após tiro no braço</Portuguese>
</Key>
<Key ID="STR_ACE_HitReactions_weaponDropChanceArmHitAI_displayName">
<English>AI Weapon Drop Chance (Arm Hit)</English>
@ -32,6 +33,7 @@
<Korean>인공지능이 무기를 떨굴 확률 (팔 피격)</Korean>
<German>KI-Wahrscheinlichkeit, die Waffe fallen zu lassen (Arm Treffer)</German>
<Italian>Probabilità dell'IA di far cadere l'arma (colpo al braccio)</Italian>
<Portuguese>Probabilidade da IA de largar a arma após tiro no braço</Portuguese>
</Key>
</Package>
</Project>

@ -88,8 +88,8 @@ GVAR(inheritedClassesMan) = [];
if (GVAR(inheritedClassesAll) pushBackUnique _type == -1) exitWith { END_COUNTER(InitPost); };
{
_x params ["_objectType", "_typeNum", "_parentPath", "_action"];
if (_object isKindOf _objectType) then {
_x params ["_objectType", "_typeNum", "_parentPath", "_action", "_excludedClasses"];
if (_type isKindOf _objectType && {_excludedClasses findIf {_type isKindOf _x} == -1}) then {
[_type, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
};
} forEach GVAR(inheritedActionsAll);
@ -102,8 +102,10 @@ GVAR(inheritedClassesMan) = [];
if (GVAR(inheritedClassesMan) pushBackUnique _type == -1) exitWith { END_COUNTER(InitPost); };
{
_x params ["_typeNum", "_parentPath", "_action"];
[_type, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
_x params ["_typeNum", "_parentPath", "_action", "_excludedClasses"];
if (_excludedClasses findIf {_type isKindOf _x} == -1) then { // skip excluded classes and children
[_type, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
};
} forEach GVAR(inheritedActionsMan);
END_COUNTER(InitPost);
}, true, ["VirtualMan_F"]] call CBA_fnc_addClassEventHandler;

@ -1,7 +1,7 @@
#include "..\script_component.hpp"
/*
* Author: esteldunedain
* Insert an ACE action to a class, under a certain path
* Inserts an ACE action to a class, under a certain path.
* Note: This function is NOT global.
*
* Arguments:
@ -10,12 +10,13 @@
* 2: Parent path of the new action <ARRAY>
* 3: Action <ARRAY>
* 4: Use Inheritance <BOOL> (default: false)
* 5: Classes excluded from inheritance (children included) <ARRAY> (default: [])
*
* Return Value:
* The entry full path, which can be used to remove the entry, or add children entries <ARRAY>.
*
* Example:
* [typeOf cursorTarget, 0, ["ACE_TapShoulderRight"],VulcanPinchAction] call ace_interact_menu_fnc_addActionToClass;
* [typeOf cursorTarget, 0, ["ACE_TapShoulderRight"], VulcanPinchAction] call ace_interact_menu_fnc_addActionToClass;
*
* Public: Yes
*/
@ -25,22 +26,30 @@ if (!params [["_objectType", "", [""]], ["_typeNum", 0, [0]], ["_parentPath", []
ERROR("Bad Params");
[]
};
TRACE_4("addActionToClass",_objectType,_typeNum,_parentPath,_action);
private _useInheritance = _this param [4, false, [false]];
private _excludedClasses = _this param [5, [], [[]]];
TRACE_6("addActionToClass",_objectType,_typeNum,_parentPath,_action,_useInheritance,_excludedClasses);
if (param [4, false, [false]]) exitwith {
if (_useInheritance) exitwith {
BEGIN_COUNTER(addAction);
private _cfgVehicles = configFile >> "CfgVehicles"; // store this so we don't resolve for every element
_excludedClasses = (_excludedClasses apply {configName (_cfgVehicles >> _x)}) - [""]; // ends up being faster than toLower'ing everything else
if (_objectType == "CAManBase") then {
GVAR(inheritedActionsMan) pushBack [_typeNum, _parentPath, _action];
GVAR(inheritedActionsMan) pushBack [_typeNum, _parentPath, _action, _excludedClasses];
{
[_x, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
} forEach GVAR(inheritedClassesMan);
} else {
GVAR(inheritedActionsAll) pushBack [_objectType, _typeNum, _parentPath, _action];
{
if (_x isKindOf _objectType) then {
private _type = _x;
if (_excludedClasses findIf {_type isKindOf _x} == -1) then { // skip excluded classes and children
[_x, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
};
} forEach GVAR(inheritedClassesAll);
} forEach (GVAR(inheritedClassesMan) - _excludedClasses);
} else {
GVAR(inheritedActionsAll) pushBack [_objectType, _typeNum, _parentPath, _action, _excludedClasses];
{
private _type = _x;
if (_type isKindOf _objectType && {_excludedClasses findIf {_type isKindOf _x} == -1}) then {
[_type, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
};
} forEach (GVAR(inheritedClassesAll) - _excludedClasses);
};
END_COUNTER(addAction);

@ -119,7 +119,7 @@ private _actions = [
// Dummy statement so it's not collapsed when there's no available actions
true
},
{[ACE_player, _target, ["isNotInside","isNotDragging", "isNotCarrying", "isNotSwimming", "notOnMap", "isNotEscorting", "isNotSurrendering", "isNotSitting", "isNotOnLadder", "isNotRefueling"]] call EFUNC(common,canInteractWith)},
{[ACE_player, _target, ["isNotInside","isNotDragging", "isNotCarrying", "isNotSwimming", "notOnMap", "isNotEscorting", "isNotSurrendering", "isNotHandcuffed", "isNotSitting", "isNotOnLadder", "isNotRefueling"]] call EFUNC(common,canInteractWith)},
{},
{},
"Spine3",

@ -36,7 +36,7 @@ if (_isTextEditing) then {
if (
_isTextEditing ||
{(isNull curatorCamera) && {
!([ACE_player, objNull, ["isNotInside","isNotDragging", "isNotCarrying", "isNotSwimming", "notOnMap", "isNotEscorting", "isNotSurrendering", "isNotSitting", "isNotOnLadder", "isNotRefueling"]] call EFUNC(common,canInteractWith))
!([ACE_player, objNull, ["isNotInside","isNotDragging", "isNotCarrying", "isNotSwimming", "notOnMap", "isNotEscorting", "isNotSurrendering", "isNotHandcuffed", "isNotSitting", "isNotOnLadder", "isNotRefueling"]] call EFUNC(common,canInteractWith))
}
}) exitWith {false};

@ -1,29 +1,63 @@
#include "..\script_component.hpp"
/*
* Author: esteldunedain
* Removes an action from a class
* Removes an action from a class.
*
* Arguments:
* 0: TypeOf of the class <STRING>
* 1: Type of action, 0 for actions, 1 for self-actions <NUMBER>
* 2: Full path of the new action <ARRAY>
* 3: Remove action from child classes <BOOL> (default: false)
*
* Return Value:
* None
*
* Example:
* [typeOf cursorTarget, 0,["ACE_TapShoulderRight","VulcanPinch"]] call ace_interact_menu_fnc_removeActionFromClass;
* [typeOf cursorTarget, 0, ["ACE_TapShoulderRight", "VulcanPinch"]] call ace_interact_menu_fnc_removeActionFromClass;
*
* Public: No
*/
params ["_objectType", "_typeNum", "_fullPath"];
params ["_objectType", "_typeNum", "_fullPath", ["_useInheritance", false, [false]]];
_objectType = _objectType call EFUNC(common,getConfigName);
private _res = _fullPath call FUNC(splitPath);
_res params ["_parentPath", "_actionName"];
if (_useInheritance) exitWith {
// Only need to run for classes that have already been initialized
{
[_x, _typeNum, _fullPath] call FUNC(removeActionFromClass);
} forEach (GVAR(inheritedClassesAll) select {_x isKindOf _objectType});
// Find same path and actionName, and check if it's a parent class, needs to be checked for all classes
private _index = GVAR(inheritedActionsAll) findIf {
_x params ["_currentType", "", "_currentParentPath", "_currentAction"];
[_objectType isKindOf _currentType, _currentParentPath, _currentAction select 0] isEqualTo [true, _parentPath, _actionName]
};
// Add to exclude classes
if (_index != -1) then {
(GVAR(inheritedActionsAll) select _index select 4) pushBackUnique _objectType;
};
// Children of CAManBase need special treatment because of inheritedActionsMan array
if (_objectType isKindOf "CAManBase") then {
private _index = GVAR(inheritedActionsMan) findIf {
_x params ["", "_currentParentPath", "_currentAction"];
[_currentParentPath, _currentAction select 0] isEqualTo [_parentPath, _actionName]
};
// Different index because array doesn't include _objectType
if (_index != -1) then {
(GVAR(inheritedActionsMan) select _index select 3) pushBackUnique _objectType;
};
};
};
private _namespace = [GVAR(ActNamespace), GVAR(ActSelfNamespace)] select _typeNum;
private _actionTrees = _namespace getOrDefault [_objectType, []];

@ -372,6 +372,16 @@ class CfgVehicles {
};
class Car_F: Car {};
class Offroad_01_base_F: Car_F {
class GVAR(anims) {
class HideBackpacks {
positions[] = {{-1.15, -1.15, -0.2}, {1.1, -1.15, -0.2}, {1.1, -2.5, -0.2}};
items[] = {"B_TacticalPack_blk", "B_TacticalPack_blk", "B_Carryall_khk", "B_Carryall_khk"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class Quadbike_01_base_F: Car_F {
class ACE_Actions: ACE_Actions {
class ACE_MainActions: ACE_MainActions {
@ -405,6 +415,49 @@ class CfgVehicles {
};
};
class Wheeled_APC_F;
class APC_Wheeled_01_base_F: Wheeled_APC_F {
class GVAR(anims) {
class showBags {
phase = 0;
// Rotate interactions with turret rotation
positions[] = {
"[0, -1.6, 0] vectorAdd ([[1, -1, 0.1], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)",
"[0, -1.6, 0] vectorAdd ([[-1, -1, 0.1], [0, 0, 1], deg (_target animationPhase 'MainTurret')] call CBA_fnc_vectRotate3D)"
};
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class APC_Wheeled_02_base_F: Wheeled_APC_F {
class GVAR(anims);
};
class APC_Wheeled_02_base_v2_F: APC_Wheeled_02_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr"};
name = "$STR_BACKPACK_CONTAINER_NAME";
text = "$STR_BACKPACK_CONTAINER_NAME";
};
};
};
class APC_Wheeled_03_base_F: Wheeled_APC_F {
class GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class Tank: LandVehicle {
class ACE_Actions {
class ACE_MainActions {
@ -432,6 +485,88 @@ class CfgVehicles {
};
};
};
class Tank_F;
class LT_01_base_F: Tank_F {
class GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr"};
name = "$STR_BACKPACK_CONTAINER_NAME";
text = "$STR_BACKPACK_CONTAINER_NAME";
};
class showBags2: showBags {
selections[] = {"vhc_bags2"};
};
};
};
class APC_Tracked_01_base_F: Tank_F {
class GVAR(anims);
};
class B_APC_Tracked_01_base_F: APC_Tracked_01_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
positions[] = {"private _pos = _target selectionPosition 'vhc_bags'; _pos set [0, -(_pos select 0)]; _pos"}; // Mirror position to other side of vehicle
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class B_APC_Tracked_01_CRV_F: B_APC_Tracked_01_base_F {
class GVAR(anims): GVAR(anims) {
class showBags: showBags {
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
};
};
};
class APC_Tracked_02_base_F: Tank_F {
class GVAR(anims);
};
class O_APC_Tracked_02_base_F: APC_Tracked_02_base_F {};
class O_APC_Tracked_02_cannon_F: O_APC_Tracked_02_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class APC_Tracked_03_base_F: Tank_F {
class GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class MBT_01_base_F: Tank_F {
class GVAR(anims);
};
class B_MBT_01_base_F: MBT_01_base_F {};
class B_MBT_01_cannon_F: B_MBT_01_base_F {
class GVAR(anims): GVAR(anims) {
class showBags {
phase = 0;
selections[] = {"vhc_bags"};
items[] = {"B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr", "B_Carryall_cbr"};
name = "$STR_a3_cfgvehicleclasses_backpacks0";
text = "$STR_a3_cfgvehicleclasses_backpacks0";
};
};
};
class Motorcycle: LandVehicle {
class ACE_Actions {

@ -54,4 +54,5 @@ PREP(push);
// misc
PREP(canFlip);
PREP(initAnimActions);
PREP(replaceTerrainObject);

@ -149,11 +149,20 @@ GVAR(isOpeningDoor) = false;
["isNotOnLadder", {getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> animationState (_this select 0) >> "ACE_isLadder") != 1}] call EFUNC(common,addCanInteractWithCondition);
["CBA_settingsInitialized", {
TRACE_2("settingsInitialized",GVAR(disableNegativeRating),GVAR(enableAnimActions));
if (GVAR(disableNegativeRating)) then {
player addEventHandler ["HandleRating", {
(_this select 1) max 0
}];
};
if (!GVAR(enableAnimActions)) exitWith {};
// Don't add inherited anim actions (but actions are added to child classes)
{
[_x, "InitPost", LINKFUNC(initAnimActions), true, [], true] call CBA_fnc_addClassEventHandler;
} forEach (keys (uiNamespace getVariable QGVAR(animActionsClasses)));
}] call CBA_fnc_addEventHandler;
{
@ -162,7 +171,6 @@ GVAR(isOpeningDoor) = false;
}] call CBA_fnc_addPlayerEventHandler;
} forEach ["loadout", "weapon"];
// add "Take _weapon_" action to dropped weapons
private _action = [
// action display name will be overwritten in modifier function

@ -16,6 +16,7 @@ DFUNC(repair_Statement) = { // moved from config because of build problems
};
if (hasInterface) then {
GVAR(initializedAnimClasses) = [];
GVAR(replaceTerrainModels) = createHashMapFromArray call (uiNamespace getVariable QGVAR(cacheReplaceTerrainModels));
};

@ -23,3 +23,13 @@ private _cacheReplaceTerrainModels = createHashMap;
} forEach _replaceTerrainClasses;
uiNamespace setVariable [QGVAR(cacheReplaceTerrainModels), compileFinal str _cacheReplaceTerrainModels];
// Cache classes with anim actions
private _animActionsClasses = (QUOTE(isClass (_x >> QQGVAR(anims)) && {!isClass (inheritsFrom _x >> QQGVAR(anims))}) configClasses (configFile >> "CfgVehicles"));
_animActionsClasses = _animActionsClasses apply { configName _x };
_animActionsClasses = _animActionsClasses select {
private _class = _x;
(_animActionsClasses findIf {(_class != _x) && {_class isKindOf _x}}) == -1 // filter classes that already have a parent in the list
};
uiNamespace setVariable [QGVAR(animActionsClasses), compileFinal (_animActionsClasses createHashMapFromArray [])];

@ -44,7 +44,7 @@ params ["_unit"];
{},
{true},
{
params ["_unit", "", "_args"];
params ["", "_unit", "_args"];
_args params ["_attachment", "_name", "_picture", "_weaponItems", "_currentWeapon"];
private _cfgWeapons = configFile >> "CfgWeapons";
@ -110,10 +110,14 @@ params ["_unit"];
QGVAR(switch_) + _x,
format ["%1: %2", localize "str_sensortype_switch", _modeName],
getText (_config >> "picture"),
LINKFUNC(switchWeaponAttachment),
{
params ["", "_unit", "_actionParams"];
_actionParams params ["_weapon", "_newAttachment", "_oldAttachment"];
[_unit, _weapon, _oldAttachment, _newAttachment] call EFUNC(common,switchAttachmentMode);
},
{true},
{},
[_currentWeapon, _x, ""]
[_currentWeapon, _x, _attachment]
] call EFUNC(interact_menu,createAction),
[],
_unit

@ -0,0 +1,194 @@
#include "..\script_component.hpp"
/*
* Author: Dystopian
* Initializes object interactions based on animations.
*
* Arguments:
* 0: Target <OBJECT>
*
* Return Value:
* None
*
* Example:
* cursorObject call ace_interaction_fnc_initAnimActions
*
* Public: No
*/
params ["_object"];
private _class = typeOf _object;
if (_class in GVAR(initializedAnimClasses)) exitWith {};
GVAR(initializedAnimClasses) pushBack _class;
private _statement = {
params ["_target", "_player", "_params"];
_params params ["_anim", "_phase", "_duration", "_text"];
TRACE_5("statement",_target,_player,_anim,_phase,_duration);
[
_duration,
[_target, _player, _anim, _phase],
{
(_this select 0) params ["_target", "_player", "_anim", "_phase"];
private _items = _target getVariable [
format [QGVAR(animsItems_%1), _anim],
getArray (configOf _target >> QGVAR(anims) >> _anim >> "items")
];
// If 1 object was spawned in, consider it a success
private _success = false;
if (_items isNotEqualTo []) then {
if (_items isEqualType "") then {
_items = [_items];
};
private _weaponHolder = objNull;
{
private _type = (_x call EFUNC(common,getItemType)) select 0;
if (_type == "") then {
private _emptyPosAGL = [];
// This covers testing vehicle stability and finding a safe position
for "_i" from 1 to 3 do {
_emptyPosAGL = [_target, _x, _player] call EFUNC(common,findUnloadPosition);
if (_emptyPosAGL isNotEqualTo []) exitWith {};
};
// If still no valid position, try the next item
if (_emptyPosAGL isEqualTo []) then {
[LELSTRING(common,NoRoomToUnload)] call EFUNC(common,displayTextStructured);
continue;
};
private _object = createVehicle [_x, _emptyPosAGL, [], 0, "CAN_COLLIDE"];
if (!isNull _object) then {
// Prevent items from taking damage when unloaded
[_object, "blockDamage", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
[EFUNC(common,statusEffect_set), [_object, "blockDamage", QUOTE(ADDON), false], 2] call CBA_fnc_waitAndExecute;
_success = true;
} else {
WARNING_1("Failed to create object of type '%1'",_x);
};
continue;
};
// Functions/code below are guaranteed to spawn in objects
_success = true;
// getItemType considers backpacks as weapons, so handle them first
if (getNumber (configFile >> "CfgVehicles" >> _x >> "isBackpack") == 1) then {
if (backpack _player == "") then {
_player addBackpackGlobal _x;
} else {
if (isNull _weaponHolder) then {
_weaponHolder = nearestObject [_player, "WeaponHolder"];
if (isNull _weaponHolder || {_player distance _weaponHolder > 2}) then {
_weaponHolder = createVehicle ["GroundWeaponHolder", [0, 0, 0], [], 0, "NONE"];
_weaponHolder setPosASL getPosASL _player;
};
};
_weaponHolder addBackpackCargoGlobal [_x, 1];
};
continue;
};
switch (_type) do {
case "weapon": {
[_player, _x, true] call CBA_fnc_addWeapon;
};
case "item": {
[_player, _x, true] call CBA_fnc_addItem;
};
case "magazine": {
[_player, _x, -1, true] call CBA_fnc_addMagazine;
};
};
} forEach _items;
};
if (!_success) exitWith {};
_target animate [_anim, _phase, true];
},
{},
_text,
{
(_this select 0) params ["_target", "", "_anim", "_phase"];
_target animationPhase _anim != _phase
},
["isNotSwimming"]
] call EFUNC(common,progressBar);
};
private _condition = {
params ["_target", "_player", "_params"];
_params params ["_anim", "_phase"];
_target animationPhase _anim != _phase
&& {[_player, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)}
};
private _config = configOf _object;
{
private _animConfig = _x;
private _anim = configName _animConfig;
private _animationSourcesConfig = _config >> "AnimationSources" >> _anim;
if !(
isClass _animationSourcesConfig // anim exist
&& {0 != [_animationSourcesConfig >> "scope", "NUMBER", 1] call CBA_fnc_getConfigEntry} // anim not hidden
&& {isNumber (_animationSourcesConfig >> "initPhase")} // anim correct (some CUP anims are inherited and cleared)
&& {0 != [_animConfig >> "enabled", "NUMBER", 1] call CBA_fnc_getConfigEntry} // anim enabled
) then {continue};
private _positions = [];
{
if (_x isEqualType "") then {
_positions pushBack compile _x;
} else {
_positions pushBack _x;
};
} forEach getArray (_animConfig >> "positions");
_positions append getArray (_animConfig >> "selections");
if (_positions isEqualTo []) then {
ERROR_2("No action position for _class %1 anim %2",_class,_anim);
continue;
};
private _phase = [_animConfig >> "phase", "NUMBER", 1] call CBA_fnc_getConfigEntry;
private _name = [_animConfig >> "name", "TEXT", localize "str_a3_cfgactions_unmountitem0"] call CBA_fnc_getConfigEntry;
private _icon = [_animConfig >> "icon", "TEXT", "\A3\ui_f\data\igui\cfg\actions\take_ca.paa"] call CBA_fnc_getConfigEntry;
private _duration = [_animConfig >> "duration", "NUMBER", 10] call CBA_fnc_getConfigEntry;
private _text = getText (_animConfig >> "text");
{
private _action = [
format [QGVAR(anim_%1_%2), _anim, _forEachIndex],
_name, _icon, _statement, _condition, {},
[_anim, _phase, _duration, _text],
_x
] call EFUNC(interact_menu,createAction);
[_class, 0, [], _action] call EFUNC(interact_menu,addActionToClass);
TRACE_3("add anim",_class,_anim,_x);
} forEach _positions;
} forEach configProperties [_config >> QGVAR(anims), "isClass _x"];

@ -4,9 +4,12 @@
* Switches weapon attachment.
*
* Arguments:
* 0: Target <OBJECT>
* 1: Player (not used) <OBJECT>
* 0: Target (not used) <OBJECT>
* 1: Player <OBJECT>
* 2: Action params <ARRAY>
* - 0: Weapon <STRING>
* - 1: New Attachment <STRING>
* - 2: Old Attachment <STRING>
*
* Return Value:
* None
@ -17,11 +20,13 @@
* Public: No
*/
params ["_unit", "", "_actionParams"];
params ["", "_unit", "_actionParams"];
_actionParams params ["_weapon", "_newAttachment", "_oldAttachment"];
TRACE_3("Switching attachment",_weapon,_newAttachment,_oldAttachment);
[_unit, "Gear"] call EFUNC(common,doGesture);
private _currWeaponType = [_unit, _weapon] call EFUNC(common,getWeaponIndex);
if (_currWeaponType == -1) exitWith {};
private _addNew = _newAttachment isNotEqualTo "";
private _removeOld = _oldAttachment isNotEqualTo "";
@ -38,22 +43,33 @@ if (_removeOld && {!([_unit, _oldAttachment] call CBA_fnc_canAddItem)}) exitWith
};
};
[_unit, "Gear"] call EFUNC(common,doGesture);
if (_removeOld) then {
[{
params ["_unit", "_weapon", "_oldAttachment"];
switch (_weapon) do {
case (primaryWeapon _unit): {_unit removePrimaryWeaponItem _oldAttachment;};
case (handgunWeapon _unit): {_unit removeHandgunItem _oldAttachment;};
default {_unit removeSecondaryWeaponItem _oldAttachment;};
params ["_unit", "_currWeaponType", "_oldAttachment"];
switch (_currWeaponType) do {
case 0: {_unit removePrimaryWeaponItem _oldAttachment};
case 1: {_unit removeSecondaryWeaponItem _oldAttachment};
case 2: {_unit removeHandgunItem _oldAttachment};
default {};
};
_unit addItem _oldAttachment;
}, [_unit, _weapon, _oldAttachment], 0.3] call CBA_fnc_waitAndExecute;
}, [_unit, _currWeaponType, _oldAttachment], 0.3] call CBA_fnc_waitAndExecute;
};
if (!_addNew) exitWith {};
[{
params ["_unit", "_weapon", "_newAttachment"];
_unit addWeaponItem [_weapon, _newAttachment];
if (_unit != ACE_player) exitWith {};
[[getText (configFile >> "CfgWeapons" >> _newAttachment >> "picture"), 4], true] call CBA_fnc_notify;
playSound "click";
}, [_unit, _weapon, _newAttachment], 1] call CBA_fnc_waitAndExecute;

@ -38,6 +38,16 @@
true
] call CBA_fnc_addSetting;
[
QGVAR(enableAnimActions), "CHECKBOX",
LSTRING(SettingAnimActionsName),
format ["ACE %1", LLSTRING(DisplayName)],
true,
true,
{[QGVAR(enableAnimActions), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_fnc_addSetting;
[
QGVAR(interactWithTerrainObjects), "CHECKBOX",
["str_a3_modules_moduleomquest_defend_f_attributes_useterrainobject0", LSTRING(interactWithTerrainObjects_Description)],

@ -1324,5 +1324,9 @@
<Spanish>Advertencia: puede provocar que algunos objetos choquen con otros.</Spanish>
<Portuguese>Aviso: pode causar que alguns objetos colidam com outros.</Portuguese>
</Key>
<Key ID="STR_ACE_Interaction_SettingAnimActionsName">
<English>Interaction with animations</English>
<Russian>Взаимодействие с анимациями</Russian>
</Key>
</Package>
</Project>

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

@ -1,30 +1,27 @@
#include "script_component.hpp"
[] call FUNC(initItemContextMenu);
addUserActionEventHandler ["headlights", "Deactivate", LINKFUNC(onLightToggled)];
call FUNC(initItemContextMenu);
["ACE3 Equipment", QGVAR(hold), LLSTRING(MomentarySwitch), {
ACE_player action ["GunLightOn", ACE_player];
ACE_player action ["IRLaserOn", ACE_player];
[] call FUNC(onLightToggled);
if !(ACE_player call CBA_fnc_canUseWeapon) exitWith {};
// Save current weapon state to reapply later
private _weaponState = (weaponState ACE_player) select [0, 3];
action ["GunLightOn", ACE_player];
action ["IRLaserOn", ACE_player];
ACE_player selectWeapon _weaponState;
true
}, {
ACE_player action ["GunLightOff", ACE_player];
ACE_player action ["IRLaserOff", ACE_player];
[] call FUNC(onLightToggled);
true
if !(ACE_player call CBA_fnc_canUseWeapon) exitWith {};
// Save current weapon state to reapply later
private _weaponState = (weaponState ACE_player) select [0, 3];
action ["GunLightOff", ACE_player];
action ["IRLaserOff", ACE_player];
ACE_player selectWeapon _weaponState;
}] call CBA_fnc_addKeybind;
["CBA_attachmentSwitched", {
params ["", "", "_item"];
private _substr = _item select [0, 8];
if (
ACE_player getVariable [QGVAR(isTurnedOn), false]
&& {_substr == "ACE_SPIR" || {_substr == "ACE_DBAL"}}
) then {
ACE_player action ["GunLightOn", ACE_player];
ACE_player action ["IRLaserOn", ACE_player];
};
}] call CBA_fnc_addEventHandler;

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

@ -10,7 +10,7 @@
* None
*
* Example:
* [] call ace_irlight_fnc_initItemContextMenu
* call ace_irlight_fnc_initItemContextMenu
*
* Public: No
*/
@ -19,30 +19,34 @@
_x params ["_variant", "_displayName"];
[
"ACE_DBAL_A3_Red", "POINTER", _displayName, [], "", {
"ACE_DBAL_A3_Red",
"POINTER",
_displayName,
[],
"",
{
params ["", "", "_item", "", "_variant"];
private _baseClass = getText (configFile >> "CfgWeapons" >> _item >> "baseWeapon");
_item != _baseClass + _variant
}, {
params ["", "", "_item", "", "_variant"];
params ["_unit", "", "_item", "_slot", "_variant"];
private _weapon = switch (_slot) do {
case "RIFLE_POINTER": {primaryWeapon _unit};
case "LAUNCHER_POINTER": {secondaryWeapon _unit};
case "PISTOL_POINTER": {handgunWeapon _unit};
default {""};
};
if (_weapon == "") exitWith {};
private _baseClass = getText (configFile >> "CfgWeapons" >> _item >> "baseWeapon");
ACE_player removePrimaryWeaponItem _item;
ACE_player addPrimaryWeaponItem (_baseClass + _variant);
playSound "click";
if (_turnedOn) then {
// Force update of flashlight
ACE_player action ["GunLightOff", ACE_player];
{
ACE_player action ["GunLightOn", ACE_player];
ACE_player action ["IRLaserOn", ACE_player];
} call CBA_fnc_execNextFrame;
};
}, false, _variant
[_unit, _weapon, _item, _baseClass + _variant] call EFUNC(common,switchAttachmentMode);
},
false,
_variant
] call CBA_fnc_addItemContextMenuOption;
} forEach [
["", LSTRING(Mode_IRDual)],

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

@ -6,7 +6,7 @@ class CfgPatches {
units[] = {"ACE_Item_Kestrel4500"};
weapons[] = {"ACE_Kestrel4500"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ACE_common", "ACE_weather"};
requiredAddons[] = {"ace_common", "ace_weather"};
author = ECSTRING(common,ACETeam);
authors[] = {ECSTRING(common,ACETeam), "Ruthberg"};
url = ECSTRING(main,URL);

@ -1,3 +1,4 @@
PREP(addHealingCommandActions);
PREP(canRequestMedic);
PREP(healingLogic);
PREP(healSelf);

@ -20,6 +20,9 @@
_unit setVariable [QGVAR(lastSuppressed), CBA_missionTime];
}] call CBA_fnc_addClassEventHandler;
// Add command actions to command AI medics to treat other units
call FUNC(addHealingCommandActions);
if (GVAR(requireItems) == 2) then {
["CAManBase", "InitPost", {
[{

@ -20,6 +20,7 @@ private _itemHash = createHashMap;
} forEach [
["@bandage", ["FieldDressing", "PackingBandage", "ElasticBandage", "QuikClot"]],
["@iv", ["SalineIV", "SalineIV_500", "SalineIV_250", "BloodIV", "BloodIV_500", "BloodIV_250", "PlasmaIV", "PlasmaIV_500", "PlasmaIV_250"]],
["tourniquet", ["ApplyTourniquet"]],
["splint", ["splint"]],
["morphine", ["morphine"]],
["epinephrine", ["epinephrine"]]

@ -0,0 +1,88 @@
#include "..\script_component.hpp"
/*
* Author: johnb43
* Adds ACE actions for the player to command medics to heal injured units.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* call ace_medical_ai_fnc_addHealingCommandActions
*
* Public: No
*/
if (!hasInterface) exitWith {};
private _action = [
QGVAR(heal),
localize "STR_A3_Task180_name",
"",
{},
{_player == leader _player},
{
private _units = units _player;
(_units select {_x call EFUNC(common,isAwake) && {_x call EFUNC(medical_treatment,isMedic)} && {!(_x call EFUNC(common,isPlayer))}}) apply {
[
[
QGVAR(medicHeal_) + str _x,
format ["%1: (%2)", [_x, false, true] call EFUNC(common,getName), groupID _x],
"",
{},
{true},
{
(_this select 2) params ["_healer", "_units"];
(_units select {_x call FUNC(isInjured)}) apply {
[
[
QGVAR(healUnit_) + str _x,
format [localize "str_action_heal_soldier", ([_x, false, true] call EFUNC(common,getName)) + " (" + str groupID _x + ")"],
"",
{
(_this select 2) params ["_healer", "_target"];
private _assignedMedic = _target getVariable [QGVAR(assignedMedic), objNull];
// Remove from previous medic's queue
if (!isNull _assignedMedic && {_healer != _assignedMedic}) then {
private _healQueue = _assignedMedic getVariable [QGVAR(healQueue), []];
_healQueue deleteAt (_healQueue find _target);
_assignedMedic setVariable [QGVAR(healQueue), _healQueue];
};
_target setVariable [QGVAR(assignedMedic), _healer];
// Add to new medic
private _healQueue = _healer getVariable [QGVAR(healQueue), []];
_healQueue deleteAt (_healQueue find _target);
_healQueue insert [0, [_target]];
_healer setVariable [QGVAR(healQueue), _healQueue];
},
{true},
{},
[_healer, _x]
] call EFUNC(interact_menu,createAction),
[],
_x
]
};
},
[_x, _units]
] call EFUNC(interact_menu,createAction),
[],
_x
]
};
}
] call EFUNC(interact_menu,createAction);
["CAManBase", 1, ["ACE_SelfActions"], _action, true] call EFUNC(interact_menu,addActionToClass);

@ -27,7 +27,13 @@ private _healQueue = _this getVariable [QGVAR(healQueue), []];
private _target = _healQueue param [0, objNull];
// If unit died or was healed, be lazy and wait for the next tick
if (!alive _target || {!(_target call FUNC(isInjured))}) exitWith {
// If the unit can't be healed, go to the next unit to be healed
if (!alive _target || {!(_target call FUNC(isInjured))} || {
private _treatmentEvent = (_this getVariable [QGVAR(currentTreatment), []]) param [2, ""];
// Target still needs healing, but the healer doesn't have the required items (only happens if GVAR(requireItems) != 0) or needs to wait
(_treatmentEvent select [0, 6]) == "#needs"
}) exitWith {
_this forceSpeed -1;
_target forceSpeed -1;
_healQueue deleteAt 0;
@ -47,6 +53,10 @@ if (_this distance _target > 2.5) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
if (CBA_missionTime >= (_this getVariable [QGVAR(nextMoveOrder), CBA_missionTime])) then {
_this setVariable [QGVAR(nextMoveOrder), CBA_missionTime + 10];
// Medic, when doing a lot of treatment, moves away from injured over time (because of animations)
// Need to allow the medic to move back to the injured again
_this forceSpeed -1;
_this doMove getPosATL _target;
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 moving to %2", _this, _target];

@ -1,7 +1,9 @@
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut, PabstMirror
* Author: BaerMitUmlaut, PabstMirror, johnb43
* Applies healing to target.
* States that contain "needs" are states in which the medic is blocked, either temporairly (HR too high/low) or until resupplied, from treating.
* States that contain "wait" are states where the medic waits temporairly before continuing treatment.
*
* Arguments:
* 0: Healer <OBJECT>
@ -16,9 +18,6 @@
* Public: No
*/
// TODO: Add AI tourniquet behaviour
// For now, AI handle player or otherwise scripted tourniquets only
params ["_healer", "_target"];
(_healer getVariable [QGVAR(currentTreatment), [-1]]) params ["_finishTime", "_treatmentTarget", "_treatmentEvent", "_treatmentArgs", "_treatmentItem"];
@ -27,13 +26,29 @@ if (_finishTime > 0) exitWith {
if (CBA_missionTime >= _finishTime) then {
TRACE_5("treatment finished",_finishTime,_treatmentTarget,_treatmentEvent,_treatmentArgs,_treatmentItem);
_healer setVariable [QGVAR(currentTreatment), nil];
private _usedItem = "";
if ((GVAR(requireItems) > 0) && {_treatmentItem != ""}) then {
([_healer, _treatmentItem] call FUNC(itemCheck)) params ["_itemOk", "_itemClassname", "_treatmentClass"];
if (!_itemOk) exitWith { _treatmentEvent = "#fail"; }; // no item after delay
// No item after treatment done
if (!_itemOk) exitWith {
_treatmentEvent = "#fail";
};
_healer removeItem _itemClassname;
if (_treatmentClass != "") then { _treatmentArgs set [2, _treatmentClass]; };
_usedItem = _itemClassname;
if (_treatmentClass != "") then {
_treatmentArgs set [2, _treatmentClass];
};
};
if ((_treatmentTarget == _target) && {(_treatmentEvent select [0, 1]) != "#"}) then {
// There is no event for tourniquet removal, so handle calling function directly
if (_treatmentEvent == QGVAR(tourniquetRemove)) exitWith {
_treatmentArgs call EFUNC(medical_treatment,tourniquetRemove);
};
[_treatmentEvent, _treatmentArgs, _target] call CBA_fnc_targetEvent;
// Splints are already logged on their own
@ -42,14 +57,25 @@ if (_finishTime > 0) exitWith {
[_target, "activity", ELSTRING(medical_treatment,Activity_bandagedPatient), [[_healer, false, true] call EFUNC(common,getName)]] call EFUNC(medical_treatment,addToLog);
};
case QEGVAR(medical_treatment,ivBagLocal): {
[_target, _treatmentArgs select 2] call EFUNC(medical_treatment,addToTriageCard);
if (_usedItem == "") then {
_usedItem = "ACE_salineIV";
};
[_target, _usedItem] call EFUNC(medical_treatment,addToTriageCard);
[_target, "activity", ELSTRING(medical_treatment,Activity_gaveIV), [[_healer, false, true] call EFUNC(common,getName)]] call EFUNC(medical_treatment,addToLog);
};
case QEGVAR(medical_treatment,medicationLocal): {
private _usedItem = ["ACE_epinephrine", "ACE_morphine"] select (_treatmentArgs select 2 == "Morphine");
if (_usedItem == "") then {
_usedItem = ["ACE_epinephrine", "ACE_morphine"] select (_treatmentArgs select 2 == "Morphine");
};
[_target, _usedItem] call EFUNC(medical_treatment,addToTriageCard);
[_target, "activity", ELSTRING(medical_treatment,Activity_usedItem), [[_healer, false, true] call EFUNC(common,getName), getText (configFile >> "CfgWeapons" >> _usedItem >> "displayName")]] call EFUNC(medical_treatment,addToLog);
};
case QEGVAR(medical_treatment,tourniquetLocal): {
[_target, "ACE_tourniquet"] call EFUNC(medical_treatment,addToTriageCard);
[_target, "activity", ELSTRING(medical_treatment,Activity_appliedTourniquet), [[_healer, false, true] call EFUNC(common,getName)]] call EFUNC(medical_treatment,addToLog);
};
};
#ifdef DEBUG_MODE_FULL
@ -60,32 +86,85 @@ if (_finishTime > 0) exitWith {
};
};
// Find a suitable limb (no tourniquets) for injecting and giving IVs
private _fnc_findNoTourniquet = {
private _bodyPart = "";
private _bodyParts = ["leftarm", "rightarm", "leftleg", "rightleg"];
private _bodyPartsSaved = +_bodyParts;
// Bandage a limb up, then remove the tourniquet on it
private _fnc_removeTourniquet = {
params [["_removeAllTourniquets", false]];
while {_bodyParts isNotEqualTo []} do {
_bodyPart = selectRandom _bodyParts;
// Ignore head & torso if not removing all tourniquets (= administering drugs/IVs)
private _offset = [2, 0] select _removeAllTourniquets;
// If no tourniquet on, use that body part
if (_tourniquets select (ALL_BODY_PARTS find _bodyPart) == 0) exitWith {};
// Bandage the least bleeding body part
private _bodyPartBleeding = [];
_bodyPartBleeding resize [[4, 6] select _removeAllTourniquets, -1];
_bodyParts deleteAt (_bodyParts find _bodyPart);
{
// Ignore head and torso, if only looking for place to administer drugs/IVs
private _partIndex = (ALL_BODY_PARTS find _x) - _offset;
if (_partIndex >= 0 && {_tourniquets select _partIndex != 0}) then {
{
_x params ["", "_amountOf", "_bleeding"];
// max 0, to set the baseline to 0, as body parts with no wounds are marked with -1
_bodyPartBleeding set [_partIndex, ((_bodyPartBleeding select _partIndex) max 0) + (_amountOf * _bleeding)];
} forEach _y;
};
} forEach GET_OPEN_WOUNDS(_target);
// If there are no open wounds, check if there are tourniquets on limbs with no open wounds (stitched or fully healed),
// as we know there have to be tourniquets at this point
if (_bodyPartBleeding findIf {_x != -1} == -1) then {
_bodyPartBleeding set [_tourniquets findIf {_x != 0}, 0];
};
// If all limbs have tourniquets, use random limb
if (_bodyPart == "") then {
_bodyPart = selectRandom _bodyPartsSaved;
// Ignore body parts that don't have open wounds (-1)
private _minBodyPartBleeding = selectMin (_bodyPartBleeding select {_x != -1});
private _selection = ALL_BODY_PARTS select ((_bodyPartBleeding find _minBodyPartBleeding) + _offset);
// If not bleeding anymore, remove the tourniquet
if (_minBodyPartBleeding == 0) exitWith {
_treatmentEvent = QGVAR(tourniquetRemove);
_treatmentTime = 7;
_treatmentArgs = [_healer, _target, _selection];
};
_bodyPart
// If no bandages available, wait
// If check is done at the start of the scope, it will miss the edge case where the unit ran out of bandages just as they finished bandaging tourniqueted body part
if !(([_healer, "@bandage"] call FUNC(itemCheck)) # 0) exitWith {
_treatmentEvent = "#needsBandage";
};
// Otherwise keep bandaging
_treatmentEvent = QEGVAR(medical_treatment,bandageLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, _selection, "FieldDressing"];
_treatmentItem = "@bandage";
};
// Find a suitable limb (no tourniquets) for adminstering drugs/IVs
private _fnc_findNoTourniquet = {
private _bodyPart = "";
// If all limbs have tourniquets, find the least damaged limb and try to bandage it
if ((_tourniquets select [2]) find 0 == -1) then {
call _fnc_removeTourniquet;
} else {
// Select a random non-tourniqueted limb otherwise
private _bodyParts = ["leftarm", "rightarm", "leftleg", "rightleg"];
while {_bodyParts isNotEqualTo []} do {
_bodyPart = selectRandom _bodyParts;
// If no tourniquet on, use that body part
if (_tourniquets select (ALL_BODY_PARTS find _bodyPart) == 0) exitWith {};
_bodyParts deleteAt (_bodyParts find _bodyPart);
};
};
_bodyPart // return
};
private _isMedic = [_healer] call EFUNC(medical_treatment,isMedic);
private _heartRate = GET_HEART_RATE(_target);
private _fractures = GET_FRACTURES(_target);
private _tourniquets = GET_TOURNIQUETS(_target);
private _treatmentEvent = "#none";
@ -94,46 +173,77 @@ private _treatmentTime = 6;
private _treatmentItem = "";
if (true) then {
if (
(GET_WOUND_BLEEDING(_target) > 0) &&
{([_healer, "@bandage"] call FUNC(itemCheck)) # 0}
) exitWith {
// Select first bleeding wound and bandage it
private _selection = "?";
if (IS_BLEEDING(_target)) exitWith {
private _hasBandage = ([_healer, "@bandage"] call FUNC(itemCheck)) # 0;
private _hasTourniquet = ([_healer, "tourniquet"] call FUNC(itemCheck)) # 0;
// Patient is not worth treating if bloodloss can't be stopped
if !(_hasBandage || _hasTourniquet) exitWith {
_treatmentEvent = "#needsBandageOrTourniquet";
};
// Bandage the heaviest bleeding body part
private _bodyPartBleeding = [0, 0, 0, 0, 0, 0];
{
private _partIndex = ALL_BODY_PARTS find _x;
// Ignore tourniqueted limbs
if (_tourniquets select (ALL_BODY_PARTS find _x) == 0 && {
_y findIf {
_x params ["", "_amount", "_percentage"];
(_amount * _percentage) > 0
} != -1}
) exitWith { _selection = _x; };
if (_tourniquets select _partIndex == 0) then {
{
_x params ["", "_amountOf", "_bleeding"];
_bodyPartBleeding set [_partIndex, (_bodyPartBleeding select _partIndex) + (_amountOf * _bleeding)];
} forEach _y;
};
} forEach GET_OPEN_WOUNDS(_target);
private _maxBodyPartBleeding = selectMax _bodyPartBleeding;
private _bodyPartIndex = _bodyPartBleeding find _maxBodyPartBleeding;
private _selection = ALL_BODY_PARTS select _bodyPartIndex;
// Apply tourniquet if moderate bleeding or no bandage is available, and if not head and torso
if (_hasTourniquet && {_bodyPartIndex > HITPOINT_INDEX_BODY} && {!_hasBandage || {_maxBodyPartBleeding > 0.3}}) exitWith {
_treatmentEvent = QEGVAR(medical_treatment,tourniquetLocal);
_treatmentTime = 7;
_treatmentArgs = [_target, _selection];
_treatmentItem = "tourniquet";
};
_treatmentEvent = QEGVAR(medical_treatment,bandageLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, _selection, "FieldDressing"];
_treatmentItem = "@bandage";
};
private _hasIV = ([_healer, "@iv"] call FUNC(itemCheck)) # 0;
private _bloodVolume = GET_BLOOD_VOLUME(_target);
private _needsIV = _bloodVolume < MINIMUM_BLOOD_FOR_STABLE_VITALS;
private _canGiveIV = _needsIV &&
{_healer call EFUNC(medical_treatment,isMedic)} &&
{([_healer, "@iv"] call FUNC(itemCheck)) # 0}; // Has IVs
private _doCPR = IN_CRDC_ARRST(_target) && {EGVAR(medical_treatment,cprSuccessChanceMin) > 0};
// If in cardiac arrest, first add some blood to injured if necessary, then do CPR (doing CPR when not enough blood is suboptimal if you have IVs)
// If healer has no IVs, allow AI to do CPR to keep injured alive
if (
IN_CRDC_ARRST(_target) &&
{EGVAR(medical_treatment,cprSuccessChanceMin) > 0} &&
{!_hasIV || {_bloodVolume >= BLOOD_VOLUME_CLASS_3_HEMORRHAGE}}
_doCPR &&
{!_canGiveIV || {_bloodVolume >= BLOOD_VOLUME_CLASS_3_HEMORRHAGE}}
) exitWith {
_treatmentEvent = QEGVAR(medical_treatment,cprLocal);
_treatmentArgs = [_healer, _target];
_treatmentTime = 15;
};
private _needsIv = _bloodVolume < MINIMUM_BLOOD_FOR_STABLE_VITALS;
private _canGiveIv = _isMedic && _hasIV && _needsIv;
private _bodypart = "";
if (_canGiveIv) then {
if (
_canGiveIV && {
// If all limbs are tourniqueted, bandage the one with the least amount of wounds, so that the tourniquet can be removed
_bodyPart = call _fnc_findNoTourniquet;
_bodyPart == ""
}
) exitWith {};
if (_canGiveIV) then {
// Check if patient's blood volume + remaining IV volume is enough to allow the patient to wake up
private _totalIvVolume = 0; //in ml
{
@ -144,79 +254,129 @@ if (true) then {
// Check if the medic has to wait, which allows for a little multitasking
if (_bloodVolume + (_totalIvVolume / 1000) >= MINIMUM_BLOOD_FOR_STABLE_VITALS) then {
_treatmentEvent = "#waitForIV";
_canGiveIv = false;
_needsIV = false;
_canGiveIV = false;
};
};
if (_canGiveIv) exitWith {
if (_canGiveIV) exitWith {
_treatmentEvent = QEGVAR(medical_treatment,ivBagLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, call _fnc_findNoTourniquet, "SalineIV"];
_treatmentArgs = [_target, _bodyPart, "SalineIV"];
_treatmentItem = "@iv";
};
if (
((_fractures select 4) == 1) &&
{([_healer, "splint"] call FUNC(itemCheck)) # 0}
) exitWith {
_treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6;
_treatmentArgs = [_healer, _target, "leftleg"];
_treatmentItem = "splint";
};
// Leg fractures
private _index = (GET_FRACTURES(_target) select [4, 2]) find 1;
if (
((_fractures select 5) == 1) &&
{([_healer, "splint"] call FUNC(itemCheck)) # 0}
_index != -1 && {
// In case the unit doesn't have a splint, set state here
_treatmentEvent = "#needsSplint";
([_healer, "splint"] call FUNC(itemCheck)) # 0
}
) exitWith {
_treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6;
_treatmentArgs = [_healer, _target, "rightleg"];
_treatmentArgs = [_healer, _target, ALL_BODY_PARTS select (_index + 4)];
_treatmentItem = "splint";
};
// Wait until the injured has enough blood before administering drugs
if (_needsIv) then {
_treatmentEvent = "#waitForIV"
// (_needsIV && !_canGiveIV), but _canGiveIV is false here, otherwise IV would be given
if (_needsIV || {_doCPR && {_treatmentEvent == "#waitForIV"}}) exitWith {
// If injured is in cardiac arrest and the healer is doing nothing else, start CPR
if (_doCPR) exitWith {
// Medic remains in this loop until injured is given enough IVs or dies
_treatmentEvent = QEGVAR(medical_treatment,cprLocal);
_treatmentArgs = [_healer, _target];
_treatmentTime = 15;
};
// If the injured needs IVs, but healer can't give it to them, have healder wait
if (_needsIV) exitWith {
_treatmentEvent = "#needsIV";
};
};
if (_treatmentEvent == "#waitForIV") exitWith {};
if ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6) exitWith {
_treatmentEvent = "#tooManyMeds";
// These checks are not exitWith, so that the medic can try to bandage up tourniqueted body parts
if ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6) then {
_treatmentEvent = "#needsFewerMeds";
};
if (
((IS_UNCONSCIOUS(_target) && {_heartRate < 160}) || {_heartRate <= 50}) &&
{([_healer, "epinephrine"] call FUNC(itemCheck)) # 0}
) exitWith {
if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) exitWith {
private _heartRate = GET_HEART_RATE(_target);
private _canGiveEpinephrine = !(_treatmentEvent in ["#needsFewerMeds", "#waitForIV"]) &&
{IS_UNCONSCIOUS(_target) || {_heartRate <= 50}} &&
{
// In case the unit doesn't have a epinephrine injector, set state here
_treatmentEvent = "#needsEpinephrine";
([_healer, "epinephrine"] call FUNC(itemCheck)) # 0
};
// This allows for some multitasking
if (_canGiveEpinephrine) then {
if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) then {
_treatmentEvent = "#waitForEpinephrineToTakeEffect";
_canGiveEpinephrine = false;
};
if (_heartRate > 180) exitWith {
_treatmentEvent = "#waitForSlowerHeart";
if (_heartRate > 180) then {
_treatmentEvent = "#needsSlowerHeart";
_canGiveEpinephrine = false;
};
};
if (_canGiveEpinephrine) exitWith {
// If all limbs are tourniqueted, bandage the one with the least amount of wounds, so that the tourniquet can be removed
_bodyPart = call _fnc_findNoTourniquet;
if (_bodyPart == "") exitWith {};
_target setVariable [QGVAR(nextEpinephrine), CBA_missionTime + 10];
_treatmentEvent = QEGVAR(medical_treatment,medicationLocal);
_treatmentTime = 2.5;
_treatmentArgs = [_target, call _fnc_findNoTourniquet, "Epinephrine"];
_treatmentArgs = [_target, _bodyPart, "Epinephrine"];
_treatmentItem = "epinephrine";
};
// Remove all remaining tourniquets by bandaging all body parts
if (_tourniquets isNotEqualTo DEFAULT_TOURNIQUET_VALUES) then {
true call _fnc_removeTourniquet;
};
// If the healer can bandage or remove tourniquets, do that
if (_treatmentEvent in [QEGVAR(medical_treatment,bandageLocal), QGVAR(tourniquetRemove)]) exitWith {};
// Otherwise, if the healer is either done or out of bandages, continue
if (
(((GET_PAIN_PERCEIVED(_target) > 0.25) && {_heartRate > 40}) || {_heartRate >= 180}) &&
{([_healer, "morphine"] call FUNC(itemCheck)) # 0}
!(_treatmentEvent in ["#needsFewerMeds", "#waitForIV"]) &&
{(GET_PAIN_PERCEIVED(_target) > 0.25) || {_heartRate >= 180}} &&
{
// In case the unit doesn't have a morphine injector, set state here
_treatmentEvent = "#needsMorphine";
([_healer, "morphine"] call FUNC(itemCheck)) # 0
}
) exitWith {
if (CBA_missionTime < (_target getVariable [QGVAR(nextMorphine), -1])) exitWith {
_treatmentEvent = "#waitForMorphineToTakeEffect";
};
if (_heartRate < 60) exitWith {
_treatmentEvent = "#waitForFasterHeart";
_treatmentEvent = "#needsFasterHeart";
};
// If all limbs are tourniqueted, bandage the one with the least amount of wounds, so that the tourniquet can be removed
_bodyPart = call _fnc_findNoTourniquet;
if (_bodyPart == "") exitWith {};
_target setVariable [QGVAR(nextMorphine), CBA_missionTime + 30];
_treatmentEvent = QEGVAR(medical_treatment,medicationLocal);
_treatmentTime = 2.5;
_treatmentArgs = [_target, call _fnc_findNoTourniquet, "Morphine"];
_treatmentArgs = [_target, _bodyPart, "Morphine"];
_treatmentItem = "morphine";
};
};
@ -224,11 +384,16 @@ if (true) then {
_healer setVariable [QGVAR(currentTreatment), [CBA_missionTime + _treatmentTime, _target, _treatmentEvent, _treatmentArgs, _treatmentItem]];
// Play animation
if ((_treatmentEvent select [0,1]) != "#") then {
private _treatmentClassname = _treatmentArgs select 2;
if (_treatmentEvent == QEGVAR(medical_treatment,splintLocal)) then { _treatmentClassname = "Splint" };
if (_treatmentEvent == QEGVAR(medical_treatment,cprLocal)) then { _treatmentClassname = "CPR" };
[_healer, _treatmentClassname, (_healer == _target)] call FUNC(playTreatmentAnim);
if ((_treatmentEvent select [0, 1]) != "#") then {
private _treatmentClassname = switch (_treatmentEvent) do {
case QEGVAR(medical_treatment,splintLocal): {"Splint"};
case QEGVAR(medical_treatment,cprLocal): {"CPR"};
case QEGVAR(medical_treatment,tourniquetLocal): {"ApplyTourniquet"};
case QGVAR(tourniquetRemove): {"RemoveTourniquet"};
default {_treatmentArgs select 2};
};
[_healer, _treatmentClassname, _healer == _target] call FUNC(playTreatmentAnim);
};
#ifdef DEBUG_MODE_FULL

@ -24,3 +24,4 @@ if !(alive _this) exitWith {false};
private _fractures = GET_FRACTURES(_this);
((_fractures select 4) == 1) || {(_fractures select 5) == 1}
}
|| { GET_TOURNIQUETS(_this) isNotEqualTo DEFAULT_TOURNIQUET_VALUES }

@ -9,3 +9,9 @@ class Extended_PreInit_EventHandlers {
init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
};
};
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
};
};

Some files were not shown because too many files have changed in this diff Show More