Merge branch 'medical-rewrite' of github.com:KoffeinFlummi/ACE3 into medical-rewrite

This commit is contained in:
Glowbal 2015-02-28 21:09:56 +01:00
commit d50466ac67
12 changed files with 365 additions and 98 deletions

View File

@ -6,7 +6,7 @@ class ACE_Medical_Actions {
displayName = "Bandage";
displayNameProgress = "Bandaging ...";
treatmentLocations[] = {"Field", "MedicalFacility", "MedicalVehicle"};
treatmentLocations[] = {"All"};
requiredMedic = 0;
treatmentTime = 5;
treatmentTimeSelfCoef = 1;
@ -35,14 +35,16 @@ class ACE_Medical_Actions {
class Epipen: Bandage {
displayName = "Epinephrine";
displayNameProgress = "Injecting Epinephrine ...";
requiredMedic = 1;
treatmentTime = 3;
items[] = {QGVAR(epinephrine)};
items[] = {QGVAR(epipen)};
callbackSuccess = QUOTE(DFUNC(treatmentBasic_epipen));
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class Bloodbag: Bandage {
displayName = "Blood Bag";
displayNameProgress = "Transfusing Blood ...";
requiredMedic = 1;
treatmentTime = 20;
items[] = {{QGVAR(bloodIV), QGVAR(bloodIV_500), QGVAR(bloodIV_250)}};
callbackSuccess = QUOTE(DFUNC(treatmentBasic_bloodbag));

View File

@ -58,6 +58,50 @@ class CfgVehicles {
name = "leg_r";
};
};
class ACE_Actions {
class Bandage_Head {
displayName = "Bandage Head";
selection = "pilot";
distance = 2.0;
//condition = QUOTE([ARR_4(_player, _target, 'head', 'Bandage')] call DFUNC(canTreat));
statement = QUOTE([ARR_4(_player, _target, 'head', 'Bandage Head')] call DFUNC(treatment));
showDisabled = 1;
priority = 2;
hotkey = "B";
enableInside = 1;
};
class Bandage_Torso: Bandage_Head {
displayName = "Bandage Torso";
selection = "Spine3";
//condition = QUOTE([ARR_4(_player, _target, 'body', 'Bandage')] call DFUNC(canTreat));
statement = QUOTE([ARR_4(_player, _target, 'body', 'Bandage')] call DFUNC(treatment));
};
class Bandage_LeftArm: Bandage_Head {
displayName = "Bandage Right Arm";
selection = "LeftForeArm";
//condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(canTreat));
statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(treatment));
};
class Bandage_RightArm: Bandage_Head {
displayName = "Bandage Right Arm";
selection = "RightForeArm";
//condition = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(canTreat));
statement = QUOTE([ARR_4(_player, _target, 'hand_r', 'Bandage')] call DFUNC(treatment));
};
class Bandage_LeftLeg: Bandage_Head {
displayName = "Bandage Left Leg";
selection = "lknee";
//condition = QUOTE([ARR_4(_player, _target, 'leg_l', 'Bandage')] call DFUNC(canTreat));
statement = QUOTE([ARR_4(_player, _target, 'leg_l', 'Bandage')] call DFUNC(treatment));
};
class Bandage_RightLeg: Bandage_Head {
displayName = "Bandage Right Leg";
selection = "rknee";
//condition = QUOTE([ARR_4(_player, _target, 'leg_r', 'Bandage')] call DFUNC(canTreat));
statement = QUOTE([ARR_4(_player, _target, 'leg_r', 'Bandage')] call DFUNC(treatment));
};
};
};
class SoldierWB: CAManBase {};

View File

@ -0,0 +1,57 @@
class CfgWeapons {
class ItemCore;
class InventoryItem_Base_F;
class InventoryFirstAidKitItem_Base_F;
class MedikitItem;
// ITEMS
class FirstAidKit: ItemCore {
type = 0;
class ItemInfo: InventoryFirstAidKitItem_Base_F {
mass = 4;
type = 201;
};
};
class Medikit: ItemCore {
type = 0;
class ItemInfo: MedikitItem {
mass = 60;
type = 201;
};
};
// @todo localize
class ACE_ItemCore;
class GVAR(fieldDressing): ACE_ItemCore {
displayname = "Bandage";
descriptionshort = "$STR_AGM_Medical_Bandage_Description";
//model = "\A3\Structures_F_EPA\Items\Medical\Bandage_F.p3d";
//picture = "\AGM_Medical\UI\AGM_bandage_ca.paa";
scope = 2;
class ItemInfo: InventoryItem_Base_F {
mass = 2;
};
};
class GVAR(morphine): GVAR(fieldDressing) {
displayName = "Morphine";
descriptionShort = "$STR_AGM_Medical_Morphine_Description";
//model = "\AGM_Medical\agm_morphine.p3d";
//picture = "\AGM_Medical\UI\AGM_morphine_ca.paa";
};
class GVAR(epipen): GVAR(fieldDressing) {
displayName = "Epipen";
descriptionShort = "$STR_AGM_Medical_Epinephrine_Description";
//model = "\AGM_Medical\agm_epipen.p3d";
//picture = "\AGM_Medical\UI\AGM_epipen_ca.paa";
};
class GVAR(bloodIV): GVAR(fieldDressing) {
displayName = "Bloodbag";
descriptionShort = "$STR_AGM_Medical_Bloodbag_Description";
//model = "\A3\Structures_F_EPA\Items\Medical\BloodBag_F.p3d";
//picture = "\AGM_Medical\UI\AGM_bloodbag_ca.paa";
class ItemInfo: ItemInfo {
mass = 10;
};
};
};

View File

@ -2,74 +2,76 @@
ADDON = false;
PREP(getTypeOfDamage);
PREP(handleDamage_airway);
PREP(handleDamage);
PREP(handleDamage_advanced);
PREP(handleDamage_basic);
PREP(handleDamage_fractures);
PREP(handleDamage_internalInjuries);
PREP(handleDamage_caching);
PREP(handleDamage_advancedSetDamage);
PREP(init);
PREP(selectionNameToNumber);
PREP(handleDamage_wounds);
PREP(handleUnitVitals);
PREP(getBloodLoss);
PREP(getBloodPressure);
PREP(getBloodVolumeChange);
PREP(getCardiacOutput);
PREP(setCardiacArrest);
PREP(addToInjuredCollection);
PREP(addHeartRateAdjustment);
PREP(setUnconscious);
PREP(getUnconsciousCondition);
PREP(addUnconsciousCondition);
PREP(setDead);
PREP(parseConfigForInjuries);
PREP(playInjuredSound);
PREP(treatment);
PREP(canTreat);
PREP(treatmentAdvanced_bandage);
PREP(treatmentAdvanced_bandageLocal);
PREP(treatmentAdvanced_medication);
PREP(treatmentAdvanced_medicationLocal);
PREP(treatmentAdvanced_CPR);
PREP(treatmentAdvanced_CPRLocal);
PREP(treatmentAdvanced_fullHeal);
PREP(treatmentAdvanced_fullHealLocal);
PREP(treatmentBasic_bandage);
PREP(treatmentBasic_morphine);
PREP(treatmentBasic_epipen);
PREP(treatmentBasic_bloodbag);
PREP(treatmentIV);
PREP(treatmentIVLocal);
PREP(treatmentTourniquet);
PREP(treatmentTourniquetLocal);
PREP(addToLog);
PREP(addToTriageCard);
PREP(actionPlaceInBodyBag);
PREP(actionCheckBloodPressure);
PREP(actionCheckBloodPressureLocal);
PREP(actionCheckPulse);
PREP(actionCheckPulseLocal);
PREP(actionCheckResponse);
PREP(actionPlaceInBodyBag);
PREP(actionRemoveTourniquet);
PREP(onTreatmentCompleted);
PREP(onMedicationUsage);
PREP(onPropagateWound);
PREP(reactionToDamage);
PREP(useItem);
PREP(useItems);
PREP(addHeartRateAdjustment);
PREP(addToInjuredCollection);
PREP(addToLog);
PREP(addToTriageCard);
PREP(addUnconsciousCondition);
PREP(canAccessMedicalEquipment);
PREP(canTreat);
PREP(determineIfFatal);
PREP(getBloodLoss);
PREP(getBloodPressure);
PREP(getBloodVolumeChange);
PREP(getCardiacOutput);
PREP(getTypeOfDamage);
PREP(getUnconsciousCondition);
PREP(handleDamage);
PREP(handleDamage_advanced);
PREP(handleDamage_advancedSetDamage);
PREP(handleDamage_airway);
PREP(handleDamage_basic);
PREP(handleDamage_caching);
PREP(handleDamage_fractures);
PREP(handleDamage_internalInjuries);
PREP(handleDamage_wounds);
PREP(handleUnitVitals);
PREP(hasItem);
PREP(hasItems);
PREP(hasMedicalEnabled);
PREP(hasTourniquetAppliedTo);
PREP(isMedic);
PREP(init);
PREP(isInMedicalFacility);
PREP(isMedic);
PREP(isMedicalVehicle);
PREP(canAccessMedicalEquipment);
PREP(determineIfFatal);
PREP(onMedicationUsage);
PREP(onPropagateWound);
PREP(parseConfigForInjuries);
PREP(playInjuredSound);
PREP(reactionToDamage);
PREP(selectionNameToNumber);
PREP(setCardiacArrest);
PREP(setDead);
PREP(setHitPointDamage);
PREP(setUnconscious);
PREP(treatment);
PREP(treatment_failure);
PREP(treatment_success);
PREP(treatmentAdvanced_bandage);
PREP(treatmentAdvanced_bandageLocal);
PREP(treatmentAdvanced_CPR);
PREP(treatmentAdvanced_CPRLocal);
PREP(treatmentAdvanced_fullHeal);
PREP(treatmentAdvanced_fullHealLocal);
PREP(treatmentAdvanced_medication);
PREP(treatmentAdvanced_medicationLocal);
PREP(treatmentBasic_bandage);
PREP(treatmentBasic_bloodbag);
PREP(treatmentBasic_epipen);
PREP(treatmentBasic_morphine);
PREP(treatmentIV);
PREP(treatmentIVLocal);
PREP(treatmentTourniquet);
PREP(treatmentTourniquetLocal);
PREP(useItem);
PREP(useItems);
GVAR(injuredUnitCollection) = [];
call FUNC(parseConfigForInjuries);

View File

@ -14,4 +14,5 @@ class CfgPatches {
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"
#include "CfgWeapons.hpp"
#include "ACE_Medical_Treatments.hpp"

View File

@ -66,11 +66,11 @@ _unit setvariable [QGVAR(hasPain), false, true];
_allUsedMedication = _unit getVariable [QGVAR(allUsedMedication), []];
{
_unit setvariable [_x select 0, nil];
}foreach _allUsedMedication;
} foreach _allUsedMedication;
_unit setVariable [QGVAR(allUsedMedication), []];
_logs = _unit getvariable [QGVAR(allLogs), []];
{
_unit setvariable [_x, nil, true];
}foreach _logs;
} foreach _logs;
_unit setvariable [QGVAR(allLogs), [], true];

