aboutsummaryrefslogtreecommitdiff
path: root/src/creature.cc
diff options
context:
space:
mode:
authorYour Name <you@example.com>2021-04-13 15:14:34 -0400
committerYour Name <you@example.com>2021-04-13 15:14:34 -0400
commit2ab51e507d620c4479e07ca0ec47d22c8c66bc90 (patch)
tree90906ecb043c01034280c767b83a88eb6df6956f /src/creature.cc
downloaddmtool-2ab51e507d620c4479e07ca0ec47d22c8c66bc90.tar.gz
dmtool-2ab51e507d620c4479e07ca0ec47d22c8c66bc90.tar.bz2
dmtool-2ab51e507d620c4479e07ca0ec47d22c8c66bc90.zip
Initial commit
Diffstat (limited to 'src/creature.cc')
-rw-r--r--src/creature.cc256
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;
+ }
+}