Merge remote-tracking branch 'upstream' into csw-fix-belt-linking

This commit is contained in:
Salluci 2023-07-12 23:42:16 +03:00
commit 3b42998f7b
54 changed files with 834 additions and 134 deletions

View File

@ -105,6 +105,7 @@ PREP(handleModifierKey);
PREP(handleModifierKeyUp);
PREP(hasItem);
PREP(hasMagazine);
PREP(hasZeusAccess);
PREP(headBugFix);
PREP(hideUnit);
PREP(interpolateFromArray);

View File

@ -16,10 +16,7 @@
*/
params ["_code"];
if (_code isEqualType "") exitWith {_code};
_code = str(_code);
_code = _code select [1, count _code - 2];
_code
toString _code

View File

@ -0,0 +1,19 @@
#include "script_component.hpp"
/*
* Author: LinkIsGrim
* Check if current player has Zeus access
*
* Arguments:
* None
*
* Return Value:
* Has Zeus <BOOL>
*
* Example:
* call ace_common_fnc_hasZeusAccess
*
* Public: Yes
*/
// Use of player is intentional
!isNull getAssignedCuratorLogic player // return

View File

@ -40,6 +40,11 @@ class Extended_Init_EventHandlers {
init = QUOTE(_this call DFUNC(initObject));
};
};
class WeaponHolder {
class ADDON {
init = QUOTE(_this call DFUNC(initObject));
};
};
class Land_Camping_Light_F {
class ADDON {
init = QUOTE(_this call DFUNC(initObject));

View File

@ -226,6 +226,32 @@ class CfgVehicles {
GVAR(canCarry) = 1;
};
// weapons dropped from dead body
class WeaponHolderSimulated: ThingX {
GVAR(canCarry) = 1;
GVAR(carryPosition[]) = {0,0.5,1.3};
GVAR(carryDirection) = 0;
// z-position floats from -1.2 to >0
// it's OK for carrying but odd for dragging
// needs workaround to drag correctly. Disabled ATM
GVAR(canDrag) = 0;
GVAR(dragPosition[]) = {0,1,0};
GVAR(dragDirection) = 0;
};
class ReammoBox;
// dropped weapons/gear
class WeaponHolder: ReammoBox {
GVAR(canCarry) = 1;
GVAR(carryPosition[]) = {0,0.5,1};
GVAR(carryDirection) = 0;
GVAR(canDrag) = 1;
GVAR(dragPosition[]) = {0,1,0};
GVAR(dragDirection) = 0;
};
class Lamps_base_F;
class Land_PortableLight_single_F: Lamps_base_F {
GVAR(canCarry) = 1;

View File

@ -1,6 +1,6 @@
#include "script_component.hpp"
/*
* Author: commy2
* Author: commy2, Dystopian
* Check if unit can carry the object. Doesn't check weight.
*
* Arguments:
@ -11,20 +11,35 @@
* Can the unit carry the object? <BOOL>
*
* Example:
* [player, cursorTarget] call ace_dragging_fnc_canCarry;
* [player, cursorTarget] call ace_dragging_fnc_canCarry
*
* Public: No
*/
params ["_unit", "_target"];
if !(alive _target && {_target getVariable [QGVAR(canCarry), false]} && {isNull objectParent _target}) exitWith {false};
if !([_unit, _target, []] call EFUNC(common,canInteractWith)) exitWith {false};
//#2644 - Units with injured legs cannot bear the extra weight of carrying an object
//The fireman carry animation does not slow down for injured legs, so you could carry and run
if ((_unit getHitPointDamage "HitLegs") >= 0.5) exitWith {false};
// a static weapon has to be empty for dragging (ignore UAV AI)
if (((typeOf _target) isKindOf "StaticWeapon") && {{(getText (configOf _x >> "simulation")) != "UAVPilot"} count crew _target > 0}) exitWith {false};
// Static weapons need to be empty for carrying (ignore UAV AI)
if (_target isKindOf "StaticWeapon") exitWith {
crew _target findIf {getText (configOf _x >> "simulation") != "UAVPilot"} == -1
};
alive _target && {vehicle _target isEqualto _target} && {_target getVariable [QGVAR(canCarry), false]} && {animationState _target in ["", "unconscious"] || (_target getVariable ["ACE_isUnconscious", false]) || (_target isKindOf "CAManBase" && {(_target getHitPointDamage "HitLegs") > 0.4})}
// Units need to be unconscious or limping
if (_target isKindOf "CAManBase") exitWith {
lifeState _target isEqualTo "INCAPACITATED"
|| {_target getHitPointDamage "HitLegs" >= 0.5}
};
// Check max items for WeaponHolders
if (["WeaponHolder", "WeaponHolderSimulated"] findIf {_target isKindOf _x} != -1) exitWith {
(count (weaponCargo _target + magazineCargo _target + itemCargo _target)) <= MAX_DRAGGED_ITEMS
};
true // return

View File

@ -1,6 +1,6 @@
#include "script_component.hpp"
/*
* Author: commy2
* Author: commy2, Dystopian
* Check if unit can drag the object. Doesn't check weight.
*
* Arguments:
@ -11,16 +11,31 @@
* Can the unit drag the object? <BOOL>
*
* Example:
* [player, cursorTarget] call ace_dragging_fnc_canDrag;
* [player, cursorTarget] call ace_dragging_fnc_canDrag
*
* Public: No
*/
params ["_unit", "_target"];
if !(alive _target && {_target getVariable [QGVAR(canDrag), false]} && {isNull objectParent _target}) exitWith {false};
if !([_unit, _target, ["isNotSwimming"]] call EFUNC(common,canInteractWith)) exitWith {false};
// a static weapon has to be empty for dragging (ignore UAV AI)
if ((typeOf _target) isKindOf "StaticWeapon" && {{(getText (configOf _x >> "simulation")) != "UAVPilot"} count crew _target > 0}) exitWith {false};
// Static weapons need to be empty for dragging (ignore UAV AI)
if (_target isKindOf "StaticWeapon") exitWith {
crew _target findIf {getText (configOf _x >> "simulation") != "UAVPilot"} == -1
};
alive _target && {vehicle _target isEqualto _target} && {_target getVariable [QGVAR(canDrag), false]} && {animationState _target in ["", "unconscious"] || (_target getVariable ["ACE_isUnconscious", false]) || (_target isKindOf "CAManBase" && {(_target getHitPointDamage "HitLegs") > 0.4})}
// Units need to be unconscious or limping
if (_target isKindOf "CAManBase") exitWith {
lifeState _target isEqualTo "INCAPACITATED"
|| {_target getHitPointDamage "HitLegs" >= 0.5}
};
// Check max items for WeaponHolders
if (["WeaponHolder", "WeaponHolderSimulated"] findIf {_target isKindOf _x} != -1) exitWith {
(count (weaponCargo _target + magazineCargo _target + itemCargo _target)) <= MAX_DRAGGED_ITEMS
};
true // return

View File

@ -33,8 +33,8 @@ if !(_unit getVariable [QGVAR(isCarrying), false]) exitWith {
[_idPFH] call CBA_fnc_removePerFrameHandler;
};
// drop if the crate is destroyed OR (target moved away from carrier (weapon disasembled))
if (!alive _target || {_unit distance _target > 10}) exitWith {
// drop if the crate is destroyed OR target moved away from carrier (weapon disassembled) OR carrier starts limping
if !(alive _target && {_unit distance _target <= 10} && {_unit getHitPointDamage "HitLegs" < 0.5}) exitWith {
TRACE_2("dead/distance",_unit,_target);
if ((_unit distance _target > 10) && {(CBA_missionTime - _startTime) < 1}) exitWith {
//attachTo seems to have some kind of network delay and target can return an odd position during the first few frames,

View File

@ -20,3 +20,5 @@
#define DRAG_ANIMATIONS ["amovpercmstpslowwrfldnon_acinpknlmwlkslowwrfldb_2", "amovpercmstpsraswpstdnon_acinpknlmwlksnonwpstdb_2", "amovpercmstpsnonwnondnon_acinpknlmwlksnonwnondb_2", "acinpknlmstpsraswrfldnon", "acinpknlmstpsnonwpstdnon", "acinpknlmstpsnonwnondnon", "acinpknlmwlksraswrfldb", "acinpknlmwlksnonwnondb", "ace_dragging", "ace_dragging_static", "ace_dragging_drop"]
#define CARRY_ANIMATIONS ["acinpercmstpsnonwnondnon", "acinpknlmstpsnonwnondnon_acinpercmrunsnonwnondnon"]
#define MAX_DRAGGED_ITEMS 3

View File

@ -40,6 +40,7 @@ class CfgWeapons {
XGVAR(replacementItem) = "ACE_WaterBottle_Half";
XGVAR(consumeAnims)[] = {QGVAR(drinkStand), QGVAR(drinkCrouch), QGVAR(drinkProne)};
XGVAR(consumeSounds)[] = {QGVAR(drink1), QGVAR(drink1), QGVAR(drink2)};
ACE_isFieldRationItem = 1;
};
class ACE_WaterBottle_Half: ACE_WaterBottle {
@ -87,6 +88,7 @@ class CfgWeapons {
XGVAR(replacementItem) = "ACE_Canteen_Half";
XGVAR(consumeAnims)[] = {QGVAR(drinkStand), QGVAR(drinkCrouch), QGVAR(drinkProne)};
XGVAR(consumeSounds)[] = {QGVAR(drink1), QGVAR(drink1), QGVAR(drink2)};
ACE_isFieldRationItem = 1;
};
class ACE_Canteen_Half: ACE_Canteen {
@ -132,6 +134,7 @@ class CfgWeapons {
XGVAR(consumeText) = CSTRING(DrinkingX);
XGVAR(consumeAnims)[] = {QGVAR(drinkStandCan), QGVAR(drinkCrouchCan), QGVAR(drinkProneCan)};
XGVAR(consumeSounds)[] = {QGVAR(drinkCan1), QGVAR(drinkCan1), QGVAR(drinkCan2)};
ACE_isFieldRationItem = 1;
};
class ACE_Can_Franta: ACE_Can_Spirit {
@ -164,6 +167,7 @@ class CfgWeapons {
XGVAR(consumeTime) = 10;
XGVAR(hungerSatiated) = 20;
XGVAR(consumeText) = CSTRING(EatingX);
ACE_isFieldRationItem = 1;
};
class ACE_MRE_BeefStew: ACE_MRE_LambCurry {
@ -225,7 +229,7 @@ class CfgWeapons {
model = QPATHTOF(data\mre_human.p3d);
picture = QPATHTOF(ui\item_mre_human_co.paa);
};
// - Misc Food ------------------------------------------------------------
class ACE_Sunflower_Seeds: ACE_ItemCore {
author = ECSTRING(common,ACETeam);
@ -240,5 +244,6 @@ class CfgWeapons {
XGVAR(consumeTime) = 10;
XGVAR(hungerSatiated) = 10;
XGVAR(consumeText) = CSTRING(EatingX);
ACE_isFieldRationItem = 1;
};
};

View File

@ -14,5 +14,6 @@ ACEX_PREP(handleEffects);
ACEX_PREP(handleHUD);
ACEX_PREP(handleRespawn);
ACEX_PREP(refillItem);
ACEX_PREP(scanFieldRations);
ACEX_PREP(setRemainingWater);
ACEX_PREP(update);

View File

@ -8,6 +8,8 @@ PREP_RECOMPILE_END;
#include "initSettings.sqf"
#define ARSENAL_CATEGORY_ICON QPATHTOF(ui\icon_survival.paa)
// Init arrays of status modifiers
GVAR(thirstModifiers) = [];
GVAR(hungerModifiers) = [];
@ -18,4 +20,9 @@ GVAR(waterSourceP3Ds) = _cache select 0;
// List of refill action offsets corresponding to the p3ds in the array above
GVAR(waterSourceOffsets) = _cache select 1;
// Custom Arsenal Tab
if (["ace_arsenal"] call EFUNC(common,isModLoaded)) then {
[keys FIELD_RATIONS_ITEMS, LLSTRING(DisplayName), ARSENAL_CATEGORY_ICON] call EFUNC(arsenal,addRightPanelButton);
};
ADDON = true;

View File

@ -30,3 +30,5 @@ private _waterSourceOffsets = [
uiNamespace setVariable [QGVAR(cacheP3Ds), compileFinal str [_waterSourceP3Ds, _waterSourceOffsets]];
TRACE_1("compiled",count _waterSourceP3Ds);
call FUNC(scanFieldRations);

View File

@ -0,0 +1,34 @@
#include "script_component.hpp"
/*
* Author: Salluci
* Caches all item classnames used as field rations, their thirst/hunger values, and whether they are treated as magazines
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* call acex_field_rations_fnc_scanFieldRations
*
* Public: No
*/
private _list = createHashMap;
private _cfgWeapons = configFile >> "CfgWeapons";
private _cfgMagazines = configFile >> "CfgMagazines";
private _fnc_isFieldRationItem = toString {
(getNumber (_x >> "ACE_isFieldRationItem") isEqualTo 1) || {(getNumber (_x >> QXGVAR(thirstQuenched))) > 0} || {(getNumber (_x >> QXGVAR(hungerSatiated))) > 0} || {(getText (_x >> QXGVAR(refillItem))) isNotEqualTo ""}
};
{
_list set [configName _x, ""];
} forEach (_fnc_isFieldRationItem configClasses _cfgWeapons);
{
_list set [configName _x, ""];
} forEach (_fnc_isFieldRationItem configClasses _cfgMagazines);
uiNamespace setVariable [QXGVAR(fieldRationItems), compileFinal str _list];

View File

@ -33,3 +33,5 @@
#define IDC_DRAINING_HUD_THIRST_ICON 7750
#define IDC_DRAINING_HUD_HUNGER_GROUP 7840
#define IDC_DRAINING_HUD_HUNGER_ICON 7850
#define FIELD_RATIONS_ITEMS (createHashMapFromArray (call (uiNamespace getVariable [QXGVAR(fieldRationItems), {createHashMap}])))

View File

@ -49,6 +49,11 @@ PREP_RECOMPILE_END;
private _gunbagWeapon = _extendedInfo getOrDefault [QGVAR(gunbagWeapon), []];
if (_gunbagWeapon isNotEqualTo []) then {
(backpackContainer _unit) setVariable [QGVAR(gunbagWeapon), _gunbagWeapon, true];
// Prevent the arsenal closed event from overwriting new info
if (!isNil QGVAR(arsenalCache)) then {
GVAR(arsenalCache) = _gunbagWeapon;
};
};
}] call CBA_fnc_addEventHandler;

View File

@ -162,6 +162,12 @@ class CfgVehicles {
exceptions[] = {"isNotSwimming"};
icon = "\a3\ui_f\data\IGUI\Cfg\simpleTasks\types\getout_ca.paa";
};
class GVAR(Gear) {
displayName = "$STR_ACTION_GEAR";
condition = QUOTE(!(lifeState _target in [ARR_2('HEALTHY','INJURED')]) && {isNull objectParent _target});
statement = QUOTE(_player action [ARR_2(QUOTE(QUOTE(Gear)),_target)]);
icon = "\A3\ui_f\data\igui\cfg\actions\gear_ca.paa";
};
};
class ACE_Torso {
@ -693,6 +699,41 @@ class CfgVehicles {
class ACE_SelfActions {};
};
// weapons dropped from dead body
class WeaponHolderSimulated: ThingX {
class ACE_Actions {
class ACE_MainActions {
displayName = CSTRING(MainAction);
distance = 3;
position = QUOTE(_target worldToModel ASLToAGL getPosASL _target);
class GVAR(Gear) {
displayName = "$STR_ACTION_GEAR";
statement = QUOTE(_player action [ARR_2(QUOTE(QUOTE(Gear)),_target)]);
icon = "\A3\ui_f\data\igui\cfg\actions\gear_ca.paa";
};
};
};
};
class ReammoBox;
// dropped weapons/gear
class WeaponHolder: ReammoBox {
class ACE_Actions {
class ACE_MainActions {
displayName = CSTRING(MainAction);
distance = 3;
position = QUOTE(_target worldToModel ASLToAGL getPosASL _target);
class GVAR(Gear) {
displayName = "$STR_ACTION_GEAR";
statement = QUOTE(_player action [ARR_2(QUOTE(QUOTE(Gear)),_target)]);
icon = "\A3\ui_f\data\igui\cfg\actions\gear_ca.paa";
};
};
};
};
class Lamps_base_F;
class Land_PortableLight_single_F: Lamps_base_F {
class EventHandlers {

View File

@ -161,3 +161,21 @@ GVAR(isOpeningDoor) = false;
[QGVAR(clearWeaponAttachmentsActionsCache)] call CBA_fnc_localEvent;
}] 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
QGVAR(takeWeapon), "take", "\A3\ui_f\data\igui\cfg\actions\take_ca.paa",
{_player action ["TakeWeapon", _target, weaponCargo _target select 0]},
{count weaponCargo _target == 1},
nil, nil, nil, nil, nil,
{
params ["_target", "", "", "_actionData"];
_actionData set [1, format [localize "STR_ACTION_TAKE_BAG", getText (configfile >> "CfgWeapons" >> weaponCargo _target select 0 >> "displayName")]];
}
] call EFUNC(interact_menu,createAction);
{
[_x, 0, ["ACE_MainActions"], _action, true] call EFUNC(interact_menu,addActionToClass);
} forEach ["WeaponHolder", "WeaponHolderSimulated"];

View File

@ -8,6 +8,7 @@ class CfgWeapons {
descriptionShort = CSTRING(wirecutterDescription);
model = QPATHTOF(data\ace_wirecutter.p3d);
picture = QPATHTOF(ui\item_wirecutter_ca.paa);
ACE_isWirecutter = 1;
scope = 2;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 25;

View File

@ -7,3 +7,5 @@ if (hasInterface) then {
if (isServer) then {
[QGVAR(destroyFence), {_this call FUNC(destroyFence)}] call CBA_fnc_addEventHandler;
};
GVAR(possibleWirecutters) = call (uiNamespace getVariable [QGVAR(possibleWirecutters), {[]}]);

View File

@ -1,3 +1,7 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"
// Cache wirecutter item classes, see XEH_postInit.sqf
private _possibleWirecutters = ("getNumber (_x >> 'ACE_isWirecutter') == 1" configClasses (configFile >> "CfgWeapons")) apply {configName _x};
uiNamespace setVariable [QGVAR(possibleWirecutters), compileFinal str _possibleWirecutters];

View File

@ -88,7 +88,7 @@
#define CUT_TIME_ENGINEER 7.5
#define HAS_WIRECUTTER(unit) (\
"ACE_wirecutter" in (unit call EFUNC(common,uniqueItems)) \
((unit call EFUNC(common,uniqueItems)) arrayIntersect GVAR(possibleWirecutters)) isNotEqualTo []\
|| {getNumber ((configOf (backpackContainer unit)) >> QGVAR(hasWirecutter)) == 1} \
|| {getNumber (configFile >> "CfgWeapons" >> (vest unit) >> QGVAR(hasWirecutter)) == 1} \
)

View File

@ -56,6 +56,13 @@ private _state = [_json] call CBA_fnc_parseJSON;
_x params ["_var", "_default"];
private _value = _state getVariable _x;
// Handle wound hashmaps deserialized as CBA_namespaces
if (typeName _value == "LOCATION") then {
private _keys = allVariables _value;
private _values = _keys apply {_value getVariable _x};
_value = _keys createHashMapFromArray _values;
};
// Treat null as nil
if (_value isEqualTo objNull) then {
_value = _default;

View File

@ -65,7 +65,7 @@
<Korean>에피네프린 사용 시 추가 회복 확률</Korean>
</Key>
<Key ID="STR_ACE_Medical_spontaneousWakeUpEpinephrineBoost_Description">
<English>Increases how often spontaneous wake up checks happen when patient has Epinephrine in their system.</English>
<English>When an unconscious patient has Epinephrine in their system, the time between spontaneous wake up checks is divided by this value.</English>
<Japanese>患者がアドレナリンを投与されると自発的に覚醒する確率を上昇させます。</Japanese>
<Chinese>增加因病患的循環系統裡面的腎上腺素自我甦醒的機率。</Chinese>
<Chinesesimp>增加因病患的循环系统里面的肾上腺素自我苏醒的机率。</Chinesesimp>

View File

@ -22,6 +22,7 @@ params ["_ctrlGroup", "_target"];
private _tourniquets = GET_TOURNIQUETS(_target);
private _fractures = GET_FRACTURES(_target);
private _bodyPartDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0, 0, 0, 0, 0, 0]];
private _damageThreshold = GET_DAMAGE_THRESHOLD(_target);
private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0];
{
@ -70,6 +71,21 @@ private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0];
[_bloodLoss] call FUNC(bloodLossToRGBA);
} else {
private _damage = _bodyPartDamage select _forEachIndex;
switch (true) do { // torso damage threshold doesn't need scaling
case (_forEachIndex > 3): { // legs: index 4 & 5
_damageThreshold = LIMPING_DAMAGE_THRESHOLD * 4;
};
case (_forEachIndex > 1): { // arms: index 2 & 3
_damageThreshold = FRACTURE_DAMAGE_THRESHOLD * 4;
};
case (_forEachIndex == 0): { // head: index 0
_damageThreshold = _damageThreshold * 1.25;
};
default { // torso: index 1
_damageThreshold = _damageThreshold * 1.5
};
};
_damage = (_damage / _damageThreshold) min 1;
[_damage] call FUNC(damageToRGBA);
};

View File

@ -33,6 +33,43 @@ private _bodyPartName = [
_entries pushBack [localize _bodyPartName, [1, 1, 1, 1]];
// Damage taken tooltip
if (GVAR(showDamageEntry)) then {
private _bodyPartDamage = (_target getVariable [QEGVAR(medical,bodyPartDamage), [0, 0, 0, 0, 0, 0]]) select _selectionN;
if (_bodyPartDamage > 0) then {
private _damageThreshold = GET_DAMAGE_THRESHOLD(_target);
switch (true) do {
case (_selectionN > 3): { // legs: index 4 & 5
_damageThreshold = LIMPING_DAMAGE_THRESHOLD * 4;
};
case (_selectionN > 1): { // arms: index 2 & 3
_damageThreshold = FRACTURE_DAMAGE_THRESHOLD * 4;
};
case (_selectionN == 0): { // head: index 0
_damageThreshold = _damageThreshold * 1.25;
};
default { // torso: index 1
_damageThreshold = _damageThreshold * 1.5;
};
};
_bodyPartDamage = (_bodyPartDamage / _damageThreshold) min 1;
switch (true) do {
case (_bodyPartDamage isEqualTo 1): {
_entries pushBack [localize LSTRING(traumaSustained4), [_bodyPartDamage] call FUNC(damageToRGBA)];
};
case (_bodyPartDamage >= 0.75): {
_entries pushBack [localize LSTRING(traumaSustained3), [_bodyPartDamage] call FUNC(damageToRGBA)];
};
case (_bodyPartDamage >= 0.5): {
_entries pushBack [localize LSTRING(traumaSustained2), [_bodyPartDamage] call FUNC(damageToRGBA)];
};
case (_bodyPartDamage >= 0.25): {
_entries pushBack [localize LSTRING(traumaSustained1), [_bodyPartDamage] call FUNC(damageToRGBA)];
};
};
};
};
// Indicate if unit is bleeding at all
if (IS_BLEEDING(_target)) then {
_entries pushBack [localize LSTRING(Status_Bleeding), [1, 0, 0, 1]];
@ -78,10 +115,10 @@ if (_target call EFUNC(common,isAwake)) then {
private _pain = GET_PAIN_PERCEIVED(_target);
if (_pain > 0) then {
private _painText = switch (true) do {
case (_pain > 0.5): {
case (_pain > PAIN_UNCONSCIOUS): {
ELSTRING(medical_treatment,Status_SeverePain);
};
case (_pain > 0.1): {
case (_pain > (PAIN_UNCONSCIOUS / 5)): {
ELSTRING(medical_treatment,Status_Pain);
};
default {

View File

@ -109,6 +109,15 @@ private _categoryColors = [ELSTRING(medical,Category), format ["| %1 |", LELSTRI
] call CBA_fnc_addSetting;
} forEach _damageColors;
[
QGVAR(showDamageEntry),
"CHECKBOX",
[LSTRING(showDamageEntry_DisplayName), LSTRING(showDamageEntry_Description)],
[ELSTRING(medical,Category), LSTRING(SubCategory)],
false,
true
] call CBA_fnc_addSetting;
[
QGVAR(showBloodlossEntry),
"CHECKBOX",

View File

@ -1250,5 +1250,29 @@
<Russian>Показывать тяжесть кровопотери в списке ранений.</Russian>
<Spanish>Mostrar la pérdida de sangre cualitativa en la lista de heridas.</Spanish>
</Key>
<Key ID="STR_ACE_Medical_GUI_showDamageEntry_DisplayName">
<English>Show Trauma Sustained</English>
<Portuguese>Mostrar Traumatismo Sofrido</Portuguese>
</Key>
<Key ID="STR_ACE_Medical_GUI_showDamageEntry_Description">
<English>Show trauma sustained in the injury list.</English>
<Portuguese>Mostrar traumatismo sofrido na lista de feridas.</Portuguese>
</Key>
<Key ID="STR_ACE_Medical_GUI_traumaSustained1">
<English>Minor Trauma</English>
<Portuguese>Traumatismo Leve</Portuguese>
</Key>
<Key ID="STR_ACE_Medical_GUI_traumaSustained2">
<English>Major Trauma</English>
<Portuguese>Traumatismo Significante</Portuguese>
</Key>
<Key ID="STR_ACE_Medical_GUI_traumaSustained3">
<English>Severe Trauma</English>
<Portuguese>Traumatismo Severo</Portuguese>
</Key>
<Key ID="STR_ACE_Medical_GUI_traumaSustained4">
<English>Chronic Trauma</English>
<Portuguese>Traumatismo Crônico</Portuguese>
</Key>
</Package>
</Project>

View File

@ -8,12 +8,14 @@ class CfgWeapons {
class FirstAidKit: ItemCore {
type = 0;
ACE_isMedicalItem = 1;
class ItemInfo: InventoryFirstAidKitItem_Base_F {
mass = 4;
};
};
class Medikit: ItemCore {
type = 0;
ACE_isMedicalItem = 1;
class ItemInfo: MedikitItem {
mass = 60;
};
@ -27,6 +29,7 @@ class CfgWeapons {
displayName = CSTRING(Bandage_Basic_Display);
descriptionShort = CSTRING(Bandage_Basic_Desc_Short);
descriptionUse = CSTRING(Bandage_Basic_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -39,6 +42,7 @@ class CfgWeapons {
model = QPATHTOF(data\packingbandage.p3d);
descriptionShort = CSTRING(Packing_Bandage_Desc_Short);
descriptionUse = CSTRING(Packing_Bandage_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -51,6 +55,7 @@ class CfgWeapons {
model = "\A3\Structures_F_EPA\Items\Medical\Bandage_F.p3d";
descriptionShort = CSTRING(Bandage_Elastic_Desc_Short);
descriptionUse = CSTRING(Bandage_Elastic_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -63,6 +68,7 @@ class CfgWeapons {
model = QPATHTOF(data\tourniquet.p3d);
descriptionShort = CSTRING(Tourniquet_Desc_Short);
descriptionUse = CSTRING(Tourniquet_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -74,6 +80,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\splint_ca.paa);
model = QPATHTOF(data\splint.p3d);
descriptionShort = CSTRING(splint_Desc_Short);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 2;
};
@ -86,6 +93,7 @@ class CfgWeapons {
model = QPATHTOF(data\morphine.p3d);
descriptionShort = CSTRING(Morphine_Desc_Short);
descriptionUse = CSTRING(Morphine_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -98,6 +106,7 @@ class CfgWeapons {
model = QPATHTOF(data\adenosine.p3d);
descriptionShort = CSTRING(adenosine_Desc_Short);
descriptionUse = CSTRING(adenosine_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -110,6 +119,7 @@ class CfgWeapons {
model = QPATHTOF(data\atropine.p3d);
descriptionShort = CSTRING(Atropine_Desc_Short);
descriptionUse = CSTRING(Atropine_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -122,6 +132,7 @@ class CfgWeapons {
model = QPATHTOF(data\epinephrine.p3d);
descriptionShort = CSTRING(Epinephrine_Desc_Short);
descriptionUse = CSTRING(Epinephrine_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -137,6 +148,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\plasmaIV_ca.paa);
descriptionShort = CSTRING(Plasma_IV_Desc_Short);
descriptionUse = CSTRING(Plasma_IV_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 10;
};
@ -167,6 +179,7 @@ class CfgWeapons {
hiddenSelectionsTextures[] = {QPATHTOF(data\IVBag_blood_1000ml_ca.paa)};
descriptionShort = CSTRING(Blood_IV_Desc_Short);
descriptionUse = CSTRING(Blood_IV_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 10;
};
@ -197,6 +210,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\salineIV_ca.paa);
descriptionShort = CSTRING(Saline_IV_Desc_Short);
descriptionUse = CSTRING(Saline_IV_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 10;
};
@ -225,6 +239,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\quickclot_ca.paa);
descriptionShort = CSTRING(QuikClot_Desc_Short);
descriptionUse = CSTRING(QuikClot_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -236,6 +251,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\personal_aid_kit_ca.paa);
descriptionShort = CSTRING(Aid_Kit_Desc_Short);
descriptionUse = CSTRING(Aid_Kit_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 10;
};
@ -248,6 +264,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\surgicalKit_ca.paa);
descriptionShort = CSTRING(SurgicalKit_Desc_Short);
descriptionUse = CSTRING(SurgicalKit_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 15;
};
@ -260,6 +277,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\suture_ca.paa);
descriptionShort = CSTRING(Suture_Desc_Short);
descriptionUse = CSTRING(Suture_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 1;
};
@ -272,6 +290,7 @@ class CfgWeapons {
picture = QPATHTOF(ui\bodybag_ca.paa);
descriptionShort = CSTRING(Bodybag_Desc_Short);
descriptionUse = CSTRING(Bodybag_Desc_Use);
ACE_isMedicalItem = 1;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 7;
};

View File

@ -48,6 +48,7 @@ PREP(medicationLocal);
PREP(onMedicationUsage);
PREP(placeInBodyBag);
PREP(removeBody);
PREP(scanMedicalItems);
PREP(setTriageStatus);
PREP(splint);
PREP(splintLocal);

View File

@ -8,6 +8,8 @@ PREP_RECOMPILE_END;
#include "initSettings.sqf"
#define ARSENAL_CATEGORY_ICON (["\A3\ui_f\data\igui\cfg\actions\heal_ca.paa", QPATHTOEF(medical_gui,data\categories\bandage_fracture.paa)] select (["ace_medical_gui"] call EFUNC(common,isModLoaded)))
// config to determine animation acceleration coefficient
// adjusting these is trail and error
// if the animation is cut of ingame, increase these values
@ -44,4 +46,9 @@ GVAR(facilityClasses) = [];
} forEach getArray _x;
} forEach configProperties [configFile >> QEGVAR(medical,facilities), "isArray _x"];
// Custom Arsenal tab
if (["ace_arsenal"] call EFUNC(common,isModLoaded)) then {
[MEDICAL_TREATMENT_ITEMS, LELSTRING(medical,Category), ARSENAL_CATEGORY_ICON] call EFUNC(arsenal,addRightPanelButton);
};
ADDON = true;

View File

@ -1,3 +1,5 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"
call FUNC(scanMedicalItems)

View File

@ -0,0 +1,34 @@
#include "script_component.hpp"
/*
* Author: Salluci
* Caches all item classnames used in ACE_Medical_Treatment_Actions
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* call ace_medical_treatment_fnc_scanMedicalItems
*
* Public: No
*/
private _list = [];
private _cfgActions = configFile >> QGVAR(actions);
private _fnc_isMedicalItem = toString {
getNumber (_x >> "ACE_isMedicalItem") isEqualTo 1
};
// get items in ACE_Medical_Treament_Actions, fallback for items without API config property
{
_list append (getArray (_x >> "items"));
} forEach ("true" configClasses _cfgActions);
{
_list pushBack (configName _x);
} forEach (_fnc_isMedicalItem configClasses (configFile >> "CfgWeapons"));
uiNamespace setVariable [QGVAR(treatmentItems), compileFinal str (_list arrayIntersect _list)]

View File

@ -83,9 +83,7 @@ if (
};
// Consume a suture for the next wound if one exists, stop stitching if none are left
if (GVAR(consumeSurgicalKit) == 2) then {
// Don't consume a suture if there are no more wounds to stitch
if (_bandagedWoundsOnPart isEqualTo []) exitWith {false};
if (GVAR(consumeSurgicalKit) == 2 && {_bandagedWoundsOnPart isNotEqualTo []}) then {
([_medic, _patient, ["ACE_suture"]] call FUNC(useItem)) params ["_user"];
!isNull _user
} else {

View File

@ -54,3 +54,5 @@
// Animations that would be played faster than this are instead skipped. (= Progress bar too quick for animation).
#define ANIMATION_SPEED_MAX_COEFFICIENT 2.5
#define MEDICAL_TREATMENT_ITEMS (call (uiNamespace getVariable [QGVAR(treatmentItems), {[]}]))

View File

@ -3,10 +3,11 @@ class ACE_Repair {
class ReplaceWheel {
displayName = CSTRING(ReplaceWheel);
displayNameProgress = CSTRING(ReplacingWheel);
forceDisplayName = 0;
repairLocations[] = {"All"};
requiredEngineer = QGVAR(engineerSetting_Wheel);
repairingTime = 10;
repairingTime = QGVAR(wheelChangeTime);
repairingTimeSelfCoef = 1;
items = QGVAR(wheelRepairRequiredItems);
condition = QFUNC(canReplaceWheel);
@ -21,6 +22,7 @@ class ACE_Repair {
animationCallerProne = "Acts_carFixingWheel";
animationCallerSelf = "Acts_carFixingWheel";
animationCallerSelfProne = "Acts_carFixingWheel";
loopAnimation = 0;
litter[] = {};
};
class RemoveWheel: ReplaceWheel {
@ -46,7 +48,7 @@ class ACE_Repair {
displayNameProgress = CSTRING(RepairingHitPoint);
condition = QFUNC(canMiscRepair);
requiredEngineer = QGVAR(engineerSetting_Repair);
repairingTime = 15;
repairingTime = QGVAR(miscRepairTime);
callbackSuccess = QFUNC(doRepair);
items = QGVAR(miscRepairRequiredItems);
itemConsumed = QGVAR(consumeItem_ToolKit);
@ -80,11 +82,14 @@ class ACE_Repair {
class FullRepair: MiscRepair {
displayName = CSTRING(fullRepair);
displayNameProgress = CSTRING(fullyRepairing);
forceDisplayName = 1;
loopAnimation = 1;
requiredEngineer = QGVAR(engineerSetting_fullRepair);
repairLocations[] = {QGVAR(fullRepairLocation)};
repairingTime = 30;
condition = "-1 != ((getAllHitPointsDamage _target param [2,[]]) findIf {_x > 0})";
repairingTime = QFUNC(getFullRepairTime);
condition = "((getAllHitPointsDamage _target) select 2) findIf {_x > 0} != -1";
callbackSuccess = QFUNC(doFullRepair);
callbackProgress = QFUNC(fullRepairProgress);
items = QGVAR(fullRepairRequiredItems);
itemConsumed = QGVAR(consumeItem_ToolKit);
};

View File

@ -17,8 +17,11 @@ PREP(doRepair);
PREP(doRepairTrack);
PREP(doReplaceTrack);
PREP(doReplaceWheel);
PREP(fullRepairProgress);
PREP(getClaimObjects);
PREP(getFullRepairTime);
PREP(getHitPointString);
PREP(getHitPointsToIgnore);
PREP(getPatchWheelTime);
PREP(getPostRepairDamage);
PREP(getRepairItems);

View File

@ -25,6 +25,9 @@ TRACE_2("addRepairActions", _vehicle,_type);
private _initializedClasses = GETMVAR(GVAR(initializedClasses),[]);
if (_type in _initializedClasses) exitWith {};
// get hitPoints to ignore
private _hitPointsToIgnore = [_vehicle] call FUNC(getHitPointsToIgnore);
// get all hitpoints and selections
(getAllHitPointsDamage _vehicle) params [["_hitPoints", []], ["_hitSelections", []]]; // Since 1.82 these are all lower case
@ -40,8 +43,6 @@ private _icon = ["a3\ui_f\data\igui\cfg\actions\repair_ca.paa", "#FFFFFF"];
private _vehCfg = configOf _vehicle;
// Custom position can be defined via config for associated hitpoint
private _hitpointPositions = getArray (_vehCfg >> QGVAR(hitpointPositions));
// Associated hitpoints can be grouped via config to produce a single repair action
private _hitpointGroups = getArray (_vehCfg >> QGVAR(hitpointGroups));
// Get turret paths
private _turretPaths = ((fullCrew [_vehicle, "gunner", true]) + (fullCrew [_vehicle, "commander", true])) apply {_x # 3};
@ -88,59 +89,32 @@ private _turretPaths = ((fullCrew [_vehicle, "gunner", true]) + (fullCrew [_vehi
_processedSelections pushBack _selection;
} else {
// Empty hitpoints don't contain enough information
if (_hitpoint isEqualTo "") exitWith { TRACE_3("Skipping Empty Hit",_hitpoint,_forEachIndex,_selection); };
// Ignore glass hitpoints
if ((_hitpoint find "glass") != -1) exitWith { TRACE_3("Skipping Glass",_hitpoint,_forEachIndex,_selection); };
// Ignore hitpoints starting with # (seems to be lights)
if ((_hitpoint select [0,1]) == "#") exitWith { TRACE_3("Skipping # hit",_hitpoint,_forEachIndex,_selection); };
// Ignore ERA/Slat armor (vanilla uses hitera_/hitslat_, pre-1.82 RHS uses era_)
// ToDo: see how community utilizes new armor system, could also check getText (_hitpointConfig >> "simulation")
if (((_hitpoint select [0,7]) == "hitera_") || {(_hitpoint select [0,8]) == "hitslat_"} || {(_hitpoint select [0,4]) == "era_"}) exitWith { TRACE_3("Skipping ERA/SLAT",_hitpoint,_forEachIndex,_selection); };
// Skip ignored hitpoints
if (_hitpoint in _hitPointsToIgnore) exitWith {
TRACE_3("Skipping ignored hitpoint",_hitpoint,_forEachIndex,_selection);
};
// Some hitpoints do not have a selection but do have an armorComponent value (seems to mainly be RHS)
// Ref https://community.bistudio.com/wiki/Arma_3_Damage_Enhancement
// this code won't support identically named hitpoints (e.g. commander turret: Duplicate HitPoint name 'HitTurret')
private _armorComponent = "";
if (_selection == "") then {
{
private _turretHitpointCfg = ([_vehCfg, _x] call CBA_fnc_getTurret) >> "HitPoints";
private _hitpointsCfg = "configName _x == _hitpoint" configClasses _turretHitpointCfg;
if (_hitpointsCfg isNotEqualTo []) exitWith {
TRACE_2("turret hitpoint configFound",_hitpoint,_x);
// only do turret hitpoints or stuff linked to visuals for now or we apparently get some weird stuff
if ((_hitpoint in ["hitturret", "hitgun"]) || {(getNumber (_hitpointsCfg # 0 >> "isGun")) == 1} || {(getNumber (_hitpointsCfg # 0 >> "isTurret")) == 1} || {(getText (_hitpointsCfg # 0 >> "visual")) != ""}) then {
private _hitpointsCfg = "configName _x == _hitpoint" configClasses (_vehCfg >> "HitPoints");
if (_hitpointsCfg isNotEqualTo []) then {
_armorComponent = getText (_hitpointsCfg # 0 >> "armorComponent");
};
if (_armorComponent == "") then {
{
private _turretHitpointCfg = ([_vehCfg, _x] call CBA_fnc_getTurret) >> "HitPoints";
private _hitpointsCfg = "configName _x == _hitpoint" configClasses _turretHitpointCfg;
if (_hitpointsCfg isNotEqualTo []) exitWith {
TRACE_2("turret hitpoint configFound",_hitpoint,_x);
_armorComponent = getText (_hitpointsCfg # 0 >> "armorComponent");
};
};
} forEach _turretPaths;
if (_armorComponent == "") then {
private _hitpointsCfg = "configName _x == _hitpoint" configClasses (_vehCfg >> "HitPoints");
if ((getText (_hitpointsCfg # 0 >> "visual")) != "") then {
_armorComponent = getText (_hitpointsCfg # 0 >> "armorComponent");
};
} forEach _turretPaths;
};
if (_armorComponent != "") then { INFO_3("%1: %2 no selection: using armorComponent %3",_type,_hitpoint,_armorComponent); };
};
if ((_selection == "") && {_armorComponent == ""}) exitWith { TRACE_3("Skipping no selection OR armor component",_hitpoint,_forEachIndex,_selection); };
//Depends hitpoints shouldn't be modified directly (will be normalized)
// Biki: Clearing 'depends' in case of inheritance cannot be an empty string (rpt warnings), but rather a "0" value.
if (!((getText (_vehCfg >> "HitPoints" >> _hitpoint >> "depends")) in ["", "0"])) exitWith {
TRACE_3("Skip Depends",_hitpoint,_forEachIndex,_selection);
};
private _childHitPoint = false;
{
{
if (_hitpoint == _x) exitWith {
_childHitPoint = true;
};
} forEach (_x select 1);
} forEach _hitpointGroups;
// If the current selection is associated with a child hitpoint, then skip
if (_childHitPoint) exitWith { TRACE_3("childHitpoint",_hitpoint,_forEachIndex,_selection); };
// Find the action position
private _position = compile format ["_target selectionPosition ['%1', 'HitPoints'];", _selection];

View File

@ -7,6 +7,7 @@
* 0: Unit that does the repairing <OBJECT>
* 1: Vehicle to repair <OBJECT>
* 2: Selected hitpointIndex <NUMBER>
* 3: Repair action classname <STRING>
*
* Return Value:
* None
@ -17,10 +18,11 @@
* Public: No
*/
params ["_unit", "_vehicle", "_hitPointIndex"];
TRACE_3("params",_unit,_vehicle,_hitPointIndex);
params ["_unit", "_vehicle", "_hitPointIndex", "_action"];
TRACE_4("params",_unit,_vehicle,_hitPointIndex,_action);
private _postRepairDamageMin = [_unit] call FUNC(getPostRepairDamage);
// override minimum damage if doing full repair
private _postRepairDamageMin = [_unit, _action isEqualTo "fullRepair"] call FUNC(getPostRepairDamage);
(getAllHitPointsDamage _vehicle) params ["_allHitPoints"];
private _hitPointClassname = _allHitPoints select _hitPointIndex;

View File

@ -0,0 +1,50 @@
#include "script_component.hpp"
/*
* Author: LinkIsGrim
* Handles full repair by periodically repairing damaged hitpoints.
*
* Arguments:
* 0: Arguments <ARRAY>
* 0: Engineer <OBJECT>
* 1: Vehicle <OBJECT>
* 2: Hitpoint <STRING> (unused)
* 3: Repair action classname <STRING>
* 1: Elapsed Time <NUMBER>
* 2: Total Time <NUMBER>
*
* Return Value:
* Continue Repair <BOOL>
*
* Example:
* [[objNull, player], 5, 10] call ace_repair_fnc_fullRepairProgress
*
* Public: No
*/
params ["_args", "_elapsedTime", "_totalTime"];
_args params ["_engineer", "_vehicle", "", "_action"];
if !((alive _vehicle) && {(abs speed _vehicle) < 1}) exitWith {false}; // make sure vehicle doesn't drive off
// Not enough time has elapsed to repair a hitpoint
if (_totalTime - _elapsedTime > ([_engineer, _vehicle] call FUNC(getFullRepairTime)) - (GVAR(miscRepairTime) * GVAR(timeCoefficientFullRepair))) exitWith {true};
private _allHitPointsDamage = getAllHitPointsDamage _vehicle;
_allHitPointsDamage params ["_hitPoints", "", "_damageValues"];
private _hitPointsToIgnore = [_vehicle] call FUNC(getHitPointsToIgnore);
private _firstDamagedIndex = {
private _hitPoint = _hitPoints select _forEachIndex;
if (_x > 0 && {!(_hitPoint in _hitPointsToIgnore)}) exitWith {_forEachIndex};
-1
} forEach _damageValues;
// Stop repairing if there are no more damaged hitpoints
// callBackSuccess to FUNC(doFullRepair) for ignored hitpoints
if (_firstDamagedIndex == -1) exitWith {true};
// Repair the first damaged hitpoint
[_engineer, _vehicle, _firstDamagedIndex, _action] call FUNC(doRepair);
true

View File

@ -0,0 +1,42 @@
#include "script_component.hpp"
/*
* Author: LinkIsGrim
* Calculates the Full Repair time based on the amount of hitpoints to repair
*
* Arguments:
* 0: Engineer <OBJECT>
* 1: Vehicle <OBJECT>
*
* Return Value:
* Repair Time <NUMBER>
*
* Example:
* [player, vehicle] call ace_repair_fnc_getFullRepairTime
*
* Public: No
*/
params ["_engineer", "_vehicle"];
private _allHitPointsDamage = getAllHitPointsDamage _vehicle;
_allHitPointsDamage params ["_hitPoints", "", "_damageValues"];
private _hitPointsToIgnore = [_vehicle] call FUNC(getHitPointsToIgnore);
private _repairsNeeded = 0;
private _doExtraRepair = false;
{
if (_x <= 0) then {continue}; // skip hitpoints that don't need repairs
private _hitPoint = _hitPoints select _forEachIndex;
if (_hitPoint in _hitPointsToIgnore) then { // only add extra repair for ignore hitpoints if they're damaged
_doExtraRepair = true;
continue
};
_repairsNeeded = _repairsNeeded + ceil (_x / 0.5); // repair is capped at 0.5 in FUNC(doRepair)
} forEach _damageValues;
if (_doExtraRepair) then {
_repairsNeeded = _repairsNeeded + 1;
};
_repairsNeeded * GVAR(miscRepairTime) * GVAR(timeCoefficientFullRepair) // return

View File

@ -0,0 +1,142 @@
#include "script_component.hpp"
/*
* Author: commy2, kymckay, LinkIsGrim
* Get list of vehicle hitpoints to ignore
*
* Arguments:
* 0: Vehicle <OBJECT>
*
* Return Value:
* HitPoints to ignore <ARRAY>
*
* Example:
* [vehicle] call ace_repair_fnc_getHitpointsToIgnore
*
* Public: No
*/
params ["_vehicle"];
private _type = typeOf _vehicle;
TRACE_2("getHitPointsToIgnore", _vehicle,_type);
private _initializedClasses = missionNamespace getVariable [QGVAR(hitPointsToIgnoreInitializedClasses), createHashMap];
if (_type in _initializedClasses) exitWith {_initializedClasses get _type};
private _vehCfg = configOf _vehicle;
private _hitpointGroups = getArray (_vehCfg >> QGVAR(hitpointGroups));
private _turretPaths = ((fullCrew [_vehicle, "gunner", true]) + (fullCrew [_vehicle, "commander", true])) apply {_x # 3};
(getAllHitPointsDamage _vehicle) params [["_hitPoints", []], ["_hitSelections", []]];
// get hitpoints of wheels with their selections
([_vehicle] call FUNC(getWheelHitPointsWithSelections)) params ["_wheelHitPoints", "_wheelHitSelections"];
private _hitPointsToIgnore = [""]; // always ignore empty hitpoints
private _processedSelections = [];
{
private _selection = _x;
private _hitpoint = toLower (_hitPoints select _forEachIndex);
private _isWheelOrTrack = _selection in _wheelHitSelections || {_hitpoint in _wheelHitPoints} || {_hitpoint in TRACK_HITPOINTS};
if (_hitpoint isEqualTo "") then { // skip empty hitpoint
continue
};
if (_isWheelOrTrack && {_selection in _processedSelections || {_selection isEqualTo ""}}) then { // skip duplicate or empty selection wheel/track
TRACE_3("Skipping duplicate Wheel/Track or empty selection",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping duplicate wheel, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
if ("glass" in _hitpoint) then { // skip glass
TRACE_3("Skipping glass",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping glass, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
if (_hitpoint select [0,1] isEqualTo "#" || {_hitpoint select [0,9] isEqualTo "hit_light"}) then { // skip lights
TRACE_3("Skipping light",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping light, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
if (_hitpoint select [0,7] isEqualTo "hitera_" || {_hitpoint select [0,8] isEqualTo "hitslat_"} || {_hitpoint select [0,4] isEqualTo "era_"}) then { // skip era/slat
TRACE_3("Skipping ERA/Slat HitPoint",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping ERA/SLAT, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
private _armorComponent = "";
if (_selection == "") then { // some hitpoints have empty selection but defined armor component (mostly RHS)
{
private _turretHitpointCfg = ([_vehCfg, _x] call CBA_fnc_getTurret) >> "HitPoints";
private _hitpointsCfg = "configName _x == _hitpoint" configClasses _turretHitpointCfg;
if (_hitpointsCfg isNotEqualTo []) exitWith {
TRACE_2("turret hitpoint configFound",_hitpoint,_x);
// only do turret hitpoints and stuff linked to visuals
if ((_hitpoint in ["hitturret", "hitgun"]) || {(getNumber (_hitpointsCfg # 0 >> "isGun")) == 1} || {(getNumber (_hitpointsCfg # 0 >> "isTurret")) == 1} || {(getText (_hitpointsCfg # 0 >> "visual")) != ""}) then {
_armorComponent = getText (_hitpointsCfg # 0 >> "armorComponent");
};
};
} forEach _turretPaths;
if (_armorComponent == "") then {
private _hitpointsCfg = "configName _x == _hitpoint" configClasses (_vehCfg >> "HitPoints");
if (_hitpointsCfg isNotEqualTo [] && {(getText (_hitpointsCfg # 0 >> "visual")) != ""}) then {
_armorComponent = getText (_hitpointsCfg # 0 >> "armorComponent");
};
};
};
if ((_selection == "") && {_armorComponent == ""}) then {
TRACE_3("Skipping no selection OR armor component",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping no selection OR armor component, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
if (!(getText (_vehCfg >> "HitPoints" >> _hitpoint >> "depends") in ["", "0"])) then { // skip depends hitpoints, should be normalized by engine
TRACE_3("Skipping depends hitpoint",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping depends hitpoint, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
if ((_hitpointGroups findIf {(_x select 1) == _hitpoint}) != -1) then { // skip child hitpoints
TRACE_3("Skipping child hitpoint",_hitpoint,_forEachIndex,_selection);
/*#ifdef DEBUG_MODE_FULL
systemChat format ["Skipping child hitpoint, hitpoint %1, index %2, selection %3", _hitpoint, _forEachIndex, _selection];
#endif*/
_hitPointsToIgnore pushBackUnique _hitpoint;
_processedSelections pushBack _selection;
continue
};
_processedSelections pushBack _selection;
} forEach _hitSelections;
_initializedClasses set [_type, _hitPointsToIgnore];
missionNamespace setVariable [QGVAR(hitPointsToIgnoreInitializedClasses), _initializedClasses];
_hitPointsToIgnore

View File

@ -5,6 +5,7 @@
*
* Arguments:
* 0: Unit that does the repairing <OBJECT>
* 1: Override for full repair <BOOL> (default: false)
*
* Return Value:
* 0: Repair Damage Threshold <NUMBER>
@ -15,11 +16,11 @@
* Public: No
*/
params ["_unit"];
TRACE_1("params",_unit);
params ["_unit", ["_override", false]];
TRACE_2("params",_unit,_override);
//If in facility or near vehicle then complete repair of hitpoint:
if (([_unit] call FUNC(isInRepairFacility) || {[_unit] call FUNC(isNearRepairVehicle)})) exitWith {0};
//If in facility, near vehicle, or doing full repair then complete repair of hitpoint:
if ((_override || {[_unit] call FUNC(isInRepairFacility)} || {[_unit] call FUNC(isNearRepairVehicle)})) exitWith {0};
private _class = _unit getVariable ["ACE_IsEngineer", getNumber (configOf _unit >> "engineer")];
//If advanced or more qualified than min, then use engineer threshold:

View File

@ -15,28 +15,15 @@
* Public: Yes
*/
#define CHECK_OBJECTS(var) ((var) findIf {(_x getVariable ["ACE_isRepairFacility", getNumber (configOf _x >> QGVAR(canRepair))] > 0) && {!(_x isKindOf "AllVehicles")} && {alive _x}} != -1)
params [["_object", objNull, [objNull]]];
TRACE_1("params",_object);
private _position = getPosASL _object;
private _isInBuilding = false;
private _checkObject = {
if (
_x getVariable ["ACE_isRepairFacility", getNumber (configOf _x >> QGVAR(canRepair))] > 0
&& {!(_x isKindOf "AllVehicles")} // check if it's not repair vehicle
&& {alive _x}
) exitWith {
_isInBuilding = true;
};
private _fnc_check = {
private _position = _object modelToWorldVisual [0, 0, eyePos _object select 2];
CHECK_OBJECTS(lineIntersectsWith [ARR_3(_position, _position vectorAdd [ARR_3(0, 0, 10)], _object)]) || {CHECK_OBJECTS(_object nearObjects 7.5)}
};
private _objects = (lineIntersectsWith [_object modelToWorldVisual [0, 0, (_position select 2)], _object modelToWorldVisual [0, 0, (_position select 2) +10], _object]);
_checkObject forEach _objects;
if (_isInBuilding) exitWith {true};
_objects = _object nearObjects 7.5;
_checkObject forEach _objects;
_isInBuilding
[[], _fnc_check, _object, QGVAR(inRepairFacilityCache), IN_REPAIR_FACILITY_CACHE_EXPIRY] call EFUNC(common,cachedCall);

View File

@ -15,14 +15,14 @@
* Public: Yes
*/
#define CHECK_OBJECTS(var) ((var) findIf {alive _x && {[_x] call FUNC(isRepairVehicle)}} != -1)
params ["_unit"];
TRACE_1("params",_unit);
private _nearObjects = nearestObjects [_unit, ["Air", "LandVehicle", "Slingload_base_F"], 20];
private _fnc_check = {
private _nearObjects = nearestObjects [_unit, ["Air", "LandVehicle", "Slingload_base_F"], 20];
CHECK_OBJECTS(_nearObjects)
};
private _return = false;
{
if (alive _x && {[_x] call FUNC(isRepairVehicle)}) exitWith {_return = true;};
} forEach _nearObjects;
_return;
[[], _fnc_check, _unit, QGVAR(nearRepairVehicleCache), NEAR_REPAIR_VEHICLE_CACHE_EXPIRY] call EFUNC(common,cachedCall);

View File

@ -148,6 +148,7 @@ if (_callbackProgress == "") then {
// Player Animation
private _callerAnim = [getText (_config >> "animationCaller"), getText (_config >> "animationCallerProne")] select (stance _caller == "PRONE");
private _loopAnim = (getNumber (_config >> "loopAnimation")) isEqualTo 1;
_caller setVariable [QGVAR(selectedWeaponOnrepair), currentWeapon _caller];
// Cannot use secondairy weapon for animation
@ -171,10 +172,27 @@ if (vehicle _caller == _caller && {_callerAnim != ""}) then {
} else {
_caller setVariable [QGVAR(repairPrevAnimCaller), animationState _caller];
};
_caller setVariable [QGVAR(repairCurrentAnimCaller), toLower _callerAnim];
[_caller, _callerAnim] call EFUNC(common,doAnimation);
};
};
if (_loopAnim) then {
private _animDoneEh = _caller addEventHandler ["AnimDone", {
params ["_caller", "_anim"];
if (_anim isEqualTo (_caller getVariable [QGVAR(repairCurrentAnimCaller), ""])) then {
[{
params ["_caller", "_anim"];
if !(isNil {_caller getVariable QGVAR(repairCurrentAnimCaller)}) then {
TRACE_2("loop",_caller,_anim);
_this call EFUNC(common,doAnimation)
};
}, [_caller, _anim], 2.5] call CBA_fnc_waitAndExecute;
};
}];
_caller setVariable [QGVAR(repairLoopAnimEh), _animDoneEh];
};
private _soundPosition = _caller modelToWorldVisualWorld (_caller selectionPosition "RightHand");
["Acts_carFixingWheel", _soundPosition, nil, 50] call EFUNC(common,playConfigSound3D);
@ -213,7 +231,10 @@ private _hitPointClassname = if (_hitPoint isEqualType "") then {
};
private _processText = getText (_config >> "displayNameProgress");
private _backupText = format [localize LSTRING(RepairingHitPoint), _hitPointClassname];
([_hitPointClassname, _processText, _backupText] call FUNC(getHitPointString)) params ["_text"];
private _text = _processText;
if (getNumber (_config >> "forceDisplayName") isNotEqualTo 1) then {
_text = ([_hitPointClassname, _processText, _backupText] call FUNC(getHitPointString)) select 0;
};
TRACE_4("display",_hitPoint,_hitPointClassname,_processText,_text);

View File

@ -29,9 +29,13 @@ TRACE_5("params",_caller,_target,_selectionName,_className,_usersOfItems);
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
};
_caller removeEventHandler ["AnimDone", _caller getVariable [QGVAR(repairLoopAnimEh), -1]];
_caller setVariable [QGVAR(repairLoopAnimEh), nil];
if (vehicle _caller == _caller && {!(_caller call EFUNC(common,isSwimming))}) then {
[_caller, _caller getVariable [QGVAR(repairPrevAnimCaller), ""], 2] call EFUNC(common,doAnimation);
};
_caller setVariable [QGVAR(repairCurrentAnimCaller), nil];
_caller setVariable [QGVAR(repairPrevAnimCaller), nil];
private _weaponSelect = (_caller getVariable [QGVAR(selectedWeaponOnrepair), ""]);

View File

@ -29,9 +29,13 @@ TRACE_4("params",_caller,_target,_selectionName,_className);
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
};
_caller removeEventHandler ["AnimDone", _caller getVariable [QGVAR(repairLoopAnimEh), -1]];
_caller setVariable [QGVAR(repairLoopAnimEh), nil];
if (vehicle _caller == _caller && {!(_caller call EFUNC(common,isSwimming))}) then {
[_caller, _caller getVariable [QGVAR(repairPrevAnimCaller), ""], 2] call EFUNC(common,doAnimation);
};
_caller setVariable [QGVAR(repairCurrentAnimCaller), nil];
_caller setVariable [QGVAR(repairPrevAnimCaller), nil];
private _weaponSelect = (_caller getVariable [QGVAR(selectedWeaponOnrepair), ""]);

View File

@ -1,7 +1,9 @@
private _category = format ["ACE %1", LLSTRING(Repair)];
[
QGVAR(displayTextOnRepair), "CHECKBOX",
[LSTRING(SettingDisplayTextName), LSTRING(SettingDisplayTextDesc)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
true, // default value
false, // isGlobal
{[QGVAR(displayTextOnRepair), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -10,7 +12,7 @@
[
QGVAR(engineerSetting_repair), "LIST",
[LSTRING(engineerSetting_Repair_name), LSTRING(engineerSetting_Repair_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[0,1,2],[LSTRING(engineerSetting_anyone), LSTRING(engineerSetting_EngineerOnly), LSTRING(engineerSetting_AdvancedOnly)],1], // [values, titles, defaultIndex]
true, // isGlobal
{[QGVAR(engineerSetting_repair), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -19,7 +21,7 @@
[
QGVAR(engineerSetting_wheel), "LIST",
[LSTRING(engineerSetting_Wheel_name), LSTRING(engineerSetting_Wheel_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[0,1,2],[LSTRING(engineerSetting_anyone), LSTRING(engineerSetting_EngineerOnly), LSTRING(engineerSetting_AdvancedOnly)],0], // [values, titles, defaultIndex]
true, // isGlobal
{[QGVAR(engineerSetting_wheel), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -28,7 +30,7 @@
[
QGVAR(patchWheelEnabled), "LIST",
[LSTRING(patchWheelEnabled_name), LSTRING(patchWheelEnabled_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[-1,0,1,2],["str_player_none", LSTRING(engineerSetting_anyone), LSTRING(engineerSetting_EngineerOnly), LSTRING(engineerSetting_AdvancedOnly)],1], // default value
true // isGlobal
] call CBA_fnc_addSetting;
@ -37,7 +39,7 @@
QGVAR(patchWheelRequiredItems),
"LIST",
[LSTRING(patchWheelRequiredItems_DisplayName), LSTRING(patchWheelRequiredItems_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[[], [ANY_TOOLKIT_FAKECLASS]], ["STR_A3_None", "STR_A3_CfgWeapons_Toolkit0"], 1],
true
] call CBA_fnc_addSetting;
@ -46,7 +48,7 @@
QGVAR(patchWheelLocation),
"LIST",
[LSTRING(patchWheelLocation_DisplayName), LSTRING(patchWheelLocation_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[["ground", "vehicle"], ["vehicle"], ["ground"]], ["str_difficulty_any", LSTRING(patchWheelOnVehicle), LSTRING(patchWheelOnGround)], 0],
true
] call CBA_fnc_addSetting;
@ -54,8 +56,8 @@
[
QGVAR(repairDamageThreshold), "SLIDER",
[LSTRING(repairDamageThreshold_name), LSTRING(repairDamageThreshold_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
[0,1,0.6,2], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
_category,
[0, 1, 0.6, 1, true],
true, // isGlobal
{[QGVAR(repairDamageThreshold), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting;
@ -63,8 +65,8 @@
[
QGVAR(repairDamageThreshold_engineer), "SLIDER",
[LSTRING(repairDamageThreshold_Engineer_name), LSTRING(repairDamageThreshold_Engineer_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
[0,1,0.4,2], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
_category,
[0, 1, 0.4, 1, true],
true, // isGlobal
{[QGVAR(repairDamageThreshold_engineer), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting;
@ -72,7 +74,7 @@
[
QGVAR(consumeItem_toolKit), "LIST", // fnc_repair expects number
[LSTRING(consumeItem_ToolKit_name), LSTRING(consumeItem_ToolKit_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[0,1],[ELSTRING(common,No), ELSTRING(common,Yes)],0], // [values, titles, defaultIndex]
true, // isGlobal
{[QGVAR(consumeItem_toolKit), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -82,7 +84,7 @@
QGVAR(locationsBoostTraining),
"CHECKBOX",
[ELSTRING(common,LocationsBoostTraining_DisplayName), LSTRING(LocationsBoostTraining_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
false,
true
] call CBA_fnc_addSetting;
@ -90,7 +92,7 @@
[
QGVAR(fullRepairLocation), "LIST",
[LSTRING(fullRepairLocation), LSTRING(fullRepairLocation_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[0,1,2,3,4],[LSTRING(useAnywhere), LSTRING(repairVehicleOnly), LSTRING(repairFacilityOnly), LSTRING(vehicleAndFacility), ELSTRING(common,Disabled)],2], // [values, titles, defaultIndex]
true, // isGlobal
{[QGVAR(fullRepairLocation), _this] call EFUNC(common,cbaSettings_settingChanged)}
@ -99,16 +101,24 @@
[
QGVAR(engineerSetting_fullRepair), "LIST",
[LSTRING(engineerSetting_fullRepair_name), LSTRING(engineerSetting_fullRepair_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[0,1,2],[LSTRING(engineerSetting_anyone), LSTRING(engineerSetting_EngineerOnly), LSTRING(engineerSetting_AdvancedOnly)],2], // [values, titles, defaultIndex]
true, // isGlobal
{[QGVAR(engineerSetting_fullRepair), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting;
[
QGVAR(timeCoefficientFullRepair), "SLIDER",
[LSTRING(timeCoefficientFullRepair_name), LSTRING(timeCoefficientFullRepair_description)],
_category,
[0,3,1.5,2],
true
] call CBA_fnc_addSetting;
[
QGVAR(addSpareParts), "CHECKBOX",
[LSTRING(addSpareParts_name), LSTRING(addSpareParts_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
true, // default value
true, // isGlobal
{[QGVAR(addSpareParts), _this] call EFUNC(common,cbaSettings_settingChanged)},
@ -119,7 +129,7 @@
QGVAR(wheelRepairRequiredItems),
"LIST",
[LSTRING(WheelRepairRequiredItems_DisplayName), LSTRING(WheelRepairRequiredItems_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[[], [ANY_TOOLKIT_FAKECLASS]], ["STR_A3_None", "STR_A3_CfgWeapons_Toolkit0"], 0],
true
] call CBA_fnc_addSetting;
@ -128,7 +138,7 @@
QGVAR(miscRepairRequiredItems),
"LIST",
[LSTRING(MiscRepairRequiredItems_DisplayName), LSTRING(MiscRepairRequiredItems_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[[], [ANY_TOOLKIT_FAKECLASS]], ["STR_A3_None", "STR_A3_CfgWeapons_Toolkit0"], 1],
true
] call CBA_fnc_addSetting;
@ -137,7 +147,7 @@
QGVAR(fullRepairRequiredItems),
"LIST",
[LSTRING(FullRepairRequiredItems_DisplayName), LSTRING(FullRepairRequiredItems_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[[[], [ANY_TOOLKIT_FAKECLASS]], ["STR_A3_None", "STR_A3_CfgWeapons_Toolkit0"], 1],
true
] call CBA_fnc_addSetting;
@ -145,18 +155,33 @@
[
QGVAR(autoShutOffEngineWhenStartingRepair), "CHECKBOX",
[LSTRING(autoShutOffEngineWhenStartingRepair_name), LSTRING(autoShutOffEngineWhenStartingRepair_description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
false, // default value
true, // isGlobal
{[QGVAR(autoShutOffEngineWhenStartingRepair), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting;
[
QGVAR(miscRepairTime), "SLIDER",
[LSTRING(miscRepairTime_name), LSTRING(miscRepairTime_description)],
_category,
[0,60,15,-1], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true
] call CBA_fnc_addSetting;
[
QGVAR(wheelChangeTime), "SLIDER",
[LSTRING(wheelChangeTime_name), LSTRING(wheelChangeTime_description)],
_category,
[0,60,10,-1], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true
] call CBA_fnc_addSetting;
[
QGVAR(patchWheelTime),
"SLIDER",
[LSTRING(patchWheelTime_DisplayName), LSTRING(patchWheelTime_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[0.1, 60, 5, 1],
true
] call CBA_fnc_addSetting;
@ -165,7 +190,7 @@
QGVAR(patchWheelMaximumRepair),
"SLIDER",
[LSTRING(patchWheelMaximumRepair_DisplayName), LSTRING(patchWheelMaximumRepair_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_repair"],
_category,
[0, 1, 0.3, 1, true],
true
] call CBA_fnc_addSetting;

View File

@ -20,6 +20,10 @@
#define DAMAGE_COLOR_SCALE ["#FFFFFF", "#FFFF7E", "#FFEC4D", "#FFD52C", "#FCB121", "#FF9916", "#FF7D16", "#FF4400", "#FF0000"]
#define IN_REPAIR_FACILITY_CACHE_EXPIRY 1
#define NEAR_REPAIR_VEHICLE_CACHE_EXPIRY 1
#define ANY_TOOLKIT_FAKECLASS QGVAR(anyToolKit)
#define PATCH_WHEEL_STEP_TIME 0.05

View File

@ -266,6 +266,12 @@
<Chinese>維修載具中...</Chinese>
<Turkish>Tamir Ediliyor...</Turkish>
</Key>
<Key ID="STR_ACE_Repair_timeCoefficientFullRepair_name">
<English>Full Repair Time Coefficient</English>
</Key>
<Key ID="STR_ACE_Repair_timeCoefficientFullRepair_description">
<English>Modifies how long it takes to perform a Full Repair.\nThe repair time is based on based on the amount of repairs needed for each part, including those normally inaccessible.</English>
</Key>
<Key ID="STR_ACE_Repair_LocationsBoostTraining_Description">
<English>Boost engineer training when in repair vehicles or facilities. Untrained becomes engineer, engineer becomes advanced engineer.</English>
<French>Améliore les compétences en ingénierie des unités en fonction du lieu où elles se trouvent ; notamment dans les véhicules de réparation ou les ateliers.\nUn soldat non formé devient ingénieur, un ingénieur devient ingénieur avancé.</French>
@ -1285,7 +1291,7 @@
<Chinese>維修門檻</Chinese>
</Key>
<Key ID="STR_ACE_Repair_repairDamageThreshold_description">
<English>What is the maximum damage that can be repaired with a toolkit?</English>
<English>Maximum damage to which a part can be repaired with a toolkit.\n0% means all damage can be repaired.</English>
<German>Der maximale Schaden, der von einem Reperatursatz behoben werden kann?</German>
<Polish>Jaki jest maksymalny poziom uszkodzeń jaki może zostać naprawiony przy pomocy narzędzi?</Polish>
<Portuguese>Qual é o dano máximo que pode ser reparado com um kit de ferramentas?</Portuguese>
@ -1315,7 +1321,7 @@
<Chinese>維修門檻 (工兵)</Chinese>
</Key>
<Key ID="STR_ACE_Repair_repairDamageThreshold_Engineer_description">
<English>What is the maximum damage that can be repaired by an engineer?</English>
<English>Maximum damage to which a part can be repaired by an engineer above the minimum level required for the repair.\n0% means all damage can be repaired.</English>
<German>Der maximale Schaden, der von einem Pionier behoben werden kann?</German>
<Polish>Jaki jest maksymalny poziom uszkodzeń jaki może zostać naprawiony przez mechanika?</Polish>
<Portuguese>Qual é o dano máximo que pode ser reparado com um engenheiro?</Portuguese>
@ -1860,7 +1866,7 @@
<Chinese>選擇的備件數量</Chinese>
</Key>
<Key ID="STR_ACE_Repair_WheelRepairRequiredItems_DisplayName">
<English>Wheel Repair Requirements</English>
<English>Wheel Change Requirements</English>
<German>Bedingungen für die Reifenreperatur</German>
<Polish>Wym. naprawy kół</Polish>
<Spanish>Requisitos de reparación de ruedas</Spanish>
@ -2062,6 +2068,18 @@
<Spanish>Apagar el motor automáticamente al efectuar una reparación</Spanish>
<Korean>수리 시 엔진을 자동으로 끕니다.</Korean>
</Key>
<Key ID="STR_ACE_Repair_miscRepairTime_name">
<English>Part Repair Time</English>
</Key>
<Key ID="STR_ACE_Repair_miscRepairTime_description">
<English>Time in seconds to complete a repair.</English>
</Key>
<Key ID="STR_ACE_Repair_wheelChangeTime_name">
<English>Wheel Change Time</English>
</Key>
<Key ID="STR_ACE_Repair_wheelChangeTime_description">
<English>Time in seconds to remove or change a wheel.</English>
</Key>
<Key ID="STR_ACE_Repair_PatchWheel">
<English>Patch Wheel</English>
<German>Radflicken</German>
@ -2071,16 +2089,16 @@
<German>Radflicken...</German>
</Key>
<Key ID="STR_ACE_Repair_patchWheelTime_DisplayName">
<English>Patch wheel time</English>
<English>Wheel Patch Time</English>
</Key>
<Key ID="STR_ACE_Repair_patchWheelTime_Description">
<English>Time it takes to patch a wheel by 5%.</English>
</Key>
<Key ID="STR_ACE_Repair_patchWheelMaximumRepair_DisplayName">
<English>Patch wheel maximum repair</English>
<English>Patch Wheel Threshold</English>
</Key>
<Key ID="STR_ACE_Repair_patchWheelMaximumRepair_Description">
<English>Maximum level a wheel can be patched.</English>
<English>Maximum level to which a wheel can be patched.</English>
</Key>
<Key ID="STR_ACE_Repair_patchWheelLocation_DisplayName">
<English>Wheel Patch Location</English>

View File

@ -28,6 +28,7 @@ Config Name | Type | Description
`acex_field_rations_refillItem` | String | Makes an item refillable, class name of item added when refilled (OPTIONAL)
`acex_field_rations_refillAmount` | Number | Amount of water required to refill item (OPTIONAL)
`acex_field_rations_refillTime` | Number | Time required to refill item (in seconds) (OPTIONAL)
`ACE_isFieldRationItem` | Number | Force adds the item to the ACE Field Rations category in ACE Arsenal (OPTIONAL)
_* Value range is 0 to 100 and can be modified by the corresponding coefficient setting._

View File

@ -38,3 +38,21 @@ class CfgVehicles {
};
};
```
### 1.3 Treatment Items
Items in `CfgWeapons` with `ACE_isMedicalItem` property will be added to the ACE Medical category in the ACE Arsenal.
```cpp
class CfgWeapons {
class MyMedicalItem {
ACE_isMedicalItem = 1;
};
};
```
Required items in `ACE_Medical_Treatment_Actions` will also be added as a fallback.
```cpp
class ACE_Medical_Treatment_Actions {
class MyCustomTreatment {
items[] = {"MyMedicalItem"};
};
};
```

View File

@ -0,0 +1,41 @@
---
layout: wiki
title: Wirecutter Framework
description: Explains how to set-up items, backpacks and vests with ACE3 wirecutter system.
group: framework
order: 5
parent: wiki
mod: ace
version:
major: 3
minor: 16
patch: 0
---
## 1. Config Values
The properties below control whether an item is considered a wirecutter. Worn items (vests and backpacks) can have "built-in" wirecutters with the `ace_logistics_wirecutter_hasWirecutter` property.
```cpp
class CfgWeapons {
class MyVest {
ace_logistics_wirecutter_hasWirecutter = 1; //1 for true, 0 for false.
};
class MyItem {
ACE_isWirecutter = 1; //1 for true, 0 for false.
};
};
class CfgVehicles {
class MyBackpack {
ace_logistics_wirecutter_hasWirecutter = 1; //1 for true, 0 for false.
};
};
```
## 2. Events
### 2.1 Listenable
Event Name | Description | Passed Parameter(s) | Locality
---------- | ----------- | ------------------- | --------
`ace_wireCuttingStarted` | Wire cutting started | `[_unit, _fence]` | Global