View File

@ -34,12 +34,12 @@ _allUsedMedication = _target getvariable [QGVAR(allUsedMedication), []];
if !(_className in _allMedsFromClassname) then {
_allMedsFromClassname pushback _className;
_x set [1, _allMedsFromClassname];
_allUsedMedication set[_foreachIndex, _x];
_allUsedMedication set [_foreachIndex, _x];
_target setvariable [QGVAR(allUsedMedication), _allUsedMedication];
};
_foundEntry = true;
};
}foreach _allUsedMedication;
} foreach _allUsedMedication;
if (!_foundEntry) then {
_allUsedMedication pushback [_variable, [_className]];
@ -48,7 +48,7 @@ if (!_foundEntry) then {
_usedMeds = _target getvariable [_variable, 0];
if (_usedMeds >= floor(_maxDosage + round(random(2)))) then {
if (_usedMeds >= floor (_maxDosage + round(random(2)))) then {
[_target] call FUNC(setDead);
};
@ -58,7 +58,7 @@ _hasOverDosed = 0;
_limit = _x select 1;
{
_classNamesUsed = _x select 1;
if ({_x == _med}count _classNamesUsed > _limit) then {
if ({_x == _med} count _classNamesUsed > _limit) then {
_hasOverDosed = _hasOverDosed + 1;
};
}foreach _allUsedMedication;
@ -84,4 +84,4 @@ _decreaseAmount = 1 / _timeInSystem;
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
_args set [3, _amountDecreased];
}, 1, [_target, _timeInSystem, _variable, 0, _decreaseAmount] ] call CBA_fnc_addPerFrameHandler;
}, 1, [_target, _timeInSystem, _variable, 0, _decreaseAmount] ] call CBA_fnc_addPerFrameHandler;

