diff --git a/addons/conversion/$PBOPREFIX$ b/addons/conversion/$PBOPREFIX$ new file mode 100644 index 000000000..81edac690 --- /dev/null +++ b/addons/conversion/$PBOPREFIX$ @@ -0,0 +1 @@ +x\kat\addons\conversion \ No newline at end of file diff --git a/addons/conversion/ACE_Medical_Treatment_Actions.hpp b/addons/conversion/ACE_Medical_Treatment_Actions.hpp new file mode 100644 index 000000000..560b1dfce --- /dev/null +++ b/addons/conversion/ACE_Medical_Treatment_Actions.hpp @@ -0,0 +1,15 @@ +class ACE_Medical_Treatment_Actions { + class CheckPulse; + class BasicBandage; + class ConvertPatient: CheckPulse { + displayName = CSTRING(convertPatient); + displayNameProgress = CSTRING(converting); + condition = QFUNC(manualConversionCondition); + medicRequired = QGVAR(manualConversionLevel); + treatmentLocations = QGVAR(manualConversionLocation); + treatmentTime = QGVAR(manualConversionTime); + allowedSelections[] = {"All"}; + items[] = {""}; + callbackSuccess = QFUNC(manualConversion); + }; +}; diff --git a/addons/conversion/CfgEventHandlers.hpp b/addons/conversion/CfgEventHandlers.hpp new file mode 100644 index 000000000..4551ce282 --- /dev/null +++ b/addons/conversion/CfgEventHandlers.hpp @@ -0,0 +1,20 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + disableModuload = "true"; + }; +}; + +class Extended_Init_EventHandlers { + class CAManBase { + class ADDON { + init = QUOTE([ARR_2((_this select 0),false)] call FUNC(init)); + }; + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_postInit)); + }; +}; diff --git a/addons/conversion/CfgFunctions.hpp b/addons/conversion/CfgFunctions.hpp new file mode 100644 index 000000000..ee54ec98c --- /dev/null +++ b/addons/conversion/CfgFunctions.hpp @@ -0,0 +1,10 @@ +class CfgFunctions { + class overwrite_ace_medical_status { + tag = "ace_medical_status"; + class ace_medical_status { + class setDead { + file = QPATHTOF(functions\fnc_setDead.sqf); + }; + }; + }; +}; \ No newline at end of file diff --git a/addons/conversion/CfgVehicles.hpp b/addons/conversion/CfgVehicles.hpp new file mode 100644 index 000000000..87067ae96 --- /dev/null +++ b/addons/conversion/CfgVehicles.hpp @@ -0,0 +1,21 @@ +class CfgVehicles { + class Man; + class CAManBase: Man { + class ACE_Actions { + class ACE_MainActions { + class KAT_TicketConversion { + displayName = CSTRING(TicketConversion); + condition = QUOTE(_target call FUNC(ticketConversionCondition)); + statement = QUOTE(_target call FUNC(ticketConversion)); + icon = QACEPATHTOF(medical_gui,ui\cross.paa); + }; + class KAT_LibConversion { + displayName = CSTRING(LibConversion); + condition = QUOTE(_target call FUNC(libConversionCondition)); + statement = QUOTE(_target call FUNC(libConversion)); + icon = QACEPATHTOF(medical_gui,ui\cross.paa); + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/addons/conversion/XEH_PREP.hpp b/addons/conversion/XEH_PREP.hpp new file mode 100644 index 000000000..f33602952 --- /dev/null +++ b/addons/conversion/XEH_PREP.hpp @@ -0,0 +1,15 @@ +PREP(conversionCheck); +PREP(conversionCondition); +PREP(fullHealLocal); +PREP(handleRespawn); +PREP(init); +PREP(KATConditionExecutionDeath); +PREP(KATConditionSecondChance); +PREP(libConversion); +PREP(libConversionCondition); +PREP(libConversionDistance); +PREP(manualConversion); +PREP(manualConversionCondition); +PREP(setDead); +PREP(ticketConversion); +PREP(ticketConversionCondition); \ No newline at end of file diff --git a/addons/conversion/XEH_postInit.sqf b/addons/conversion/XEH_postInit.sqf new file mode 100644 index 000000000..7b802e18e --- /dev/null +++ b/addons/conversion/XEH_postInit.sqf @@ -0,0 +1,50 @@ +#include "script_component.hpp" + +[QEGVAR(misc,handleRespawn), LINKFUNC(handleRespawn)] call CBA_fnc_addEventHandler; +[QACEGVAR(medical_treatment,fullHealLocalMod), LINKFUNC(fullHealLocal)] call CBA_fnc_addEventHandler; + +["kat_conversion_convertCasualty", { + private _type = typeOf player; + private _group = createGroup [(side player), true]; + private _previousUnit = player; + private _setName = name _previousUnit; + private _loadout = getUnitLoadout player; + private _unit = _group createUnit [_type, [0,0,0], [], 0, "NONE"]; + _unit setUnitLoadout _loadout; + + _previousUnit setVariable [QEGVAR(vitals,simpleMedical), false, true]; + _previousUnit setVariable [QGVAR(currentConverted), true, true]; + + selectPlayer _unit; + + ["kat_conversion_unitTransfer", [_previousUnit]] call CBA_fnc_serverEvent; + + _previousUnit setName _setName; + + forceRespawn player; + deleteVehicle _unit; +}] call CBA_fnc_addEventHandler; + +["kat_conversion_unitTransfer", { + params ["_previousUnit"]; + private _group2 = createGroup [(side _previousUnit), true]; + [_previousUnit] join _group2; + _group2 setGroupOwner 2; + [_previousUnit, true] call ACEFUNC(medical,setUnconscious); +}] call CBA_fnc_addEventHandler; + +["kat_conversion_respawnTimer", { + params ["_time"]; + private _currentRespawnTime = playerRespawnTime; + setPlayerRespawnTime _time; + _currentUnit = player; + + [{ + params ["_currentUnit"]; + + (lifeState _currentUnit isEqualTo "HEALTHY") + }, { + params [_currentRespawnTime]; + setPlayerRespawnTime _currentRespawnTime; + }, [_currentUnit, _currentRespawnTime], 360, {}] call CBA_fnc_waitUntilAndExecute; +}] call CBA_fnc_addEventHandler; \ No newline at end of file diff --git a/addons/conversion/XEH_preInit.sqf b/addons/conversion/XEH_preInit.sqf new file mode 100644 index 000000000..92e69c3d6 --- /dev/null +++ b/addons/conversion/XEH_preInit.sqf @@ -0,0 +1,142 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +#define CBA_SETTINGS_CAT "KAT - ADV Medical: Conversion" + +[ + QGVAR(enable), + "CHECKBOX", + [LLSTRING(CONVERSION_ENABLE), LLSTRING(CONVERSION_ENABLE_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(enableConversionMessage), + "CHECKBOX", + [LLSTRING(CONVERSION_MESSAGE), LLSTRING(CONVERSION_MESSAGE_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(enableTicketConversion), + "CHECKBOX", + [LLSTRING(CONVERSION_TICKET_CONVERSION), LLSTRING(CONVERSION_TICKET_CONVERSION_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(ticketConversionGain), + "SLIDER", + [LLSTRING(CONVERSION_TICKET_CONVERSION_GAIN), LLSTRING(CONVERSION_TICKET_CONVERSION_GAIN_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [0, 10, 3, 0], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(enableLiberationConversion), + "CHECKBOX", + [LLSTRING(CONVERSION_LIBERATION_CONVERSION), LLSTRING(CONVERSION_LIBERATION_CONVERSION_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(enableLiberationConversionGain), + "SLIDER", + [LLSTRING(CONVERSION_LIBERATION_CONVERSION_GAIN), LLSTRING(CONVERSION_LIBERATION_CONVERSION_GAIN_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [0, 100, 50, 0], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(enableLiberationConversionDistance), + "SLIDER", + [LLSTRING(CONVERSION_LIBERATION_CONVERSION_DISTANCE), LLSTRING(CONVERSION_LIBERATION_CONVERSION_DISTANCE_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [0, 5000, 1000, 0], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(enableSpectatorRespawn), + "CHECKBOX", + [LLSTRING(CONVERSION_SPECTATOR_RESPAWN), LLSTRING(CONVERSION_SPECTATOR_RESPAWN_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(forceVehicleConversion), + "CHECKBOX", + [LLSTRING(CONVERSION_FORCE_VEHICLE), LLSTRING(CONVERSION_FORCE_VEHICLE_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(convertVehicles), + "EDITBOX", + [LLSTRING(CONVERSION_FORCE_VEHICLE_LIST), LLSTRING(CONVERSION_FORCE_VEHICLE_LIST_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + "'kat_stretcher'", + 1, + { + private _array = [_this, "CfgVehicles"] call EFUNC(chemical,getList); + missionNamespace setVariable [QGVAR(convertVehicles), _array, true]; + }, + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(allowManualConversion), + "CHECKBOX", + [LLSTRING(CONVERSION_MANUAL_CONVERSION), LLSTRING(CONVERSION_MANUAL_CONVERSION_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [false], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(manualConversionLevel), + "LIST", + [LLSTRING(CONVERSION_MANUAL_CONVERSION_LEVEL), LLSTRING(CONVERSION_MANUAL_CONVERSION_LEVEL_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [[0, 1, 2], ["STR_ACE_Medical_Treatment_Anyone", "STR_ACE_Medical_Treatment_Medics", "STR_ACE_Medical_Treatment_Doctors"], 0], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(manualConversionLocation), + "LIST", + [LLSTRING(CONVERSION_MANUAL_CONVERSION_LOCATION), LLSTRING(CONVERSION_MANUAL_CONVERSION_LOCATION_DESC)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [[0,1,2,3],["STR_ACE_Common_Anywhere", "STR_ACE_Common_Vehicle", "STR_ACE_Medical_Treatment_MedicalFacilities", "STR_ACE_Medical_Treatment_VehiclesAndFacilities"],0], + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(manualConversionTime), + "SLIDER", + [LLSTRING(CONVERSION_LIBERATION_CONVERSION_TIME)], + [CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)], + [0, 60, 15, 0], + true +] call CBA_Settings_fnc_init; + +ADDON = true; \ No newline at end of file diff --git a/addons/conversion/config.cpp b/addons/conversion/config.cpp new file mode 100644 index 000000000..ebb8c0e54 --- /dev/null +++ b/addons/conversion/config.cpp @@ -0,0 +1,35 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + requiredVersion = REQUIRED_VERSION; + units[] = {}; + weapons[] = {}; + magazines[] = {}; + requiredAddons[] = { + "ace_medical", + "ace_medical_ai", + "ace_medical_blood", + "ace_medical_damage", + "ace_medical_engine", + "ace_medical_feedback", + "ace_medical_gui", + "ace_medical_statemachine", + "ace_medical_status", + "ace_medical_treatment", + "ace_medical_vitals", + "ace_dogtags", + "cba_settings" + }; + author = "Mazinski"; + authors[] = {"Mazinski"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgFunctions.hpp" +#include "CfgVehicles.hpp" +#include "ACE_Medical_Treatment_Actions.hpp" diff --git a/addons/misc/functions/fnc_conditionExecutionDeath.sqf b/addons/conversion/functions/fnc_KATConditionExecutionDeath.sqf similarity index 51% rename from addons/misc/functions/fnc_conditionExecutionDeath.sqf rename to addons/conversion/functions/fnc_KATConditionExecutionDeath.sqf index 9403b1776..348ceff09 100644 --- a/addons/misc/functions/fnc_conditionExecutionDeath.sqf +++ b/addons/conversion/functions/fnc_KATConditionExecutionDeath.sqf @@ -1,8 +1,8 @@ #include "..\script_component.hpp" /* - * Author: BaerMitUmlaut - * Modified: Blue - * Condition for an execution caused death (fatal injury received in cardiac arrest). + * Author: mharis001 + * Edited: Blue, Mazinski.H + * Condition for going into cardiac arrest upon receiving a fatal injury. * * Arguments: * 0: Unit @@ -11,16 +11,16 @@ * None * * Example: - * [player] call ace_medical_statemachine_fnc_conditionExecutionDeath + * [player] call kat_conversion_fnc_conditionSecondChance * * Public: No */ params ["_unit"]; -(if (isPlayer _unit) then { +(if (isPlayer _unit || (GET_CONVERT_STATUS(_unit) && LIB_CONVERSION_DISTANCE(_unit))) then { ACEGVAR(medical_statemachine,fatalInjuriesPlayer) != FATAL_INJURIES_NEVER } else { - (ACEGVAR(medical_statemachine,fatalInjuriesAI) != FATAL_INJURIES_NEVER) && {!(_unit getVariable [QGVAR(PreventInstantAIDeath), false])} + (ACEGVAR(medical_statemachine,fatalInjuriesAI) != FATAL_INJURIES_NEVER) && {!(_unit getVariable [QEGVAR(misc,PreventInstantAIDeath), false])} }) -&& {!(_unit getVariable [QACEGVAR(medical,deathBlocked), false])} +&& {!(_unit getVariable [QACEGVAR(medical,deathBlocked), false])} \ No newline at end of file diff --git a/addons/misc/functions/fnc_conditionSecondChance.sqf b/addons/conversion/functions/fnc_KATConditionSecondChance.sqf similarity index 61% rename from addons/misc/functions/fnc_conditionSecondChance.sqf rename to addons/conversion/functions/fnc_KATConditionSecondChance.sqf index 0f3e42ef6..4bae57b45 100644 --- a/addons/misc/functions/fnc_conditionSecondChance.sqf +++ b/addons/conversion/functions/fnc_KATConditionSecondChance.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: mharis001 - * Modified: Blue + * Edited: Blue, Mazinski.H * Condition for going into cardiac arrest upon receiving a fatal injury. * * Arguments: @@ -11,15 +11,15 @@ * None * * Example: - * [player] call ace_medical_statemachine_fnc_conditionSecondChance + * [player] call kat_conversion_fnc_conditionSecondChance * * Public: No */ params ["_unit"]; -if (isPlayer _unit) then { +if (isPlayer _unit || (GET_CONVERT_STATUS(_unit) && LIB_CONVERSION_DISTANCE(_unit))) then { ACEGVAR(medical_statemachine,fatalInjuriesPlayer) != FATAL_INJURIES_ALWAYS } else { - ACEGVAR(medical_statemachine,fatalInjuriesAI) != FATAL_INJURIES_ALWAYS || {_unit getVariable [QGVAR(PreventInstantAIDeath), false]} -}; + ACEGVAR(medical_statemachine,fatalInjuriesAI) != FATAL_INJURIES_ALWAYS || {_unit getVariable [QEGVAR(misc,PreventInstantAIDeath), false]} +} \ No newline at end of file diff --git a/addons/conversion/functions/fnc_conversionCheck.sqf b/addons/conversion/functions/fnc_conversionCheck.sqf new file mode 100644 index 000000000..1bcf2a036 --- /dev/null +++ b/addons/conversion/functions/fnc_conversionCheck.sqf @@ -0,0 +1,22 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Condition for automatic conversion + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_conversionCheck + * + * Public: No + */ + +params ["_unit"]; + +if ((!(ACEGVAR(medical_statemachine,AIUnconsciousness))) && (!isPlayer _unit) && LIB_CONVERSION_DISTANCE(_unit)) then { + GET_CONVERT_STATUS(_unit) != true +} \ No newline at end of file diff --git a/addons/conversion/functions/fnc_conversionCondition.sqf b/addons/conversion/functions/fnc_conversionCondition.sqf new file mode 100644 index 000000000..bb52c3b29 --- /dev/null +++ b/addons/conversion/functions/fnc_conversionCondition.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Check if a unit is in a stable state for resource conversion + * + * Arguments: + * 0: The patient + * + * Return Value: + * Has no critical health conditions + * + * Example: + * [player] call kat_conversion_conversionCondition + * + * Public: No + */ + +params ["_unit"]; + +private _bloodVolume = GET_BLOOD_VOLUME_LITERS(_unit); +if (_bloodVolume < ACEGVAR(medical,const_stableVitalsBloodThreshold)) exitWith { false }; + +if IN_CRDC_ARRST(_unit) exitWith { false }; + +private _bloodPressure = GET_BLOOD_PRESSURE(_unit); +_bloodPressure params ["_bloodPressureL", "_bloodPressureH"]; +if (_bloodPressureL < 50 || {_bloodPressureH < 60}) exitWith { false }; + +private _heartRate = GET_HEART_RATE(_unit); +if (_heartRate < 70 || _heartRate > 100) exitWith { false }; + +private _o2 = GET_KAT_SPO2(_unit); +if (_o2 < EGVAR(breathing,Stable_spo2)) exitWith { false }; + +private _fractures = _unit getVariable [QEGVAR(surgery,fractures), [0,0,0,0,0,0]]; +if (({_x == 0} count _fracture) != 6) exitWith { false }; + +true \ No newline at end of file diff --git a/addons/conversion/functions/fnc_fullHealLocal.sqf b/addons/conversion/functions/fnc_fullHealLocal.sqf new file mode 100644 index 000000000..69d473f4e --- /dev/null +++ b/addons/conversion/functions/fnc_fullHealLocal.sqf @@ -0,0 +1,25 @@ +#include "..\script_component.hpp" +/* + * Author: MiszczuZPolski + * Local callback for fully healing a patient. + * + * Arguments: + * 0: Patient + * + * Return Value: + * None + * + * Example: + * [player] call kat_vitals_fnc_fullHealLocal + * + * Public: No + */ + +params ["_patient"]; + +if (hasInterface && GVAR(enable)) then { + _patient setVariable [QGVAR(convert), true, true]; +}; + +_patient setVariable [QGVAR(currentConverted), false, true]; +_patient setVariable [QGVAR(associatedPlayer), player, true]; \ No newline at end of file diff --git a/addons/conversion/functions/fnc_handleRespawn.sqf b/addons/conversion/functions/fnc_handleRespawn.sqf new file mode 100644 index 000000000..31a3d7f40 --- /dev/null +++ b/addons/conversion/functions/fnc_handleRespawn.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: MiszczuZPolski + * Local callback for fully healing a patient. + * + * Arguments: + * 0: Patient + * + * Return Value: + * None + * + * Example: + * [player] call kat_vitals_fnc_handleRespawn + * + * Public: No + */ + +params ["_patient"]; + +[_patient] call FUNC(fullHealLocal); \ No newline at end of file diff --git a/addons/conversion/functions/fnc_init.sqf b/addons/conversion/functions/fnc_init.sqf new file mode 100644 index 000000000..583552f78 --- /dev/null +++ b/addons/conversion/functions/fnc_init.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Initializes unit variables. + * + * Arguments: + * 0: Patient + * + * Return Value: + * None + * + * Example: + * [player] call kat_vitals_fnc_init + * + * Public: No + */ + +params ["_patient"]; + +[_patient] call FUNC(fullHealLocal); \ No newline at end of file diff --git a/addons/conversion/functions/fnc_libConversion.sqf b/addons/conversion/functions/fnc_libConversion.sqf new file mode 100644 index 000000000..1b7f00647 --- /dev/null +++ b/addons/conversion/functions/fnc_libConversion.sqf @@ -0,0 +1,28 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Converts patient to Liberation Supply + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_libConversion + * + * Public: No + */ + +params ["_patient"]; + +private _storageAreas = (([getPos _patient] call KPLIB_fnc_getNearestFob) nearobjects (GRLIB_fob_range)) select {(_x getVariable ["KP_liberation_storage_type",-1]) == 0}; +private _crate = [KP_liberation_supplyCrate, GVAR(enableLiberationConversionGain), [(position _patient) select 0, (position _patient) select 1, 10000]] call KPLIB_fnc_createCrate; + +{ + if ([_crate, _x] call KPLIB_fnc_crateToStorage) then { break }; +} forEach _storageAreas; + +_patient setDamage 1; +deleteVehicle _patient; \ No newline at end of file diff --git a/addons/conversion/functions/fnc_libConversionCondition.sqf b/addons/conversion/functions/fnc_libConversionCondition.sqf new file mode 100644 index 000000000..66a8413bf --- /dev/null +++ b/addons/conversion/functions/fnc_libConversionCondition.sqf @@ -0,0 +1,30 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Checks if patient can be converted into Liberation Supply + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_libConversionCondition + * + * Public: No + */ + +params ["_patient"]; + +if !(GVAR(enableLiberationConversion)) exitWith { false }; +if ((missionNamespace getVariable ["GRLIB_fob_range", -1]) == -1) exitWith { false }; +if !(_patient getVariable [QGVAR(currentConverted), false]) exitWith { false }; + +if ((_patient distance2d ([getPos _patient] call KPLIB_fnc_getNearestFob)) > GRLIB_fob_range) exitWith { false }; + +if !([_patient] call FUNC(conversionCondition)) exitWith { false }; + +if (GVAR(forceVehicleConversion) && ((isNull objectParent _patient) || !((objectParent _patient) in GVAR(convertVehicles)))) exitWith { false }; + +true \ No newline at end of file diff --git a/addons/conversion/functions/fnc_libConversionDistance.sqf b/addons/conversion/functions/fnc_libConversionDistance.sqf new file mode 100644 index 000000000..88785188c --- /dev/null +++ b/addons/conversion/functions/fnc_libConversionDistance.sqf @@ -0,0 +1,25 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Checks if patient is far enough away from a Liberation FOB to be converted + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_libConversionDistance + * + * Public: No + */ + +params ["_patient"]; + +if ((missionNamespace getVariable ["GRLIB_fob_range", -1]) == -1) exitWith { true }; +if !(GVAR(enableLiberationConversion)) exitWith { true }; +if !(GVAR(enableConversionDistance)) exitWith { true }; +if ((_patient distance2d ([getPos _patient] call KPLIB_fnc_getNearestFob)) < enableLiberationConversionDistance) exitWith { true }; + +false \ No newline at end of file diff --git a/addons/conversion/functions/fnc_manualConversion.sqf b/addons/conversion/functions/fnc_manualConversion.sqf new file mode 100644 index 000000000..785c841f4 --- /dev/null +++ b/addons/conversion/functions/fnc_manualConversion.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Performs initial patient conversion + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_manualConversion + * + * Public: No + */ + + params ["_medic", "_patient"]; + +["kat_conversion_convertCasualty", _patient] call CBA_fnc_localEvent; \ No newline at end of file diff --git a/addons/conversion/functions/fnc_manualConversionCondition.sqf b/addons/conversion/functions/fnc_manualConversionCondition.sqf new file mode 100644 index 000000000..9d89dc380 --- /dev/null +++ b/addons/conversion/functions/fnc_manualConversionCondition.sqf @@ -0,0 +1,23 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Checks if patient can be manually converted + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_manualConversionCondition + * + * Public: No + */ + +params ["_medic", "_patient"]; + +if !(IS_UNCONSCIOUS(_patient)) exitWith { false }; +if (GVAR(enableLiberationConversion) && !(LIB_CONVERSION_DISTANCE(_patient))) exitWith { false }; + +true \ No newline at end of file diff --git a/addons/conversion/functions/fnc_setDead.sqf b/addons/conversion/functions/fnc_setDead.sqf new file mode 100644 index 000000000..12ebc79bc --- /dev/null +++ b/addons/conversion/functions/fnc_setDead.sqf @@ -0,0 +1,58 @@ +#include "..\script_component.hpp" +/* + * Author: commy2 + * Edited: Mazinski + * Kills a local unit. + * + * Arguments: + * 0: The unit + * 1: Reason for death + * 2: Killer + * 3: Instigator + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit", ["_reason", "#setDead"], ["_source", objNull], ["_instigator", objNull]]; +TRACE_4("setDead",_unit,_reason,_source,_instigator); + +// If patient is marked for conversion, send them into arrest rather than killing them if the reason for dying is that they are AI +private _unitState = [_unit, ACEGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState; + +if (GET_CONVERT_STATUS(_unit) && (_reason isEqualTo "CardiacArrest:DeathAI" || _reason isEqualTo "Unconscious:DeathAI") && LIB_CONVERSION_DISTANCE(_unit)) exitWith { + [_unit, ACEGVAR(medical,STATE_MACHINE), _unitState, "CardiacArrest"] call CBA_statemachine_fnc_manualTransition; +}; + +// No heart rate or blood pressure to measure when dead +_unit setVariable [VAR_HEART_RATE, 0, true]; +_unit setVariable [VAR_BLOOD_PRESS, [0, 0], true]; + +// Clear uncon variable just to be safe +_unit setVariable [VAR_UNCON, nil, true]; + +_unit setVariable [QACEGVAR(medical,causeOfDeath), _reason, true]; + +// Send a local event before death +[QACEGVAR(medical,death), [_unit]] call CBA_fnc_localEvent; + +// Update the state machine if necessary (forced respawn, scripted death, etc) +if (_unitState isNotEqualTo "Dead") then { + [_unit, ACEGVAR(medical,STATE_MACHINE), _unitState, "Dead"] call CBA_statemachine_fnc_manualTransition; +}; + +// (#8803) Reenable damage if disabled to prevent having live units in dead state +// Keep this after death event for compatibility with third party hooks +if (!isDamageAllowed _unit) then { + WARNING_1("setDead executed on unit with damage blocked - %1",_this); + _unit allowDamage true; +}; + +// Kill the unit without changing visual apperance +private _prevDamage = _unit getHitPointDamage "HitHead"; + +_unit setHitPointDamage ["HitHead", 1, true, _source, _instigator]; + +_unit setHitPointDamage ["HitHead", _prevDamage, true, _source, _instigator]; \ No newline at end of file diff --git a/addons/conversion/functions/fnc_ticketConversion.sqf b/addons/conversion/functions/fnc_ticketConversion.sqf new file mode 100644 index 000000000..4d49a9bef --- /dev/null +++ b/addons/conversion/functions/fnc_ticketConversion.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Converts patient to respawn tickets + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_ticketConversion + * + * Public: No + */ + +params ["_patient"]; + +[(side _patient), GVAR(ticketConversionGain)] call BIS_fnc_respawnTickets; + +if (GVAR(enableSpectatorRespawn)) then { + if (lifeState (_patient getVariable [QGVAR(associatedPlayer), objNull]) isEqualTo "DEAD-RESPAWN") then { + ["kat_conversion_respawnTimer", 0] call CBA_fnc_localEvent; + }; +}; + +_patient setDamage 1; +deleteVehicle _patient; \ No newline at end of file diff --git a/addons/conversion/functions/fnc_ticketConversionCondition.sqf b/addons/conversion/functions/fnc_ticketConversionCondition.sqf new file mode 100644 index 000000000..869e3c319 --- /dev/null +++ b/addons/conversion/functions/fnc_ticketConversionCondition.sqf @@ -0,0 +1,28 @@ +#include "..\script_component.hpp" +/* + * Author: Mazinski + * Checks if patient can be converted into respawn tickets + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_conversion_fnc_ticketConversionCondition + * + * Public: No + */ + +params ["_patient"]; + +if !(GVAR(enableTicketConversion)) exitWith { false }; +if !(_patient getVariable [QGVAR(currentConverted), false]) exitWith { false }; + +if !(_patient call ACEFUNC(medical_treatment,isInMedicalFacility)) exitWith { false }; +if !([_patient] call FUNC(conversionCondition)) exitWith { false }; + +if (GVAR(forceVehicleConversion) && ((isNull objectParent _patient) || !((objectParent _patient) in GVAR(convertVehicles)))) exitWith { false }; + +true \ No newline at end of file diff --git a/addons/conversion/script_component.hpp b/addons/conversion/script_component.hpp new file mode 100644 index 000000000..792efc6cd --- /dev/null +++ b/addons/conversion/script_component.hpp @@ -0,0 +1,17 @@ +#define COMPONENT conversion +#define COMPONENT_BEAUTIFIED KAT - Conversion +#include "\x\kat\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_CONVERSION + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_CONVERSION + #define DEBUG_SETTINGS DEBUG_SETTINGS_CONVERSION +#endif + +#include "\x\kat\addons\main\script_macros.hpp" \ No newline at end of file diff --git a/addons/conversion/stringtable.xml b/addons/conversion/stringtable.xml new file mode 100644 index 000000000..8e9fed82c --- /dev/null +++ b/addons/conversion/stringtable.xml @@ -0,0 +1,101 @@ + + + + + Enable Casualty Conversion + + + Enables Casualty Conversion for Players and Select AI + + + Display Conversion + + + Enables text in patient menu that they are converted + + + Ticket for Patient Conversion + + + Enables ticket gain when converting casualties + + + Tickets Gained + + + How many tickets should be regained when converting patients + + + Liberation Supply for Patient Conversion + + + Enables supply gain when converting casualties + + + Supply Gained + + + How much supply should be gien when converting patients + + + Distance Required + + + How far do Liberation patients need to be from a FOB for a conversion to be valid + + + One Life Conversion + + + Prevents spectating players from respawning until their body has been converted + + + Force Vehicle Conversion + + + Should patients only be allowed to be converted when in a vehicle? + + + Conversion Vehicles + + + List of vehicles that can be used for conversion + + + Enable Manual Initial Conversion + + + Enables manual initial conversion by medical personnel + + + Medical Level for Conversion + + + What level should a player be in order to perform an initial conversion + + + Location for Conversion + + + What medical facility should a player be in order to perform an initial conversion + + + Manual Conversion Time + + + Converted + + + Convert Casualty to Tickets + + + Convert Casualty to Liberation Supply + + + Perform Initial Conversion + + + Converting + + + diff --git a/addons/gui/functions/fnc_updateInjuryList.sqf b/addons/gui/functions/fnc_updateInjuryList.sqf index 55511183e..2f41be081 100644 --- a/addons/gui/functions/fnc_updateInjuryList.sqf +++ b/addons/gui/functions/fnc_updateInjuryList.sqf @@ -132,6 +132,10 @@ if (_target call ACEFUNC(common,isAwake)) then { }; }; +if (_target getVariable [QEGVAR(conversion,currentConverted),false] && EGVAR(conversion,enableConversionMessage)) then { + _entries pushBack [LELSTRING(conversion,ConversionText), [0.35, 0.72, 0.82, 1]]; +}; + // Skip the rest as they're body part specific if (_selectionN == -1) exitWith { // Add all entries to injury list diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index a0396d871..4fcee97eb 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -330,6 +330,12 @@ #define VAR_BLOODPRESSURE_CHANGE QEGVAR(circulation,bloodPressureChange) #define GET_BLOODPRESSURE_CHANGE(unit) (unit getVariable [VAR_BLOODPRESSURE_CHANGE, [0,0]]) +// Conversion +#define UNIT_CONVERT QEGVAR(conversion,convert) +#define GET_CONVERT_STATUS(unit) (unit getVariable [UNIT_CONVERT, false]) + +#define LIB_CONVERSION_DISTANCE(unit) ([unit] call EFUNC(conversion,libConversionDistance)) + // Pharma #define VAR_VASOCONSTRICTION QEGVAR(pharma,alphaAction) #define GET_VASOCONSTRICTION(unit) (unit getVariable [VAR_VASOCONSTRICTION, 1]) diff --git a/addons/misc/CfgFunctions.hpp b/addons/misc/CfgFunctions.hpp index b1b6edfb4..b41cfab86 100644 --- a/addons/misc/CfgFunctions.hpp +++ b/addons/misc/CfgFunctions.hpp @@ -51,15 +51,4 @@ class CfgFunctions { }; }; }; - class overwrite_ace_medical_statemachine { - tag = "ace_medical_statemachine"; - class ace_medical_statemachine { - class conditionExecutionDeath { - file = QPATHTOF(functions\fnc_conditionExecutionDeath.sqf); - }; - class conditionSecondChance { - file = QPATHTOF(functions\fnc_conditionSecondChance.sqf); - }; - }; - }; }; diff --git a/addons/misc/XEH_PREP.hpp b/addons/misc/XEH_PREP.hpp index 05244afb9..ddf3d8c47 100644 --- a/addons/misc/XEH_PREP.hpp +++ b/addons/misc/XEH_PREP.hpp @@ -6,10 +6,8 @@ PREP(canCheckDogtag); PREP(canStitchFullBody); PREP(carryObject); PREP(checkArmbandCondition); -PREP(conditionExecutionDeath); PREP(conditionIV); PREP(conditionIVstand); -PREP(conditionSecondChance); PREP(FAK_ammoToArray); PREP(FAK_arrayToAmmo); PREP(FAK_checkRepack); diff --git a/addons/statemachine/$PBOPREFIX$ b/addons/statemachine/$PBOPREFIX$ new file mode 100644 index 000000000..c89e17185 --- /dev/null +++ b/addons/statemachine/$PBOPREFIX$ @@ -0,0 +1 @@ +x\kat\addons\statemachine \ No newline at end of file diff --git a/addons/statemachine/Statemachine.hpp b/addons/statemachine/Statemachine.hpp new file mode 100644 index 000000000..89f8929a5 --- /dev/null +++ b/addons/statemachine/Statemachine.hpp @@ -0,0 +1,21 @@ +// Overwrite for ACE_Medical_StateMachine +class ACE_Medical_StateMachine { + class Unconscious { + class DeathAI { + condition = QUOTE(call EFUNC(conversion,conversionCheck)); + }; + }; + class FatalInjury { + class SecondChance { + condition = QUOTE(call EFUNC(conversion,conversionKATConditionSecondChance)); + }; + }; + class CardiacArrest { + class DeathAI { + condition = QUOTE(call EFUNC(conversion,conversionCheck)); + }; + class Execution { + condition = QUOTE(call EFUNC(conversion,KATConditionExecutionDeath)); + }; + }; +}; \ No newline at end of file diff --git a/addons/statemachine/config.cpp b/addons/statemachine/config.cpp new file mode 100644 index 000000000..b3f22ff34 --- /dev/null +++ b/addons/statemachine/config.cpp @@ -0,0 +1,21 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + requiredVersion = REQUIRED_VERSION; + units[] = {}; + weapons[] = {}; + magazines[] = {}; + requiredAddons[] = { + "ace_medical", + "ace_medical_statemachine" + }; + author = "Mazinski"; + authors[] = {"Mazinski"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "Statemachine.hpp" diff --git a/addons/statemachine/script_component.hpp b/addons/statemachine/script_component.hpp new file mode 100644 index 000000000..2dc8e10ce --- /dev/null +++ b/addons/statemachine/script_component.hpp @@ -0,0 +1,17 @@ +#define COMPONENT statemachine +#define COMPONENT_BEAUTIFIED KAT - StateMachine +#include "\x\kat\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_STATEMACHINE + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_STATEMACHINE + #define DEBUG_SETTINGS DEBUG_SETTINGS_STATEMACHINE +#endif + +#include "\x\kat\addons\main\script_macros.hpp" \ No newline at end of file diff --git a/addons/vitals/functions/fnc_handleUnitVitals.sqf b/addons/vitals/functions/fnc_handleUnitVitals.sqf index 133a24314..60ea66af7 100644 --- a/addons/vitals/functions/fnc_handleUnitVitals.sqf +++ b/addons/vitals/functions/fnc_handleUnitVitals.sqf @@ -159,14 +159,24 @@ switch (true) do { }; case (IN_CRDC_ARRST(_unit)): {}; // if in cardiac arrest just break now to avoid throwing unneeded events case ((_spo2 < EGVAR(breathing,SpO2_cardiacValue)) && EGVAR(breathing,SpO2_cardiacActive)): { + TRACE_2("SpO2 below Cardiac Value",_unit,_spo2); + if ((_unit getVariable [QEGVAR(conversion,convert), false]) && (isPlayer _unit) && LIB_CONVERSION_DISTANCE(_unit)) then { + ["kat_conversion_convertCasualty", _unit] call CBA_fnc_localEvent; + }; [QACEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; }; case (_hemorrhage == 4): { TRACE_3("Class IV Hemorrhage",_unit,_hemorrhage,_bloodVolume); + if ((_unit getVariable [QEGVAR(conversion,convert), false]) && (isPlayer _unit) && LIB_CONVERSION_DISTANCE(_unit)) then { + ["kat_conversion_convertCasualty", _unit] call CBA_fnc_localEvent; + }; [QACEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; }; case (_heartRate < 20 || {_heartRate > 220}): { TRACE_2("heartRate Fatal",_unit,_heartRate); + if ((_unit getVariable [QEGVAR(conversion,convert), false]) && (isPlayer _unit) && LIB_CONVERSION_DISTANCE(_unit)) then { + ["kat_conversion_convertCasualty", _unit] call CBA_fnc_localEvent; + }; [QACEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; }; case (_bloodPressureL < 20 || {_bloodPressureL > 180}): { @@ -187,14 +197,6 @@ switch (true) do { }; }; -#ifdef DEBUG_MODE_FULL -private _cardiacOutput = [_unit] call ACEFUNC(medical_status,getCardiacOutput); -if (!isPlayer _unit) then { - private _painLevel = _unit getVariable [VAR_PAIN, 0]; - hintSilent format["blood volume: %1, blood loss: [%2, %3]\nhr: %4, bp: %5, pain: %6", round(_bloodVolume * 100) / 100, round(_woundBloodLoss * 1000) / 1000, round((_woundBloodLoss / (0.001 max _cardiacOutput)) * 100) / 100, round(_heartRate), _bloodPressure, round(_painLevel * 100) / 100]; -}; -#endif - END_COUNTER(Vitals); //placed outside the counter as 3rd-party code may be called from this event diff --git a/addons/vitals/functions/fnc_hasStableVitals.sqf b/addons/vitals/functions/fnc_hasStableVitals.sqf index 58ed2f125..7e096050e 100644 --- a/addons/vitals/functions/fnc_hasStableVitals.sqf +++ b/addons/vitals/functions/fnc_hasStableVitals.sqf @@ -24,6 +24,8 @@ if IN_CRDC_ARRST(_unit) exitWith { false }; if (_unit getVariable [QEGVAR(surgery,sedated), false]) exitWith { false }; if (_unit getVariable [QEGVAR(surgery,reboa), false]) exitWith { false }; +if (_unit getVariable [QEGVAR(conversion,convert),false]) exitWith { false }; + private _cardiacOutput = [_unit] call ACEFUNC(medical_status,getCardiacOutput); private _bloodLoss = _unit call ACEFUNC(medical_status,getBloodLoss); if (_bloodLoss > (ACEGVAR(medical,const_bloodLossKnockOutThreshold) * _cardiacOutput / 2)) exitWith { false }; @@ -38,4 +40,4 @@ if (_heartRate < 40) exitWith { false }; private _o2 = GET_KAT_SPO2(_unit); if (_o2 < EGVAR(breathing,Stable_spo2)) exitWith { false }; -true +true \ No newline at end of file