aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYour Name <you@example.com>2021-04-20 12:40:37 -0400
committerYour Name <you@example.com>2021-04-20 12:40:37 -0400
commitcd57ad6e208728bafcbc8c7d7b85d88603706978 (patch)
tree7cb0fc9511a0e8124e497d53edbe38d646dd8299 /src
parent2cae1aa33f80ce0844fb54a84ce103146a7fe7ad (diff)
downloaddmtool-cd57ad6e208728bafcbc8c7d7b85d88603706978.tar.gz
dmtool-cd57ad6e208728bafcbc8c7d7b85d88603706978.tar.bz2
dmtool-cd57ad6e208728bafcbc8c7d7b85d88603706978.zip
Updated natural armor and skills
Diffstat (limited to 'src')
-rw-r--r--src/armor.cc6
-rw-r--r--src/creature.cc108
-rw-r--r--src/creature.h26
-rw-r--r--src/dmtool.cc27
-rw-r--r--src/feature.h5
-rw-r--r--src/item.h4
-rw-r--r--src/jsonable.h1
-rw-r--r--src/rules.h137
-rw-r--r--src/spellcasting.cc2
-rw-r--r--src/spellcasting.h7
-rw-r--r--src/weapon.cc5
11 files changed, 214 insertions, 114 deletions
diff --git a/src/armor.cc b/src/armor.cc
index e7ed323..54284c7 100644
--- a/src/armor.cc
+++ b/src/armor.cc
@@ -1,6 +1,7 @@
#include "armor.h"
#include "creature.h"
#include "entry.h"
+#include "rules.h"
#include <string>
#include <sstream>
@@ -16,10 +17,11 @@ namespace entry{
text << genText(static_cast<const Item&>(a), c);
text << ": AC: " << a.getACBonus();
if(a.getArmorType() == "light") {
- text << " + dex (i.e., " << (a.getACBonus() + c.getBonus("dex")) << ")";
+ text << " + dex (i.e., " << (a.getACBonus() + c.getBonus(rules::Ability::Dex())) << ")";
} else if(a.getArmorType() == "medium") {
int actualBonus = a.getACBonus();
- actualBonus += (c.getBonus("dex") > 2)? 2 : c.getBonus("dex");
+ int dex = c.getBonus(rules::Ability::Dex());
+ actualBonus += (dex > 2)? 2 : dex;
text << " + dex max 2 (i.e., " << actualBonus << ")";
}
if(a.getStrRequirement() > 0) {
diff --git a/src/creature.cc b/src/creature.cc
index 53a4994..ac616ac 100644
--- a/src/creature.cc
+++ b/src/creature.cc
@@ -14,9 +14,20 @@ typedef nlohmann::json json;
using namespace std;
namespace creature {
+ template<typename T> map<T, int> makeMap(map<string, int> src) {
+ //cout << "Got here!\n";
+ map<T, int> ret;
+ for(auto& [abilityStr, val] : src) {
+ ret.insert({T(abilityStr), val});
+ }
+ //cout << "And here!\n";
+ return ret;
+ }
+
Creature::Creature(const json& data)
- : inventory(json2ptrvec<entry::Item>(data["inventory"])), stats(data["stats"]), skills(data["skills"]), 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"]), saves(data["saves"]), langs(data["langs"]), cr(data["cr"]), proficiency(data["prof"]), dmgImmunities(json2vec<dmgType>(data["d_immunities"])), dmgResistances(json2vec<dmgType>(data["d_resistances"])), dmgVulnerabilities(json2vec<dmgType>(data["d_vulnerabilities"])), condImmunities(json2vec<dmgType>(data["c_immunities"])), features(json2ptrvec<entry::Feature>(data["features"]))
+ : inventory(json2ptrvec<entry::Item>(data["inventory"])), stats(makeMap<rules::Ability>(data["stats"])), skills(makeMap<rules::Skill>(data["skills"])), 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"]), saves(json2vec<rules::Ability>(data["saves"])), langs(data["langs"]), cr(data["cr"]), proficiency(data["prof"]), natArmorName(data["natural_armor"]["name"]), natArmorBonus(data["natural_armor"]["bonus"]), dmgImmunities(json2vec<dmgType>(data["d_immunities"])), dmgResistances(json2vec<dmgType>(data["d_resistances"])), dmgVulnerabilities(json2vec<dmgType>(data["d_vulnerabilities"])), condImmunities(json2vec<dmgType>(data["c_immunities"])), features(json2ptrvec<entry::Feature>(data["features"]))
{
+ //cout << "...And here!\n";
// Initialize names and hp
if(((map<string, json>) data).contains("givenName")) {
givenName = data["givenName"];
@@ -24,7 +35,7 @@ namespace creature {
hp = data["hp"];
} else {
givenName = "Jerry"; //TODO: Autogenerate
- hpMax = this->getBonus("con") * hdCount;
+ hpMax = this->getBonus(rules::Ability::Con()) * hdCount;
for(int i = 0; i < hdCount; i++) {
hpMax += roll(hdSides);
}
@@ -95,15 +106,15 @@ namespace creature {
}
}
- int Creature::getSkillBonus(const string& skill) const {
- int bonus = this->getBonus(rules::skill2ability[skill]);
+ int Creature::getSkillBonus(const rules::Skill& skill) const {
+ int bonus = this->getBonus(skill.getAbility());
if(skills.contains(skill)) {
bonus += skills.at(skill) * getProficiency();
}
return bonus;
}
- int Creature::getAbilitySaveBonus(const string& ability) const {
+ int Creature::getAbilitySaveBonus(const rules::Ability& ability) const {
int bonus = this->getBonus(ability);
if(find(saves.begin(), saves.end(), ability) != saves.end()) {
bonus += getProficiency();
@@ -124,35 +135,40 @@ namespace creature {
}
}
- map<string, int> Creature::getSkills() const {
- map<string, int> s;
+ map<rules::Skill, int> Creature::getSkills() const {
+ map<rules::Skill, int> s;
for(auto skill : skills) {
- s[skill.first] = getSkillBonus(skill.first);
+ s.insert({skill.first, getSkillBonus(skill.first)});
}
return s;
}
- map<string, int> Creature::getSaves() const {
- map<string, int> s;
+ map<rules::Ability, int> Creature::getSaves() const {
+ map<rules::Ability, int> s;
for(auto save : saves) {
- s[save] = this->getBonus(save) + getProficiency();
+ s.insert({save, this->getBonus(save) + getProficiency()});
}
return s;
}
- void Creature::setScore(const string& ability, int score) {
- stats[ability] = score;
+ void Creature::setScore(const rules::Ability& ability, int score) {
+ stats.insert({ability, score});
}
- void Creature::setProfLevel(const string& skill, int level) {
- skills[skill] = level;
+ void Creature::setProfLevel(const rules::Skill& skill, int level) {
+ skills.insert({skill, level});
}
const int getAC(const Creature& c) {
- int baseBonus = 10 + c.getBonus("dex");
+ auto natArmor = c.getNaturalArmor();
+ if(! natArmor.first.empty()) {
+ return natArmor.second;
+ }
+ int dex = c.getBonus(rules::Ability::Dex());
+ int baseBonus = 10 + dex;
int miscBonus = 0;
for(auto a : getItems<entry::Armor>(c)) {
- if(c.getScore("str") < a->getStrRequirement()) {
+ if(c.getScore(rules::Ability::Str()) < a->getStrRequirement()) {
continue;
}
auto armorType = a->getArmorType();
@@ -161,9 +177,9 @@ namespace creature {
} else {
baseBonus = a->getACBonus();
if(armorType == "light") {
- baseBonus += c.getBonus("dex");
+ baseBonus += dex;
} else if(armorType == "medium") {
- baseBonus += (c.getBonus("dex") > 2)? 2 : c.getBonus("dex");
+ baseBonus += (dex > 2)? 2 : dex;
}
}
}
@@ -181,19 +197,24 @@ namespace creature {
string genText(const Creature& c) {
stringstream text;
text << c.getGivenName() << " (" << c.getCreatureName() << "): " << c.getHP() << "/" << c.getHPMax() << " hp, " << getAC(c) << " ac";
- string armor = utils::join(mapItems(creature::getItems<entry::Armor>(c)), ", ");
- if(! armor.empty()) {
- text << " (" << armor << ")";
+ if(! c.getNaturalArmor().first.empty()) {
+ text << " (" << c.getNaturalArmor().first << ")";
+ } else {
+ string armor = utils::join(mapItems(creature::getItems<entry::Armor>(c)), ", ");
+ if(! armor.empty()) {
+ text << " (" << armor << ")";
+ }
}
text << ", speed " << c.getSpeed() << "\n";
text << "A cr " << c.getCR() << " " << c.getAlignment() << " " << c.getSize() << " " << c.getType() << ".\n";
text << "Stats:\n";
- //text << setiosflags(ios::fixed) << setw(6);
- for(auto ability : rules::abilities) {
- text << " " << setw(6) << std::left << ability;
+ using namespace rules;
+ vector<rules::Ability> abilities {Ability::Str(), Ability::Dex(), Ability::Con(), Ability::Int(), Ability::Wis(), Ability::Cha()};
+ for(auto ability : abilities) {
+ text << " " << setw(6) << std::left << ability.getAbbrev();
}
text << "\n";
- for(auto ability : rules::abilities) {
+ for(auto ability : abilities) {
text << setw(7) << std::left << (to_string(c.getScore(ability)) + "(" + to_string(c.getBonus(ability)) + ")");
}
text << "\n";
@@ -201,26 +222,33 @@ namespace creature {
if(! c.getSenses().empty()) {
text << utils::join(c.getSenses(), ", ") << ". ";
}
- text << "Passive Perception " << 10 + c.getBonus("wis") << "\n";
+ text << "Passive Perception " << 10 + c.getSkillBonus(rules::Skill::Perception()) << "\n";
if(! c.getLanguages().empty()) {
text << "Languages: " << c.getLanguages() << "\n";
}
-
- text << "\nSkills:\n";
- for(auto skill : c.getSkills()) {
- text << skill.first << " (+" << skill.second << ")\n";
+ if(! c.getSkills().empty()) {
+ text << "\nSkills:\n";
+ for(auto skill : c.getSkills()) {
+ text << skill.first.getName() << " (+" << skill.second << ")\n";
+ }
}
- text << "\nSaves:\n";
- for(auto save : c.getSaves()) {
- text << save.first << " (+" << save.second << ")\n";
+ if(! c.getSaves().empty()) {
+ text << "\nSaves:\n";
+ for(auto save : c.getSaves()) {
+ text << save.first.getAbbrev() << " (+" << save.second << ")\n";
+ }
}
- text << "\nFeatures:\n";
- for(auto f: c.getFeatures()) {
- text << f->getText(c) << "\n";
+ if(! c.getFeatures().empty()) {
+ text << "\nFeatures:\n";
+ for(auto f: c.getFeatures()) {
+ text << f->getText(c) << "\n";
+ }
}
- text << "\nInventory:\n";
- for(auto i : c.getInventory()) {
- text << i->getText(c) << "\n";
+ if(! c.getInventory().empty()) {
+ text << "\nInventory:\n";
+ for(auto i : c.getInventory()) {
+ text << i->getText(c) << "\n";
+ }
}
return text.str();
diff --git a/src/creature.h b/src/creature.h
index 7327de9..1c8db21 100644
--- a/src/creature.h
+++ b/src/creature.h
@@ -1,6 +1,7 @@
#pragma once
#include "json.hpp"
#include "jsonable.h"
+#include "rules.h"
namespace entry {
class Feature;
@@ -34,10 +35,10 @@ namespace creature {
virtual ~Creature() {};
// Getters
- int getSkillBonus(const std::string& skill) const;
- int getAbilitySaveBonus(const std::string& ability) const;
- std::map<std::string, int> getSkills(void) const;
- std::map<std::string, int> getSaves(void) const;
+ int getSkillBonus(const rules::Skill& skill) const;
+ int getAbilitySaveBonus(const rules::Ability& ability) const;
+ std::map<rules::Skill, int> getSkills(void) const;
+ std::map<rules::Ability, int> getSaves(void) const;
// Inline getters
std::string getCreatureName(void) const {return creatureName;}
@@ -46,13 +47,14 @@ namespace creature {
std::string getSize(void) const {return size;}
std::string getAlignment(void) const {return alignment;}
double getCR(void) const {return cr;}
+ std::pair<std::string, int> getNaturalArmor(void) const {return {natArmorName, natArmorBonus};}
std::string getLanguages(void) const {return langs;}
int getHP(void) const {return hp;}
int getHPMax(void) const {return hpMax;}
std::vector<std::string> getSenses(void) const {return senses;}
std::string getSpeed(void) const {return speed;}
- int getScore(const std::string& ability) const {return stats.at(ability);}
- int getBonus(const std::string& ability) const {return (int) (getScore(ability) - 10) / 2;}
+ int getScore(const rules::Ability& ability) const {return stats.at(ability);}
+ int getBonus(const rules::Ability& ability) const {return (int) (getScore(ability) - 10) / 2;}
int getProficiency(void) const {return proficiency;}
std::vector<std::shared_ptr<entry::Feature>> getFeatures(void) const {return features;}
std::vector<std::shared_ptr<entry::Item>> getInventory(void) const {return inventory;}
@@ -61,8 +63,8 @@ namespace creature {
// Setters (mutators)
void setGivenName(std::string name) {givenName = name;}
void applyDamage(int amount, const std::string& type, const std::vector<std::string>& qualifiers);
- void setScore(const std::string& ability, int score);
- void setProfLevel(const std::string& skill, int level);
+ void setScore(const rules::Ability& ability, int score);
+ void setProfLevel(const rules::Skill& skill, int level);
void addInventoryItem(std::shared_ptr<entry::Item> item);
void removeInventoryItem(const std::string& itemName);
@@ -74,8 +76,8 @@ namespace creature {
int hpMax;
int hp;
std::vector<std::shared_ptr<entry::Item>> inventory;
- std::map<std::string, int> stats;
- std::map<std::string, int> skills;
+ std::map<rules::Ability, int> stats;
+ std::map<rules::Skill, int> skills;
//Immutable variables
const std::string creatureName;
@@ -85,11 +87,13 @@ namespace creature {
const int hdCount;
const int hdSides;
const std::string speed;
- const std::vector<std::string> saves;
+ const std::vector<rules::Ability> saves;
const std::vector<std::string> senses;
const std::string langs;
const double cr;
const int proficiency;
+ const std::string natArmorName;
+ const int natArmorBonus;
const std::vector<dmgType> dmgImmunities;
const std::vector<dmgType> dmgResistances;
const std::vector<dmgType> dmgVulnerabilities;
diff --git a/src/dmtool.cc b/src/dmtool.cc
index 7f2c72c..f9d32ab 100644
--- a/src/dmtool.cc
+++ b/src/dmtool.cc
@@ -17,24 +17,34 @@ void usage(string exename) {
cout << indDesc << "List creatures and objects.\n";
cout << indOpt << "cp old-path new-path\n";
cout << indDesc << "Copy old-path to new-path.\n";
+ cout << indOpt << "mv old-path new-path\n";
+ cout << indDesc << "Move old-path to new-path.\n";
cout << indOpt << "rm path\n";
cout << indDesc << "Remove existing creature, object, or directory.\n";
cout << indOpt << "roll path name\n";
cout << indDesc << "Roll a skill check, save, or attack.\n";
cout << indOpt << "damage path amount [type]\n";
cout << indDesc << "Damage creature by amount. Type defaults to \"force\".\n";
+ cout << indOpt << "heal path amount\n";
+ cout << indDesc << "Heal creature by amount.\n";
+ cout << indOpt << "reset path\n";
+ cout << indDesc << "Reset creature to full health (as if completing a long rest).\n";
cout << indOpt << "set path field value\n";
cout << indDesc << "Set a field to a new value, where field is any of:\n";
cout << indDesc << " ability (str, dex, con, int, wis, cha); value is new ability score\n";
cout << indDesc << " skill (athletics, \"sleight of hand\", etc.); value is (none|proficient|expert)\n";
- cout << indDesc << " name; value is new given name\n";
- cout << indOpt << "add path object\n";
- cout << indDesc << "Add object to creature's inventory. If it is armor or a weapon, it will automatically be equipped (if applicable)\n";
-
+ cout << indDesc << " name; value is new given name.\n";
+ cout << indOpt << "add path entry\n";
+ cout << indDesc << "Add entry to creature, where entry is an item or spell.\n";
cout << indOpt << "help\n";
cout << indDesc << "Show this help.\n";
}
+void print(string path) {
+ creature::Creature c(utils::loadJson(path));
+ cout << genText(c);
+}
+
void list(vector<string> args) {
string baseDir = settings::getString("savedir");
vector<string> listPaths;
@@ -48,8 +58,7 @@ void list(vector<string> args) {
for(auto listPath : listPaths) {
if(fs::is_regular_file(fs::status(listPath))) {
// Try loading and printing stuff about it
- creature::Creature c(utils::loadJson(listPath));
- cout << genText(c);
+ print(listPath);
}
else if(fs::is_directory(fs::status(listPath))) {
for(fs::directory_entry path : filesystem::directory_iterator(listPath)) {
@@ -64,9 +73,12 @@ void list(vector<string> args) {
}
void cp(vector<string> args) {}
+void mv(vector<string> args) {}
void rm(vector<string> args) {}
void roll(vector<string> args) {}
void damage(vector<string> args) {}
+void heal(vector<string> args) {}
+void reset(vector<string> args) {}
void set(vector<string> args) {}
void add(vector<string> args) {}
@@ -82,9 +94,12 @@ int main(int argc, char *argv[]) {
args.erase(args.begin());
if(cmd == "ls") list(args);
else if(cmd == "cp") cp(args);
+ else if(cmd == "mv") mv(args);
else if(cmd == "rm") rm(args);
else if(cmd == "roll") roll(args);
else if(cmd == "damage") damage(args);
+ else if(cmd == "heal") heal(args);
+ else if(cmd == "reset") reset(args);
else if(cmd == "set") set(args);
else if(cmd == "add") add(args);
else if(cmd == "help") usage(exename);
diff --git a/src/feature.h b/src/feature.h
index f3073d8..69112ea 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -7,10 +7,9 @@ namespace entry {
class Feature : public Entry {
public:
static std::shared_ptr<Feature> create(const nlohmann::json& data);
+ virtual ~Feature() {}
protected:
- Feature(const nlohmann::json& data) : Entry(data) {};
+ Feature(const nlohmann::json& data) : Entry(data) {}
};
-
- //std::string genText(const Feature& f, const creature::Creature& c);
}
diff --git a/src/item.h b/src/item.h
index 096513e..b0b06af 100644
--- a/src/item.h
+++ b/src/item.h
@@ -7,15 +7,17 @@ namespace entry {
class Item : public Entry {
public:
static std::shared_ptr<Item> create(const nlohmann::json& data);
+ virtual ~Item() {}
protected:
- Item(const nlohmann::json& data) : Entry(data) {};
+ Item(const nlohmann::json& data) : Entry(data) {}
};
class Substantial {
public:
virtual int getCost(void) const = 0;
virtual double getWeight(void) const = 0;
+ virtual ~Substantial() {}
};
std::string genText(const Substantial& s);
diff --git a/src/jsonable.h b/src/jsonable.h
index 4be2bec..d6866b8 100644
--- a/src/jsonable.h
+++ b/src/jsonable.h
@@ -8,6 +8,7 @@ class Jsonable {
public:
virtual nlohmann::json toJson(void) const = 0;
operator nlohmann::json() const {return toJson();}
+ virtual ~Jsonable() {}
};
template<typename T> std::vector<T> json2vec(const nlohmann::json& data) {
diff --git a/src/rules.h b/src/rules.h
index c1cc6e1..8b54e8d 100644
--- a/src/rules.h
+++ b/src/rules.h
@@ -1,57 +1,104 @@
#pragma once
+#include "jsonable.h"
#include <vector>
#include <map>
+#include <string>
+#include <iostream>
using namespace std;
namespace rules {
- static vector<string> abilities {"str", "dex", "con", "int", "wis", "cha"};
-
- static map<string, string> skill2ability {
- {"Athletics", "str"},
- {"Acrobatics", "dex"},
- {"Sleight of Hand", "dex"},
- {"Stealth", "dex"},
- {"Arcana", "int"},
- {"History", "int"},
- {"Investigation", "int"},
- {"Nature", "int"},
- {"Religion", "int"},
- {"Animal Handling", "wis"},
- {"Insight", "wis"},
- {"Medicine", "wis"},
- {"Perception", "wis"},
- {"Survival", "wis"},
- {"Deception", "cha"},
- {"Intimidation", "cha"},
- {"Performance", "cha"},
- {"Persuasion", "cha"}
- };
+ class Ability : public Jsonable {
+ public:
+ string getFull() const {return abilities.at(getAbbrev());}
+ string getAbbrev() const {return abbrev;}
+ virtual nlohmann::json toJson(void) const {
+ return getAbbrev();
+ }
+ bool operator<(const Ability& rhs) const {return getAbbrev() < rhs.getAbbrev();}
+ bool operator==(const Ability& rhs) const {return getAbbrev() == rhs.getAbbrev();}
+
+ Ability() {}
+ explicit Ability(const nlohmann::json& data) : abbrev(data) {}
+
+ virtual ~Ability() {}
- static map<string, map<string, int>> armor {
- {"light", {
- {"padded", 11},
- {"leather", 11},
- {"studded leather", 12}
- }},
- {"medium", {
- {"hide", 12},
- {"chain shirt", 13},
- {"scale mail", 14},
- {"breastplate", 14},
- {"half plate", 15}
- }},
- {"heavy", {
- {"ring mail", 14},
- {"chain mail", 16},
- {"splint", 17},
- {"plate", 18}
- }},
- {"misc", {
- {"shield", 2},
- {"ring of protection", 1}
- }}
+ static Ability Str() {return Ability("str");}
+ static Ability Dex() {return Ability("dex");}
+ static Ability Con() {return Ability("con");}
+ static Ability Int() {return Ability("int");}
+ static Ability Wis() {return Ability("wis");}
+ static Ability Cha() {return Ability("cha");}
+
+ private:
+ const string abbrev;
+
+ const map<string, string> abilities {
+ {"str", "Strength"},
+ {"dex", "Dexterity"},
+ {"con", "Constitution"},
+ {"int", "Intelligence"},
+ {"wis", "Wisdom"},
+ {"cha", "Charisma"}
+ };
};
+ class Skill : public Jsonable {
+ public:
+ string getName() const {return name;}
+ Ability getAbility() const {return Ability(skill2ability.at(getName()));}
+ virtual nlohmann::json toJson(void) const {
+ return getName();
+ }
+ bool operator<(const Skill& rhs) const {return getName() < rhs.getName();}
+ bool operator==(const Skill& rhs) const {return getName() == rhs.getName();}
+
+ virtual ~Skill() {}
+
+ static Skill Athletics() {return Skill("Athletics");}
+ static Skill Acrobatics() {return Skill("Acrobatics");}
+ static Skill SleightOfHand() {return Skill("Sleight of Hand");}
+ static Skill Stealth() {return Skill("Stealth");}
+ static Skill Arcana() {return Skill("Arcana");}
+ static Skill History() {return Skill("History");}
+ static Skill Investigation() {return Skill("Investigation");}
+ static Skill Nature() {return Skill("Nature");}
+ static Skill Religion() {return Skill("Religion");}
+ static Skill AnimalHandling() {return Skill("Animal Handling");}
+ static Skill Insight() {return Skill("Insight");}
+ static Skill Medicine() {return Skill("Medicine");}
+ static Skill Perception() {return Skill("Perception");}
+ static Skill Survival() {return Skill("Survival");}
+ static Skill Deception() {return Skill("Deception");}
+ static Skill Intimidation() {return Skill("Intimidation");}
+ static Skill Performance() {return Skill("Performance");}
+ static Skill Persuasion() {return Skill("Persuasion");}
+
+ explicit Skill(const nlohmann::json& data) : name(data) {}
+
+ private:
+ const string name;
+
+ const map<string, string> skill2ability {
+ {"Athletics", "str"},
+ {"Acrobatics", "dex"},
+ {"Sleight of Hand", "dex"},
+ {"Stealth", "dex"},
+ {"Arcana", "int"},
+ {"History", "int"},
+ {"Investigation", "int"},
+ {"Nature", "int"},
+ {"Religion", "int"},
+ {"Animal Handling", "wis"},
+ {"Insight", "wis"},
+ {"Medicine", "wis"},
+ {"Perception", "wis"},
+ {"Survival", "wis"},
+ {"Deception", "cha"},
+ {"Intimidation", "cha"},
+ {"Performance", "cha"},
+ {"Persuasion", "cha"}
+ };
+ };
}
diff --git a/src/spellcasting.cc b/src/spellcasting.cc
index 62af6de..e36fd5b 100644
--- a/src/spellcasting.cc
+++ b/src/spellcasting.cc
@@ -33,7 +33,7 @@ namespace entry {
string genText(const Spellcasting& s, const creature::Creature& c) {
stringstream text;
text << genText(static_cast<const Feature&>(s), c);
- text << ": Spellcasting ability: " << s.getAbility();
+ text << ": Spellcasting ability: " << s.getAbility().getFull();
text << " (spell save DC " << 8 + c.getBonus(s.getAbility()) + c.getProficiency();
text << ", +" << c.getBonus(s.getAbility()) + c.getProficiency() << " to hit with spell attacks).";
if(s.isInnate()) {
diff --git a/src/spellcasting.h b/src/spellcasting.h
index 0ea235c..654a386 100644
--- a/src/spellcasting.h
+++ b/src/spellcasting.h
@@ -3,6 +3,7 @@
#include "json.hpp"
#include "spell.h"
#include "jsonable.h"
+#include "rules.h"
typedef nlohmann::json json;
@@ -23,11 +24,11 @@ namespace entry {
class Spellcasting : public Feature {
public:
- Spellcasting(const json& data, const json& base) : Feature(base), innate(data["innate"]), ability(data["spellcasting_ability"]), spellsBySlot(json2vec<SlotLevel>(data["levels"])) {}
+ Spellcasting(const json& data, const json& base) : Feature(base), innate(data["innate"]), ability(rules::Ability(data["spellcasting_ability"])), spellsBySlot(json2vec<SlotLevel>(data["levels"])) {}
virtual ~Spellcasting() {}
bool isInnate(void) const {return innate;}
- std::string getAbility(void) const {return ability;}
+ rules::Ability getAbility(void) const {return ability;}
std::vector<SlotLevel> getSpellsBySlot(void) const {return spellsBySlot;}
virtual std::string getText(const creature::Creature& c) const;
@@ -41,7 +42,7 @@ namespace entry {
private:
const bool innate;
- const std::string ability;
+ const rules::Ability ability;
const std::vector<SlotLevel> spellsBySlot;
};
diff --git a/src/weapon.cc b/src/weapon.cc
index 3a42e80..af75736 100644
--- a/src/weapon.cc
+++ b/src/weapon.cc
@@ -1,5 +1,6 @@
#include "weapon.h"
#include "creature.h"
+#include "rules.h"
#include <string>
#include <sstream>
#include <algorithm>
@@ -22,9 +23,9 @@ namespace entry {
stringstream text;
text << genText(static_cast<const Item&>(w), c);
// Determine best ability bonus
- int abilityBonus = c.getBonus("str");
+ int abilityBonus = c.getBonus(rules::Ability::Str());
if(w.getProperties().count("finesse")) {
- abilityBonus = max(abilityBonus, c.getBonus("dex"));
+ abilityBonus = max(abilityBonus, c.getBonus(rules::Ability::Dex()));
}
text << ": +" << abilityBonus + c.getProficiency() << " to hit, ";
if(w.getReach() > 0) {