View File

@ -0,0 +1,78 @@
/*
* Author: KoffeinFlummi
* My very own setHitPointDamage since BIS's one is buggy when affecting a remote unit.
* It also doesn't change the overall damage. This does.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: HitPoint <STRING>
* 2: Damage <NUMBER>
* 3: Disable overall damage adjustment (optional) <BOOL>
*
* Return Value:
* nil
*
* Public: Yes
*/
#include "script_component.hpp"
private ["_unit", "_selection", "_damage", "_selections", "_damages", "_damageOld", "_damageSumOld", "_damageNew", "_damageSumNew", "_damageFinal"];
_unit = _this select 0;
_selection = _this select 1;
_damage = _this select 2;
// Unit isn't local, give function to machine where it is.
if !(local _unit) exitWith {
[_this, "ace_medical_fnc_setHitPointDamage", _unit] call EFUNC(common,execRemoteFnc);
};
// Check if overall damage adjustment is disabled
if (count _this > 3 && {_this select 3}) exitWith {
_unit setHitPointDamage [_selection, _damage];
};
_selections = [
"HitHead",
"HitBody",
"HitLeftArm",
"HitRightArm",
"HitLeftLeg",
"HitRightLeg"
];
if !(_selection in _selections) exitWith {
_unit setHitPointDamage [_selection, _damage];
};
GVAR(unit) = _unit;
_damages = [_selections, {GVAR(unit) getHitPointDamage _this}] call EFUNC(common,map);
_damageOld = damage _unit;
_damageSumOld = 0;
{
_damageSumOld = _damageSumOld + _x;
} forEach _damages;
_damageSumOld = _damageSumOld max 0.001;
_damages set [_selections find _selection, _damage];
_damageSumNew = 0;
{
_damageSumNew = _damageSumNew + _x;
} forEach _damages;
_damageNew = _damageSumNew / 6;
if (_damageOld > 0) then {
_damageNew = _damageOld * (_damageSumNew / _damageSumOld);
};
// @todo: prevent death
_unit setDamage _damageNew;
{
_damageFinal = (_damages select _forEachIndex);
_unit setHitPointDamage [_x, _damageFinal];
} forEach _selections;

