Limping / Splint Treatment (#6947)

* Improve adjustment calcs / wound blood loss / medications

fix func descriptions

Calc wound blood loss on events

reorder includes so scritpmacroMed has global effect

trivial optimization for getCardiacOutput

Fix var

Fix wounds not reopening (nil _category)

Fix surgical kit inherting canBandage conditional

debug hitpoints

Update ACE_Medical_Treatment_Actions.hpp

Use woundBleeding for IS_BLEEDING macro

rework medication vars

comments

Reset var in init / fullHeal

Update addons/medical_treatment/functions/fnc_onMedicationUsage.sqf

Co-Authored-By: PabstMirror <pabstmirror@gmail.com>

* Change wound data array

Drop unique id and merge classId and category

* Splinting and treatment and gui

* Add arm fractures and aim effects

* localizations and event

* fix

* cleanup

* Apply suggestions from code review

Co-Authored-By: PabstMirror <pabstmirror@gmail.com>

* formating, rename bone images

* Apply suggestions from code review

Co-Authored-By: PabstMirror <pabstmirror@gmail.com>

* disable calls to extension

* Update fnc_onMedicationUsage.sqf

* Medical - Skip unneeded setVars on initUnit (#6949)

*  Medical - Transfer state machine state on locality (#6950)

* Medical - Transfer state machine state on locality

* Fix feedback isUnconscious var

* Exclude AI

* Make UAV excludes consistant, formating

* Update fnc_treatmentFullHealLocal.sqf

* reset fractures on respawn
This commit is contained in:
PabstMirror 2019-05-11 23:13:59 -05:00 committed by GitHub
parent 746d384a04
commit e56cc0d74e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 615 additions and 229 deletions

View File

@ -19,8 +19,8 @@
//Status Effect EHs: //Status Effect EHs:
[QGVAR(setStatusEffect), {_this call FUNC(statusEffect_set)}] call CBA_fnc_addEventHandler; [QGVAR(setStatusEffect), {_this call FUNC(statusEffect_set)}] call CBA_fnc_addEventHandler;
["forceWalk", false, ["ACE_SwitchUnits", "ACE_Attach", "ACE_dragging", "ACE_Explosives", "ACE_Ladder", "ACE_Sandbag", "ACE_refuel", "ACE_rearm", "ACE_Trenches"]] call FUNC(statusEffect_addType); ["forceWalk", false, ["ace_advanced_fatigue", "ACE_SwitchUnits", "ACE_Attach", "ACE_dragging", "ACE_Explosives", "ACE_Ladder", "ACE_Sandbag", "ACE_refuel", "ACE_rearm", "ACE_Trenches"]] call FUNC(statusEffect_addType);
["blockSprint", false, []] call FUNC(statusEffect_addType); ["blockSprint", false, ["ace_advanced_fatigue", "ace_medical_fracture"]] call FUNC(statusEffect_addType);
["setCaptive", true, [QEGVAR(captives,Handcuffed), QEGVAR(captives,Surrendered)]] call FUNC(statusEffect_addType); ["setCaptive", true, [QEGVAR(captives,Handcuffed), QEGVAR(captives,Surrendered)]] call FUNC(statusEffect_addType);
["blockDamage", false, ["fixCollision", "ACE_cargo"]] call FUNC(statusEffect_addType); ["blockDamage", false, ["fixCollision", "ACE_cargo"]] call FUNC(statusEffect_addType);
["blockEngine", false, ["ACE_Refuel"]] call FUNC(statusEffect_addType); ["blockEngine", false, ["ACE_Refuel"]] call FUNC(statusEffect_addType);

View File

@ -6,7 +6,7 @@
* Arguments: * Arguments:
* 0: Namespace <OBJECT><LOCATION><MISSIONNAMESPACE> * 0: Namespace <OBJECT><LOCATION><MISSIONNAMESPACE>
* 1: Number Set ID <STRING> * 1: Number Set ID <STRING>
* 2: Operation (sum, product, min, max, avg) <STRING> * 2: Operation (sum, product, min, max, avg) (Case Sensitive) <STRING>
* *
* Return Value: * Return Value:
* Value <NUMBER> * Value <NUMBER>
@ -19,11 +19,19 @@
*/ */
params ["_namespace", "_setID", "_op"]; params ["_namespace", "_setID", "_op"];
TRACE_3("params",_namespace,_setID,_op); TRACE_3("arithmeticGetResult",_namespace,_setID,_op);
private _data = (_namespace getVariable _setID) param [2, []]; private _data = (_namespace getVariable _setID) param [2, []];
switch (_op) do { switch (_op) do {
case ("max"): {
private _result = -1e99;
{
_result = _result max (call _x);
nil
} count _data;
_result // return
};
case ("sum"): { case ("sum"): {
private _result = 0; private _result = 0;
{ {
@ -48,14 +56,6 @@ switch (_op) do {
} count _data; } count _data;
_result // return _result // return
}; };
case ("max"): {
private _result = -1e99;
{
_result = _result max (call _x);
nil
} count _data;
_result // return
};
case ("avg"): { case ("avg"): {
private _result = 0; private _result = 0;
{ {

View File

@ -6,9 +6,7 @@
if (!hasInterface) exitWith {}; if (!hasInterface) exitWith {};
[missionNamespace, "ACE_setCustomAimCoef", QUOTE(ADDON), { [missionNamespace, "ACE_setCustomAimCoef", QUOTE(ADDON), {
private _pain = GET_PAIN_PERCEIVED(ACE_player); (linearConversion [0, 1, GET_PAIN_PERCEIVED(ACE_player), 1, 5, true]) + (ACE_player getVariable [QEGVAR(medical_engine,aimFracture), 0])
linearConversion [0, 1, _pain, 1, 5, true];
}] call EFUNC(common,arithmeticSetSource); }] call EFUNC(common,arithmeticSetSource);
#ifdef DEBUG_MODE_FULL #ifdef DEBUG_MODE_FULL

View File

@ -3,7 +3,8 @@
["medical", { ["medical", {
// Hide when patient display is up because they might overlap // Hide when patient display is up because they might overlap
if (!isNull EGVAR(medical_gui,displayPatientInformationTarget)) exitWith {""}; private _display = uiNamespace getVariable [QEGVAR(medical_gui,RscPatientInfo), displayNull];
if (!isNull _display) exitWith {"Paused"};
private _unit = cursorTarget; private _unit = cursorTarget;
if (!(_unit isKindOf "CAManBase")) then {_unit = cursorObject}; if (!(_unit isKindOf "CAManBase")) then {_unit = cursorObject};
@ -59,6 +60,10 @@
_return pushBack format ["Hitpoints: [HHed:%1] [HBod: %2]", (_unit getHitPointDamage "HitHead") toFixed 2, (_unit getHitPointDamage "HitBody") toFixed 2]; _return pushBack format ["Hitpoints: [HHed:%1] [HBod: %2]", (_unit getHitPointDamage "HitHead") toFixed 2, (_unit getHitPointDamage "HitBody") toFixed 2];
_return pushBack format ["[HHnd:%1] [HLeg: %2] %3", (_unit getHitPointDamage "HitHands") toFixed 2, (_unit getHitPointDamage "HitLegs") toFixed 2, _limping]; _return pushBack format ["[HHnd:%1] [HLeg: %2] %3", (_unit getHitPointDamage "HitHands") toFixed 2, (_unit getHitPointDamage "HitLegs") toFixed 2, _limping];
private _fractures = _unit getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]];
private _canSprint = if (isSprintAllowed _unit) then {""} else {"[<t color ='#FFCC22'>Sprint Blocked</t>]"};
_return pushBack format ["Fractures: %1 %2", _fractures, _canSprint];
// Tourniquets: // Tourniquets:
_return pushBack "------- Tourniquets: -------"; _return pushBack "------- Tourniquets: -------";
@ -82,24 +87,24 @@
_return pushBack "------- Wounds: -------"; _return pushBack "------- Wounds: -------";
private _wounds = _unit getVariable [QEGVAR(medical,openWounds), []]; private _wounds = _unit getVariable [QEGVAR(medical,openWounds), []];
{ {
_x params ["", "_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage", "_xCategory"]; _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"];
_return pushBack format ["%1: [%2-%3] [x%4] [Bld: %5] [Dmg: %6]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xCategory, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2];
} forEach _wounds; } forEach _wounds;
// Bandaged Wounds: // Bandaged Wounds:
_return pushBack "------- Bandaged Wounds: -------"; _return pushBack "------- Bandaged Wounds: -------";
private _wounds = _unit getVariable [QEGVAR(medical,bandagedWounds), []]; private _wounds = _unit getVariable [QEGVAR(medical,bandagedWounds), []];
{ {
_x params ["", "_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage", "_xCategory"]; _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"];
_return pushBack format ["%1: [%2-%3] [x%4] [Bld: %5] [Dmg: %6]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xCategory, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2];
} forEach _wounds; } forEach _wounds;
// Stitched Wounds: // Stitched Wounds:
_return pushBack "------- Stitched Wounds: -------"; _return pushBack "------- Stitched Wounds: -------";
private _wounds = _unit getVariable [QEGVAR(medical,stitchedWounds), []]; private _wounds = _unit getVariable [QEGVAR(medical,stitchedWounds), []];
{ {
_x params ["", "_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage", "_xCategory"]; _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"];
_return pushBack format ["%1: [%2-%3] [x%4] [Bld: %5] [Dmg: %6]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xCategory, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2];
} forEach _wounds; } forEach _wounds;
// IVs: // IVs:
@ -139,6 +144,10 @@
_return pushBack "------- Medications Raw: -------"; _return pushBack "------- Medications Raw: -------";
_return append _rawMedications; _return append _rawMedications;
if (_unit isEqualTo ACE_player) then {
_return pushBack format ["ACE_setCustomAimCoef: %1", [missionNamespace, "ACE_setCustomAimCoef", "max"] call EFUNC(common,arithmeticGetResult)];
};
// Footer: // Footer:
_return pushBack "</t>"; _return pushBack "</t>";

View File

@ -12,3 +12,23 @@ private _categoryArray = [LELSTRING(medical,Category_DisplayName), "?"];
{[QGVAR(spontaneousWakeUpChance), _this] call EFUNC(common,cbaSettings_settingChanged)}, {[QGVAR(spontaneousWakeUpChance), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart true // Needs mission restart
] call CBA_settings_fnc_init; ] call CBA_settings_fnc_init;
[
QEGVAR(medical,limping), "LIST",
[LSTRING(setting_limping_DisplayName), LSTRING(setting_limping_Description)],
_categoryArray,
[[0,1,2],[LELSTRING(common,disabled), LLSTRING(setting_limping_limpOnOpenWounds), LLSTRING(setting_limping_limpRequiresStitching)], 1], // [values, titles, defaultIndex]
true, // isGlobal
{[QEGVAR(medical,limping), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_settings_fnc_init;
[
QEGVAR(medical,fractures), "LIST",
[LSTRING(setting_fractures_DisplayName), LSTRING(setting_fractures_Description)],
_categoryArray,
[[0,1,2],[LELSTRING(common,disabled), LLSTRING(setting_fractures_splintHealsFully), LLSTRING(setting_fractures_splintHasEffects)], 1], // [values, titles, defaultIndex]
true, // isGlobal
{[QEGVAR(medical,fractures), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_settings_fnc_init;

View File

@ -481,5 +481,29 @@
<Korean>뚜껑 닫기</Korean> <Korean>뚜껑 닫기</Korean>
<Polish>Zamknij pokrywę</Polish> <Polish>Zamknij pokrywę</Polish>
</Key> </Key>
<Key ID="STR_ACE_Medical_setting_limping_DisplayName">
<English>Limping</English>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_Description">
<English>Limp when unit has leg wounds...(todo)</English>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_limpOnOpenWounds">
<English>Limp on open wounds</English>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_limpRequiresStitching">
<English>Limp on open or bandaged wounds</English>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_DisplayName">
<English>Fractues</English>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_Description">
<English>Limp fractures... (todo)</English>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_splintHealsFully">
<English>Splints fully heal fractures</English>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_splintHasEffects">
<English>Splints heal (but cannot sprint)</English>
</Key>
</Package> </Package>
</Project> </Project>

View File

@ -36,6 +36,7 @@ class ACE_Medical_Injuries {
pain = 0.8; pain = 0.8;
minDamage = 0.1; minDamage = 0.1;
causeLimping = 1; causeLimping = 1;
causeFracture = 1;
}; };
// Slicing wounds made with a sharp instrument, leaving even edges. They may be as minimal as a paper cut or as significant as a surgical incision. // Slicing wounds made with a sharp instrument, leaving even edges. They may be as minimal as a paper cut or as significant as a surgical incision.
class Cut { class Cut {
@ -59,6 +60,7 @@ class ACE_Medical_Injuries {
pain = 0.9; pain = 0.9;
minDamage = 0.35; minDamage = 0.35;
causeLimping = 1; causeLimping = 1;
causeFracture = 1;
}; };
// Deep, narrow wounds produced by sharp objects such as nails, knives, and broken glass. // Deep, narrow wounds produced by sharp objects such as nails, knives, and broken glass.
class PunctureWound { class PunctureWound {

View File

@ -17,11 +17,13 @@ addMissionEventHandler ["Loaded",{
}]; }];
// decide which woundsHandler to use by whether the extension is present or not // decide which woundsHandler to use by whether the extension is present or not
if ("ace_medical" callExtension "version" != "") then { // if ("ace_medical" callExtension "version" != "") then {
DFUNC(woundsHandlerActive) = LINKFUNC(woundsHandler);
} else { // DFUNC(woundsHandlerActive) = LINKFUNC(woundsHandler);
// } else {
INFO("Using woundsHandlerSQF");
DFUNC(woundsHandlerActive) = LINKFUNC(woundsHandlerSQF); DFUNC(woundsHandlerActive) = LINKFUNC(woundsHandlerSQF);
}; // };
[QEGVAR(medical,woundReceived), { [QEGVAR(medical,woundReceived), {
params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"]; params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"];

View File

@ -24,7 +24,7 @@ _bodyPartDamage params ["_headDamage", "_bodyDamage", "_leftArmDamage", "_rightA
// Exclude non penetrating body damage // Exclude non penetrating body damage
{ {
_x params ["", "", "_bodyPartN", "_amountOf", "", "_damage"]; _x params ["", "_bodyPartN", "_amountOf", "", "_damage"];
if (_bodyPartN == 1 && {_damage < PENETRATION_THRESHOLD}) then { if (_bodyPartN == 1 && {_damage < PENETRATION_THRESHOLD}) then {
_bodyDamage = _bodyDamage - (_amountOf * _damage); _bodyDamage = _bodyDamage - (_amountOf * _damage);
}; };

View File

@ -19,7 +19,8 @@ private _injuriesConfigRoot = configFile >> "ACE_Medical_Injuries";
// --- parse wounds // --- parse wounds
GVAR(woundClassNames) = []; GVAR(woundClassNames) = [];
GVAR(woundsData) = []; // @todo classTypes are strings currently. Convert them to unqiue IDs instead. GVAR(woundClassNamesComplex) = []; // index = 10 * classID + category; [will contain nils] e.g. ["aMinor", "aMed", "aLarge", nil, nil..."bMinor"]
GVAR(woundsData) = [];
private _woundsConfig = _injuriesConfigRoot >> "wounds"; private _woundsConfig = _injuriesConfigRoot >> "wounds";
private _classID = 0; private _classID = 0;
@ -34,17 +35,20 @@ private _classID = 0;
private _minDamage = GET_NUMBER(_entry >> "minDamage",0); private _minDamage = GET_NUMBER(_entry >> "minDamage",0);
private _maxDamage = GET_NUMBER(_entry >> "maxDamage",-1); private _maxDamage = GET_NUMBER(_entry >> "maxDamage",-1);
private _causes = GET_ARRAY(_entry >> "causes",[]); private _causes = GET_ARRAY(_entry >> "causes",[]);
private _causeLimping = GET_NUMBER(_entry >> "causeLimping",0); private _causeLimping = GET_NUMBER(_entry >> "causeLimping",0) == 1;
private _causeFracture = GET_NUMBER(_entry >> "causeFracture",0) == 1;
if !(_causes isEqualTo []) then { if !(_causes isEqualTo []) then {
GVAR(woundClassNames) pushBack _className; GVAR(woundClassNames) pushBack _className;
GVAR(woundsData) pushBack [_classID, _selections, _bleeding, _pain, [_minDamage, _maxDamage], _causes, _className, _causeLimping]; GVAR(woundsData) pushBack [_classID, _selections, _bleeding, _pain, [_minDamage, _maxDamage], _causes, _className, _causeLimping, _causeFracture];
{
GVAR(woundClassNamesComplex) set [10 * _classID + _forEachIndex, format ["%1%2", _className, _x]];
} forEach ["Minor", "Medium", "Large"];
_classID = _classID + 1; _classID = _classID + 1;
}; };
} forEach configProperties [_woundsConfig, "isClass _x"]; } forEach configProperties [_woundsConfig, "isClass _x"];
// --- parse damage types // --- parse damage types
GVAR(allDamageTypes) = []; // @todo, currently unused by handle damage (was GVAR(allAvailableDamageTypes))
GVAR(allDamageTypesData) = [] call CBA_fnc_createNamespace; GVAR(allDamageTypesData) = [] call CBA_fnc_createNamespace;
// minimum lethal damage collection, mapped to damageTypes // minimum lethal damage collection, mapped to damageTypes
@ -57,8 +61,6 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
private _entry = _x; private _entry = _x;
private _className = configName _entry; private _className = configName _entry;
GVAR(allDamageTypes) pushBack _className;
// Check if this type is in the causes of a wound class, if so, we will store the wound types for this damage type // Check if this type is in the causes of a wound class, if so, we will store the wound types for this damage type
private _woundTypes = []; private _woundTypes = [];
{ {
@ -89,8 +91,8 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
]; ];
TRACE_1("",_extensionArgs); TRACE_1("",_extensionArgs);
private _extensionRes = "ace_medical" callExtension _extensionArgs; // private _extensionRes = "ace_medical" callExtension _extensionArgs;
TRACE_1("",_extensionRes); // TRACE_1("",_extensionRes);
} forEach configProperties [_damageTypesConfig, "isClass _x"]; } forEach configProperties [_damageTypesConfig, "isClass _x"];
// extension loading // extension loading
@ -121,8 +123,8 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
]; ];
TRACE_1("",_extensionArgs); TRACE_1("",_extensionArgs);
private _extensionRes = "ace_medical" callExtension _extensionArgs; // private _extensionRes = "ace_medical" callExtension _extensionArgs;
TRACE_1("",_extensionRes); // TRACE_1("",_extensionRes);
} forEach GVAR(woundsData); } forEach GVAR(woundsData);
"ace_medical" callExtension "ConfigComplete"; // "ace_medical" callExtension "ConfigComplete";

View File

@ -18,6 +18,8 @@
* Public: No * Public: No
*/ */
WARNING("this function needs to be updated for changes to woundsHandlerSQF");
params ["_unit", "_bodyPart", "_damage", "_typeOfDamage"]; params ["_unit", "_bodyPart", "_damage", "_typeOfDamage"];
TRACE_4("start",_unit,_bodyPart,_damage,_typeOfDamage); TRACE_4("start",_unit,_bodyPart,_damage,_typeOfDamage);

View File

@ -19,17 +19,14 @@
*/ */
params ["_unit", "_bodyPart", "_damage", "_typeOfDamage"]; params ["_unit", "_bodyPart", "_damage", "_typeOfDamage"];
TRACE_4("start",_unit,_bodyPart,_damage,_typeOfDamage); TRACE_4("woundsHandlerSQF",_unit,_bodyPart,_damage,_typeOfDamage);
// Convert the selectionName to a number and ensure it is a valid selection. // Convert the selectionName to a number and ensure it is a valid selection.
private _bodyPartN = ALL_BODY_PARTS find toLower _bodyPart; private _bodyPartN = ALL_BODY_PARTS find toLower _bodyPart;
if (_bodyPartN < 0) exitWith {}; if (_bodyPartN < 0) exitWith { ERROR_1("invalid body part %1",_bodyPart); };
if (_typeOfDamage isEqualTo "") then { if ((_typeOfDamage isEqualTo "") || {isNil {GVAR(allDamageTypesData) getVariable _typeOfDamage}}) then {
_typeOfDamage = "unknown"; WARNING_1("damage type [%1] not found",_typeOfDamage);
};
if (isNil {GVAR(allDamageTypesData) getVariable _typeOfDamage} ) then {
_typeOfDamage = "unknown"; _typeOfDamage = "unknown";
}; };
@ -65,22 +62,22 @@ private _allPossibleInjuries = [];
} forEach _woundTypes; } forEach _woundTypes;
// No possible wounds available for this damage type or damage amount. // No possible wounds available for this damage type or damage amount.
if (_highestPossibleSpot < 0) exitWith {}; if (_highestPossibleSpot < 0) exitWith { TRACE_2("no wounds possible",_damage,_highestPossibleSpot); };
// Administration for open wounds and ids // Administration for open wounds and ids
private _openWounds = _unit getVariable [QEGVAR(medical,openWounds), []]; private _openWounds = _unit getVariable [QEGVAR(medical,openWounds), []];
private _woundID = _unit getVariable [QEGVAR(medical,lastUniqueWoundID), 1]; // Unique wound ids are not used anywhere: ToDo Remove from openWounds array
private _updateDamageEffects = false;
private _painLevel = 0; private _painLevel = 0;
private _critialDamage = false; private _critialDamage = false;
private _bodyPartDamage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _bodyPartDamage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]];
private _bodyPartVisParams = [_unit, false, false, false, false]; // params array for EFUNC(medical_engine,updateBodyPartVisuals); private _bodyPartVisParams = [_unit, false, false, false, false]; // params array for EFUNC(medical_engine,updateBodyPartVisuals);
private _woundsCreated = [];
{ {
_x params ["_thresholdMinDam", "_thresholdWoundCount"]; _x params ["_thresholdMinDam", "_thresholdWoundCount"];
if (_thresholdMinDam <= _damage) exitWith { if (_thresholdMinDam <= _damage) exitWith {
private _woundDamage = _damage / (_thresholdWoundCount max 1); // If the damage creates multiple wounds private _woundDamage = _damage / (_thresholdWoundCount max 1); // If the damage creates multiple wounds
for "_i" from 0 to (_thresholdWoundCount-1) do { for "_i" from 1 to _thresholdWoundCount do {
// Find the injury we are going to add. Format [ classID, allowdSelections, bleedingRate, injuryPain] // Find the injury we are going to add. Format [ classID, allowdSelections, bleedingRate, injuryPain]
private _oldInjury = if (random 1 >= 0.85) then { private _oldInjury = if (random 1 >= 0.85) then {
_woundTypes select _highestPossibleSpot _woundTypes select _highestPossibleSpot
@ -88,15 +85,13 @@ private _woundsCreated = [];
selectRandom _allPossibleInjuries selectRandom _allPossibleInjuries
}; };
_oldInjury params ["_woundClassIDToAdd", "", "_injuryBleedingRate", "_injuryPain"]; _oldInjury params ["_woundClassIDToAdd", "", "_injuryBleedingRate", "_injuryPain", "", "", "", "_causeLimping", "_causeFracture"];
private _bodyPartNToAdd = [floor random 6, _bodyPartN] select _isSelectionSpecific; // 6 == count ALL_BODY_PARTS private _bodyPartNToAdd = [floor random 6, _bodyPartN] select _isSelectionSpecific; // 6 == count ALL_BODY_PARTS
_bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _woundDamage]; _bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _woundDamage];
_bodyPartVisParams set [[1,2,3,3,4,4] select _bodyPartNToAdd, true]; // Mark the body part index needs updating _bodyPartVisParams set [[1,2,3,3,4,4] select _bodyPartNToAdd, true]; // Mark the body part index needs updating
// Create a new injury. Format [ID, classID, bodypart, percentage treated, bleeding rate]
private _injury = [_woundID, _woundClassIDToAdd, _bodyPartNToAdd, 1, _injuryBleedingRate];
// The higher the nastiness likelihood the higher the change to get a painful and bloody wound // The higher the nastiness likelihood the higher the change to get a painful and bloody wound
private _nastinessLikelihood = linearConversion [0, 20, (_woundDamage / _thresholdWoundCount), 0.5, 30, true]; private _nastinessLikelihood = linearConversion [0, 20, (_woundDamage / _thresholdWoundCount), 0.5, 30, true];
@ -110,16 +105,15 @@ private _woundsCreated = [];
// wound category (minor [0..0.5], medium[0.5..1.0], large[1.0+]) // wound category (minor [0..0.5], medium[0.5..1.0], large[1.0+])
private _category = floor linearConversion [0, 1, _bleedingModifier, 0, 2, true]; private _category = floor linearConversion [0, 1, _bleedingModifier, 0, 2, true];
// wound category (minor, medium, large) private _classComplex = 10 * _woundClassIDToAdd + _category;
private _category = floor ((0 max _bleeding min 0.1) / 0.05);
_injury set [4, _bleeding]; // Create a new injury. Format [0:classComplex, 1:bodypart, 2:amountOf, 3:bleedingRate, 4:woundDamage]
_injury set [5, _woundDamage]; private _injury = [_classComplex, _bodyPartNToAdd, 1, _bleeding, _woundDamage];
_injury set [6, _category];
if (_bodyPartNToAdd == 0 || {_bodyPartNToAdd == 1 && {_woundDamage > PENETRATION_THRESHOLD}}) then { if (_bodyPartNToAdd == 0 || {_bodyPartNToAdd == 1 && {_woundDamage > PENETRATION_THRESHOLD}}) then {
_critialDamage = true; _critialDamage = true;
}; };
#ifdef DEBUG_MODE_FULL #ifdef DEBUG_MODE_FULL
systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, _woundDamage toFixed 2, _woundDamage > PENETRATION_THRESHOLD, _bleeding toFixed 3, _pain toFixed 3]; systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, _woundDamage toFixed 2, _woundDamage > PENETRATION_THRESHOLD, _bleeding toFixed 3, _pain toFixed 3];
#endif #endif
@ -139,44 +133,53 @@ private _woundsCreated = [];
[QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent; [QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent;
}; };
}; };
case (_causeFracture && {EGVAR(medical,fractures) > 0} && {_bodyPartNToAdd > 1} && {_woundDamage > FRACTURE_DAMAGE_THRESHOLD}): {
TRACE_1("limb fracture",_bodyPartNToAdd);
// todo: play sound?
private _fractures = _unit getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]];
_fractures set [_bodyPartNToAdd, 1];
_unit setVariable [QEGVAR(medical,fractures), _fractures, true];
[QEGVAR(medical,fracture), [_unit, _bodyPartNToAdd]] call CBA_fnc_localEvent; // local event for fracture
_updateDamageEffects = true;
};
case (_causeLimping && {EGVAR(medical,limping) > 0} && {_bodyPartNToAdd > 3} && {_woundDamage > LIMPING_DAMAGE_THRESHOLD}): {
_updateDamageEffects = true;
}; };
// todo `forceWalk` based on leg damage
private _causeLimping = (GVAR(woundsData) select _woundClassIDToAdd) select 7;
if (_causeLimping == 1 && {_woundDamage > LIMPING_DAMAGE_THRESHOLD} && {_bodyPartNToAdd > 3}) then {
[_unit, true] call EFUNC(medical_engine,setLimping);
}; };
// if possible merge into existing wounds // if possible merge into existing wounds
private _createNewWound = true; private _createNewWound = true;
{ {
_x params ["", "_classID", "_bodyPartN", "_oldAmountOf", "_oldBleeding", "_oldDamage", "_oldCategory"]; _x params ["_classID", "_bodyPartN", "_oldAmountOf", "_oldBleeding", "_oldDamage"];
if (_woundClassIDToAdd == _classID && {_bodyPartNToAdd == _bodyPartN && {(_woundDamage < PENETRATION_THRESHOLD) isEqualTo (_oldDamage < PENETRATION_THRESHOLD)}}) then { if (
if (_oldCategory == _category) exitWith { (_classComplex == _classID) &&
{_bodyPartNToAdd == _bodyPartN} &&
{(_bodyPartNToAdd != 1) || {(_woundDamage < PENETRATION_THRESHOLD) isEqualTo (_oldDamage < PENETRATION_THRESHOLD)}} && // penetrating body damage is handled differently
{(_bodyPartNToAdd > 3) || {!_causeLimping} || {(_woundDamage <= LIMPING_DAMAGE_THRESHOLD) isEqualTo (_oldDamage <= LIMPING_DAMAGE_THRESHOLD)}} // ensure limping damage is stacked correctly
) exitWith {
TRACE_2("merging with existing wound",_injury,_x);
private _newAmountOf = _oldAmountOf + 1; private _newAmountOf = _oldAmountOf + 1;
_x set [3, _newAmountOf]; _x set [2, _newAmountOf];
private _newBleeding = (_oldAmountOf * _oldBleeding + _bleeding) / _newAmountOf; private _newBleeding = (_oldAmountOf * _oldBleeding + _bleeding) / _newAmountOf;
_x set [4, _newBleeding]; _x set [3, _newBleeding];
private _newDamage = (_oldAmountOf * _oldDamage + _woundDamage) / _newAmountOf; private _newDamage = (_oldAmountOf * _oldDamage + _woundDamage) / _newAmountOf;
_x set [5, _newDamage]; _x set [4, _newDamage];
_createNewWound = false; _createNewWound = false;
}; };
};
} forEach _openWounds; } forEach _openWounds;
if (_createNewWound) then { if (_createNewWound) then {
TRACE_1("adding new wound",_injury);
_openWounds pushBack _injury; _openWounds pushBack _injury;
}; };
// New injuries will also increase the wound ID
_woundID = _woundID + 1;
// Store the injury so we can process it later correctly.
_woundsCreated pushBack _injury;
}; };
}; };
} forEach _thresholds; } forEach _thresholds;
if (_updateDamageEffects) then {
[_unit] call EFUNC(medical_engine,updateDamageEffects);
};
_unit setVariable [QEGVAR(medical,openWounds), _openWounds, true]; _unit setVariable [QEGVAR(medical,openWounds), _openWounds, true];
_unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; _unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true];
@ -190,4 +193,4 @@ if (_critialDamage || {_painLevel > PAIN_UNCONSCIOUS}) then {
[_unit] call FUNC(handleIncapacitation); [_unit] call FUNC(handleIncapacitation);
}; };
TRACE_5("exit",_unit,_painLevel,GET_PAIN(_unit),_unit getVariable QEGVAR(medical,openWounds),_woundsCreated); TRACE_4("exit",_unit,_painLevel,GET_PAIN(_unit),_unit getVariable QEGVAR(medical,openWounds));

View File

@ -1,6 +1,6 @@
PREP(handleDamage); PREP(handleDamage);
PREP(damageBodyPart); PREP(damageBodyPart);
PREP(updateBodyPartVisuals); PREP(updateBodyPartVisuals);
PREP(setLimping); PREP(updateDamageEffects);
PREP(setStructuralDamage); PREP(setStructuralDamage);
PREP(setUnconsciousAnim); PREP(setUnconsciousAnim);

View File

@ -1,5 +1,12 @@
#include "script_component.hpp" #include "script_component.hpp"
[QGVAR(updateDamageEffects), LINKFUNC(updateDamageEffects)] call CBA_fnc_addEventHandler;
["unit", {
params ["_new"];
[_new] call FUNC(updateDamageEffects); // Run on new controlled unit to update QGVAR(aimFracture)
}, true] call CBA_fnc_addPlayerEventHandler;
["CAManBase", "init", { ["CAManBase", "init", {
params ["_unit"]; params ["_unit"];

View File

@ -1,30 +0,0 @@
#include "script_component.hpp"
/*
* Author: commy2
* Forces a unit to limp or not.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Limping (optional, default: true) <BOOLEAN>
*
* Return Value:
* None
*
* Example:
* [player, true] call ace_medical_engine_fnc_setLimping
*
* Public: No
*/
params [["_unit", objNull, [objNull]], ["_isLimping", true, [false]]];
if (!local _unit) exitWith {
ERROR("Unit not local or null");
};
_unit setVariable [QEGVAR(medical,isLimping), _isLimping, true];
// refresh
private _isDamaged = _unit getHitPointDamage "HitLegs" >= DAMAGED_MIN_THRESHOLD && {_unit getHitPointDamage "HitLegs" != LIMPING_MIN_DAMAGE};
[_unit, "Legs", _isDamaged] call FUNC(damageBodyPart);

View File

@ -0,0 +1,67 @@
#include "script_component.hpp"
/*
* Author: commy2, PabstMirror
* Updates damage effects for limping and fractures
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Limping (optional, default: true) <BOOLEAN>
*
* Return Value:
* None
*
* Example:
* [player] call ace_medical_engine_fnc_updateDamageEffects
*
* Public: No
*/
params [["_unit", objNull, [objNull]]];
if (!local _unit) exitWith { ERROR("Unit not local or null"); };
private _isLimping = false;
if (EGVAR(medical,fractures) > 0) then {
private _fractures = _unit getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]];
TRACE_1("",_fractures);
if (((_fractures select 4) == 1) || {(_fractures select 5) == 1}) then {
TRACE_1("limping because of fracture",_fractures);
_isLimping = true;
};
private _aimFracture = 0;
if ((_fractures select 2) == 1) then { _aimFracture = _aimFracture + 4; };
if ((_fractures select 3) == 1) then { _aimFracture = _aimFracture + 4; };
if (EGVAR(medical,fractures) == 2) then { // the limp with a splint will still cause effects
private _isSprintBlocked = ((_fractures select 4) == -1) || {(_fractures select 5) == -1}; // block sprinting if we have a leg splint on
if (_isSprintBlocked || {!isSprintAllowed _unit}) then { // only update status effect if we need to
TRACE_1("updating status effect",_isSprintBlocked);
[_unit, "blockSprint", QEGVAR(medical,fracture), _isSprintBlocked] call EFUNC(common,statusEffect_set);
};
if ((_fractures select 2) == 1) then { _aimFracture = _aimFracture + 2; };
if ((_fractures select 3) == 1) then { _aimFracture = _aimFracture + 2; };
};
_unit setVariable [QGVAR(aimFracture), _aimFracture, false]; // local only var, used in ace_medical's postInit to set ACE_setCustomAimCoef
};
if (!_isLimping && {EGVAR(medical,limping) > 0}) then {
private _woundsToCheck = _unit getVariable [QEGVAR(medical,openWounds), []];
if (EGVAR(medical,limping) == 2) then {
_woundsToCheck = _woundsToCheck + (_unit getVariable [QEGVAR(medical,bandagedWounds), []]); // do not append
};
{
_x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "", "_xDamage"];
if ((_xBodyPartN > 3) && {_xAmountOf > 0} && {_xDamage > LIMPING_DAMAGE_THRESHOLD} && {
(EGVAR(medical_damage,woundsData) select (_xClassID / 10)) select 7}) exitWith { // select _causeLimping from woundsData
TRACE_1("limping because of wound",_x);
_isLimping = true;
};
} forEach _woundsToCheck;
};
_unit setVariable [QEGVAR(medical,isLimping), _isLimping, true];
// refresh
private _isDamaged = _unit getHitPointDamage "HitLegs" >= DAMAGED_MIN_THRESHOLD && {_unit getHitPointDamage "HitLegs" != LIMPING_MIN_DAMAGE};
[_unit, "Legs", _isDamaged] call FUNC(damageBodyPart);

View File

@ -74,12 +74,15 @@
// Minimum leg damage required for limping // Minimum leg damage required for limping
#define LIMPING_DAMAGE_THRESHOLD 0.30 #define LIMPING_DAMAGE_THRESHOLD 0.30
// Minimum limb damage required for fracture
#define FRACTURE_DAMAGE_THRESHOLD 0.50
// Minimum body part damage required for blood effect on uniform // Minimum body part damage required for blood effect on uniform
#define VISUAL_BODY_DAMAGE_THRESHOLD 0.35 #define VISUAL_BODY_DAMAGE_THRESHOLD 0.35
// Empty wound data, used for some default return values // Empty wound data, used for some default return values
// [ID, classID, bodypartIndex, amountOf, bloodloss, damage, category] // [classID, bodypartIndex, amountOf, bloodloss, damage]
#define EMPTY_WOUND [-1, -1, -1, 0, 0, 0, 0] #define EMPTY_WOUND [-1, -1, 0, 0, 0]
// Base time to bandage each wound category // Base time to bandage each wound category
#define BANDAGE_TIME_S 4 #define BANDAGE_TIME_S 4

View File

@ -56,8 +56,7 @@ GVAR(heartBeatEffectRunning) = false;
// Update effects to match new unit's current status (this also handles respawn) // Update effects to match new unit's current status (this also handles respawn)
["unit", { ["unit", {
params ["_new"]; params ["_new"];
private _status = IS_UNCONSCIOUS(_new);
private _status = _new getVariable ["ace_unconscious", false];
if (["task_force_radio"] call EFUNC(common,isModLoaded)) then { if (["task_force_radio"] call EFUNC(common,isModLoaded)) then {
_new setVariable ["tf_voiceVolume", [1, 0] select _status, true]; _new setVariable ["tf_voiceVolume", [1, 0] select _status, true];

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -25,7 +25,7 @@ private _bloodLossOnBodyPart = 0;
// Add all bleeding from wounds on selection // Add all bleeding from wounds on selection
{ {
_x params ["", "", "_bodyPartN", "_amountOf", "_bleeding"]; _x params ["", "_bodyPartN", "_amountOf", "_bleeding"];
if (_bodyPartN == _partIndex) then { if (_bodyPartN == _partIndex) then {
_bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _bleeding); _bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _bleeding);

View File

@ -20,16 +20,17 @@ params ["_ctrlGroup", "_target"];
// Get tourniquets, damage, and blood loss for target // Get tourniquets, damage, and blood loss for target
private _tourniquets = GET_TOURNIQUETS(_target); private _tourniquets = GET_TOURNIQUETS(_target);
private _fractures = _target getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]];
private _bodyPartDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0, 0, 0, 0, 0, 0]]; private _bodyPartDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0, 0, 0, 0, 0, 0]];
private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0]; private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0];
{ {
_x params ["", "", "_bodyPartN", "_amountOf", "_bleeding"]; _x params ["", "_bodyPartN", "_amountOf", "_bleeding"];
_bodyPartBloodLoss set [_bodyPartN, (_bodyPartBloodLoss select _bodyPartN) + (_bleeding * _amountOf)]; _bodyPartBloodLoss set [_bodyPartN, (_bodyPartBloodLoss select _bodyPartN) + (_bleeding * _amountOf)];
} forEach (_target getVariable [QEGVAR(medical,openWounds), []]); } forEach (_target getVariable [QEGVAR(medical,openWounds), []]);
{ {
_x params ["_bodyPartIDC", ["_tourniquetIDC", -1]]; _x params ["_bodyPartIDC", ["_tourniquetIDC", -1], ["_fractureIDC", -1]];
// Show or hide the tourniquet icon // Show or hide the tourniquet icon
if (_tourniquetIDC != -1) then { if (_tourniquetIDC != -1) then {
@ -37,6 +38,27 @@ private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0];
private _ctrlTourniquet = _ctrlGroup controlsGroupCtrl _tourniquetIDC; private _ctrlTourniquet = _ctrlGroup controlsGroupCtrl _tourniquetIDC;
_ctrlTourniquet ctrlShow _hasTourniquet; _ctrlTourniquet ctrlShow _hasTourniquet;
}; };
// Show or hide fractrue/bones
if (_fractureIDC != -1) then {
private _ctrlBone = _ctrlGroup controlsGroupCtrl _fractureIDC;
switch (_fractures select _forEachIndex) do {
case (0): {
_ctrlBone ctrlShow false;
};
case (1): {
_ctrlBone ctrlShow true;
_ctrlBone ctrlSetTextColor [1, 0, 0, 1];
};
case (-1): {
if (EGVAR(medical,fractures) == 2) then {
_ctrlBone ctrlShow true;
_ctrlBone ctrlSetTextColor [0, 0, 1, 1];
} else {
_ctrlBone ctrlShow false;
};
};
};
};
// Update body part color based on blood loss and damage // Update body part color based on blood loss and damage
private _bloodLoss = _bodyPartBloodLoss select _forEachIndex; private _bloodLoss = _bodyPartBloodLoss select _forEachIndex;
@ -52,8 +74,8 @@ private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0];
} forEach [ } forEach [
[IDC_BODY_HEAD], [IDC_BODY_HEAD],
[IDC_BODY_TORSO], [IDC_BODY_TORSO],
[IDC_BODY_ARMLEFT, IDC_BODY_ARMLEFT_T], [IDC_BODY_ARMLEFT, IDC_BODY_ARMLEFT_T, IDC_BODY_ARMLEFT_B],
[IDC_BODY_ARMRIGHT, IDC_BODY_ARMRIGHT_T], [IDC_BODY_ARMRIGHT, IDC_BODY_ARMRIGHT_T, IDC_BODY_ARMRIGHT_B],
[IDC_BODY_LEGLEFT, IDC_BODY_LEGLEFT_T], [IDC_BODY_LEGLEFT, IDC_BODY_LEGLEFT_T, IDC_BODY_LEGLEFT_B],
[IDC_BODY_LEGRIGHT, IDC_BODY_LEGRIGHT_T] [IDC_BODY_LEGRIGHT, IDC_BODY_LEGRIGHT_T, IDC_BODY_LEGRIGHT_B]
]; ];

View File

@ -58,6 +58,14 @@ switch (GET_HEMORRHAGE(_target)) do {
if (HAS_TOURNIQUET_APPLIED_ON(_target,_selectionN)) then { if (HAS_TOURNIQUET_APPLIED_ON(_target,_selectionN)) then {
_entries pushBack [localize LSTRING(Status_Tourniquet_Applied), [0.77, 0.51, 0.08, 1]]; _entries pushBack [localize LSTRING(Status_Tourniquet_Applied), [0.77, 0.51, 0.08, 1]];
}; };
switch ((_target getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]]) select _selectionN) do {
case (1): {_entries pushBack [localize LSTRING(Status_Fractured), [1, 0, 0, 1]];};
case (-1): {
if (EGVAR(medical,fractures) == 2) then { // Ignore if the split has no effect
_entries pushBack [localize LSTRING(Status_SplintApplied), [1, 1, 1, 1]];
};
};
};
// Indicate the amount of pain the unit is in // Indicate the amount of pain the unit is in
if ([_target] call EFUNC(common,isAwake)) then { if ([_target] call EFUNC(common,isAwake)) then {
@ -93,7 +101,9 @@ if (_totalIvVolume >= 1) then {
private _woundEntries = []; private _woundEntries = [];
private _fnc_getWoundDescription = { private _fnc_getWoundDescription = {
private _className = EGVAR(medical_damage,woundsData) select _woundClassID select 6; private _classIndex = _woundClassID / 10;
private _category = _woundClassID % 10;
private _className = EGVAR(medical_damage,woundsData) select _classIndex select 6;
private _suffix = ["Minor", "Medium", "Large"] select _category; private _suffix = ["Minor", "Medium", "Large"] select _category;
private _woundName = localize format [ELSTRING(medical_damage,%1_%2), _className, _suffix]; private _woundName = localize format [ELSTRING(medical_damage,%1_%2), _className, _suffix];
if (_amountOf >= 1) then { if (_amountOf >= 1) then {
@ -104,7 +114,7 @@ private _fnc_getWoundDescription = {
}; };
{ {
_x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "", "", "_category"]; _x params ["_woundClassID", "_bodyPartN", "_amountOf"];
if (_selectionN == _bodyPartN) then { if (_selectionN == _bodyPartN) then {
if (_amountOf > 0) then { if (_amountOf > 0) then {
_woundEntries pushBack [call _fnc_getWoundDescription, [1, 1, 1, 1]]; _woundEntries pushBack [call _fnc_getWoundDescription, [1, 1, 1, 1]];
@ -117,14 +127,14 @@ private _fnc_getWoundDescription = {
} forEach (_target getVariable [QEGVAR(medical,openWounds), []]); } forEach (_target getVariable [QEGVAR(medical,openWounds), []]);
{ {
_x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "", "", "_category"]; _x params ["_woundClassID", "_bodyPartN", "_amountOf"];
if (_selectionN == _bodyPartN && {_amountOf > 0}) then { if (_selectionN == _bodyPartN && {_amountOf > 0}) then {
_woundEntries pushBack [format ["[B] %1", call _fnc_getWoundDescription], [0.88, 0.7, 0.65, 1]]; _woundEntries pushBack [format ["[B] %1", call _fnc_getWoundDescription], [0.88, 0.7, 0.65, 1]];
}; };
} forEach (_target getVariable [QEGVAR(medical,bandagedWounds), []]); } forEach (_target getVariable [QEGVAR(medical,bandagedWounds), []]);
{ {
_x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "", "", "_category"]; _x params ["_woundClassID", "_bodyPartN", "_amountOf"];
if (_selectionN == _bodyPartN && {_amountOf > 0}) then { if (_selectionN == _bodyPartN && {_amountOf > 0}) then {
_woundEntries pushBack [format ["[S] %1", call _fnc_getWoundDescription], [0.7, 0.7, 0.7, 1]]; _woundEntries pushBack [format ["[S] %1", call _fnc_getWoundDescription], [0.7, 0.7, 0.7, 1]];
}; };

View File

@ -45,6 +45,24 @@ class GVAR(BodyImage): RscControlsGroupNoScrollbars {
idc = IDC_BODY_LEGRIGHT; idc = IDC_BODY_LEGRIGHT;
text = QPATHTOF(data\body_image\leg_right.paa); text = QPATHTOF(data\body_image\leg_right.paa);
}; };
class ArmLeftB: Background {
idc = IDC_BODY_ARMLEFT_B;
text = QPATHTOF(data\body_image\arm_left_b.paa);
colorText[] = {0, 0, 0.8, 1};
show = 0;
};
class ArmRightB: ArmLeftB {
idc = IDC_BODY_ARMRIGHT_B;
text = QPATHTOF(data\body_image\arm_right_b.paa);
};
class LegLeftB: ArmLeftB {
idc = IDC_BODY_LEGLEFT_B;
text = QPATHTOF(data\body_image\leg_left_b.paa);
};
class LegRightB: ArmLeftB {
idc = IDC_BODY_LEGRIGHT_B;
text = QPATHTOF(data\body_image\leg_right_b.paa);
};
class ArmLeftT: Background { class ArmLeftT: Background {
idc = IDC_BODY_ARMLEFT_T; idc = IDC_BODY_ARMLEFT_T;
text = QPATHTOF(data\body_image\arm_left_t.paa); text = QPATHTOF(data\body_image\arm_left_t.paa);
@ -549,6 +567,22 @@ class RscTitles {
w = POS_W(8.5); w = POS_W(8.5);
h = POS_H(8.5); h = POS_H(8.5);
}; };
class ArmLeftB: ArmLeftB {
w = POS_W(8.5);
h = POS_H(8.5);
};
class ArmRightB: ArmRightB {
w = POS_W(8.5);
h = POS_H(8.5);
};
class LegLeftB: LegLeftB {
w = POS_W(8.5);
h = POS_H(8.5);
};
class LegRightB: LegRightB {
w = POS_W(8.5);
h = POS_H(8.5);
};
class ArmLeftT: ArmLeftT { class ArmLeftT: ArmLeftT {
w = POS_W(8.5); w = POS_W(8.5);
h = POS_H(8.5); h = POS_H(8.5);

View File

@ -67,6 +67,10 @@
#define IDC_BODY_ARMRIGHT_T 6040 #define IDC_BODY_ARMRIGHT_T 6040
#define IDC_BODY_LEGLEFT_T 6045 #define IDC_BODY_LEGLEFT_T 6045
#define IDC_BODY_LEGRIGHT_T 6050 #define IDC_BODY_LEGRIGHT_T 6050
#define IDC_BODY_ARMLEFT_B 6055
#define IDC_BODY_ARMRIGHT_B 6060
#define IDC_BODY_LEGRIGHT_B 6065
#define IDC_BODY_LEGLEFT_B 6070
#define IDC_TRIAGE_STATUS 7000 #define IDC_TRIAGE_STATUS 7000
#define IDC_TRIAGE_SELECT 7100 #define IDC_TRIAGE_SELECT 7100

View File

@ -775,6 +775,12 @@
<Chinesesimp>大量失血</Chinesesimp> <Chinesesimp>大量失血</Chinesesimp>
<Chinese>大量失血</Chinese> <Chinese>大量失血</Chinese>
</Key> </Key>
<Key ID="STR_ACE_Medical_GUI_Status_Fractured">
<English>Fractured</English>
</Key>
<Key ID="STR_ACE_Medical_GUI_Status_SplintApplied">
<English>Splint Applied</English>
</Key>
<!-- <!--
Strings above match Blood2 but seem to differ in some languages, determine which is best to use Strings above match Blood2 but seem to differ in some languages, determine which is best to use
--> -->

Binary file not shown.

View File

@ -20,6 +20,16 @@ class Extended_Respawn_EventHandlers {
class CAManBase { class CAManBase {
class ADDON { class ADDON {
respawn = QUOTE(call FUNC(resetStateDefault)); respawn = QUOTE(call FUNC(resetStateDefault));
exclude[] = {IGNORE_BASE_UAVPILOTS};
};
};
};
class Extended_Local_EventHandlers {
class CAManBase {
class ADDON {
local = QUOTE(call FUNC(localityChangedEH));
exclude[] = {IGNORE_BASE_UAVPILOTS};
}; };
}; };
}; };

View File

@ -7,5 +7,7 @@ PREP(handleStateDefault);
PREP(handleStateInjured); PREP(handleStateInjured);
PREP(handleStateUnconscious); PREP(handleStateUnconscious);
PREP(leftStateCardiacArrest); PREP(leftStateCardiacArrest);
PREP(localityChangedEH);
PREP(localityTransfer);
PREP(resetStateDefault); PREP(resetStateDefault);
PREP(transitionSecondChance); PREP(transitionSecondChance);

View File

@ -1 +1,3 @@
#include "script_component.hpp" #include "script_component.hpp"
[QGVAR(localityTransfer), LINKFUNC(localityTransfer)] call CBA_fnc_addEventHandler;

View File

@ -19,13 +19,7 @@ params ["_unit"];
// If the unit died the loop is finished // If the unit died the loop is finished
if (!alive _unit) exitWith {}; if (!alive _unit) exitWith {};
if (!local _unit) exitWith {};
// If locality changed, broadcast the last medical state and finish the local loop
if (!local _unit) exitWith {
_unit setVariable [VAR_HEART_RATE, GET_HEART_RATE(_unit), true];
_unit setVariable [VAR_BLOOD_PRESS, _unit getVariable [VAR_BLOOD_PRESS, [80, 120]], true];
_unit setVariable [VAR_BLOOD_VOL, GET_BLOOD_VOLUME(_unit), true];
};
[_unit] call EFUNC(medical_vitals,handleUnitVitals); [_unit] call EFUNC(medical_vitals,handleUnitVitals);

View File

@ -19,13 +19,7 @@ params ["_unit"];
// If the unit died the loop is finished // If the unit died the loop is finished
if (!alive _unit) exitWith {}; if (!alive _unit) exitWith {};
if (!local _unit) exitWith {};
// If locality changed, broadcast the last medical state and finish the local loop
if (!local _unit) exitWith {
_unit setVariable [VAR_HEART_RATE, GET_HEART_RATE(_unit), true];
_unit setVariable [VAR_BLOOD_PRESS, _unit getVariable [VAR_BLOOD_PRESS, [80, 120]], true];
_unit setVariable [VAR_BLOOD_VOL, GET_BLOOD_VOLUME(_unit), true];
};
[_unit] call EFUNC(medical_vitals,handleUnitVitals); [_unit] call EFUNC(medical_vitals,handleUnitVitals);

View File

@ -19,13 +19,7 @@ params ["_unit"];
// If the unit died the loop is finished // If the unit died the loop is finished
if (!alive _unit) exitWith {}; if (!alive _unit) exitWith {};
if (!local _unit) exitWith {};
// If locality changed, broadcast the last medical state and finish the local loop
if (!local _unit) exitWith {
_unit setVariable [VAR_HEART_RATE, GET_HEART_RATE(_unit), true];
_unit setVariable [VAR_BLOOD_PRESS, _unit getVariable [VAR_BLOOD_PRESS, [80, 120]], true];
_unit setVariable [VAR_BLOOD_VOL, GET_BLOOD_VOLUME(_unit), true];
};
[_unit] call EFUNC(medical_vitals,handleUnitVitals); [_unit] call EFUNC(medical_vitals,handleUnitVitals);

View File

@ -0,0 +1,33 @@
#include "script_component.hpp"
/*
* Author: PabstMirror
* Handles locality switch.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: isLocal <BOOL>
*
* Return Value:
* None
*
* Example:
* [player, true] call ace_medical_statemachine_fnc_localityChangedEH
*
* Public: No
*/
params ["_unit", "_isLocal"];
TRACE_2("localityChangedEH",_unit,_isLocal);
if (!alive _unit) exitWith {TRACE_1("dead", _this)};
if (!_isLocal) then {
// If locality changed, broadcast the last medical state
_unit setVariable [VAR_HEART_RATE, GET_HEART_RATE(_unit), true];
_unit setVariable [VAR_BLOOD_PRESS, _unit getVariable [VAR_BLOOD_PRESS, [80, 120]], true];
_unit setVariable [VAR_BLOOD_VOL, GET_BLOOD_VOLUME(_unit), true];
private _currentState = [_unit, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
TRACE_2("sending current state",_unit,_currentState);
[QGVAR(localityTransfer), [_unit, _currentState], _unit] call CBA_fnc_targetEvent;
};

View File

@ -0,0 +1,26 @@
#include "script_component.hpp"
/*
* Author: PabstMirror
* Handles locality switch.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: State <STRING>
*
* Return Value:
* None
*
* Example:
* [player, "Injured"] call ace_medical_statemachine_fnc_localityTransfer
*
* Public: No
*/
params ["_unit", "_currentState"];
TRACE_2("localityTransfer",_unit,_currentState);
private _oldState = [_unit, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
if (_oldState != _currentState) then {
TRACE_2("changing state",_oldState,_currentState);
[_unit, EGVAR(medical,STATE_MACHINE), _oldState, _currentState, {}, "LocalityChange"] call CBA_statemachine_fnc_manualTransition;
};

View File

@ -19,8 +19,8 @@ class Extended_PostInit_EventHandlers {
class Extended_Init_EventHandlers { class Extended_Init_EventHandlers {
class CAManBase { class CAManBase {
class ADDON { class ADDON {
onRespawn = 1; init = QUOTE([ARR_2((_this select 0), false)] call FUNC(initUnit));
init = QUOTE(call FUNC(initUnit)); exclude[] = {IGNORE_BASE_UAVPILOTS};
}; };
}; };
}; };

View File

@ -5,17 +5,23 @@
* *
* Arguments: * Arguments:
* 0: The Unit <OBJECT> * 0: The Unit <OBJECT>
* 1: Is Respawned <BOOL>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [bob] call ace_medical_status_fnc_init * [bob, false] call ace_medical_status_fnc_initUnit
* *
* Public: No * Public: No
*/ */
params ["_unit"]; params ["_unit", ["_isRespawn", true]];
TRACE_2("initUnit",_unit,_isRespawn);
if (!_isRespawn) then { // Always add respawn EH (same as CBA's onRespawn=1)
_unit addEventHandler ["Respawn", {[(_this select 0), true] call FUNC(initUnit)}];
};
if (!local _unit) exitWith {}; if (!local _unit) exitWith {};
@ -23,6 +29,9 @@ if (damage _unit > 0) then {
_unit setDamage 0; _unit setDamage 0;
}; };
if (_isRespawn) then {
TRACE_1("reseting all vars on respawn",_isRespawn); // note: state is handled by ace_medical_statemachine_fnc_resetStateDefault
// - Blood and heart ---------------------------------------------------------- // - Blood and heart ----------------------------------------------------------
_unit setVariable [VAR_BLOOD_VOL, DEFAULT_BLOOD_VOLUME, true]; _unit setVariable [VAR_BLOOD_VOL, DEFAULT_BLOOD_VOLUME, true];
_unit setVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE, true]; _unit setVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE, true];
@ -41,6 +50,7 @@ _unit setVariable [QEGVAR(medical,openWounds), [], true];
_unit setVariable [QEGVAR(medical,bandagedWounds), [], true]; _unit setVariable [QEGVAR(medical,bandagedWounds), [], true];
_unit setVariable [QEGVAR(medical,stitchedWounds), [], true]; _unit setVariable [QEGVAR(medical,stitchedWounds), [], true];
_unit setVariable [QEGVAR(medical,isLimping), false, true]; _unit setVariable [QEGVAR(medical,isLimping), false, true];
_unit setVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0], true];
// - Misc --------------------------------------------------------------------- // - Misc ---------------------------------------------------------------------
_unit setVariable [VAR_UNCON, false, true]; _unit setVariable [VAR_UNCON, false, true];
@ -59,9 +69,6 @@ _unit setVariable [QEGVAR(medical,triageCard), [], true];
// damage storage // damage storage
_unit setVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0], true]; _unit setVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0], true];
#ifdef DEBUG_TESTRESULTS
_unit setVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0], true];
#endif
// medication // medication
_unit setVariable [VAR_MEDICATIONS, [], true]; _unit setVariable [VAR_MEDICATIONS, [], true];
@ -72,9 +79,10 @@ private _logs = _unit getVariable [QEGVAR(medical,allLogs), []];
_unit setVariable [_x, nil]; _unit setVariable [_x, nil];
} forEach _logs; } forEach _logs;
_unit setVariable [QEGVAR(medical,allLogs), [], true]; _unit setVariable [QEGVAR(medical,allLogs), [], true];
};
[{ [{
params ["_unit"]; params ["_unit"];
TRACE_2("Unit Init",_unit,local _unit); TRACE_3("Unit Init",_unit,local _unit,typeOf _unit);
[QGVAR(initialized), [_unit]] call CBA_fnc_localEvent; [QGVAR(initialized), [_unit]] call CBA_fnc_localEvent;
}, [_unit], 0.5] call CBA_fnc_waitAndExecute; }, [_unit], 0.5] call CBA_fnc_waitAndExecute;

View File

@ -20,7 +20,7 @@ params ["_unit"];
private _tourniquets = GET_TOURNIQUETS(_unit); private _tourniquets = GET_TOURNIQUETS(_unit);
private _bodyPartBleeding = [0,0,0,0,0,0]; private _bodyPartBleeding = [0,0,0,0,0,0];
{ {
_x params ["", "", "_bodyPart", "_amountOf", "_bleeeding"]; _x params ["", "_bodyPart", "_amountOf", "_bleeeding"];
if (_tourniquets select _bodyPart == 0) then { if (_tourniquets select _bodyPart == 0) then {
_bodyPartBleeding set [_bodyPart, (_bodyPartBleeding select _bodyPart) + (_amountOf * _bleeeding)]; _bodyPartBleeding set [_bodyPart, (_bodyPartBleeding select _bodyPart) + (_amountOf * _bleeeding)];
}; };

View File

@ -83,6 +83,19 @@ class GVAR(Actions) {
callbackSuccess = QFUNC(treatmentTourniquetRemove); callbackSuccess = QFUNC(treatmentTourniquetRemove);
condition = QUOTE([ARR_2(_target,_bodyPart)] call FUNC(hasTourniquetAppliedTo)); condition = QUOTE([ARR_2(_target,_bodyPart)] call FUNC(hasTourniquetAppliedTo));
}; };
// --- splint
class Splint: BasicBandage {
displayName = CSTRING(Apply_Splint);
displayNameProgress = CSTRING(Applying_Splint);
category = "bandage";
icon = QPATHTOEF(medical_gui,ui\splint.paa);
allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"};
items[] = {"ACE_splint"};
treatmentTime = 7;
callbackSuccess = QFUNC(splint);
condition = QFUNC(splintCondition);
litter[] = {};
};
// --- syringes // --- syringes
class Morphine: FieldDressing { class Morphine: FieldDressing {

View File

@ -70,6 +70,17 @@ class CfgWeapons {
mass = 2; mass = 2;
}; };
}; };
class ACE_splint: ACE_ItemCore {
scope = 2;
author = ECSTRING(common,ACETeam);
displayName = CSTRING(splint_Display);
picture = QPATHTOF(ui\items\tourniquet_x_ca.paa);
model = QPATHTOF(data\tourniquet.p3d);
descriptionShort = CSTRING(splint_Desc_Short);
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 2;
};
};
class ACE_morphine: ACE_ItemCore { class ACE_morphine: ACE_ItemCore {
scope = 2; scope = 2;
author = ECSTRING(common,ACETeam); author = ECSTRING(common,ACETeam);

View File

@ -36,6 +36,10 @@ PREP(treatmentTourniquet);
PREP(treatmentTourniquetLocal); PREP(treatmentTourniquetLocal);
PREP(treatmentTourniquetRemove); PREP(treatmentTourniquetRemove);
PREP(splint);
PREP(splintCondition);
PREP(splintLocal);
// misc // misc
PREP(addToLog); PREP(addToLog);
PREP(addToTriageCard); PREP(addToTriageCard);

View File

@ -16,6 +16,7 @@ if (isServer) then {
[QGVAR(treatmentIVLocal), FUNC(treatmentIVLocal)] call CBA_fnc_addEventHandler; [QGVAR(treatmentIVLocal), FUNC(treatmentIVLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentCPRLocal), FUNC(treatmentCPRLocal)] call CBA_fnc_addEventHandler; [QGVAR(treatmentCPRLocal), FUNC(treatmentCPRLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentFullHealLocal), FUNC(treatmentFullHealLocal)] call CBA_fnc_addEventHandler; [QGVAR(treatmentFullHealLocal), FUNC(treatmentFullHealLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentSplintLocal), FUNC(splintLocal)] call CBA_fnc_addEventHandler;
// action events // action events
[QGVAR(actionCheckPulseLocal), FUNC(actionCheckPulseLocal)] call CBA_fnc_addEventHandler; [QGVAR(actionCheckPulseLocal), FUNC(actionCheckPulseLocal)] call CBA_fnc_addEventHandler;

View File

@ -28,7 +28,7 @@ private _index = ALL_BODY_PARTS find toLower _bodypart;
private _canBandage = false; private _canBandage = false;
{ {
_x params ["", "", "_bodyPartN", "_amountOf", "_bleeding"]; _x params ["", "_bodyPartN", "_amountOf", "_bleeding"];
// If any single wound on the bodypart is bleeding bandaging can go ahead // If any single wound on the bodypart is bleeding bandaging can go ahead
if (_bodyPartN == _index && {_amountOf * _bleeding > 0}) exitWith { if (_bodyPartN == _index && {_amountOf * _bleeding > 0}) exitWith {

View File

@ -37,15 +37,14 @@ private _woundIndex = -1;
private _effectivenessFound = -1; private _effectivenessFound = -1;
{ {
_x params ["", "_classID", "_partIndexN", "_amountOf", "_bleeding", "_damage", "_category"]; _x params ["_classID", "_partIndexN", "_amountOf", "_bleeding", "_damage"];
// Ignore wounds on other bodyparts // Ignore wounds on other bodyparts
if (_partIndexN == _partIndex) then { if (_partIndexN == _partIndex) then {
private _woundEffectiveness = _effectiveness; private _woundEffectiveness = _effectiveness;
// Select the classname from the wound classname storage // Select the classname from the wound classname storage
private _suffix = ["Minor", "Medium", "Large"] select _category; private _className = EGVAR(medical_damage,woundClassNamesComplex) select _classID;
private _className = format ["%1%2", EGVAR(medical_damage,woundClassNames) select _classID, _suffix];
// Get the effectiveness of the bandage on this wound type // Get the effectiveness of the bandage on this wound type
if (isClass (_config >> _className)) then { if (isClass (_config >> _className)) then {

View File

@ -22,11 +22,13 @@ if (_partIndex < 0) exitWith { 0 };
private _targetWound = [_patient, _bandage, _partIndex] call FUNC(findMostEffectiveWound); private _targetWound = [_patient, _bandage, _partIndex] call FUNC(findMostEffectiveWound);
_targetWound params ["_wound", "_woundIndex", "_effectiveness"]; _targetWound params ["_wound", "_woundIndex", "_effectiveness"];
TRACE_3("findMostEffectiveWound",_wound,_woundIndex,_effectiveness);
// Everything is patched up on this body part already // Everything is patched up on this body part already
if (_wound isEqualTo EMPTY_WOUND) exitWith { 0 }; if (_wound isEqualTo EMPTY_WOUND) exitWith { 0 };
_wound params ["", "", "", "_amountOf", "_bloodloss", "_damage", "_category"]; _wound params ["_classID", "", "_amountOf", "_bloodloss", "_damage"];
private _category = (_classID % 10);
// Base bandage time is based on wound size and remaining percentage // Base bandage time is based on wound size and remaining percentage
private _bandageTime = ([ private _bandageTime = ([

View File

@ -20,12 +20,9 @@
params ["_target", "_impact", "_part", "_injuryIndex", "_injury", "_bandage"]; params ["_target", "_impact", "_part", "_injuryIndex", "_injury", "_bandage"];
TRACE_6("handleBandageOpening",_target,_impact,_part,_injuryIndex,_injury,_bandage); TRACE_6("handleBandageOpening",_target,_impact,_part,_injuryIndex,_injury,_bandage);
private _classID = _injury select 1; _injury params ["_classID", "_bodyPartN"];
private _bodyPartN = _injury select 2;
private _category = _injury select 6;
private _postfix = ["Minor", "Medium", "Large"] select _category;
private _className = format ["%1%2", EGVAR(medical_damage,woundClassNames) select _classID, _postfix];
private _className = EGVAR(medical_damage,woundClassNamesComplex) select _classID;
private _reopeningChance = DEFAULT_BANDAGE_REOPENING_CHANCE; private _reopeningChance = DEFAULT_BANDAGE_REOPENING_CHANCE;
private _reopeningMinDelay = DEFAULT_BANDAGE_REOPENING_MIN_DELAY; private _reopeningMinDelay = DEFAULT_BANDAGE_REOPENING_MIN_DELAY;
private _reopeningMaxDelay = DEFAULT_BANDAGE_REOPENING_MAX_DELAY; private _reopeningMaxDelay = DEFAULT_BANDAGE_REOPENING_MAX_DELAY;
@ -64,17 +61,18 @@ TRACE_5("configs",_bandage,_className,_reopeningChance,_reopeningMinDelay,_reope
private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []];
private _exist = false; private _exist = false;
{ {
_x params ["", "_id", "_partN", "_amountOf", "", "", "_oldCategory"]; _x params ["_id", "_partN", "_amountOf"];
if (_id == _classID && {_partN == _bodyPartN && {_oldCategory == _category}}) exitWith { if (_id == _classID && {_partN == _bodyPartN}) exitWith {
_x set [3, _amountOf + _impact]; _x set [2, _amountOf + _impact];
_bandagedWounds set [_forEachIndex, _x]; TRACE_2("adding to existing bandagedWound",_id,_partN);
_exist = true; _exist = true;
}; };
} forEach _bandagedWounds; } forEach _bandagedWounds;
if (!_exist) then { if (!_exist) then {
TRACE_2("adding new bandagedWound",_classID,_bodyPartN);
private _bandagedInjury = +_injury; private _bandagedInjury = +_injury;
_bandagedInjury set [3, _impact]; _bandagedInjury set [2, _impact];
_bandagedWounds pushBack _bandagedInjury; _bandagedWounds pushBack _bandagedInjury;
}; };
@ -96,29 +94,34 @@ if (random 1 <= _reopeningChance) then {
private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
if (count _openWounds - 1 < _injuryIndex) exitWith { TRACE_2("index bounds",_injuryIndex,count _openWounds); }; if (count _openWounds - 1 < _injuryIndex) exitWith { TRACE_2("index bounds",_injuryIndex,count _openWounds); };
_injury params ["", "_classID", "_bodyPartN", "", "", "", "_category"]; _injury params ["_classID", "_bodyPartN"];
private _selectedInjury = _openWounds select _injuryIndex; private _selectedInjury = _openWounds select _injuryIndex;
if (_selectedInjury select 1 == _classID && {_selectedInjury select 2 == _bodyPartN}) then { // matching the IDs _selectedInjury params ["_selClassID", "_selBodyPart", "_selAmmount"];
if ((_selClassID == _classID) && {_selBodyPart == _bodyPartN}) then { // matching the IDs
private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []];
private _exist = false; private _exist = false;
{ {
_x params ["", "_id", "_partN", "_amountOf", "", "", "_oldCategory"]; _x params ["_id", "_partN", "_amountOf"];
if (_id == _classID && {_partN == _bodyPartN && {_oldCategory == _category}}) exitWith { if ((_id == _classID) && {_partN == _bodyPartN}) exitWith {
_x set [3, 0 max (_amountOf - _impact)]; TRACE_2("bandagedWound exists",_id,_classID);
_bandagedWounds set [_forEachIndex, _x]; _x set [2, 0 max (_amountOf - _impact)];
_exist = true; _exist = true;
}; };
} forEach _bandagedWounds; } forEach _bandagedWounds;
if (_exist) then { if (_exist) then {
TRACE_2("Reopening Wound",_bandagedWounds,_openWounds); TRACE_2("Reopening Wound",_bandagedWounds,_openWounds);
_selectedInjury set [3, (_selectedInjury select 3) + _impact]; _selectedInjury set [2, _selAmmount + _impact];
_openWounds set [_injuryIndex, _selectedInjury];
_target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true]; _target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true];
_target setVariable [QEGVAR(medical,openWounds), _openWounds, true]; _target setVariable [QEGVAR(medical,openWounds), _openWounds, true];
[_target] call EFUNC(medical_status,updateWoundBloodLoss); [_target] call EFUNC(medical_status,updateWoundBloodLoss);
// Check if we gained limping from this wound re-opening
if ((EGVAR(medical,limping) == 1) && {_bodyPartN > 3}) then {
[_target] call EFUNC(medical_engine,updateDamageEffects);
};
}; };
} else { } else {
TRACE_3("no match",_selectedInjury,_classID,_bodyPartN); TRACE_3("no match",_selectedInjury,_classID,_bodyPartN);

View File

@ -0,0 +1,25 @@
#include "script_component.hpp"
/*
* Author: PabstMirror
* Apply a splint to the patient
*
* Arguments:
* 0: The medic <OBJECT>
* 1: The patient <OBJECT>
* 2: Body part <STRING>
*
* Return Value:
* Nothing
*
* Example:
* [player, cursorObject, "LeftLeg"] call ace_medical_treatment_fnc_splint
*
* Public: No
*/
params ["_caller", "_target", "_bodyPart"];
TRACE_3("splint",_caller,_target,_bodyPart);
private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
[QGVAR(treatmentSplintLocal), [_caller, _target, _partIndex], _target] call CBA_fnc_targetEvent;

View File

@ -0,0 +1,25 @@
#include "script_component.hpp"
/*
* Author: PabstMirror
* Can apply a splint to the patient
*
* Arguments:
* 0: The medic <OBJECT>
* 1: The patient <OBJECT>
* 2: Body part <STRING>
*
* Return Value:
* Nothing
*
* Example:
* [player, cursorObject, "LeftLeg"] call ace_medical_treatment_fnc_splintCondition
*
* Public: No
*/
params ["", "_patient", "_bodyPart"];
private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
private _fractures = _patient getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]];
(_fractures select _partIndex) == 1

View File

@ -0,0 +1,31 @@
#include "script_component.hpp"
/*
* Author: PabstMirror
* Apply a splint to the patient
*
* Arguments:
* 0: The medic <OBJECT>
* 1: The patient <OBJECT>
* 2: Body part index <NUMBER>
*
* Return Value:
* Nothing
*
* Example:
* [player, cursorObject, 4] call ace_medical_treatment_fnc_splintLocal
*
* Public: No
*/
params ["_caller", "_target", "_bodyPartNum"];
TRACE_3("splintLocal",_caller,_target,_bodyPart);
// Place a tourniquet on the bodypart
private _fractures = _target getVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0]];
_fractures set [_bodyPartNum, -1];
_target setVariable [QEGVAR(medical,fractures), _fractures, true];
// Check if we fixed limping from this treatment
[_target] call EFUNC(medical_engine,updateDamageEffects);
// toDo: AddToLog:

View File

@ -31,9 +31,10 @@ _targetWound params ["_wound", "_woundIndex", "_effectiveness"];
if (_effectiveness == -1) exitWith {}; if (_effectiveness == -1) exitWith {};
// Find the impact this bandage has and reduce the amount this injury is present // Find the impact this bandage has and reduce the amount this injury is present
private _amountOf = _wound select 3; private _amountOf = _wound select 2;
private _impact = _effectiveness min _amountOf; private _impact = _effectiveness min _amountOf;
_wound set [3, _amountOf - _impact]; _amountOf = _amountOf - _impact;
_wound set [2, _amountOf];
_openWounds set [_woundIndex, _wound]; _openWounds set [_woundIndex, _wound];
_target setVariable [QEGVAR(medical,openWounds), _openWounds, true]; _target setVariable [QEGVAR(medical,openWounds), _openWounds, true];
@ -45,4 +46,9 @@ if (_impact > 0 && {GVAR(advancedBandages) && {GVAR(woundReopening)}}) then {
[_target, _impact, _partIndex, _woundIndex, _wound, _bandage] call FUNC(handleBandageOpening); [_target, _impact, _partIndex, _woundIndex, _wound, _bandage] call FUNC(handleBandageOpening);
}; };
// Check if we fixed limping from this treatment
if ((EGVAR(medical,limping) == 1) && {_partIndex > 3} && {_amountOf <= 0} && {_target getVariable [QEGVAR(medical,isLimping), false]}) then {
[_target] call EFUNC(medical_engine,updateDamageEffects);
};
true true

View File

@ -39,6 +39,7 @@ _target setVariable [QEGVAR(medical,openWounds), [], true];
_target setVariable [QEGVAR(medical,bandagedWounds), [], true]; _target setVariable [QEGVAR(medical,bandagedWounds), [], true];
_target setVariable [QEGVAR(medical,stitchedWounds), [], true]; _target setVariable [QEGVAR(medical,stitchedWounds), [], true];
_target setVariable [QEGVAR(medical,isLimping), false, true]; _target setVariable [QEGVAR(medical,isLimping), false, true];
_target setVariable [QEGVAR(medical,fractures), [0,0,0,0,0,0], true];
// - Update wound bleeding // - Update wound bleeding
[_target] call EFUNC(medical_status,updateWoundBloodLoss); [_target] call EFUNC(medical_status,updateWoundBloodLoss);
@ -53,9 +54,6 @@ _target setVariable [QEGVAR(medical,ivBags), nil, true];
// damage storage // damage storage
_target setVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0], true]; _target setVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0], true];
#ifdef DEBUG_TESTRESULTS
_target setVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0], true];
#endif
// generic medical admin // generic medical admin
_target setVariable [VAR_CRDC_ARRST, false, true]; _target setVariable [VAR_CRDC_ARRST, false, true];
@ -70,7 +68,7 @@ _target setVariable [VAR_MEDICATIONS, [], true];
// Reset triage card since medication is all reset // Reset triage card since medication is all reset
_target setVariable [QEGVAR(medical,triageCard), [], true]; _target setVariable [QEGVAR(medical,triageCard), [], true];
[_target, false] call EFUNC(medical_engine,setLimping); [_target] call EFUNC(medical_engine,updateDamageEffects);
// Resetting damage // Resetting damage
_target setDamage 0; _target setDamage 0;

View File

@ -26,7 +26,7 @@ private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), [
private _stitchedWounds = _target getVariable [QEGVAR(medical,stitchedWounds), []]; private _stitchedWounds = _target getVariable [QEGVAR(medical,stitchedWounds), []];
//In case two people stitch up one patient and the last wound has already been closed we can stop already //In case two people stitch up one patient and the last wound has already been closed we can stop already
if (count _bandagedWounds == 0) exitWith { false }; if (_bandagedWounds isEqualTo []) exitWith { false };
//Has enough time elapsed that we can close another wound? //Has enough time elapsed that we can close another wound?
if (_totalTime - _elapsedTime <= (count _bandagedWounds - 1) * 5) then { if (_totalTime - _elapsedTime <= (count _bandagedWounds - 1) * 5) then {
@ -35,6 +35,15 @@ if (_totalTime - _elapsedTime <= (count _bandagedWounds - 1) * 5) then {
_target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true]; _target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true];
_target setVariable [QEGVAR(medical,stitchedWounds), _stitchedWounds, true]; _target setVariable [QEGVAR(medical,stitchedWounds), _stitchedWounds, true];
TRACE_3("stitched",_treatedWound,count _bandagedWounds,count _stitchedWounds); TRACE_3("stitched",_treatedWound,count _bandagedWounds,count _stitchedWounds);
// Check if we fixed limping from this treatment
if ((EGVAR(medical,limping) == 2) && {_target getVariable [QEGVAR(medical,isLimping), false]}) then {
_treatedWound params ["", "_partN"];
if (_partN > 3) then { // only for LEG wounds
TRACE_3("updating damage effects",_target,_partN,local _target);
[QEGVAR(medical_engine,updateDamageEffects), [_target], _target] call CBA_fnc_targetEvent;
};
};
}; };
true true

View File

@ -56,7 +56,7 @@ private _partIndex = (ALL_BODY_PARTS find toLower _bodyPart) max 0;
private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
{ {
_x params ["", "", "_bodyPartN", "_amountOf", "_percentageOpen"]; _x params ["", "_bodyPartN", "_amountOf", "_percentageOpen"];
if (_bodyPartN isEqualTo _partIndex) then { if (_bodyPartN isEqualTo _partIndex) then {
_bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _percentageOpen); _bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _percentageOpen);

View File

@ -765,6 +765,12 @@
<Chinesesimp>用于压迫静脉与动脉的血液流动, 达到减缓失血速度的目的</Chinesesimp> <Chinesesimp>用于压迫静脉与动脉的血液流动, 达到减缓失血速度的目的</Chinesesimp>
<Chinese>用於壓迫靜脈與動脈的血液流動, 達到減緩失血速度的目的</Chinese> <Chinese>用於壓迫靜脈與動脈的血液流動, 達到減緩失血速度的目的</Chinese>
</Key> </Key>
<Key ID="STR_ACE_Medical_treatment_splint_Display">
<English>Splint</English>
</Key>
<Key ID="STR_ACE_Medical_treatment_splint_Desc_Short">
<English>Stabilizes a fractured limb</English>
</Key>
<Key ID="STR_ACE_Medical_treatment_Morphine_Display"> <Key ID="STR_ACE_Medical_treatment_Morphine_Display">
<English>Morphine autoinjector</English> <English>Morphine autoinjector</English>
<German>Morphium-Autoinjektor</German> <German>Morphium-Autoinjektor</German>
@ -1960,6 +1966,12 @@
<Chinesesimp>移除军用止血带</Chinesesimp> <Chinesesimp>移除军用止血带</Chinesesimp>
<Chinese>移除軍用止血帶</Chinese> <Chinese>移除軍用止血帶</Chinese>
</Key> </Key>
<Key ID="STR_ACE_Medical_treatment_Apply_Splint">
<English>Apply Splint</English>
</Key>
<Key ID="STR_ACE_Medical_treatment_Applying_Splint">
<English>Applying Splint...</English>
</Key>
<Key ID="STR_ACE_Medical_treatment_Actions_Diagnose"> <Key ID="STR_ACE_Medical_treatment_Actions_Diagnose">
<English>Diagnose</English> <English>Diagnose</English>
<German>Diagnose</German> <German>Diagnose</German>