#include "creature.h" #include "json.hpp" #include "dice.h" #include "rules.h" #include "feature.h" #include "weapon.h" #include "armor.h" #include #include #include #include #include using namespace nlohmann; using namespace std; namespace creature { Creature::Creature(json dat) : data(dat) { if(! ((map) data).contains("maxHP")) { data["maxHP"] = getBonus("con") * (int) data["hit_die_count"]; for(int i = 0; i < data["hit_die_count"]; i++) { data["maxHP"] = ((int) data["maxHP"]) + roll(data["hit_die_sides"]); } data["currentHP"] = data["maxHP"]; data["givenName"] = "Jerry"; //TODO: Autogenerate } } Creature::~Creature() {} void Creature::save(string saveFile) { ofstream f(saveFile); f << std::setw(4) << data << std::endl; } string Creature::getCreatureName() const { return data["name"]; } string Creature::getGivenName() const { return data["givenName"]; } void Creature::setGivenName(string name) { data["givenName"] = name; } string Creature::getType() const { return data["type"]; } string Creature::getSize() const { return data["size"]; } string Creature::getAlignment() const { return data["alignment"]; } double Creature::getCR() const { return data["cr"]; } string Creature::getLanguages() const { return data["langs"]; } int Creature::getHP() const { return data["currentHP"]; } int Creature::getHPMax() const { return data["maxHP"]; } // True if type without matching qualifiers is in subdata bool conditionApplies(const string& type, const vector& qualifiers, const json& subdata) { bool applies = false; for(auto con : subdata) { if(con["type"] == type) { applies = true; for(string qualifier : qualifiers) { if(find(con["qualifiers"].begin(), con["qualifiers"].end(), qualifier) == con["qualifiers"].end()) { applies = false; } } } } return applies; } void Creature::applyDamage(int amount, const string& type, const vector& qualifiers) { if(! conditionApplies(type, qualifiers, data["d_immunities"])) { if(conditionApplies(type, qualifiers, data["d_resistances"])) { data["currentHP"] = ((int) data["currentHP"]) - amount / 2; } else if(conditionApplies(type, qualifiers, data["d_vulnerabilities"])) { data["currentHP"] = ((int) data["currentHP"]) - amount * 2; } else { data["currentHP"] = ((int) data["currentHP"]) - amount; } } } vector Creature::getSenses() const { vector senses; for(string sense : data["senses"]) { senses.push_back(sense); } return senses; } int Creature::getBonus(const string& ability) const { return (int) (getScore(ability) - 10) / 2; } int Creature::getSkillBonus(const string& skill) const { int bonus = getBonus(skill2ability[skill]); bonus += getProficiencyLevel(skill) * getProficiency(); return bonus; } int Creature::getProficiencyLevel(const string& skill) const { if(data["skills"].find(skill) != data["skills"].end()) { return ((int) data["skills"][skill]); } return 0; } int Creature::getScore(const string& ability) const { return data["stats"][ability]; } void Creature::setScore(const string& ability, int score) { data["stats"][ability] = score; } int Creature::getAC() const { int baseBonus = 10 + getBonus("dex"); int miscBonus = 0; for(auto a : getItems(*this)) { if(getScore("str") < a->getStrRequirement()) { continue; } auto armorType = a->getArmorType(); if(armorType== "misc" || armorType == "shield") { miscBonus += a->getACBonus(); } else { baseBonus = a->getACBonus(); if(armorType == "light") { baseBonus += getBonus("dex"); } else if(armorType == "medium") { baseBonus += (getBonus("dex") > 2)? 2 : getBonus("dex"); } } } return baseBonus + miscBonus; } string Creature::getSpeed() const { return data["speed"]; } int Creature::getAbilitySaveBonus(const string& ability) const { int bonus = getBonus(ability); if(find(data["saves"].begin(), data["saves"].end(), ability) != data["saves"].end()) { bonus += getProficiency(); } return bonus; } int Creature::getProficiency() const { return data["prof"]; } vector> Creature::getFeatures() const { vector> f; for(auto feat : data["features"]) { f.push_back(shared_ptr(new Feature(feat))); } return f; } vector> Creature::getInventory() const { vector> i; for(auto item : data["inventory"]) { i.push_back(Item::create(item)); } return i; } void Creature::addInventoryItem(Item item) { data["inventory"].push_back(item.toJson()); } void Creature::removeInventoryItem(const string& name) { for(auto it = data["inventory"].begin(); it != data["inventory"].end(); it++) { auto i = Item::create(*it); if(i->getName() == name) { data["inventory"].erase(it); break; } } } map Creature::getSkills() const { map s; for(auto skill : (map) data["skills"]) { s[skill.first] = getSkillBonus(skill.first); } return s; } map Creature::getSaves() const { map s; for(auto save : data["saves"]) { s[save] = getBonus(save) + getProficiency(); } return s; } }