#include "creature.h" #include "json.hpp" #include "dice.h" #include "rules.h" #include "feature.h" #include "weapon.h" #include "armor.h" #include #include typedef nlohmann::json json; using namespace std; namespace creature { Creature::Creature(const json& data) : inventory(json2ptrvec(data["inventory"])), creatureName(data["name"]), size(data["size"]), type(data["type"]), alignment(data["alignment"]), hdCount(data["hit_die_count"]), hdSides(data["hit_die_sides"]), speed(data["speed"]), stats(data["stats"]), skills(data["skills"]), saves(data["saves"]), langs(data["langs"]), cr(data["cr"]), proficiency(data["prof"]), dmgImmunities(json2vec(data["d_immunities"])), dmgResistances(json2vec(data["d_resistances"])), dmgVulnerabilities(json2vec(data["d_vulnerabilities"])), condImmunities(json2vec(data["c_immunities"])), features(json2ptrvec(data["features"])) { // Initialize names and hp if(((map) data).contains("givenName")) { givenName = data["givenName"]; hpMax = data["hpMax"]; hp = data["hp"]; } else { givenName = "Jerry"; //TODO: Autogenerate hpMax = this->getBonus("con") * hdCount; for(int i = 0; i < hdCount; i++) { hpMax += roll(hdSides); } hp = hpMax; } } template vector getJsonVectP(vector src) { vector ret; for(T i : src) { ret.push_back(i->toJson()); } return ret; } nlohmann::json Creature::toJson() const { return nlohmann::json({ {"name", creatureName}, {"size", size}, {"type", type}, {"alignment", alignment}, {"hit_die_count", hdCount}, {"hit_die_sides", hdSides}, {"speed", speed}, {"stats", stats}, {"skills", skills}, {"saves", saves}, {"langs", langs}, {"cr", cr}, {"prof", proficiency}, {"d_immunities", dmgImmunities}, {"d_resistances", dmgResistances}, {"d_vulnerabilities", dmgVulnerabilities}, {"c_immunities", condImmunities}, {"givenName", givenName}, {"hpMax", hpMax}, {"hp", hp}, {"inventory", getJsonVectP(inventory)}, {"features", getJsonVectP(features)} }); } // True if type without matching qualifiers is in subdata bool conditionApplies(const string& type, const vector& qualifiers, const vector subdata) { bool applies = false; for(dmgType 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, dmgImmunities)) { if(conditionApplies(type, qualifiers, dmgResistances)) { hp -= amount / 2; } else if(conditionApplies(type, qualifiers, dmgVulnerabilities)) { hp -= amount * 2; } else { hp -= amount; } } } int Creature::getSkillBonus(const string& skill) const { int bonus = this->getBonus(skill2ability[skill]); if(skills.contains(skill)) { bonus += skills.at(skill) * getProficiency(); } return bonus; } int Creature::getAbilitySaveBonus(const string& ability) const { int bonus = this->getBonus(ability); if(find(saves.begin(), saves.end(), ability) != saves.end()) { bonus += getProficiency(); } return bonus; } void Creature::addInventoryItem(shared_ptr item) { inventory.push_back(item); } void Creature::removeInventoryItem(const string& name) { for(auto it = inventory.begin(); it != inventory.end(); it++) { if((*it)->getName() == name) { inventory.erase(it); break; } } } map Creature::getSkills() const { map s; for(auto skill : skills) { s[skill.first] = getSkillBonus(skill.first); } return s; } map Creature::getSaves() const { map s; for(auto save : saves) { s[save] = this->getBonus(save) + getProficiency(); } return s; } const int getAC(const Creature& c) { int baseBonus = 10 + c.getBonus("dex"); int miscBonus = 0; for(auto a : getItems(c)) { if(c.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 += c.getBonus("dex"); } else if(armorType == "medium") { baseBonus += (c.getBonus("dex") > 2)? 2 : c.getBonus("dex"); } } } return baseBonus + miscBonus; } }