mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Merge pull request #1256 from acemod/medicalExtension
Medical Extension for handleDamage wounds
This commit is contained in:
commit
552b2f390f
BIN
ace_medical.dll
Normal file
BIN
ace_medical.dll
Normal file
Binary file not shown.
@ -21,3 +21,7 @@ class CfgPatches {
|
||||
#include "ACE_Settings.hpp"
|
||||
#include "UI\RscTitles.hpp"
|
||||
#include "UI\triagecard.hpp"
|
||||
|
||||
class ACE_Extensions {
|
||||
extensions[] += {"ace_medical"};
|
||||
};
|
||||
|
@ -24,120 +24,43 @@ _damage = _this select 2;
|
||||
_typeOfProjectile = _this select 3;
|
||||
_typeOfDamage = _this select 4;
|
||||
|
||||
// Convert the selectionName to a number and ensure it is a valid selection.
|
||||
_bodyPartn = [_selectionName] call FUNC(selectionNameToNumber);
|
||||
if (_bodyPartn < 0) exitwith {};
|
||||
|
||||
// Get the injury type information. Format: [typeDamage thresholds, selectionSpecific, woundTypes]
|
||||
_injuryTypeInfo = missionNamespace getvariable [format[QGVAR(woundInjuryType_%1), _typeOfDamage],[[], false, []]];
|
||||
|
||||
// This are the available injuries for this damage type. Format [[classtype, selections, bloodloss, minimalDamage, pain], ..]
|
||||
_allInjuriesForDamageType = _injuryTypeInfo select 2;
|
||||
// It appears we are dealing with an unknown type of damage.
|
||||
|
||||
if (count _allInjuriesForDamageType == 0) then {
|
||||
// grabbing the configuration for unknown damage type
|
||||
_injuryTypeInfo = missionNamespace getvariable [QGVAR(woundInjuryType_unknown),[[], false, []]];
|
||||
_allInjuriesForDamageType = _injuryTypeInfo select 2;
|
||||
};
|
||||
|
||||
// find the available injuries for this damage type and damage amount
|
||||
_highestPossibleSpot = -1;
|
||||
_highestPossibleDamage = -1;
|
||||
_allPossibleInjuries = [];
|
||||
{
|
||||
_damageLevels = _x select 4;
|
||||
_minDamage = _damageLevels select 0;
|
||||
_maxDamage = _damageLevels select 1;
|
||||
|
||||
// Check if the damage is higher as the min damage for the specific injury
|
||||
if (_damage >= _minDamage && {_damage <= _maxDamage || _maxDamage < 0}) then {
|
||||
//_classType = _x select 0;
|
||||
_selections = _x select 1;
|
||||
//_bloodLoss = _x select 2;
|
||||
//_pain = _x select 3;
|
||||
|
||||
// Check if the injury can be applied to the given selection name
|
||||
if ("All" in _selections || _selectionName in _selections) then {
|
||||
|
||||
// Find the wound which has the highest minimal damage, so we can use this later on for adding the correct injuries
|
||||
if (_minDamage > _highestPossibleDamage) then {
|
||||
_highestPossibleSpot = _foreachIndex;
|
||||
_highestPossibleDamage = _minDamage;
|
||||
};
|
||||
|
||||
// Store the valid possible injury for the damage type, damage amount and selection
|
||||
_allPossibleInjuries pushback _x;
|
||||
};
|
||||
};
|
||||
}foreach _allInjuriesForDamageType;
|
||||
|
||||
// No possible wounds available for this damage type or damage amount.
|
||||
if (_highestPossibleSpot < 0) exitwith {};
|
||||
|
||||
// Administration for open wounds and ids
|
||||
_openWounds = _unit getvariable[QGVAR(openWounds), []];
|
||||
_woundID = _unit getvariable[QGVAR(lastUniqueWoundID), 1];
|
||||
|
||||
_extensionOutput = "ace_medical" callExtension format ["HandleDamageWounds,%1,%2,%3,%4", _selectionName, _damage, _typeOfDamage, _woundID];
|
||||
|
||||
_painToAdd = 0;
|
||||
_woundsCreated = [];
|
||||
|
||||
call compile _extensionOutput;
|
||||
_foundIndex = -1;
|
||||
{
|
||||
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 [ classID, allowdSelections, bloodloss, painOfInjury, minimalDamage]
|
||||
_toAddInjury = if (random(1) >= 0.85) then {_allInjuriesForDamageType select _highestPossibleSpot} else {_allPossibleInjuries select (floor(random (count _allPossibleInjuries)));};
|
||||
_toAddClassID = _toAddInjury select 0;
|
||||
_foundIndex = -1;
|
||||
|
||||
_bodyPartNToAdd = if (_injuryTypeInfo select 1) then {_bodyPartn} else {floor(random(6))};
|
||||
// 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 1 == _toAddClassID && {_x select 2 == _bodyPartNToAdd}) 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, _bodyPartNToAdd, 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 _foundIndex;
|
||||
_injury set [3, (_injury select 3) + 1];
|
||||
};
|
||||
// Store the injury so we can process it later correctly.
|
||||
_woundsCreated pushback _injury;
|
||||
|
||||
// Collect the pain that is caused by this injury
|
||||
_painToAdd = _painToAdd + (_toAddInjury select 3);
|
||||
_toAddClassID = _x select 1;
|
||||
_bodyPartNToAdd = _x select 2;
|
||||
{
|
||||
// Check if we have an id of the given class on the given bodypart already
|
||||
if (_x select 1 == _toAddClassID && {_x select 2 == _bodyPartNToAdd}) exitwith {
|
||||
_foundIndex = _foreachIndex;
|
||||
};
|
||||
};
|
||||
}foreach (_injuryTypeInfo select 0); // foreach damage thresholds
|
||||
}foreach _openWounds;
|
||||
|
||||
_unit setvariable [QGVAR(openWounds), _openWounds, !USE_WOUND_EVENT_SYNC];
|
||||
if (_foundIndex < 0) then {
|
||||
// Since it is a new injury, we will have to add it to the open wounds array to store it
|
||||
_openWounds pushback _x;
|
||||
} 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 _foundIndex;
|
||||
_injury set [3, (_injury select 3) + 1];
|
||||
};
|
||||
}foreach _woundsCreated;
|
||||
|
||||
_unit setvariable [QGVAR(openWounds), _openWounds, true];
|
||||
|
||||
// Only update if new wounds have been created
|
||||
if (count _woundsCreated > 0) then {
|
||||
_unit setvariable [QGVAR(lastUniqueWoundID), _woundID, true];
|
||||
};
|
||||
|
||||
if (USE_WOUND_EVENT_SYNC) then {
|
||||
// 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);
|
||||
}foreach _woundsCreated;
|
||||
};
|
||||
|
||||
_painLevel = _unit getvariable [QGVAR(pain), 0];
|
||||
_unit setvariable [QGVAR(pain), _painLevel + _painToAdd];
|
||||
|
@ -118,4 +118,58 @@ _selectionSpecific = getNumber(_damageTypesConfig >> "selectionSpecific");
|
||||
if (isNumber(_damageTypesConfig >> _x >> "selectionSpecific")) then { _selectionSpecificType = getNumber(_damageTypesConfig >> _x >> "selectionSpecific");};
|
||||
};
|
||||
missionNamespace setvariable [_varName, [_typeThresholds, _selectionSpecificType > 0, _woundTypes]];
|
||||
|
||||
private ["_minDamageThresholds", "_amountThresholds"];
|
||||
// extension loading
|
||||
_minDamageThresholds = "";
|
||||
_amountThresholds = "";
|
||||
{
|
||||
_minDamageThresholds = _minDamageThresholds + str(_x select 0);
|
||||
_amountThresholds = _amountThresholds + str(_x select 1);
|
||||
if (_forEachIndex < (count _typeThresholds) - 1) then {
|
||||
_minDamageThresholds = _minDamageThresholds + ":";
|
||||
_amountThresholds = _amountThresholds + ":";
|
||||
};
|
||||
}foreach _typeThresholds;
|
||||
|
||||
"ace_medical" callExtension format ["addDamageType,%1,%2,%3,%4,%5", _type, GVAR(minLethalDamages) select _foreachIndex, _minDamageThresholds, _amountThresholds, _selectionSpecificType];
|
||||
|
||||
}foreach _allFoundDamageTypes;
|
||||
|
||||
|
||||
// Extension loading
|
||||
|
||||
{
|
||||
private ["_classID", "_className", "_allowedSelections", "_bloodLoss", "_pain", "_minDamage", "_maxDamage", "_causes", "_classDisplayName", "_extensionInput", "_selections", "_causesArray"];
|
||||
// add shit to addInjuryType
|
||||
_classID = _x select 0;
|
||||
_className = GVAR(woundClassNames) select _forEachIndex;
|
||||
_allowedSelections = "";
|
||||
|
||||
_selections = _x select 1;
|
||||
{
|
||||
_allowedSelections = _allowedSelections + _x;
|
||||
if (_forEachIndex < (count _selections) - 1) then {
|
||||
_allowedSelections = _allowedSelections + ":";
|
||||
};
|
||||
}foreach _selections;
|
||||
|
||||
_bloodLoss = _x select 2;
|
||||
_pain = _x select 3;
|
||||
_minDamage = (_x select 4) select 0;
|
||||
_maxDamage = (_x select 4) select 1;
|
||||
_causes = "";
|
||||
_causesArray = (_x select 5);
|
||||
{
|
||||
_causes = _causes + _x;
|
||||
if (_forEachIndex < (count _causesArray) - 1) then {
|
||||
_causes = _causes + ":";
|
||||
};
|
||||
}foreach _causesArray;
|
||||
_classDisplayName = _x select 6;
|
||||
|
||||
"ace_medical" callExtension format["addInjuryType,%1,%2,%3,%4,%5,%6,%7,%8,%9", _classID, _className, _allowedSelections, _bloodLoss, _pain, _minDamage, _maxDamage, _causes, _classDisplayName];
|
||||
|
||||
}foreach _allWoundClasses;
|
||||
|
||||
"ace_medical" callExtension "ConfigComplete";
|
||||
|
@ -125,6 +125,7 @@ add_subdirectory(fcs)
|
||||
add_subdirectory(break_line)
|
||||
add_subdirectory(clipboard)
|
||||
add_subdirectory(advanced_ballistics)
|
||||
add_subdirectory(medical)
|
||||
|
||||
# Test Extension for dynamically loading/unloading built extensions; does not build in release
|
||||
if (DEVEL)
|
||||
|
13
extensions/medical/CMakeLists.txt
Normal file
13
extensions/medical/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
set(ACE_EXTENSION_NAME "ace_medical")
|
||||
|
||||
file(GLOB SOURCES *.h *.hpp *.c *.cpp)
|
||||
|
||||
add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES})
|
||||
target_link_libraries(${ACE_EXTENSION_NAME} ace_common)
|
||||
set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1)
|
||||
set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_END_STATIC 1)
|
||||
endif()
|
11
extensions/medical/DamageType.cpp
Normal file
11
extensions/medical/DamageType.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "DamageType.h"
|
||||
|
||||
ace::medical::injuries::DamageType::DamageType(std::string aTypeName, double minimalLethalDamage, std::vector<double> minDamage, std::vector<double> amountOfInjuresOnDamage, bool specificOnly)
|
||||
: typeName(aTypeName), minLethalDamage(minimalLethalDamage), minDamageThreshold(minDamage), amountOfInjuresOnDamage(amountOfInjuresOnDamage), selectionSpecific(specificOnly)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ace::medical::injuries::DamageType::~DamageType()
|
||||
{
|
||||
}
|
28
extensions/medical/DamageType.h
Normal file
28
extensions/medical/DamageType.h
Normal file
@ -0,0 +1,28 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace ace {
|
||||
namespace medical {
|
||||
namespace injuries {
|
||||
class InjuryType;
|
||||
|
||||
class DamageType
|
||||
{
|
||||
public:
|
||||
DamageType(std::string aTypeName, double minimalLethalDamage, std::vector<double> minDamageThreshold, std::vector<double> amountOfInjuresOnDamage, bool specificOnly);
|
||||
~DamageType();
|
||||
|
||||
std::string typeName;
|
||||
double minLethalDamage;
|
||||
std::vector<double> minDamageThreshold;
|
||||
std::vector<double> amountOfInjuresOnDamage;
|
||||
|
||||
bool selectionSpecific;
|
||||
|
||||
std::vector<std::shared_ptr<InjuryType>> possibleInjuries;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
13
extensions/medical/InjuryType.cpp
Normal file
13
extensions/medical/InjuryType.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "InjuryType.h"
|
||||
#include "DamageType.h"
|
||||
|
||||
|
||||
ace::medical::injuries::InjuryType::InjuryType(signed int anId, const std::string& aClassname, std::vector<std::string>& allowedSelections, double theBloodLoss, double thePain, double minimumDamage, double maximumDamage, std::vector<std::string>& possibleCauses, std::string& aDisplayname)
|
||||
: ID(anId), className(aClassname), selections(allowedSelections), bloodLoss(theBloodLoss), pain(thePain), minDamage(minimumDamage), maxDamage(maximumDamage), causes(possibleCauses), displayName(aDisplayname)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ace::medical::injuries::InjuryType::~InjuryType()
|
||||
{
|
||||
}
|
27
extensions/medical/InjuryType.h
Normal file
27
extensions/medical/InjuryType.h
Normal file
@ -0,0 +1,27 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ace {
|
||||
namespace medical {
|
||||
namespace injuries {
|
||||
class DamageType;
|
||||
|
||||
class InjuryType
|
||||
{
|
||||
public:
|
||||
InjuryType(signed int anId, const std::string& aClassname, std::vector<std::string>& allowedSelections, double theBloodLoss, double thePain, double minimumDamage, double maximumDamage, std::vector<std::string>& possibleCauses, std::string& aDisplayname);
|
||||
~InjuryType();
|
||||
|
||||
signed int ID;
|
||||
std::string className;
|
||||
std::vector<std::string> selections;
|
||||
double bloodLoss;
|
||||
double pain;
|
||||
double minDamage;
|
||||
double maxDamage;
|
||||
std::vector<std::string> causes;
|
||||
std::string displayName;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
18
extensions/medical/OpenWound.cpp
Normal file
18
extensions/medical/OpenWound.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "OpenWound.h"
|
||||
#include <sstream>
|
||||
|
||||
ace::medical::injuries::OpenWound::OpenWound(int anID, int aClassID, int aBodyPartId, double aPercentage, double aBl, double painAmount) :
|
||||
woundID(anID), classID(aClassID), bodyPart(aBodyPartId), percentage(aPercentage), bloodlossRate(aBl), pain(painAmount)
|
||||
{
|
||||
}
|
||||
|
||||
ace::medical::injuries::OpenWound::~OpenWound()
|
||||
{
|
||||
}
|
||||
|
||||
std::string ace::medical::injuries::OpenWound::AsString()
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "[" << woundID << "," << classID << "," << bodyPart << "," << 1 << "," << bloodlossRate << "]";
|
||||
return stream.str();
|
||||
}
|
26
extensions/medical/OpenWound.h
Normal file
26
extensions/medical/OpenWound.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ace {
|
||||
namespace medical {
|
||||
namespace injuries {
|
||||
class OpenWound
|
||||
{
|
||||
public:
|
||||
OpenWound(int anID, int aClassID, int aBodyPartId, double aPercentage, double aBl, double painAmount);
|
||||
~OpenWound();
|
||||
|
||||
std::string AsString();
|
||||
|
||||
int woundID;
|
||||
int classID;
|
||||
int percentage;
|
||||
double bodyPart;
|
||||
double bloodlossRate;
|
||||
double pain;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
242
extensions/medical/handleDamage.cpp
Normal file
242
extensions/medical/handleDamage.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
#include "handleDamage.h"
|
||||
#include "OpenWound.h"
|
||||
#include "DamageType.h"
|
||||
#include "InjuryType.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ace {
|
||||
namespace medical {
|
||||
|
||||
handleDamage::handleDamage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
handleDamage& handleDamage::GetInstance()
|
||||
{
|
||||
static handleDamage instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
handleDamage::~handleDamage()
|
||||
{
|
||||
}
|
||||
|
||||
std::string handleDamage::HandleDamageWounds(const std::string& selectionName, double amountOfDamage, const std::string& typeOfDamage, int woundID)
|
||||
{
|
||||
std::vector<ace::medical::injuries::OpenWound> wounds;
|
||||
int selectionN = SelectionToNumber(selectionName);
|
||||
std::stringstream stream;
|
||||
|
||||
if (selectionN >= 0)
|
||||
{
|
||||
double painToAdd = 0;
|
||||
wounds = GetInjuryInfoFor(typeOfDamage, amountOfDamage, selectionN, woundID);
|
||||
|
||||
stream << "_woundsCreated = [";
|
||||
for (int i = 0; i < wounds.size(); ++i)
|
||||
{
|
||||
stream << wounds.at(i).AsString();
|
||||
if (i != wounds.size() - 1)
|
||||
{
|
||||
stream << ",";
|
||||
}
|
||||
|
||||
painToAdd += wounds.at(i).pain;
|
||||
}
|
||||
stream << "];";
|
||||
|
||||
stream << "_painToAdd = " << painToAdd << ";";
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::vector<ace::medical::injuries::OpenWound> handleDamage::GetInjuryInfoFor(const std::string& typeOfDamage, double amountOfDamage, int selection, int woundID)
|
||||
{
|
||||
std::vector<ace::medical::injuries::OpenWound> injuriesToAdd;
|
||||
std::vector<std::shared_ptr<ace::medical::injuries::InjuryType>> information;
|
||||
std::shared_ptr<ace::medical::injuries::InjuryType> highestSpot = nullptr;
|
||||
|
||||
for (auto & damageType : damageTypes)
|
||||
{
|
||||
if (damageType->typeName == typeOfDamage)
|
||||
{
|
||||
for (auto & possibleInjury : damageType->possibleInjuries)
|
||||
{
|
||||
if (amountOfDamage >= possibleInjury->minDamage && (amountOfDamage <= possibleInjury->maxDamage || possibleInjury->maxDamage <= 0))
|
||||
{
|
||||
if (highestSpot == NULL)
|
||||
highestSpot = possibleInjury;
|
||||
|
||||
if (possibleInjury->minDamage > highestSpot->minDamage)
|
||||
highestSpot = possibleInjury;
|
||||
|
||||
information.push_back(possibleInjury);
|
||||
}
|
||||
}
|
||||
if (highestSpot == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
for (double & threshold : damageType->minDamageThreshold)
|
||||
{
|
||||
if (amountOfDamage >= threshold)
|
||||
{
|
||||
double amountOfInjuriesOnDamage = damageType->amountOfInjuresOnDamage.at(c);
|
||||
for (double injuryAmount = 0; injuryAmount < amountOfInjuriesOnDamage; ++injuryAmount)
|
||||
{
|
||||
std::shared_ptr<ace::medical::injuries::InjuryType> injuryToAdd;
|
||||
if (rand() % 100 >= 85)
|
||||
{
|
||||
injuryToAdd = highestSpot;
|
||||
}
|
||||
else
|
||||
{
|
||||
injuryToAdd = information.at(0);
|
||||
}
|
||||
|
||||
int bodyPartID = selection;
|
||||
if (!damageType->selectionSpecific)
|
||||
{
|
||||
bodyPartID = rand() % 6;
|
||||
}
|
||||
|
||||
injuries::OpenWound newWound(woundID++, injuryToAdd->ID, bodyPartID, 1, injuryToAdd->bloodLoss, injuryToAdd->pain);
|
||||
injuriesToAdd.push_back(newWound);
|
||||
}
|
||||
}
|
||||
++c;
|
||||
}
|
||||
return injuriesToAdd;
|
||||
}
|
||||
}
|
||||
return injuriesToAdd;
|
||||
}
|
||||
|
||||
std::string handleDamage::AddDamageType(const std::vector<std::string>& input)
|
||||
{
|
||||
if (input.size() == 5)
|
||||
{
|
||||
std::string typeName = input[0];
|
||||
double minimalLethalDamage = std::stod(input[1]);
|
||||
std::vector<double> minDamageThreshold = inputToVectorDouble(input[2]);
|
||||
std::vector<double> amountOfInjuresOnDamage = inputToVectorDouble(input[3]);
|
||||
bool selectionSpecific = std::stod(input[4]) > 0;
|
||||
|
||||
std::shared_ptr<ace::medical::injuries::DamageType> type(new ace::medical::injuries::DamageType(typeName, minimalLethalDamage, minDamageThreshold, amountOfInjuresOnDamage, selectionSpecific));
|
||||
damageTypes.push_back(type);
|
||||
|
||||
std::stringstream stream;
|
||||
|
||||
stream << "ADDED: " << typeName << " - " << minimalLethalDamage << " - [";
|
||||
for (double & sel : minDamageThreshold)
|
||||
{
|
||||
stream << sel << " -";
|
||||
}
|
||||
stream << "] - [";
|
||||
for (double & sel : amountOfInjuresOnDamage)
|
||||
{
|
||||
stream << sel << " -";
|
||||
}
|
||||
stream << "] - " << selectionSpecific;
|
||||
return stream.str();
|
||||
}
|
||||
return "failed";
|
||||
}
|
||||
|
||||
std::string handleDamage::AddInjuryType(const std::vector<std::string>& input)
|
||||
{
|
||||
if (input.size() == 9)
|
||||
{
|
||||
int ID = std::stod(input[0]);
|
||||
std::string className = input[1];
|
||||
std::vector<std::string> allowedSelections = inputToVector(input[2]);
|
||||
double bloodLoss = std::stod(input[3]);
|
||||
double pain = std::stod(input[4]);
|
||||
|
||||
double minDamage = std::stod(input[5]);
|
||||
double maxDamage = std::stod(input[6]);
|
||||
std::vector<std::string> possibleCauses = inputToVector(input[7]);
|
||||
std::string displayName = input[8];
|
||||
|
||||
std::shared_ptr<ace::medical::injuries::InjuryType> type(new ace::medical::injuries::InjuryType(ID, className, allowedSelections, bloodLoss, pain, minDamage, maxDamage, possibleCauses, displayName));
|
||||
injuryTypes.push_back(type);
|
||||
std::stringstream stream;
|
||||
|
||||
stream << "ADDED: " << ID << " - " << className << " - [";
|
||||
for (std::string & sel : allowedSelections)
|
||||
{
|
||||
stream << sel << " -";
|
||||
}
|
||||
stream << "] - ";
|
||||
stream << bloodLoss << " - " << pain << " - " << minDamage << " - " << maxDamage;
|
||||
for (std::string & sel : possibleCauses)
|
||||
{
|
||||
stream << sel << " -";
|
||||
}
|
||||
stream << displayName;
|
||||
return stream.str();
|
||||
}
|
||||
return "failed";
|
||||
}
|
||||
|
||||
void handleDamage::FinalizeDefinitions()
|
||||
{
|
||||
// We are finding all possible injuries for a specific damage type here, so we don't have to figure that out at a later stage.
|
||||
for (auto & damageType : damageTypes)
|
||||
{
|
||||
for (auto & injuryType : injuryTypes)
|
||||
{
|
||||
std::vector<std::string>::iterator it = std::find(injuryType->causes.begin(), injuryType->causes.end(), damageType->typeName);
|
||||
// outputstream << " Evaluating causes: " << (it != injuryType->causes.end()) << " ";
|
||||
if (it != injuryType->causes.end())
|
||||
{
|
||||
damageType->possibleInjuries.push_back(injuryType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int handleDamage::SelectionToNumber(const std::string& selectionName)
|
||||
{
|
||||
// TODO use dynamic selections instead
|
||||
std::vector<std::string> selections = { "head", "body", "hand_l", "hand_r", "leg_l", "leg_r" };
|
||||
std::vector<std::string>::iterator it = find(selections.begin(), selections.end(), selectionName);
|
||||
if (it != selections.end())
|
||||
{
|
||||
return it - selections.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; // TODO throw exception
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> handleDamage::inputToVector(const std::string& input)
|
||||
{
|
||||
std::istringstream ss(input);
|
||||
std::string token;
|
||||
|
||||
std::vector<std::string> output;
|
||||
while (std::getline(ss, token, ':')) {
|
||||
output.push_back(token);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
std::vector<double> handleDamage::inputToVectorDouble(const std::string& input)
|
||||
{
|
||||
std::istringstream ss(input);
|
||||
std::string token;
|
||||
|
||||
std::vector<double> output;
|
||||
while (std::getline(ss, token, ':')) {
|
||||
output.push_back(std::stod(token));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
92
extensions/medical/handleDamage.h
Normal file
92
extensions/medical/handleDamage.h
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace ace {
|
||||
namespace medical {
|
||||
|
||||
namespace injuries {
|
||||
class DamageType;
|
||||
class InjuryType;
|
||||
class OpenWound;
|
||||
}
|
||||
|
||||
class handleDamage
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static handleDamage& GetInstance();
|
||||
|
||||
~handleDamage();
|
||||
|
||||
/**
|
||||
* Find new open wounds from advanced medical based upon the received damage.
|
||||
*
|
||||
* @param selectionName A string representation of the bodypart (for example: leg_r)
|
||||
* @param amountOfDamage The damage received
|
||||
* @param typeOfDamage The type of the damage received
|
||||
* @param woundID latest wound ID
|
||||
* @return SQF string containing _woundsCreated and _painAdded.
|
||||
*/
|
||||
std::string HandleDamageWounds(const std::string& selectionName, double amountOfDamage, const std::string& typeOfDamage, int woundID);
|
||||
|
||||
/**
|
||||
* Find new open wounds from advanced medical based upon the received damage.
|
||||
*
|
||||
* @param typeOfDamage The type of the damage received
|
||||
* @param amountOfDamage The damage received
|
||||
* @param selection A number representation of the bodypart. Number from 0 to 6.
|
||||
* @param woundID latest wound ID
|
||||
* @return New open wounds.
|
||||
*/
|
||||
std::vector<ace::medical::injuries::OpenWound> GetInjuryInfoFor(const std::string& typeOfDamage, double amountOfDamage, int selection, int woundID);
|
||||
|
||||
/**
|
||||
* Add a new damage type from extension input parameters
|
||||
*
|
||||
* @param sqfDamageTypeDefinition
|
||||
* @return String with result of addition: ADDED [parameters] or FAILED
|
||||
*/
|
||||
std::string AddDamageType(const std::vector<std::string>& sqfDamageTypeDefinition);
|
||||
|
||||
/**
|
||||
* Add a new injury type from extension input parameters
|
||||
*
|
||||
* @param sqfDamageTypeDefinition
|
||||
* @return String with result of addition: ADDED [parameters] or FAILED
|
||||
*/
|
||||
std::string AddInjuryType(const std::vector<std::string>& sqfInjuryDefinition);
|
||||
|
||||
/**
|
||||
* Convert a selectionName to a number
|
||||
*
|
||||
* @param selectionName
|
||||
* @return number of selection
|
||||
*/
|
||||
int SelectionToNumber(const std::string& selectionName);
|
||||
|
||||
/**
|
||||
* Lets the system know that all data has been added
|
||||
*/
|
||||
void FinalizeDefinitions();
|
||||
|
||||
private:
|
||||
handleDamage();
|
||||
|
||||
handleDamage(handleDamage const&) = delete;
|
||||
void operator=(handleDamage const&) = delete;
|
||||
|
||||
std::vector<std::string> inputToVector(const std::string& input);
|
||||
std::vector<double> inputToVectorDouble(const std::string& input);
|
||||
|
||||
std::vector<std::shared_ptr<ace::medical::injuries::DamageType>> damageTypes;
|
||||
std::vector<std::shared_ptr<ace::medical::injuries::InjuryType>> injuryTypes;
|
||||
std::vector<std::string> selections;
|
||||
std::vector<std::string> hitPoints;
|
||||
};
|
||||
}
|
||||
}
|
68
extensions/medical/medical.cpp
Normal file
68
extensions/medical/medical.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* ace_medical.cpp
|
||||
*
|
||||
* Author:
|
||||
* Glowbal
|
||||
*/
|
||||
|
||||
#include "shared.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "handleDamage.h"
|
||||
#include "OpenWound.h"
|
||||
|
||||
extern "C" {
|
||||
EXPORT void __stdcall RVExtension(char *output, int outputSize, const char *function);
|
||||
};
|
||||
|
||||
std::vector<std::string> parseExtensionInput(const std::string& input)
|
||||
{
|
||||
std::istringstream ss(input);
|
||||
std::string token;
|
||||
|
||||
std::vector<std::string> output;
|
||||
while (std::getline(ss, token, ',')) {
|
||||
output.push_back(token);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
void __stdcall RVExtension(char *output, int outputSize, const char *function) {
|
||||
if (!strcmp(function, "version")) {
|
||||
strncpy(output, ACE_FULL_VERSION_STR, outputSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string returnValue = "";
|
||||
std::vector<std::string> arguments = parseExtensionInput(function);
|
||||
if (arguments.size() > 0)
|
||||
{
|
||||
std::string command = arguments.at(0);
|
||||
arguments.erase(arguments.begin());
|
||||
|
||||
if (command == "addInjuryType") {
|
||||
returnValue = ace::medical::handleDamage::GetInstance().AddInjuryType(arguments);
|
||||
}
|
||||
else if (command == "addDamageType") {
|
||||
returnValue = ace::medical::handleDamage::GetInstance().AddDamageType(arguments);
|
||||
}
|
||||
else if (command == "HandleDamageWounds") {
|
||||
if (arguments.size() >= 4) {
|
||||
std::string selectionName = arguments.at(0);
|
||||
double amountOfDamage = std::stod(arguments.at(1));
|
||||
std::string typeOfDamage = arguments.at(2);
|
||||
int woundID = std::stoi(arguments.at(3));
|
||||
returnValue = ace::medical::handleDamage::GetInstance().HandleDamageWounds(selectionName, amountOfDamage, typeOfDamage, woundID);
|
||||
}
|
||||
}
|
||||
else if (command == "ConfigComplete") {
|
||||
ace::medical::handleDamage::GetInstance().FinalizeDefinitions();
|
||||
}
|
||||
}
|
||||
strncpy(output, returnValue.c_str(), outputSize);
|
||||
output[outputSize - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user