View File

@ -22,20 +22,24 @@ _target = _this select 1;
_selectionName = _this select 2;
_className = _this select 3;
_config = (ConfigFile >> "ACE_Medical_Treatments" >> "Basic" >> _className);
if (GVAR(level)>=1) then {
_config = (ConfigFile >> "ACE_Medical_Treatments" >> "Advanced" >> _className);
if !(_target isKindOf "CAManBase") exitWith {false};
_config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level) >= 1) then {
_config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};
if !(isClass _config) exitwith {false};
// Check for required class
_medicRequired = getNumber (_config >> "requiredMedic");
if !([_caller, _medicRequired] call FUNC(isMedic) || [_target, _medicRequired] call FUNC(isMedic)) exitwith {false};
// Check item
_items = getArray (_config >> "items");
if (count _items > 0 && {!([_caller, _target, _items] call FUNC(hasItems))}) exitwith {false};
// Check allowed locations
_locations = getArray (_config >> "treatmentLocations");
_return = false;
if ("All" in _locations) then {
_return = true;
@ -48,23 +52,6 @@ if ("All" in _locations) then {
};
if !(_return) exitwith {false};
// Parse the config for the success callback
_callbackSuccess = getText (_config >> "callbackSuccess");
if (isNil _callbackSuccess) then {
_callbackSuccess = compile _callbackSuccess;
} else {
_callbackSuccess = missionNamespace getvariable _callbackSuccess;
};
// Parse the config for the failure callback
_callbackFailure = getText (_config >> "callbackFailure");
if (isNil _callbackFailure) then {
_callbackFailure = compile _callbackFailure;
} else {
_callbackFailure = missionNamespace getvariable _callbackFailure;
};
// Parse the config for the progress callback
_callbackProgress = getText (_config >> "callbackProgress");
if (isNil _callbackProgress) then {
@ -73,21 +60,30 @@ if (isNil _callbackProgress) then {
_callbackProgress = missionNamespace getvariable _callbackProgress;
};
// Start treatment
_treatmentTime = getNumber (_config >> "treatmentTime");
[_treatmentTime, [_caller, _target, _selectionName, _className, _items], _callbackSuccess, _callbackFailure, (localize ""), _callbackProgress] call EFUNC(common,progressBar);
[
_treatmentTime,
[_caller, _target, _selectionName, _className, _items],
DFUNC(treatment_success),
DFUNC(treatment_failure),
getText (_config >> "displayNameProgress"),
_callbackProgress
] call EFUNC(common,progressBar);
// Patient Animation
_patientAnim = getText (_confg >> "animationPatient");
if (_caller != _target && {vehicle _target == _target} && {_patientAnim != ""}) then {
[_target, _patientAnim] call EFUNC(common,doAnimation);
};
// Player Animation
_callerAnim = [getText (_config >> "animationCaller"), getText (_config >> "animationCallerProne")] select (stance _caller == "PRONE");
if (_caller == _target) then {
_callerAnim = [getText (_config >> "animationCallerSelf"), getText (_config >> "animationCallerSelfProne")] select (stance _caller == "PRONE");
};
_wpn = ["non", "rfl", "pst"] select (["", primaryWeapon _caller, handgunWeapon _caller] find (currentWeapon _caller));
_callerAnim = [_callerAnim, "[wpn]", _wpn] call CBA_fnc_replace;
_patientAnim = getText (_confg >> "animationPatient");
if (_caller != _target && {vehicle _target == _target} && {_patientAnim != ""}) then {
[_target, _patientAnim] call EFUNC(common,doAnimation);
};
if (vehicle _caller == _caller && {_callerAnim != ""}) then {
if (primaryWeapon _caller == "") then {
_caller addWeapon "ACE_FakePrimaryWeapon";
@ -97,6 +93,7 @@ if (vehicle _caller == _caller && {_callerAnim != ""}) then {
[_caller, _callerAnim] call EFUNC(common,doAnimation);
};
// Display Icon
_iconDisplayed = getText (_config >> "actionIconPath");
if (_iconDisplayed != "") then {
[QGVAR(treatmentActionIcon), true, _iconDisplayed, [1,1,1,1], getNumber(_config >> "actionIconDisplayTime")] call EFUNC(common,displayIcon);

View File

@ -0,0 +1,37 @@
/*
* Author: KoffeinFlummi
* Callback when the bandaging treatment is complete
*
* Arguments:
* 0: The medic <OBJECT>
* 1: The patient <OBJECT>
* 2: Selection Name <STRING>
* 3: Treatment classname <STRING>
*
* Return Value:
* nil
*
* Public: No
*/
#include "script_component.hpp"
#define BANDAGEHEAL 0.8
private ["_caller", "_target","_selection","_className","_config","_callback"];
_caller = _this select 0;
_target = _this select 1;
_selection = _this select 2;
_className = _this select 3;
if (_selection == "all") then {
_target setDamage ((damage _target - BANDAGEHEAL) max 0);
} else {
_hitSelections = ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"];
_hitPoints = ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"];
_point = _hitPoints select (_hitSelections find _selection);
systemChat _point;
_damage = ((_target getHitPointDamage _point) - BANDAGEHEAL) max 0;
[_target, _point, _damage] call FUNC(setHitPointDamage);
};

View File

@ -0,0 +1,40 @@
/*
* Author: KoffeinFlummi, Glowbal
* Callback when the treatment fails
*
* Arguments:
* 0: The medic <OBJECT>
* 1: The patient <OBJECT>
* 2: SelectionName <STRING>
* 3: Treatment classname <STRING>
*
* Return Value:
* nil
*
* Public: No
*/
#include "script_component.hpp"
private ["_caller", "_target","_selectionName","_className","_config","_callback"];
_caller = _this select 0;
_target = _this select 1;
_selectionName = _this select 2;
_className = _this select 3;
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
[_caller, _caller getvariable [QGVAR(treatmentPrevAnimCaller), ""]] call EFUNC(common,doAnimation);
_caller setvariable [QGVAR(treatmentPrevAnimCaller), nil];
};
// Record specific callback
_config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level) >= 1) then {
_config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};
_callback = getText (_config >> "callbackFailure");
_this call compile _callback

View File

@ -1,5 +1,5 @@
/*
* Author: Glowbal
* Author: KoffeinFlummi, Glowbal
* Callback when the treatment is completed
*
* Arguments:
@ -7,25 +7,34 @@
* 1: The patient <OBJECT>
* 2: SelectionName <STRING>
* 3: Treatment classname <STRING>
* 4: completed <BOOL>
*
* Return Value:
* nil
*
* Public: false
* Public: No
*/
#include "script_component.hpp"
private ["_caller", "_target","_selectionName","_className", "_completed"];
private ["_caller", "_target","_selectionName","_className","_config","_callback"];
_caller = _this select 0;
_target = _this select 1;
_selectionName = _this select 2;
_className = _this select 3;
_completed = _this select 4;
if (primaryWeapon _caller == "ACE_FakePrimaryWeapon") then {
_caller removeWeapon "ACE_FakePrimaryWeapon";
[_caller, _caller getvariable [QGVAR(treatmentPrevAnimCaller), ""]] call EFUNC(common,doAnimation);
_caller setvariable [QGVAR(treatmentPrevAnimCaller), nil];
};
// Record specific callback
_config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level) >= 1) then {
_config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};
_callback = getText (_config >> "callbackSuccess");
_this call compile _callback