diff options
Diffstat (limited to 'src/creature.cc')
-rw-r--r-- | src/creature.cc | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/src/creature.cc b/src/creature.cc new file mode 100644 index 0000000..1a1463c --- /dev/null +++ b/src/creature.cc @@ -0,0 +1,256 @@ +#include "creature.h" +#include "json.hpp" +#include "dice.h" +#include "rules.h" +#include "feature.h" +#include "weapon.h" +#include "armor.h" +#include <algorithm> +#include <iostream> + +typedef nlohmann::json json; +using namespace std; + +namespace creature { + vector<dmgType> initDmgType(const json& dat) { + vector<dmgType> stuff; + for(json x : dat) { + stuff.push_back(dmgType(x)); + } + return stuff; + } + + Creature::Creature(json data) + : 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(initDmgType(data["d_immunities"])), dmgResistances(initDmgType(data["d_resistances"])), dmgVulnerabilities(initDmgType(data["d_vulnerabilities"])), condImmunities(initDmgType(data["c_immunities"])) + { + cout << "Initialized this far...\n\n"; + // Initialize features + inventory + for(json data : data["features"]) { + features.push_back(feature::Feature::create(data)); + } + for(json data : data["inventory"]) { + inventory.push_back(item::Item::create(data)); + } + // Initialize names and hp + if(((map<string, json>) 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<typename T> vector<json> getJsonVectP(vector<T> src) { + vector<json> ret; + for(T i : src) { + ret.push_back(i->toJson()); + } + return ret; + } + + template<typename T> vector<json> getJsonVectR(vector<T> src) { + vector<json> 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", getJsonVectR(dmgImmunities)}, + {"d_resistances", getJsonVectR(dmgResistances)}, + {"d_vulnerabilities", getJsonVectR(dmgVulnerabilities)}, + {"c_immunities", getJsonVectR(condImmunities)}, + {"givenName", givenName}, + {"hpMax", hpMax}, + {"hp", hp}, + {"inventory", getJsonVectP(inventory)}, + {"features", getJsonVectP(features)} + }); + } + + Creature::~Creature() {} + + string Creature::getCreatureName() const { + return creatureName; + } + + string Creature::getGivenName() const { + return givenName; + } + + void Creature::setGivenName(string name) { + givenName = name; + } + + string Creature::getType() const { + return type; + } + + string Creature::getSize() const { + return size; + } + + string Creature::getAlignment() const { + return alignment; + } + + double Creature::getCR() const { + return cr; + } + + string Creature::getLanguages() const { + return langs; + } + + int Creature::getHP() const { + return hp; + } + + int Creature::getHPMax() const { + return hpMax; + } + + // True if type without matching qualifiers is in subdata + bool conditionApplies(const string& type, const vector<string>& qualifiers, const vector<dmgType> 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<string>& 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; + } + } + } + + vector<string> Creature::getSenses() const { + return senses; + } + + 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::getScore(const string& ability) const { + return stats.at(ability); + } + + void Creature::setScore(const string& ability, int score) { + stats[ability] = score; + } + + string Creature::getSpeed() const { + return speed; + } + + 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; + } + + int Creature::getProficiency() const { + return proficiency; + } + + vector<shared_ptr<feature::Feature>> Creature::getFeatures() const { + return features; + } + + vector<shared_ptr<item::Item>> Creature::getInventory() const { + return inventory; + } + + void Creature::addInventoryItem(shared_ptr<item::Item> 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<string, int> Creature::getSkills() const { + map<string, int> s; + for(auto skill : skills) { + s[skill.first] = getSkillBonus(skill.first); + } + return s; + } + + map<string, int> Creature::getSaves() const { + map<string, int> 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<item::Armor>(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; + } +} |