diff --git a/addons/medical_gui/ui/cross_grave.paa b/addons/medical_gui/ui/cross_grave.paa new file mode 100644 index 0000000000..f3b7f1570c Binary files /dev/null and b/addons/medical_gui/ui/cross_grave.paa differ diff --git a/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp b/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp index a9c6eca5d7..9ed1b2998e 100644 --- a/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp +++ b/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp @@ -253,6 +253,16 @@ class GVAR(actions) { consumeItem = 1; litter[] = {}; }; + class Grave: BodyBag { + displayName = CSTRING(DigGrave); + displayNameProgress = CSTRING(DiggingGrave); + icon = QPATHTOEF(medical_gui,ui\cross_grave.paa); + treatmentTime = QGVAR(treatmentTimeGrave); + condition = QFUNC(canDigGrave); + callbackSuccess = QFUNC(placeInGrave); + items[] = {}; + consumeItem = 0; + }; class CPR: BasicBandage { displayName = CSTRING(Actions_CPR); displayNameProgress = CSTRING(Actions_PerformingCPR); diff --git a/addons/medical_treatment/XEH_PREP.hpp b/addons/medical_treatment/XEH_PREP.hpp index a6266b1508..11fabc5440 100644 --- a/addons/medical_treatment/XEH_PREP.hpp +++ b/addons/medical_treatment/XEH_PREP.hpp @@ -6,6 +6,7 @@ PREP(bandageLocal); PREP(bodyCleanupLoop); PREP(canBandage); PREP(canCPR); +PREP(canDigGrave); PREP(canPlaceInBodyBag); PREP(canSplint); PREP(canStitch); @@ -47,6 +48,8 @@ PREP(medication); PREP(medicationLocal); PREP(onMedicationUsage); PREP(placeInBodyBag); +PREP(placeInBodyBagOrGrave); +PREP(placeInGrave); PREP(removeBody); PREP(scanMedicalItems); PREP(setTriageStatus); diff --git a/addons/medical_treatment/XEH_postInit.sqf b/addons/medical_treatment/XEH_postInit.sqf index 3d01cb7158..e943b0c8c3 100644 --- a/addons/medical_treatment/XEH_postInit.sqf +++ b/addons/medical_treatment/XEH_postInit.sqf @@ -25,7 +25,7 @@ if (isServer) then { [QGVAR(fullHealLocal), LINKFUNC(fullHealLocal)] call CBA_fnc_addEventHandler; [QGVAR(ivBagLocal), LINKFUNC(ivBagLocal)] call CBA_fnc_addEventHandler; [QGVAR(medicationLocal), LINKFUNC(medicationLocal)] call CBA_fnc_addEventHandler; -[QGVAR(placeInBodyBag), LINKFUNC(placeInBodyBag)] call CBA_fnc_addEventHandler; +[QGVAR(placeInBodyBagOrGrave), LINKFUNC(placeInBodyBagOrGrave)] call CBA_fnc_addEventHandler; [QGVAR(splintLocal), LINKFUNC(splintLocal)] call CBA_fnc_addEventHandler; [QGVAR(tourniquetLocal), LINKFUNC(tourniquetLocal)] call CBA_fnc_addEventHandler; @@ -61,3 +61,35 @@ if (isServer) then { [_toReplace, _replacements] call EFUNC(common,registerItemReplacement); } forEach (configProperties [configFile >> QEGVAR(medical,replacementItems), "isArray _x"]); }] call CBA_fnc_addEventHandler; + +if (["ace_trenches"] call EFUNC(common,isModLoaded)) then { + if (hasInterface) then { + private _checkHeadstoneAction = [ + QGVAR(checkHeadstone), + LLSTRING(checkHeadstoneName), + QPATHTOEF(medical_gui,ui\cross_grave.paa), + { + [ + [_target getVariable QGVAR(headstoneData)], + true + ] call CBA_fnc_notify; + }, + {!isNil {_target getVariable QGVAR(headstoneData)}}, + {}, + [], + [1.05, 0.02, 0.3] //position in centre of cross + ] call EFUNC(interact_menu,createAction); + + ["Land_Grave_dirt_F", 0, [], _checkHeadstoneAction] call EFUNC(interact_menu,addActionToClass); + }; + + if (isServer) then { + ["ace_placedInBodyBag", { + params ["_target", "_restingPlace"]; + TRACE_2("ace_placedInBodyBag eh",_target,_restingPlace); + + private _targetName = [_target, false, true] call EFUNC(common,getName); + _restingPlace setVariable [QGVAR(headstoneData), _targetName, true]; + }] call CBA_fnc_addEventHandler; + }; +}; diff --git a/addons/medical_treatment/functions/fnc_canDigGrave.sqf b/addons/medical_treatment/functions/fnc_canDigGrave.sqf new file mode 100644 index 0000000000..85c76382ec --- /dev/null +++ b/addons/medical_treatment/functions/fnc_canDigGrave.sqf @@ -0,0 +1,23 @@ +#include "..\script_component.hpp" +/* + * Author: Ruthberg, commy2, esteldunedain, drofseh + * Checks if a unit can dig a grave at the position of the patient. + * + * Arguments: + * 0: Medic + * 1: Patient + * + * Return Value: + * Can dig + * + * Example: + * [player, cursorObject] call ace_medical_treatment_fnc_canDigGrave + * + * Public: No + */ + +params ["_medic", "_patient"]; + +if !(["ace_trenches"] call EFUNC(common,isModLoaded)) exitWith {false}; + +(GVAR(allowGraveDigging) > 0) && {_patient call EFUNC(common,canDig)} && {_medic call EFUNC(trenches,hasEntrenchingTool)} diff --git a/addons/medical_treatment/functions/fnc_placeInBodyBag.sqf b/addons/medical_treatment/functions/fnc_placeInBodyBag.sqf index fd4a62a10b..df73a16952 100644 --- a/addons/medical_treatment/functions/fnc_placeInBodyBag.sqf +++ b/addons/medical_treatment/functions/fnc_placeInBodyBag.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: Glowbal + * Author: Glowbal, drofseh * Places a dead body inside a body bag. * * Arguments: @@ -24,30 +24,5 @@ if ((alive _patient) && {!GVAR(allowBodyBagUnconscious)}) exitWith { [LSTRING(bodybagWhileStillAlive)] call EFUNC(common,displayTextStructured); }; -if (!local _patient) exitWith { - TRACE_1("Calling where local",local _patient); - [QGVAR(placeInBodyBag), [nil, _patient], _patient] call CBA_fnc_targetEvent; -}; - -if (alive _patient) then { - TRACE_1("Manually killing with setDead",_patient); - [_patient, "buried_alive", _medic] call EFUNC(medical_status,setDead); -}; - -private _position = (getPosASL _patient) vectorAdd [0, 0, 0.2]; - -private _headPos = _patient modelToWorldVisual (_patient selectionPosition "head"); -private _spinePos = _patient modelToWorldVisual (_patient selectionPosition "Spine3"); -private _direction = (_headPos vectorFromTo _spinePos) call CBA_fnc_vectDir; - -// Move the body away so it won't collide with the body bag object -// This setPosASL seems to need to be called where the unit is local -_patient setPosASL [-5000, -5000, 0]; - -// Create the body bag object, set its position to prevent it from flipping -private _bodyBag = createVehicle ["ACE_bodyBagObject", [0, 0, 0], [], 0, "NONE"]; -_bodyBag setPosASL _position; -_bodyBag setDir _direction; - -// Server will handle hiding and deleting the body -["ace_placedInBodyBag", [_patient, _bodyBag]] call CBA_fnc_globalEvent; +// Body bag needs to be a little higher to prevent it from flipping +[_this, "ACE_bodyBagObject", [0, 0, 0.2]] call FUNC(placeInBodyBagOrGrave); diff --git a/addons/medical_treatment/functions/fnc_placeInBodyBagOrGrave.sqf b/addons/medical_treatment/functions/fnc_placeInBodyBagOrGrave.sqf new file mode 100644 index 0000000000..33a577da81 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_placeInBodyBagOrGrave.sqf @@ -0,0 +1,57 @@ +#include "..\script_component.hpp" +/* + * Author: Glowbal, drofseh + * Places a dead body inside a body bag or grave. + * + * Arguments: + * 0: Arguments + * - 0: Medic + * - 1: Patient + * 1: Resting Place Classname + * 2: Offset (default: [0,0,0]) + * 3: Rotation (default: 0) + * + * Return Value: + * None + * + * Example: + * [[player, cursorObject], "ACE_bodyBagObject"] call ace_medical_treatment_fnc_placeInBodyBagOrGrave + * + * Public: No + */ + +params ["_args", "_restingPlaceClass", ["_offset", [0,0,0]], ["_rotation", 0]]; +_args params ["_medic", "_patient"]; +TRACE_1("placeInBodyBagOrGrave",_patient); + +if (!local _patient) exitWith { + TRACE_1("Calling where local",local _patient); + [QGVAR(placeInBodyBagOrGrave), _this, _patient] call CBA_fnc_targetEvent; +}; + +if (alive _patient) then { + TRACE_1("Manually killing with setDead",_patient); + [_patient, "buried_alive", _medic] call EFUNC(medical_status,setDead); +}; + +private _headPos = _patient modelToWorldVisual (_patient selectionPosition "head"); +private _spinePos = _patient modelToWorldVisual (_patient selectionPosition "Spine3"); +private _direction = (_headPos vectorFromTo _spinePos) call CBA_fnc_vectDir; +private _position = getPosASL _patient; +// apply adjustments +_position = _position vectorAdd _offset; +_direction = _direction + _rotation; + + +// Move the body away so it won't collide with the body bag object +// This setPosASL seems to need to be called where the unit is local +_patient setPosASL [-5000, -5000, 0]; + +// Create the body bag object, set its position to prevent it from flipping +private _restingPlace = createVehicle [_restingPlaceClass, [0, 0, 0], [], 0, "NONE"]; +_restingPlace setPosASL _position; +_restingPlace setDir _direction; + +// Server will handle hiding and deleting the body +// Keep event name as body bag only to avoid breaking things for others +["ace_placedInBodyBag", [_patient, _restingPlace]] call CBA_fnc_globalEvent; diff --git a/addons/medical_treatment/functions/fnc_placeInGrave.sqf b/addons/medical_treatment/functions/fnc_placeInGrave.sqf new file mode 100644 index 0000000000..f9ebf582f3 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_placeInGrave.sqf @@ -0,0 +1,31 @@ +#include "..\script_component.hpp" +/* + * Author: Glowbal, drofseh + * Places a dead body inside a grave. + * + * Arguments: + * 0: Medic + * 1: Patient + * + * Return Value: + * None + * + * Example: + * [player, cursorObject] call ace_medical_treatment_fnc_placeInGrave + * + * Public: No + */ + +params ["_medic", "_patient"]; +TRACE_1("placeInGrave",_patient); + +if ((alive _patient) && {GVAR(allowGraveDigging) < 2}) exitWith { + [LSTRING(bodybagWhileStillAlive)] call EFUNC(common,displayTextStructured); +}; + +private _graveClassname = missionNameSpace getVariable [QGVAR(graveClassname), "Land_Grave_dirt_F"]; +// Land_Grave_dirt_F needs to be rotated 90 degrees to line up with the body +private _graveRotation = missionNameSpace getVariable [QGVAR(graveRotation), 90]; + +[_this, _graveClassname, [0,0,0], _graveRotation] call FUNC(placeInBodyBagOrGrave); + diff --git a/addons/medical_treatment/initSettings.sqf b/addons/medical_treatment/initSettings.sqf index fd83a9995f..18e28608a8 100644 --- a/addons/medical_treatment/initSettings.sqf +++ b/addons/medical_treatment/initSettings.sqf @@ -125,6 +125,15 @@ true ] call CBA_fnc_addSetting; +[ + QGVAR(treatmentTimeGrave), + "SLIDER", + [LSTRING(TreatmentTimeGrave_DisplayName), LSTRING(TreatmentTimeGrave_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory_Treatment)], + [0.1, 120, 30, 1], + true +] call CBA_fnc_addSetting; + [ QGVAR(medicEpinephrine), "LIST", @@ -305,6 +314,15 @@ true ] call CBA_fnc_addSetting; +[ + QGVAR(allowGraveDigging), + "LIST", + [LSTRING(AllowGaveDigging_DisplayName), LSTRING(AllowGaveDigging_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory_Treatment)], + [[0, 1, 2], [ELSTRING(common,Disabled), LSTRING(AllowGaveDigging_graveOnlyDead), ELSTRING(common,Yes)], 1], + true +] call CBA_fnc_addSetting; + [ QGVAR(holsterRequired), "LIST", diff --git a/addons/medical_treatment/stringtable.xml b/addons/medical_treatment/stringtable.xml index e597980f9e..8f91fefc7c 100644 --- a/addons/medical_treatment/stringtable.xml +++ b/addons/medical_treatment/stringtable.xml @@ -412,6 +412,12 @@ 装入裹尸袋时间 초 단위로 시체 운반용 부대를 사용하는데 걸리는 시간을 정합니다. + + Grave Digging Time + + + Time, in seconds, required to dig a grave for a body. + Allow Epinephrine Erlaube Epiniphrin @@ -825,6 +831,15 @@ 能够将昏迷的伤员装入尸袋中。 기절상태의 인원을 시체운반용부대에 옮겨 담을 수 있는지를 정합니다. + + Allow Grave Digging + + + Enables digging graves to dispose of corpses. + + + Only if dead + Allow IV Transfusion Erlaube Bluttransfusionen @@ -4445,6 +4460,12 @@ 將屍體放入屍袋中... Vücut, ceset torbasına yerleştiriliyor... + + Dig grave for body + + + Digging grave for body... + %1 has bandaged patient %1 has vendado al paciente @@ -4686,6 +4707,9 @@ 身体抽搐了一下,可能还没死! 꿈틀대는걸 보니 죽은 것 같지는 않습니다! + + Check name on headstone + Bandage Rollover Bandażowanie Wielu Ran diff --git a/docs/wiki/framework/medical-treatment-framework.md b/docs/wiki/framework/medical-treatment-framework.md index adb9cd485d..ca10a9878a 100644 --- a/docs/wiki/framework/medical-treatment-framework.md +++ b/docs/wiki/framework/medical-treatment-framework.md @@ -56,3 +56,17 @@ class ACE_Medical_Treatment_Actions { }; }; ``` + +## 2. Mission Variables + +### 2.1 Grave Digging Object Configuration + +The object created when digging a grave can be modified by setting the `ace_medical_treatment_graveClassname` variable. +```sqf +ace_medical_treatment_graveClassname = "Land_Grave_11_F"; // classname, e.g. unmarked gravel (no headstone OR check actions) +``` + +The object's rotation can also be modified, if necessary. +```sqf +ace_medical_treatment_graveRotation = 0; // rotation angle (will depend on model classname) +```