aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYour Name <you@example.com>2021-05-19 18:00:16 -0400
committerYour Name <you@example.com>2021-05-19 18:00:16 -0400
commitbe88609c825e18201f240415fe74a31c1a789484 (patch)
tree8b051262fcd9e1388ba45f14369112d3d9fb0d52 /src
parent38e33d8756a5b652965be8ada478b5c4238b857c (diff)
downloaddmtool-be88609c825e18201f240415fe74a31c1a789484.tar.gz
dmtool-be88609c825e18201f240415fe74a31c1a789484.tar.bz2
dmtool-be88609c825e18201f240415fe74a31c1a789484.zip
Added git command; refactoring
Diffstat (limited to 'src')
-rw-r--r--src/cmd.h1
-rw-r--r--src/cmd_manipulate.cc6
-rw-r--r--src/cmd_usage.cc2
-rw-r--r--src/creature.cc211
-rw-r--r--src/creature.h78
-rw-r--r--src/defines.h9
-rw-r--r--src/dmtool.cc2
7 files changed, 180 insertions, 129 deletions
diff --git a/src/cmd.h b/src/cmd.h
index 69c258b..b5d3d72 100644
--- a/src/cmd.h
+++ b/src/cmd.h
@@ -25,6 +25,7 @@ namespace cmd {
std::string del(std::vector<std::string> args);
std::string edit(std::vector<std::string> args);
std::string spellcasting(std::vector<std::string> args);
+ std::string git(std::vector<std::string> args);
//Queries
std::string attacks(std::vector<std::string> args);
diff --git a/src/cmd_manipulate.cc b/src/cmd_manipulate.cc
index 9fc019e..2dff5e1 100644
--- a/src/cmd_manipulate.cc
+++ b/src/cmd_manipulate.cc
@@ -246,4 +246,10 @@ namespace cmd {
utils::saveJson(*c, p);
return text.str();
}
+
+ std::string git(std::vector<std::string> args) {
+ std::string root = getTruePath("").string();
+ std::system(("cd " + root + " && " + utils::join(args, " ")).c_str());
+ return "";
+ }
}
diff --git a/src/cmd_usage.cc b/src/cmd_usage.cc
index 53e9d01..6219996 100644
--- a/src/cmd_usage.cc
+++ b/src/cmd_usage.cc
@@ -45,6 +45,8 @@ namespace cmd {
text << indDesc << " init; adds spellcasting to a creature which currently does not have spellcasting" << std::endl;
text << indDesc << " ability value; sets the spellcasting ability, where value is the ability name" << std::endl;
text << indDesc << " level l slots; sets the number of slots at spell level l to slots" << std::endl;
+ text << indOpt << "git [command]" << std::endl;
+ text << indDesc << "Execute a git command within the dmtool folder." << std::endl;
text << indOpt << "help" << std::endl;
text << indDesc << "Show this help." << std::endl;
return text.str();
diff --git a/src/creature.cc b/src/creature.cc
index 7060c10..5130362 100644
--- a/src/creature.cc
+++ b/src/creature.cc
@@ -10,23 +10,80 @@
#include <iostream>
#include <sstream>
#include <iomanip>
-
-using namespace std;
+#include <cmath>
namespace creature {
+
+ struct creatureImpl {
+ std::string givenName;
+ int hpMax;
+ int hp;
+ std::vector<std::shared_ptr<entry::Item>> inventory;
+ std::map<rules::Ability, int> stats;
+ std::map<rules::Skill, int> skills;
+ int prof;
+ std::string size;
+ std::string alignment;
+ int hit_die_count;
+ int hit_die_sides;
+ std::string speed;
+ std::vector<rules::Ability> saves;
+ std::vector<std::string> senses;
+ std::string langs;
+ double cr;
+ bool observant;
+ NatArmor natural_armor;
+ std::vector<dmgType> d_immunities;
+ std::vector<dmgType> d_resistances;
+ std::vector<dmgType> d_vulnerabilities;
+ std::vector<dmgType> c_immunities;
+ std::vector<std::shared_ptr<entry::Feature>> features;
+ };
+ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(creatureImpl, givenName, hpMax, hp, inventory, stats, skills, prof, size, alignment, hit_die_count, hit_die_sides, speed, saves, senses, langs, cr, observant, natural_armor, d_immunities, d_resistances, d_vulnerabilities, c_immunities, features);
+
+ NLOHMANN_FRIEND_DEFS(entry::Entry, Creature, data);
+
+ Creature::Creature() : data(new creatureImpl()) {}
+
+ // Pile of (simple) getters
+ std::string Creature::getCreatureName(void) const {return getName();}
+ std::string Creature::getGivenName(void) const {return data->givenName;}
+ std::string Creature::getSize(void) const {return data->size;}
+ std::string Creature::getAlignment(void) const {return data->alignment;}
+ double Creature::getCR(void) const {return data->cr;}
+ NatArmor Creature::getNaturalArmor(void) const {return data->natural_armor;}
+ std::string Creature::getLanguages(void) const {return data->langs;}
+ int Creature::getHP(void) const {return data->hp;}
+ int Creature::getHPMax(void) const {return data->hpMax;}
+ std::vector<std::string> Creature::getSenses(void) const {return data->senses;}
+ std::string Creature::getSpeed(void) const {return data->speed;}
+ int Creature::getScore(const rules::Ability& ability) const {return data->stats.at(ability);}
+ int Creature::getBonus(const rules::Ability& ability) const {return std::floor((getScore(ability) - 10) / 2.0);}
+ int Creature::getProficiency(void) const {return data->prof;}
+ std::vector<std::shared_ptr<entry::Feature>> Creature::getFeatures(void) const {return data->features;}
+ std::vector<std::shared_ptr<entry::Item>> Creature::getInventory(void) const {return data->inventory;}
+ std::vector<dmgType> Creature::getDmgImmunities(void) const {return data->d_immunities;}
+ std::vector<dmgType> Creature::getDmgResistances(void) const {return data->d_resistances;}
+ std::vector<dmgType> Creature::getDmgVulnerabilities(void) const {return data->d_vulnerabilities;}
+ std::vector<dmgType> Creature::getCondImmunities(void) const {return data->c_immunities;}
+
+ // Simple setters
+ void Creature::setGivenName(const std::string& name) {data->givenName = name;}
+ void Creature::setProficiency(int p) {data->prof = p;}
+
void Creature::init() {
- if(hpMax == -1) {
+ if(data->hpMax == -1) {
// Initialize hp
- hpMax = getBonus(rules::Ability::Con()) * hit_die_count;
- for(int i = 0; i < hit_die_count; i++) {
- hpMax += dice::roll(hit_die_sides);
+ data->hpMax = getBonus(rules::Ability::Con()) * data->hit_die_count;
+ for(int i = 0; i < data->hit_die_count; i++) {
+ data->hpMax += dice::roll(data->hit_die_sides);
}
- hp = hpMax;
+ data->hp = data->hpMax;
}
}
// True if type without matching qualifiers is in subdata
- bool conditionApplies(const string& type, const vector<rules::Qualifier>& qualifiers, const vector<dmgType> subdata) {
+ bool conditionApplies(const std::string& type, const std::vector<rules::Qualifier>& qualifiers, const std::vector<dmgType> subdata) {
bool applies = false;
for(dmgType con : subdata) {
if(con.type == type) {
@@ -41,66 +98,66 @@ namespace creature {
return applies;
}
- void Creature::applyDamage(int amount, const string& type, const vector<rules::Qualifier>& qualifiers) {
+ void Creature::applyDamage(int amount, const std::string& type, const std::vector<rules::Qualifier>& qualifiers) {
if(! conditionApplies(type, qualifiers, getDmgImmunities())) {
if(conditionApplies(type, qualifiers, getDmgResistances())) {
- hp -= amount / 2;
+ data->hp -= amount / 2;
} else if(conditionApplies(type, qualifiers, getDmgVulnerabilities())) {
- hp -= amount * 2;
+ data->hp -= amount * 2;
} else {
- hp -= amount;
+ data->hp -= amount;
}
}
}
void Creature::applyHealing(int amount) {
- hp += amount;
- if(hp > hpMax) {
- hp = hpMax;
+ data->hp += amount;
+ if(data->hp > data->hpMax) {
+ data->hp = data->hpMax;
}
}
int Creature::getSkillBonus(const rules::Skill& skill) const {
int bonus = this->getBonus(skill.getAbility());
- if(skills.contains(skill)) {
- bonus += skills.at(skill) * getProficiency();
+ if(data->skills.contains(skill)) {
+ bonus += data->skills.at(skill) * getProficiency();
}
return bonus;
}
int Creature::getAbilitySaveBonus(const rules::Ability& ability) const {
int bonus = this->getBonus(ability);
- if(find(saves.begin(), saves.end(), ability) != saves.end()) {
+ if(find(data->saves.begin(), data->saves.end(), ability) != data->saves.end()) {
bonus += getProficiency();
}
return bonus;
}
- void Creature::addInventoryItem(shared_ptr<entry::Item> item) {
- inventory.push_back(item);
+ void Creature::addInventoryItem(std::shared_ptr<entry::Item> item) {
+ data->inventory.push_back(item);
}
void Creature::addSpellcasting() {
if(getSpellcasting()) {
- throw runtime_error("Creature " + getName() + " already has spellcasting");
+ throw std::runtime_error("Creature " + getName() + " already has spellcasting");
}
std::shared_ptr<entry::Feature> sc(new entry::Spellcasting());
- features.push_back(sc);
+ data->features.push_back(sc);
}
- shared_ptr<entry::Spellcasting> Creature::getSpellcasting() const {
+ std::shared_ptr<entry::Spellcasting> Creature::getSpellcasting() const {
for(auto f : getFeatures()) {
if(f->getType() == "spells") {
return dynamic_pointer_cast<entry::Spellcasting>(f);
}
}
- return shared_ptr<entry::Spellcasting>();
+ return std::shared_ptr<entry::Spellcasting>();
}
- void Creature::addSpell(shared_ptr<entry::Spell> spell) {
+ void Creature::addSpell(std::shared_ptr<entry::Spell> spell) {
auto sc = getSpellcasting();
if(! sc) {
- throw runtime_error("Creature " + getName() + " has no spellcasting");
+ throw std::runtime_error("Creature " + getName() + " has no spellcasting");
}
std::size_t level = spell->getLevel();
while(sc->getSlotLevels().size() <= level) {
@@ -109,7 +166,7 @@ namespace creature {
sc->getSlotLevels()[level]->spells.push_back(spell);
}
- void Creature::removeSpell(shared_ptr<entry::Spell> spell) {
+ void Creature::removeSpell(std::shared_ptr<entry::Spell> spell) {
auto sc = getSpellcasting();
if(sc) {
if(sc->getSlotLevels().size() > (size_t) spell->getLevel()) {
@@ -124,26 +181,26 @@ namespace creature {
}
}
- void Creature::removeInventoryItem(shared_ptr<entry::Item> item) {
- for(auto it = inventory.begin(); it != inventory.end(); it++) {
+ void Creature::removeInventoryItem(std::shared_ptr<entry::Item> item) {
+ for(auto it = data->inventory.begin(); it != data->inventory.end(); it++) {
if(*it == item) {
- inventory.erase(it);
+ data->inventory.erase(it);
break;
}
}
}
- map<rules::Skill, int> Creature::getSkills() const {
- map<rules::Skill, int> s;
- for(auto skill : skills) {
+ std::map<rules::Skill, int> Creature::getSkills() const {
+ std::map<rules::Skill, int> s;
+ for(auto skill : data->skills) {
s.insert({skill.first, getSkillBonus(skill.first)});
}
return s;
}
- map<rules::Ability, int> Creature::getSaves() const {
- map<rules::Ability, int> s;
- for(auto save : saves) {
+ std::map<rules::Ability, int> Creature::getSaves() const {
+ std::map<rules::Ability, int> s;
+ for(auto save : data->saves) {
s.insert({save, this->getBonus(save) + getProficiency()});
}
return s;
@@ -151,23 +208,23 @@ namespace creature {
void Creature::setScore(const rules::Ability& ability, int score) {
int initBonus = getBonus(ability);
- stats[ability] = score;
+ data->stats[ability] = score;
if(ability == rules::Ability::Con()) {
int delta = getBonus(ability) - initBonus;
- hpMax += delta * hit_die_count;
- hp += delta * hit_die_count;
+ data->hpMax += delta * data->hit_die_count;
+ data->hp += delta * data->hit_die_count;
}
}
void Creature::setProfLevel(const rules::Skill& skill, int level) {
- skills[skill] = level;
+ data->skills[skill] = level;
if(level == 0) {
- skills.erase(skill);
+ data->skills.erase(skill);
}
}
void Creature::longRest() {
- hp = hpMax;
+ data->hp = data->hpMax;
}
const int getAC(const Creature& c) {
@@ -197,10 +254,10 @@ namespace creature {
return baseBonus + miscBonus;
}
- vector<shared_ptr<entry::Weapon>> getAttacks(const Creature& c) {
- vector<shared_ptr<entry::Weapon>> a = utils::castPtrs<entry::Item, entry::Weapon>(c.getInventory());
+ std::vector<std::shared_ptr<entry::Weapon>> getAttacks(const Creature& c) {
+ std::vector<std::shared_ptr<entry::Weapon>> a = utils::castPtrs<entry::Item, entry::Weapon>(c.getInventory());
for(auto attack : utils::castPtrs<entry::Feature, entry::Attack>(c.getFeatures())) {
- a.push_back(shared_ptr<entry::Weapon>(new entry::Weapon(attack->getWeapon())));
+ a.push_back(std::shared_ptr<entry::Weapon>(new entry::Weapon(attack->getWeapon())));
}
return a;
}
@@ -215,97 +272,97 @@ namespace creature {
return *bestA;
}
- template<typename T> vector<string> mapItems(const vector<shared_ptr<T>>& items) {
- vector<string> out;
+ template<typename T> std::vector<std::string> mapItems(const std::vector<std::shared_ptr<T>>& items) {
+ std::vector<std::string> out;
for(auto i : items) {
out.push_back(i->getName());
}
return out;
}
- vector<string> dmgTypes2text(vector<dmgType> dmg) {
- vector<string> ret;
+ std::vector<std::string> dmgTypes2text(std::vector<dmgType> dmg) {
+ std::vector<std::string> ret;
for(dmgType t : dmg) {
ret.push_back(t.getText());
}
return ret;
}
- string formatDmgTypeVector(string title, vector<dmgType> dmg) {
+ std::string formatDmgTypeVector(std::string title, std::vector<dmgType> dmg) {
return title + ": " + utils::join(dmgTypes2text(dmg), "; ");
}
- string Creature::getText() const {
- stringstream text;
+ std::string Creature::getText() const {
+ std::stringstream text;
text << getGivenName() << " (" << getCreatureName() << "): " << getHP() << "/" << getHPMax() << " hp, " << getAC(*this) << " ac";
if(! getNaturalArmor().name.empty()) {
text << " (" << getNaturalArmor().name << ")";
} else {
- string armor = utils::join(mapItems(utils::castPtrs<entry::Item, entry::Armor>(getInventory())), ", ");
+ std::string armor = utils::join(mapItems(utils::castPtrs<entry::Item, entry::Armor>(getInventory())), ", ");
if(! armor.empty()) {
text << " (" << armor << ")";
}
}
- text << ", speed " << getSpeed() << endl;
- text << "A cr " << getCR() << " " << getAlignment() << " " << getSize() << " " << getType() << "." << endl;
- text << "Stats:" << endl;
+ text << ", speed " << getSpeed() << std::endl;
+ text << "A cr " << getCR() << " " << getAlignment() << " " << getSize() << " " << getType() << "." << std::endl;
+ text << "Stats:" << std::endl;
using namespace rules;
- vector<rules::Ability> abilities {Ability::Str(), Ability::Dex(), Ability::Con(), Ability::Int(), Ability::Wis(), Ability::Cha()};
+ std::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 << " " << std::setw(6) << std::left << ability.getAbbrev();
}
- text << endl;
+ text << std::endl;
for(auto ability : abilities) {
- text << setw(7) << std::left << (to_string(getScore(ability)) + "(" + to_string(getBonus(ability)) + ")");
+ text << std::setw(7) << std::left << (std::to_string(getScore(ability)) + "(" + std::to_string(getBonus(ability)) + ")");
}
- text << endl;
+ text << std::endl;
text << "Senses: ";
if(! getSenses().empty()) {
text << utils::join(getSenses(), ", ") << ". ";
}
- text << "Passive Perception " << 10 + getSkillBonus(rules::Skill::Perception()) << endl;
+ text << "Passive Perception " << 10 + getSkillBonus(rules::Skill::Perception()) << std::endl;
if(! getLanguages().empty()) {
- text << "Languages: " << getLanguages() << endl;
+ text << "Languages: " << getLanguages() << std::endl;
}
- text << "Proficiency: " << getProficiency() << endl;
+ text << "Proficiency: " << getProficiency() << std::endl;
if(! getSkills().empty()) {
- text << endl << "Skills:" << endl;
+ text << std::endl << "Skills:" << std::endl;
for(auto skill : getSkills()) {
- text << " * " << skill.first.getName() << " (+" << skill.second << ")" << endl;
+ text << " * " << skill.first.getName() << " (+" << skill.second << ")" << std::endl;
}
}
if(! getSaves().empty()) {
- text << endl << "Saves:" << endl;
+ text << std::endl << "Saves:" << std::endl;
for(auto save : getSaves()) {
- text << " * " << save.first.getAbbrev() << " (+" << save.second << ")" << endl;
+ text << " * " << save.first.getAbbrev() << " (+" << save.second << ")" << std::endl;
}
}
if(! getDmgImmunities().empty()) {
- text << formatDmgTypeVector("\nDamage Immunities", getDmgImmunities()) << endl;
+ text << formatDmgTypeVector("\nDamage Immunities", getDmgImmunities()) << std::endl;
}
if(! getDmgResistances().empty()) {
- text << formatDmgTypeVector("\nDamage Resistances", getDmgResistances()) << endl;
+ text << formatDmgTypeVector("\nDamage Resistances", getDmgResistances()) << std::endl;
}
if(! getDmgVulnerabilities().empty()) {
- text << formatDmgTypeVector("\nDamage Vulnerabilities", getDmgVulnerabilities()) << endl;
+ text << formatDmgTypeVector("\nDamage Vulnerabilities", getDmgVulnerabilities()) << std::endl;
}
if(! getCondImmunities().empty()) {
- text << formatDmgTypeVector("\nCondition Immunities", getCondImmunities()) << endl;
+ text << formatDmgTypeVector("\nCondition Immunities", getCondImmunities()) << std::endl;
}
if(! getFeatures().empty()) {
- text << endl << "Features:" << endl;
+ text << std::endl << "Features:" << std::endl;
for(auto f: getFeatures()) {
- text << " * " << f->getText(*this) << endl;
+ text << " * " << f->getText(*this) << std::endl;
}
}
if(! getInventory().empty()) {
- text << endl << "Inventory:" << endl;
+ text << std::endl << "Inventory:" << std::endl;
for(auto i : getInventory()) {
- text << " * " << i->getText(*this) << endl;
+ text << " * " << i->getText(*this) << std::endl;
}
}
if(! Entry::getText().empty()) {
- text << endl << Entry::getText() << endl;
+ text << std::endl << Entry::getText() << std::endl;
}
return text.str();
diff --git a/src/creature.h b/src/creature.h
index b2a01e6..c343482 100644
--- a/src/creature.h
+++ b/src/creature.h
@@ -4,7 +4,6 @@
#include "entry.h"
#include "feature.h"
#include "item.h"
-#include <cmath>
#include <nlohmann/json.hpp>
namespace entry {
@@ -16,6 +15,7 @@ namespace entry {
namespace creature {
class Creature;
+ struct creatureImpl;
struct dmgType {
std::string type;
@@ -40,6 +40,7 @@ namespace creature {
class Creature : public entry::Entry {
public:
+ Creature();
virtual ~Creature() {}
virtual void init() override;
@@ -49,41 +50,37 @@ namespace creature {
int getAbilitySaveBonus(const rules::Ability& ability) const;
std::map<rules::Skill, int> getSkills(void) const;
std::map<rules::Ability, int> getSaves(void) const;
-
//Override getText
virtual std::string getText() const override;
-
- // Inline getters
- std::string getCreatureName(void) const {return getName();}
- std::string getGivenName(void) const {return givenName;}
- std::string getSize(void) const {return size;}
- std::string getAlignment(void) const {return alignment;}
- double getCR(void) const {return cr;}
- NatArmor getNaturalArmor(void) const {return natural_armor;}
- 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 rules::Ability& ability) const {return stats.at(ability);}
- int getBonus(const rules::Ability& ability) const {return std::floor((getScore(ability) - 10) / 2.0);}
- int getProficiency(void) const {return prof;}
- std::vector<std::shared_ptr<entry::Feature>> getFeatures(void) const {return features;}
+ std::string getCreatureName(void) const;
+ std::string getGivenName(void) const;
+ std::string getSize(void) const;
+ std::string getAlignment(void) const;
+ double getCR(void) const;
+ NatArmor getNaturalArmor(void) const;
+ std::string getLanguages(void) const;
+ int getHP(void) const;
+ int getHPMax(void) const;
+ std::vector<std::string> getSenses(void) const;
+ std::string getSpeed(void) const;
+ int getScore(const rules::Ability& ability) const;
+ int getBonus(const rules::Ability& ability) const;
+ int getProficiency(void) const;
+ std::vector<std::shared_ptr<entry::Feature>> getFeatures(void) const;
std::shared_ptr<entry::Spellcasting> getSpellcasting(void) const;
- std::vector<std::shared_ptr<entry::Item>> getInventory(void) const {return inventory;}
- std::vector<dmgType> getDmgImmunities(void) const {return d_immunities;}
- std::vector<dmgType> getDmgResistances(void) const {return d_resistances;}
- std::vector<dmgType> getDmgVulnerabilities(void) const {return d_vulnerabilities;}
- std::vector<dmgType> getCondImmunities(void) const {return c_immunities;}
-
+ std::vector<std::shared_ptr<entry::Item>> getInventory(void) const;
+ std::vector<dmgType> getDmgImmunities(void) const;
+ std::vector<dmgType> getDmgResistances(void) const;
+ std::vector<dmgType> getDmgVulnerabilities(void) const;
+ std::vector<dmgType> getCondImmunities(void) const;
// Setters (mutators)
- void setGivenName(std::string name) {givenName = name;}
+ void setGivenName(const std::string& name);
void applyDamage(int amount, const std::string& type, const std::vector<rules::Qualifier>& qualifiers);
void applyHealing(int amount);
void setScore(const rules::Ability& ability, int score);
void setProfLevel(const rules::Skill& skill, int level);
- void setProficiency(int p) {prof = p;}
+ void setProficiency(int p);
void addInventoryItem(std::shared_ptr<entry::Item> item);
void addSpellcasting(void);
void addSpell(std::shared_ptr<entry::Spell> spell);
@@ -91,33 +88,10 @@ namespace creature {
void removeInventoryItem(std::shared_ptr<entry::Item> item);
void longRest(void);
- NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Entry, Creature, givenName, hpMax, hp, inventory, stats, skills, prof, size, alignment, hit_die_count, hit_die_sides, speed, saves, senses, langs, cr, observant, natural_armor, d_immunities, d_resistances, d_vulnerabilities, c_immunities, features);
+ NLOHMANN_FRIEND_DECLARES(Creature);
private:
- std::string givenName;
- int hpMax;
- int hp;
- std::vector<std::shared_ptr<entry::Item>> inventory;
- std::map<rules::Ability, int> stats;
- std::map<rules::Skill, int> skills;
- int prof;
- std::string size;
- std::string alignment;
- int hit_die_count;
- int hit_die_sides;
- std::string speed;
- std::vector<rules::Ability> saves;
- std::vector<std::string> senses;
- std::string langs;
- double cr;
- bool observant;
- NatArmor natural_armor;
- std::vector<dmgType> d_immunities;
- std::vector<dmgType> d_resistances;
- std::vector<dmgType> d_vulnerabilities;
- std::vector<dmgType> c_immunities;
- std::vector<std::shared_ptr<entry::Feature>> features;
-
+ std::shared_ptr<creatureImpl> data;
};
// Helper function to get all attacks (weapons and pseudo-weapons included)
diff --git a/src/defines.h b/src/defines.h
index 587656a..78ab770 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -2,3 +2,12 @@
friend void to_json(nlohmann::json& nlohmann_json_j, const Derived& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<Super>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Derived& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<Super&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } \
virtual nlohmann::json serialize(void) const override { nlohmann::json ret; to_json(ret, *this); return ret; }
+
+#define NLOHMANN_FRIEND_DECLARES(Type) \
+ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t); \
+ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t); \
+ virtual nlohmann::json serialize(void) const override { nlohmann::json ret; to_json(ret, *this); return ret; }
+
+#define NLOHMANN_FRIEND_DEFS(Super, Derived, PImpl) \
+ void to_json(nlohmann::json& nlohmann_json_j, const Derived& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<Super>(nlohmann_json_t)); nlohmann::to_json(nlohmann_json_j, *nlohmann_json_t.PImpl); } \
+ void from_json(const nlohmann::json& nlohmann_json_j, Derived& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<Super&>(nlohmann_json_t)); nlohmann::from_json(nlohmann_json_j, *nlohmann_json_t.PImpl); }
diff --git a/src/dmtool.cc b/src/dmtool.cc
index f4fe19c..90f7813 100644
--- a/src/dmtool.cc
+++ b/src/dmtool.cc
@@ -46,6 +46,7 @@ int main(int argc, char *argv[]) {
try {
std::string exename = argv[0];
std::vector<std::string> args(&argv[1], &argv[argc]);
+ auto argsWithFlags = args;
std::vector<std::string> flags = extractFlags(args);
cmd::mkdir({cmd::getTruePath("")});
if(args.empty()) {
@@ -71,6 +72,7 @@ int main(int argc, char *argv[]) {
else if(cmd == "del") std::cout << cmd::del(args);
else if(cmd == "edit") std::cout << cmd::edit(args);
else if(cmd == "spellcasting") std::cout << cmd::spellcasting(args);
+ else if(cmd == "git") std::cout << cmd::git(argsWithFlags);
else if(cmd == "help") std::cout << cmd::usage(exename);
else std::cout << cmd::list(argsOrig);
} catch(std::exception& e) {