diff --git a/addons/medical/functions/fnc_handleDamage_wounds.sqf b/addons/medical/functions/fnc_handleDamage_wounds.sqf index 2b8e27d75a..a156a284a5 100644 --- a/addons/medical/functions/fnc_handleDamage_wounds.sqf +++ b/addons/medical/functions/fnc_handleDamage_wounds.sqf @@ -71,7 +71,7 @@ if (_highestPossibleSpot < 0) exitwith { }; }; -// admin for open wounds and ids +// Administration for open wounds and ids _openWounds = _unit getvariable[QGVAR(openWounds), []]; _woundID = _unit getvariable[QGVAR(lastUniqueWoundID), 1]; @@ -81,16 +81,38 @@ _woundsCreated = []; if (_x select 0 <= _damage) exitwith { for "_i" from 0 to (1+ floor(random(_x select 1)-1)) /* step +1 */ do { - // Find the injury we are going to add. Format [ classType, allowdSelections, bloodloss, painOfInjury, minimalDamage] + // Find the injury we are going to add. Format [ classID, allowdSelections, bloodloss, painOfInjury, minimalDamage] _toAddInjury = _allPossibleInjuries select (floor(random (count _allPossibleInjuries))); + _toAddClassID = _toAddInjury select 0; + _foundIndex = -1; - // Create a new injury. Format [ID, classname, bodypart, percentage treated, bloodloss rate] - _injury = [_woundID, _toAddInjury select 0, if (_injuryTypeInfo select 1) then {_bodyPartn} else {floor(random(6))}, 1, _toAddInjury select 2]; + // If the injury type is selection part specific, we will check if one of those injury types already exists and find the spot for it.. + if ((_injuryTypeInfo select 1)) then { + { + // Check if we have an id of the given class on the given bodypart already + if (_x select 0 == _toAddClassID && {_x select 2 == _bodyPartn}) exitwith { + _foundIndex = _foreachIndex; + }; + }foreach _openWounds; + }; + _injury = []; + if (_foundIndex < 0) then { + // Create a new injury. Format [ID, classID, bodypart, percentage treated, bloodloss rate] + _injury = [_woundID, _toAddInjury select 0, if (_injuryTypeInfo select 1) then {_bodyPartn} else {floor(random(6))}, 1, _toAddInjury select 2]; + + // Since it is a new injury, we will have to add it to the open wounds array to store it + _openWounds pushback _injury; + + // New injuries will also increase the wound ID + _woundID = _woundID + 1; + } else { + // We already have one of these, so we are just going to increase the number that we have of it with a new one. + _injury = _openWounds select _foreachIndex; + _injury set [3, (_injury select 3) + 1]; + }; // Store the injury so we can process it later correctly. - _openWounds pushback _injury; _woundsCreated pushback _injury; - _woundID = _woundID + 1; // Collect the pain that is caused by this injury _painToAdd = _painToAdd + (_toAddInjury select 3); @@ -99,8 +121,13 @@ _woundsCreated = []; }foreach (_injuryTypeInfo select 0); _unit setvariable [QGVAR(openWounds), _openWounds]; -_unit setvariable [QGVAR(lastUniqueWoundID), _woundID, true]; +// Only update if new wounds have been created +if (count _woundsCreated > 0) then { + _unit setvariable [QGVAR(lastUniqueWoundID), _woundID, true]; +}; + +// TODO Should this be done in a single broadcast? // Broadcast the new injuries across the net in parts. One broadcast per injury. Prevents having to broadcast one massive array of injuries. { ["medical_propagateWound", [_unit, _x]] call EFUNC(common,globalEvent); diff --git a/addons/medical/functions/fnc_parseConfigForInjuries.sqf b/addons/medical/functions/fnc_parseConfigForInjuries.sqf index 3ef3b4c684..8fac99f8a1 100644 --- a/addons/medical/functions/fnc_parseConfigForInjuries.sqf +++ b/addons/medical/functions/fnc_parseConfigForInjuries.sqf @@ -17,15 +17,21 @@ private ["_injuriesRootConfig", "_woundsConfig", "_allWoundClasses", "_amountOf" _injuriesRootConfig = (configFile >> "ACE_Medical_Advanced" >> "Injuries"); _allTypes = ["stab", "grenade", "bullet", "explosive", "shell", "punch", "vehiclecrash", "backblast", "falling", "bite", "ropeburn"]; +// Collect all available damage types from the config _allFoundDamageTypes = []; _configDamageTypes = (_injuriesRootConfig >> "damageTypes"); for "_i" from 0 to (count _configDamageTypes -1) /* step +1 */ do { + // Only get the subclasses in damageType class if (isClass(_configDamageTypes select _i)) then { _allFoundDamageTypes pushback (configName (_configDamageTypes select _i)); }; }; GVAR(allAvailableDamageTypes) = _allFoundDamageTypes; +// Creating a hash map to map wound IDs to classnames +GVAR(woundClassNameIDHash) = HASHCREATE; + +// function for parsing a sublcass of an injury _parseForSubClassWounds = { _subClass = _this select 0; if (isClass (_entry >> _subClass)) exitwith { @@ -37,8 +43,10 @@ _parseForSubClassWounds = { _subClassminDamage = if (isNumber(_subClassConfig >> "minDamage")) then { getNumber(_subClassConfig >> "minDamage");} else { _minDamage }; _subClasscauses = if (isArray(_subClassConfig >> "causes")) then { getArray(_subClassConfig >> "causes");} else { _causes }; _subClassDisplayName = if (isText(_entry >> "name")) then { getText(_entry >> "name");} else {_classDisplayName + " " + _subClass}; - if (count _selections > 0 && count _causes > 0) then { - _allWoundClasses pushback [_subClasstype, _subClassselections, _subClassbloodLoss, _subClasspain, _subClassminDamage, _subClasscauses, _subClassDisplayName]; + if (count _selections > 0 && {count _causes > 0}) then { + HASH_SET(GVAR(woundClassNameIDHash), _classID, _subClasstype); + _allWoundClasses pushback [_classID, _subClassselections, _subClassbloodLoss, _subClasspain, _subClassminDamage, _subClasscauses, _subClassDisplayName]; + _classID = _classID + 1; }; true; }; @@ -48,6 +56,7 @@ _parseForSubClassWounds = { // TODO classTypes are strings currently. Convert them to unqiue IDs instead. _woundsConfig = (_injuriesRootConfig >> "wounds"); _allWoundClasses = []; +_classID = 0; if (isClass _woundsConfig) then { _amountOf = count _woundsConfig; for "_i" from 0 to (_amountOf -1) /* step +1 */ do { @@ -60,11 +69,15 @@ if (isClass _woundsConfig) then { _minDamage = if (isNumber(_entry >> "minDamage")) then { getNumber(_entry >> "minDamage");} else {0}; _causes = if (isArray(_entry >> "causes")) then { getArray(_entry >> "causes");} else {[]}; _classDisplayName = if (isText(_entry >> "name")) then { getText(_entry >> "name");} else {_classType}; + + // TODO instead of hardcoding minor, medium and large just go through all sub classes recursively until none are found if (["Minor"] call _parseForSubClassWounds || ["Medium"] call _parseForSubClassWounds || ["Large"] call _parseForSubClassWounds) exitwith {}; // continue to the next one // There were no subclasses, so we will add this one instead. if (count _selections > 0 && count _causes > 0) then { - _allWoundClasses pushback [_classType, _selections, _bloodLoss, _pain, _minDamage, _causes, _classDisplayName]; + HASH_SET(GVAR(woundClassNameIDHash), _classID, _classType); + _allWoundClasses pushback [_classID, _selections, _bloodLoss, _pain, _minDamage, _causes, _classDisplayName]; + _classID = _classID + 1; }; true; }; @@ -76,6 +89,7 @@ _damageTypesConfig = (configFile >> "ACE_Medical_Advanced" >> "Injuries" >> "dam _thresholds = getArray(_damageTypesConfig >> "thresholds"); _selectionSpecific = getNumber(_damageTypesConfig >> "selectionSpecific"); +// Linking injuries to the woundInjuryType variables. { _varName = format[QGVAR(woundInjuryType_%1),_x]; _woundTypes = []; @@ -93,4 +107,4 @@ _selectionSpecific = getNumber(_damageTypesConfig >> "selectionSpecific"); if (isNumber(_damageTypesConfig >> _x >> "selectionSpecific")) then { _selectionSpecificType = getNumber(_damageTypesConfig >> _x >> "selectionSpecific");}; }; missionNamespace setvariable [_varName, [_typeThresholds, _selectionSpecificType > 0, _woundTypes]]; -}foreach _allTypes; +}foreach _allFoundDamageTypes; diff --git a/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf b/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf index a84312fcc5..ac7b81cdf3 100644 --- a/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf +++ b/addons/medical/functions/fnc_treatmentAdvanced_bandageLocal.sqf @@ -43,12 +43,12 @@ _mostEffectiveInjury = _openWounds select 0; // Only parse injuries that are for the selected bodypart. if (_x select 2 == _part) then { _woundEffectivenss = _effectiveness; - + _classID = (_x select 1); // Check if this wound type has attributes specified for the used bandage - if (isClass (_config >> (_x select 1))) then { + if (HASH_HASKEY(GVAR(woundClassNameIDHash), _classID)) then { // Collect the effectiveness from the used bandage for this wound type - _woundTreatmentConfig = (_config >> (_x select 1)); + _woundTreatmentConfig = (_config >> (HASH_GET(GVAR(woundClassNameIDHash), _classID))); if (isNumber (_woundTreatmentConfig >> "effectiveness")) then { _woundEffectivenss = getNumber (_woundTreatmentConfig >> "effectiveness"); };