ACE3/extensions/medical/handleDamage.cpp
Glowbal d448c9e7c0 Fixed select new injuryToAdd always selects first
It should not always take the first injury in the list. That would with the current configuration almost always be the same injury as in `highestSpot`.

This might need to be expanded with something that prefers higher damage types.
2015-06-13 12:37:41 +02:00

244 lines
9.5 KiB
C++

#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
{
int indexNewInjuryToAdd = rand() % information.size();
injuryToAdd = information.at(indexNewInjuryToAdd);
}
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;
}
}
}