mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Rework pain simulation
This commit is contained in:
parent
1128ff0f3f
commit
f11a8848e3
@ -1,3 +1,5 @@
|
||||
PREP(addCustomPain);
|
||||
PREP(addDamageToUnit);
|
||||
PREP(adjustPainLevel);
|
||||
PREP(getCustomPain);
|
||||
PREP(setCustomPain);
|
||||
PREP(setUnconscious);
|
||||
|
35
addons/medical/functions/fnc_addCustomPain.sqf
Normal file
35
addons/medical/functions/fnc_addCustomPain.sqf
Normal file
@ -0,0 +1,35 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: BaerMitUmlaut
|
||||
* Adds pain from external components or mods on a unit.
|
||||
*
|
||||
* Custom pain will never decrease when calling this function, the maximum of
|
||||
* the current and the parameter value will be used. Use setCustomPain in
|
||||
* combination with getCustomPain to decrease custom pain instead. This
|
||||
* function is intended for pain events, like pain from bumping your head.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit (needs to be local) <OBJECT>
|
||||
* 1: Pain amount (range: 0..1) <NUMBER>
|
||||
* 2: Pain index, -1 to assign new index (default: 0) <NUMBER>
|
||||
* 3: Enable pain decay (default: true) <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* Pain index <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* // One time light pain event (without an index, can be changed by other mods), e.g. bumping your head
|
||||
* [player, 0.3] call ace_medical_fnc_addCustomPain;
|
||||
* // Pain source that can be manually decreased later, e.g. an open wound
|
||||
* mod_painIdx = [player, 0.5, [mod_painIdx] param [0, -1]] call ace_medical_fnc_addCustomPain;
|
||||
* // Permanent pain source that does not decay, e.g. a broken heart
|
||||
* mod_painIdx = [player, 1, [mod_painIdx] param [0, -1], false] call ace_medical_fnc_addCustomPain;
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
params ["_unit", "_addedPain", "_index", "_enableDecay"];
|
||||
|
||||
private _oldPain = [_unit, _index] call FUNC(getCustomPain);
|
||||
private _newPain = 0 max (_oldPain max _addedPain) min 1;
|
||||
|
||||
[_unit, _newPain, _index, _enableDecay] call FUNC(setCustomPain);
|
@ -1,28 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Public interface to allow external modules to safely adjust pain levels.
|
||||
* Added pain can be positive or negative (Note: ignores painCoefficient setting)
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The patient <OBJECT>
|
||||
* 1: Added ammount of pain (can be negative) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* The new pain level <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* [guy, 0.5] call ace_medical_fnc_adjustPainLevel
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
|
||||
params ["_unit", "_addedPain"];
|
||||
|
||||
if (!local _unit) exitWith { ERROR_1("unit [%1] is not local",_unit); };
|
||||
|
||||
private _pain = GET_PAIN(_unit);
|
||||
|
||||
_pain = 0 max (_pain + _addedPain) min 1;
|
||||
|
||||
_unit setVariable [VAR_PAIN, _pain];
|
27
addons/medical/functions/fnc_getCustomPain.sqf
Normal file
27
addons/medical/functions/fnc_getCustomPain.sqf
Normal file
@ -0,0 +1,27 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: BaerMitUmlaut
|
||||
* Gets pain from external components or mods on a unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit (needs to be local) <OBJECT>
|
||||
* 1: Pain index (default: 0) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* Pain amount <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* private _pain = [player, mod_painIdx] call ace_medical_fnc_getCustomPain;
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
params [
|
||||
["_unit", objNull, [objNull]],
|
||||
["_index", 0, [0]]
|
||||
];
|
||||
|
||||
if (!local _unit) exitWith {
|
||||
ERROR_1("Unit [%1] is not local",_unit);
|
||||
};
|
||||
|
||||
[_unit, _index] call EFUNC(medical_vitals,getCustomPain);
|
41
addons/medical/functions/fnc_setCustomPain.sqf
Normal file
41
addons/medical/functions/fnc_setCustomPain.sqf
Normal file
@ -0,0 +1,41 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: BaerMitUmlaut
|
||||
* Sets pain from external components or mods on a unit.
|
||||
*
|
||||
* This function allows you to define your own mod's pain source, which you can
|
||||
* manually increase and decrease later. If you want to be Zeus compatible,
|
||||
* make sure to save the returned index on the unit itself, as it might not be
|
||||
* the same for every unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit (needs to be local) <OBJECT>
|
||||
* 1: Pain amount (range: 0..1) <NUMBER>
|
||||
* 2: Pain index, -1 to assign new index (default: 0) <NUMBER>
|
||||
* 3: Enable pain decay (default: true) <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* Pain index <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* // Pain source that can be manually decreased later, e.g. an open wound
|
||||
* mod_painIdx = [player, 0.5, [mod_painIdx] param [0, -1]] call ace_medical_fnc_setCustomPain;
|
||||
* // Heal custom pain source, e.g. treat an open wound
|
||||
* mod_painIdx = [player, 0, [mod_painIdx] param [0, -1]] call ace_medical_fnc_setCustomPain;
|
||||
* // Permanent pain source that does not decay, e.g. a broken heart
|
||||
* mod_painIdx = [player, 1, [mod_painIdx] param [0, -1], false] call ace_medical_fnc_addCustomPain;
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
params [
|
||||
["_unit", objNull, [objNull]],
|
||||
["_pain", 0, [0]],
|
||||
["_index", 0, [0]],
|
||||
["_enableDecay", true, [false]]
|
||||
];
|
||||
|
||||
if (!local _unit) exitWith {
|
||||
ERROR_1("Unit [%1] is not local",_unit);
|
||||
};
|
||||
|
||||
[_unit, _pain, _index, _enableDecay] call EFUNC(medical_vitals,setCustomPain);
|
@ -114,8 +114,8 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
|
||||
|
||||
private _classComplex = 10 * _woundClassIDToAdd + _category;
|
||||
|
||||
// Create a new injury. Format [0:classComplex, 1:bodypart, 2:amountOf, 3:bleedingRate, 4:woundDamage]
|
||||
private _injury = [_classComplex, _bodyPartNToAdd, 1, _bleeding, _woundDamage];
|
||||
// Create a new injury. Format [0:classComplex, 1:bodypart, 2:amountOf, 3:bleedingRate, 4:woundDamage, 5:pain]
|
||||
private _injury = [_classComplex, _bodyPartNToAdd, 1, _bleeding, _woundDamage, _painLevel];
|
||||
|
||||
if (_bodyPartNToAdd == 0 || {_bodyPartNToAdd == 1 && {_woundDamage > PENETRATION_THRESHOLD}}) then {
|
||||
_critialDamage = true;
|
||||
@ -156,7 +156,7 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
|
||||
// if possible merge into existing wounds
|
||||
private _createNewWound = true;
|
||||
{
|
||||
_x params ["_classID", "_bodyPartN", "_oldAmountOf", "_oldBleeding", "_oldDamage"];
|
||||
_x params ["_classID", "_bodyPartN", "_oldAmountOf", "_oldBleeding", "_oldDamage", "_oldPainLevel"];
|
||||
if (
|
||||
(_classComplex == _classID) &&
|
||||
{_bodyPartNToAdd == _bodyPartN} &&
|
||||
@ -170,6 +170,8 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
|
||||
_x set [3, _newBleeding];
|
||||
private _newDamage = (_oldAmountOf * _oldDamage + _woundDamage) / _newAmountOf;
|
||||
_x set [4, _newDamage];
|
||||
private _newPainLevel = _painLevel max _oldPainLevel;
|
||||
_x set [5, _newPainLevel];
|
||||
_createNewWound = false;
|
||||
};
|
||||
} forEach _openWounds;
|
||||
@ -193,8 +195,6 @@ _unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true];
|
||||
|
||||
_bodyPartVisParams call EFUNC(medical_engine,updateBodyPartVisuals);
|
||||
|
||||
[QEGVAR(medical,injured), [_unit, _painLevel]] call CBA_fnc_localEvent;
|
||||
|
||||
if (_critialDamage || {_painLevel > PAIN_UNCONSCIOUS}) then {
|
||||
[_unit] call FUNC(handleIncapacitation);
|
||||
};
|
||||
|
@ -10,12 +10,6 @@ class Extended_PreInit_EventHandlers {
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_PostInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_FILE(XEH_postInit));
|
||||
};
|
||||
};
|
||||
|
||||
class Extended_Init_EventHandlers {
|
||||
class CAManBase {
|
||||
class ADDON {
|
||||
|
@ -1,5 +1,4 @@
|
||||
PREP(addMedicationAdjustment);
|
||||
PREP(adjustPainLevel);
|
||||
PREP(getBloodLoss);
|
||||
PREP(getBloodPressure);
|
||||
PREP(getBloodVolumeChange);
|
||||
|
@ -1,4 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
// Handle pain changes on injury
|
||||
[QEGVAR(medical,injured), LINKFUNC(adjustPainLevel)] call CBA_fnc_addEventHandler;
|
@ -1,31 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Interface to allow external modules to affect the pain level
|
||||
* Sets the new pain level to the max between the input and current level
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The patient <OBJECT>
|
||||
* 1: Desired pain level (0 .. 1) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [guy, 0.5] call ace_medical_status_fnc_adjustPainLevel
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_unit", "_desiredPainLevel"];
|
||||
|
||||
if (!local _unit) exitWith { ERROR("unit is not local"); };
|
||||
|
||||
TRACE_2("adjustPainLevel",_unit,_desiredPainLevel);
|
||||
|
||||
_desiredPainLevel = _desiredPainLevel * EGVAR(medical,painCoefficient);
|
||||
|
||||
private _pain = GET_PAIN(_unit);
|
||||
_pain = 0 max (_pain max _desiredPainLevel) min 1;
|
||||
|
||||
_unit setVariable [VAR_PAIN, _pain];
|
@ -1,4 +1,6 @@
|
||||
PREP(getCustomPain);
|
||||
PREP(handleUnitVitals);
|
||||
PREP(setCustomPain);
|
||||
PREP(updateHeartRate);
|
||||
PREP(updatePainSuppress);
|
||||
PREP(updatePain);
|
||||
PREP(updatePeripheralResistance);
|
||||
|
23
addons/medical_vitals/functions/fnc_getCustomPain.sqf
Normal file
23
addons/medical_vitals/functions/fnc_getCustomPain.sqf
Normal file
@ -0,0 +1,23 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: BaerMitUmlaut
|
||||
* Gets pain from external components or mods on a unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Pain index (default: 0) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* Pain amount <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* private _pain = [player, mod_painIdx] call ace_medical_vitals_fnc_getCustomPain;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
params ["_unit", ["_index", 0]];
|
||||
|
||||
private _customPain = _unit getVariable [QGVAR(customPain), []];
|
||||
|
||||
// Absolute value for non decaying pain, which is saved as a negative value
|
||||
abs (_customPain param [_index, 0])
|
@ -58,18 +58,6 @@ if !(_inPain isEqualTo IS_IN_PAIN(_unit)) then {
|
||||
_unit setVariable [VAR_IN_PAIN, _inPain, true];
|
||||
};
|
||||
|
||||
// Handle pain due tourniquets, that have been applied more than 120 s ago
|
||||
private _tourniquetPain = 0;
|
||||
private _tourniquets = GET_TOURNIQUETS(_unit);
|
||||
{
|
||||
if (_x > 0 && {CBA_missionTime - _x > 120}) then {
|
||||
_tourniquetPain = _tourniquetPain max (CBA_missionTime - _x - 120) * 0.001;
|
||||
};
|
||||
} forEach _tourniquets;
|
||||
if (_tourniquetPain > 0) then {
|
||||
[_unit, _tourniquetPain] call EFUNC(medical_status,adjustPainLevel);
|
||||
};
|
||||
|
||||
// Get Medication Adjustments:
|
||||
private _hrTargetAdjustment = 0;
|
||||
private _painSupressAdjustment = 0;
|
||||
@ -99,7 +87,7 @@ if !(_adjustments isEqualTo []) then {
|
||||
};
|
||||
|
||||
private _heartRate = [_unit, _hrTargetAdjustment, _deltaT, _syncValues] call FUNC(updateHeartRate);
|
||||
[_unit, _painSupressAdjustment, _deltaT, _syncValues] call FUNC(updatePainSuppress);
|
||||
[_unit, _painSupressAdjustment, _deltaT, _syncValues] call FUNC(updatePain);
|
||||
[_unit, _peripheralResistanceAdjustment, _deltaT, _syncValues] call FUNC(updatePeripheralResistance);
|
||||
|
||||
private _bloodPressure = GET_BLOOD_PRESSURE(_unit);
|
||||
|
37
addons/medical_vitals/functions/fnc_setCustomPain.sqf
Normal file
37
addons/medical_vitals/functions/fnc_setCustomPain.sqf
Normal file
@ -0,0 +1,37 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: BaerMitUmlaut
|
||||
* Sets pain from external components or mods on a unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Pain amount (range: 0..1) <NUMBER>
|
||||
* 2: Pain index, -1 to assign new index (default: 0) <NUMBER>
|
||||
* 3: Enable pain decay (default: true) <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* Pain index <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* mod_painIdx = [player, 0.5, [mod_painIdx] param [0, -1]] call ace_medical_vitals_fnc_setCustomPain;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
params ["_unit", "_pain", ["_index", 0], ["_enableDecay", true]];
|
||||
|
||||
private _customPain = _unit getVariable [QGVAR(customPain), [0]];
|
||||
|
||||
_pain = 0 max _pain min 1;
|
||||
|
||||
if (_index == -1) then {
|
||||
_index = count _customPain;
|
||||
};
|
||||
|
||||
if (!_enableDecay) then {
|
||||
_pain = -_pain;
|
||||
};
|
||||
|
||||
_customPain set [_index, _pain];
|
||||
_unit setVariable [QGVAR(customPain), _customPain];
|
||||
|
||||
_index
|
86
addons/medical_vitals/functions/fnc_updatePain.sqf
Normal file
86
addons/medical_vitals/functions/fnc_updatePain.sqf
Normal file
@ -0,0 +1,86 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Update the pain suppression
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Pain Suppress Adjustments <NUMBER>
|
||||
* 2: Time since last update <NUMBER>
|
||||
* 3: Sync value? <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, 0, 1, false] call ace_medical_vitals_fnc_updatePainSuppress
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_unit", "_painSupressAdjustment", "_deltaT", "_syncValue"];
|
||||
|
||||
_unit setVariable [VAR_PAIN_SUPP, 0 max _painSupressAdjustment, _syncValue];
|
||||
|
||||
// Pain value formula: maximum of
|
||||
// - most painful open wound * (1 + 0.1 * count of open wounds)
|
||||
// - most painful bandaged wound * (1 + 0.1 * count of bandaged wounds)
|
||||
// - most painful stitched wound * (1 + 0.1 * count of stitched wounds)
|
||||
// - most painful tourniquet
|
||||
|
||||
// Pain from wounds
|
||||
private _woundsPain = selectMax ([
|
||||
GET_OPEN_WOUNDS(_unit),
|
||||
GET_BANDAGED_WOUNDS(_unit),
|
||||
GET_STITCHED_WOUNDS(_unit)
|
||||
] apply {
|
||||
selectMax (_x apply { _x#5 })
|
||||
});
|
||||
|
||||
// Pain from tourniquets
|
||||
private _tourniquetPain = selectMax (GET_TOURNIQUETS(_unit) apply {
|
||||
if (_x > 0 && {CBA_missionTime - _x > 120}) then {
|
||||
(CBA_missionTime - _x - 120) * 0.001
|
||||
} else {
|
||||
0
|
||||
};
|
||||
});
|
||||
|
||||
// Pain from other components or mods
|
||||
private _customPain = selectMax (_unit getVariable [QGVAR(customPain), []] apply { abs _x });
|
||||
|
||||
// Update total pain
|
||||
private _totalPain = selectMax [_woundsPain, _tourniquetPain, _customPain];
|
||||
_unit setVariable [VAR_PAIN, 0 max _totalPain min 1, _syncValue];
|
||||
|
||||
// Pain decay
|
||||
// Open wounds do not have pain decay
|
||||
// Closed and bandaged wound pain decays at the same rate (because stitching hurts, too)
|
||||
// Decaying custom pain sources are positive, non-decaying custom pain is negative
|
||||
|
||||
// Bandaged and stitched wounds
|
||||
{
|
||||
{
|
||||
_x set [5, 0 max (_x#5 - _deltaT / PAIN_FADE_TIME)];
|
||||
} forEach _x;
|
||||
} forEach [
|
||||
GET_BANDAGED_WOUNDS(_unit),
|
||||
GET_STITCHED_WOUNDS(_unit)
|
||||
];
|
||||
|
||||
// Custom pain sources
|
||||
private _customPain = _unit getVariable [QGVAR(customPain), []];
|
||||
{
|
||||
if (_x > 0) then {
|
||||
_customPain set [_forEachIndex, 0 max (_x - _deltaT / PAIN_FADE_TIME)];
|
||||
};
|
||||
} forEach _customPain;
|
||||
// No need to setVariable because array reference
|
||||
|
||||
|
||||
// Handles simple medication pain supppression
|
||||
if (isNil QEGVAR(medical_treatment,advancedMedication) || {!EGVAR(medical_treatment,advancedMedication)}) then {
|
||||
private _painSupress = _unit getVariable [VAR_PAIN_SUPP, 0];
|
||||
_painSupress = _painSupress - _deltaT / PAIN_SUPPRESSION_FADE_TIME;
|
||||
_unit setVariable [VAR_PAIN_SUPP, 0 max _painSupress, _syncValue];
|
||||
};
|
@ -1,34 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Update the pain suppression
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Pain Suppress Adjustments <NUMBER>
|
||||
* 2: Time since last update <NUMBER>
|
||||
* 3: Sync value? <BOOL>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, 0, 1, false] call ace_medical_vitals_fnc_updatePainSuppress
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_unit", "_painSupressAdjustment", "_deltaT", "_syncValue"];
|
||||
|
||||
_unit setVariable [VAR_PAIN_SUPP, 0 max _painSupressAdjustment, _syncValue];
|
||||
|
||||
// Handle continuous pain reduction
|
||||
private _pain = GET_PAIN(_unit);
|
||||
_unit setVariable [VAR_PAIN, 0 max (_pain - _deltaT / PAIN_FADE_TIME), _syncValue];
|
||||
|
||||
// Handles simple medication
|
||||
if (isNil QEGVAR(medical_treatment,advancedMedication) || {!EGVAR(medical_treatment,advancedMedication)}) then {
|
||||
private _painSupress = _unit getVariable [VAR_PAIN_SUPP, 0];
|
||||
_painSupress = _painSupress - _deltaT / PAIN_SUPPRESSION_FADE_TIME;
|
||||
_unit setVariable [VAR_PAIN_SUPP, 0 max _painSupress, _syncValue];
|
||||
};
|
Loading…
Reference in New Issue
Block a user