aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYour Name <you@example.com>2021-04-16 11:23:27 -0400
committerYour Name <you@example.com>2021-04-16 11:23:27 -0400
commit4618763c0e3a723bf4bb43c7b9edbce87240e0af (patch)
treea18aa4bf7da05ac02b4e37b199aeeb82da977aea /src
parentdfce4d0398a8bafbb7ad7a31345af181c0269c09 (diff)
downloaddmtool-4618763c0e3a723bf4bb43c7b9edbce87240e0af.tar.gz
dmtool-4618763c0e3a723bf4bb43c7b9edbce87240e0af.tar.bz2
dmtool-4618763c0e3a723bf4bb43c7b9edbce87240e0af.zip
Rebased feature/item on entry
Diffstat (limited to 'src')
-rw-r--r--src/armor.cc34
-rw-r--r--src/armor.h8
-rw-r--r--src/creature.cc6
-rw-r--r--src/creature.h14
-rw-r--r--src/entry.cc15
-rw-r--r--src/entry.h39
-rw-r--r--src/feature.cc2
-rw-r--r--src/feature.h29
-rw-r--r--src/item.cc11
-rw-r--r--src/item.h33
-rw-r--r--src/spellcasting.cc68
-rw-r--r--src/spellcasting.h7
-rw-r--r--src/test.cc20
-rw-r--r--src/weapon.cc20
-rw-r--r--src/weapon.h8
15 files changed, 227 insertions, 87 deletions
diff --git a/src/armor.cc b/src/armor.cc
new file mode 100644
index 0000000..e7ed323
--- /dev/null
+++ b/src/armor.cc
@@ -0,0 +1,34 @@
+#include "armor.h"
+#include "creature.h"
+#include "entry.h"
+#include <string>
+#include <sstream>
+
+using namespace std;
+
+namespace entry{
+ string Armor::getText(const creature::Creature& c) const {
+ return genText(*this, c);
+ }
+
+ string genText(const Armor& a, const creature::Creature& c) {
+ stringstream text;
+ 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")) << ")";
+ } else if(a.getArmorType() == "medium") {
+ int actualBonus = a.getACBonus();
+ actualBonus += (c.getBonus("dex") > 2)? 2 : c.getBonus("dex");
+ text << " + dex max 2 (i.e., " << actualBonus << ")";
+ }
+ if(a.getStrRequirement() > 0) {
+ text << ", Mininum str: " << a.getStrRequirement();
+ }
+ if(a.stealthDisadvantage()) {
+ text << ", Imposes stealth disadvantage";
+ }
+ text << ". " << genText(static_cast<const Substantial&>(a));
+ return text.str();
+ }
+}
diff --git a/src/armor.h b/src/armor.h
index 2df1fff..57402cb 100644
--- a/src/armor.h
+++ b/src/armor.h
@@ -2,8 +2,8 @@
#include "item.h"
#include "json.hpp"
-namespace item {
- class Armor : public Item {
+namespace entry {
+ class Armor : public Item , public Substantial {
public:
Armor(const nlohmann::json& data, const nlohmann::json& base) : Item(base), acBonus(data["ac"]), armorType(data["type"]), strRequirement(data["strength"]), stealthDis(data["disadvantage"]), cost(data["cost"]), weight(data["weight"]) {}
@@ -14,6 +14,8 @@ namespace item {
int getCost(void) const {return cost;}
double getWeight(void) const {return weight;}
+ virtual std::string getText(const creature::Creature& c) const;
+
/*virtual nlohmann::json toJson(void) const {
auto data = Item::toJson();
data["ac"] = acBonus;
@@ -33,4 +35,6 @@ namespace item {
const int cost;
const double weight;
};
+
+ std::string genText(const Armor& a, const creature::Creature& c);
}
diff --git a/src/creature.cc b/src/creature.cc
index 3587ab0..13b54d3 100644
--- a/src/creature.cc
+++ b/src/creature.cc
@@ -13,7 +13,7 @@ using namespace std;
namespace creature {
Creature::Creature(const json& data)
- : inventory(json2ptrvec<item::Item>(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<dmgType>(data["d_immunities"])), dmgResistances(json2vec<dmgType>(data["d_resistances"])), dmgVulnerabilities(json2vec<dmgType>(data["d_vulnerabilities"])), condImmunities(json2vec<dmgType>(data["c_immunities"])), features(json2ptrvec<feature::Feature>(data["features"]))
+ : inventory(json2ptrvec<entry::Item>(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<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"]))
{
// Initialize names and hp
if(((map<string, json>) data).contains("givenName")) {
@@ -109,7 +109,7 @@ namespace creature {
return bonus;
}
- void Creature::addInventoryItem(shared_ptr<item::Item> item) {
+ void Creature::addInventoryItem(shared_ptr<entry::Item> item) {
inventory.push_back(item);
}
@@ -141,7 +141,7 @@ namespace creature {
const int getAC(const Creature& c) {
int baseBonus = 10 + c.getBonus("dex");
int miscBonus = 0;
- for(auto a : getItems<item::Armor>(c)) {
+ for(auto a : getItems<entry::Armor>(c)) {
if(c.getScore("str") < a->getStrRequirement()) {
continue;
}
diff --git a/src/creature.h b/src/creature.h
index 88326f4..fee7c35 100644
--- a/src/creature.h
+++ b/src/creature.h
@@ -2,10 +2,10 @@
#include "json.hpp"
#include "jsonable.h"
-namespace feature {
+namespace entry {
class Feature;
}
-namespace item {
+namespace entry {
class Item;
}
class Armor;
@@ -54,15 +54,15 @@ namespace creature {
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 getProficiency(void) const {return proficiency;}
- std::vector<std::shared_ptr<feature::Feature>> getFeatures(void) const {return features;}
- std::vector<std::shared_ptr<item::Item>> getInventory(void) const {return inventory;}
+ std::vector<std::shared_ptr<entry::Feature>> getFeatures(void) const {return features;}
+ std::vector<std::shared_ptr<entry::Item>> getInventory(void) const {return inventory;}
// 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 addInventoryItem(std::shared_ptr<item::Item> item);
+ void addInventoryItem(std::shared_ptr<entry::Item> item);
void removeInventoryItem(const std::string& itemName);
virtual json toJson(void) const;
@@ -72,7 +72,7 @@ namespace creature {
std::string givenName;
int hpMax;
int hp;
- std::vector<std::shared_ptr<item::Item>> inventory;
+ std::vector<std::shared_ptr<entry::Item>> inventory;
//Immutable variables
const std::string creatureName;
@@ -93,7 +93,7 @@ namespace creature {
const std::vector<dmgType> dmgResistances;
const std::vector<dmgType> dmgVulnerabilities;
const std::vector<dmgType> condImmunities;
- const std::vector<std::shared_ptr<feature::Feature>> features;
+ const std::vector<std::shared_ptr<entry::Feature>> features;
};
diff --git a/src/entry.cc b/src/entry.cc
new file mode 100644
index 0000000..b6431f0
--- /dev/null
+++ b/src/entry.cc
@@ -0,0 +1,15 @@
+#include "entry.h"
+
+namespace creature {
+ class Creature;
+}
+
+namespace entry {
+ std::string genText(const Entry& e, const creature::Creature& c) {
+ return e.getName() + " (" + e.getType() + ")";
+ }
+
+ std::string Entry::getText(const creature::Creature& c) const {
+ return genText(*this, c);
+ }
+}
diff --git a/src/entry.h b/src/entry.h
new file mode 100644
index 0000000..20f38e0
--- /dev/null
+++ b/src/entry.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "json.hpp"
+#include "jsonable.h"
+#include <memory>
+
+namespace creature {
+ class Creature;
+}
+
+namespace entry {
+ class Entry : public Jsonable {
+ public:
+ virtual ~Entry() {}
+
+ std::string getName(void) const {return name;}
+ std::string getType(void) const {return type;}
+ std::string getText(void) const {return text;}
+ virtual std::string getText(const creature::Creature& c) const;
+
+ virtual nlohmann::json toJson(void) const {
+ return nlohmann::json({
+ {"name", name},
+ {"type", type},
+ {"text", text}
+ });
+ }
+
+ protected:
+ Entry(const nlohmann::json& data) : name(data["name"]), type(data["type"]), text(data["text"]) {};
+
+ private:
+ const std::string name;
+ const std::string type;
+ const std::string text;
+ };
+
+ // Set up default text generation
+ std::string genText(const Entry& e, const creature::Creature& c);
+}
diff --git a/src/feature.cc b/src/feature.cc
index 84f23fe..4972ccc 100644
--- a/src/feature.cc
+++ b/src/feature.cc
@@ -8,7 +8,7 @@
using namespace std;
typedef nlohmann::json json;
-namespace feature {
+namespace entry {
shared_ptr<Feature> Feature::create(const json& data) {
if(data["type"] == "spellcasting") {
return utils::loadDFromJson<Feature, Spellcasting>(data);
diff --git a/src/feature.h b/src/feature.h
index 01802bf..f3073d8 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -1,33 +1,16 @@
#pragma once
#include "json.hpp"
-#include "jsonable.h"
+#include "entry.h"
#include <memory>
-namespace feature {
- class Feature : public Jsonable {
+namespace entry {
+ class Feature : public Entry {
public:
static std::shared_ptr<Feature> create(const nlohmann::json& data);
- virtual ~Feature() {}
-
- std::string getName(void) const {return name;}
- std::string getType(void) const {return type;}
- virtual std::string getText(void) const {return text;}
-
- virtual nlohmann::json toJson(void) const {
- return nlohmann::json({
- {"name", name},
- {"type", type},
- {"text", text}
- });
- }
-
protected:
- Feature(const nlohmann::json& data) : name(data["name"]), type(data["type"]), text(data["text"]) {};
-
- private:
- const std::string name;
- const std::string type;
- const std::string text;
+ Feature(const nlohmann::json& data) : Entry(data) {};
};
+
+ //std::string genText(const Feature& f, const creature::Creature& c);
}
diff --git a/src/item.cc b/src/item.cc
index f602be2..6c91206 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -5,12 +5,12 @@
#include "utils.h"
#include <iostream>
#include <memory>
+#include <sstream>
using namespace std;
typedef nlohmann::json json;
-namespace item {
-
+namespace entry {
shared_ptr<Item> Item::create(const json& data) {
if(data["type"] == "weapon") {
return utils::loadDFromJson<Item, Weapon>(data);
@@ -19,4 +19,11 @@ namespace item {
}
return shared_ptr<Item>(new Item(data));
}
+
+ string genText(const Substantial& s) {
+ stringstream text;
+ text << "Cost: " << s.getCost() << " cp, i.e., " << utils::getCostString(s.getCost());
+ text << ". Weight: " << s.getWeight() << " lbs.";
+ return text.str();
+ }
}
diff --git a/src/item.h b/src/item.h
index a415947..096513e 100644
--- a/src/item.h
+++ b/src/item.h
@@ -1,33 +1,22 @@
#pragma once
#include "json.hpp"
-#include "jsonable.h"
+#include "entry.h"
#include <memory>
-namespace item {
- class Item : public Jsonable {
+namespace entry {
+ class Item : public Entry {
public:
static std::shared_ptr<Item> create(const nlohmann::json& data);
- virtual ~Item() {}
-
- std::string getName(void) const {return name;}
- std::string getType(void) const {return type;}
- virtual std::string getText(void) const {return text;}
-
- virtual nlohmann::json toJson(void) const {
- return nlohmann::json({
- {"name", name},
- {"type", type},
- {"text", text}
- });
- }
-
protected:
- Item(const nlohmann::json& data) : name(data["name"]), type(data["type"]), text(data["text"]) {};
+ Item(const nlohmann::json& data) : Entry(data) {};
+ };
- private:
- const std::string name;
- const std::string type;
- const std::string text;
+ class Substantial {
+ public:
+ virtual int getCost(void) const = 0;
+ virtual double getWeight(void) const = 0;
};
+
+ std::string genText(const Substantial& s);
}
diff --git a/src/spellcasting.cc b/src/spellcasting.cc
new file mode 100644
index 0000000..62af6de
--- /dev/null
+++ b/src/spellcasting.cc
@@ -0,0 +1,68 @@
+#include "spellcasting.h"
+#include "creature.h"
+#include "utils.h"
+#include <string>
+#include <sstream>
+#include <vector>
+
+using namespace std;
+
+namespace entry {
+ string Spellcasting::getText(const creature::Creature& c) const {
+ return genText(*this, c);
+ }
+
+ string toOrdinal(size_t number) {
+ string suffix = "th";
+ if (number % 100 < 11 || number % 100 > 13) {
+ switch (number % 10) {
+ case 1:
+ suffix = "st";
+ break;
+ case 2:
+ suffix = "nd";
+ break;
+ case 3:
+ suffix = "rd";
+ break;
+ }
+ }
+ return to_string(number) + suffix;
+ }
+
+ 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 << " (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()) {
+ text << " (spellcasting is innate).";
+ }
+ int levelNumber = 0;
+ for(auto level : s.getSpellsBySlot()) {
+ text << "\n";
+ if(level.numSlots == 0) {
+ if(s.isInnate()) {
+ text << "At will: ";
+ } else {
+ text << "Cantrips: ";
+ }
+ } else {
+ if(s.isInnate()) {
+ text << level.numSlots << "/day each: ";
+ } else {
+ text << toOrdinal(levelNumber) << " level (" << level.numSlots << " slots): ";
+ }
+ }
+ vector<string> names;
+ for(auto spell : level.spells) {
+ names.push_back(spell.getName());
+ }
+ text << utils::join(names, ", ");
+ levelNumber++;
+ }
+
+ return text.str();
+ }
+}
diff --git a/src/spellcasting.h b/src/spellcasting.h
index f996322..0ea235c 100644
--- a/src/spellcasting.h
+++ b/src/spellcasting.h
@@ -6,7 +6,7 @@
typedef nlohmann::json json;
-namespace feature {
+namespace entry {
struct SlotLevel : public Jsonable {
SlotLevel(const json& data) : numSlots(data["slots"]), spells(jsonList2vec<spell::Spell>("spellcasting", data["spells"])) {}
virtual ~SlotLevel() {}
@@ -29,11 +29,12 @@ namespace feature {
bool isInnate(void) const {return innate;}
std::string getAbility(void) const {return ability;}
std::vector<SlotLevel> getSpellsBySlot(void) const {return spellsBySlot;}
+ virtual std::string getText(const creature::Creature& c) const;
virtual json toJson(void) const {
auto data = Feature::toJson();
data["innate"] = innate;
- data["ability"] = ability;
+ data["spellcasting_ability"] = ability;
data["levels"] = spellsBySlot;
return data;
}
@@ -43,4 +44,6 @@ namespace feature {
const std::string ability;
const std::vector<SlotLevel> spellsBySlot;
};
+
+ std::string genText(const Spellcasting& s, const creature::Creature& c);
}
diff --git a/src/test.cc b/src/test.cc
index 1ce3d90..3c47537 100644
--- a/src/test.cc
+++ b/src/test.cc
@@ -7,6 +7,7 @@
#include "item.h"
#include "armor.h"
#include "weapon.h"
+#include "spellcasting.h"
using namespace std;
@@ -20,7 +21,7 @@ template<typename T> vector<string> mapItems(const vector<shared_ptr<T>>& items)
int main(int argc, char *argv[]) {
creature::Creature c(utils::loadJson(argv[argc-1]));
- cout << c.getCreatureName() << " " << c.getGivenName() << ", a cr " << c.getCR() << " " << c.getAlignment() << " " << c.getSize() << " " << c.getType() << ", has " << c.getHP() << " hp, ac " << creature::getAC(c) << " (" << utils::join(mapItems(creature::getItems<item::Armor>(c)), ", ") << "), speaks " << c.getLanguages() << ", has " << utils::join(c.getSenses(), ", ") << ", speed " << c.getSpeed() << ", and wields " << utils::join(mapItems(creature::getItems<item::Weapon>(c)), ", ") << ".\n Stats:\n";
+ cout << c.getCreatureName() << " " << c.getGivenName() << ", a cr " << c.getCR() << " " << c.getAlignment() << " " << c.getSize() << " " << c.getType() << ", has " << c.getHP() << " hp, ac " << creature::getAC(c) << " (" << utils::join(mapItems(creature::getItems<entry::Armor>(c)), ", ") << "), speaks " << c.getLanguages() << ", has " << utils::join(c.getSenses(), ", ") << ", speed " << c.getSpeed() << ", and wields " << utils::join(mapItems(creature::getItems<entry::Weapon>(c)), ", ") << ".\n Stats:\n";
for(auto ability : abilities) {
cout << ability << ": " << c.getScore(ability) << " (" << c.getBonus(ability) << ")\n";
}
@@ -34,21 +35,14 @@ int main(int argc, char *argv[]) {
}
cout << "\nFeatures:\n";
for(auto f: c.getFeatures()) {
- cout << f->getName() << " (" << f->getType() << "):\n";
- cout << f->getText() << "\n\n";
+ cout << f->getText(c) << "\n";
}
- cout << "\nWeapons:\n";
- for(auto w : creature::getItems<item::Weapon>(c)) {
- cout << w->getName() << " (" << w->getCost() << " cp, i.e., " << utils::getCostString(w->getCost()) << ", " << w->getWeight() << "lbs): ";
- cout << item::genActionText(*w, c);
- }
- cout << "\nArmor:\n";
- for(auto a : creature::getItems<item::Armor>(c)) {
- cout << a->getName() << " (" << a->getCost() << " cp, i.e., " << utils::getCostString(a->getCost()) << ", " << a->getWeight() << "lbs): ";
- cout << "AC bonus: " << a->getACBonus() << "; type: " << a->getArmorType() << "; strReq: " << a->getStrRequirement() << "; stealthDis: " << a->stealthDisadvantage() << "\n";
+ cout << "\nInventory:\n";
+ for(auto i : c.getInventory()) {
+ cout << i->getText(c) << "\n";
}
- cout << "We strike him with mace, dealing 5 fire damage!\n";
+ cout << "\nWe strike him with mace, dealing 5 fire damage!\n";
c.applyDamage(5, "fire", vector<string>());
cout << "Now he has " << c.getHP() << " out of " << c.getHPMax() << " hp.\n";
diff --git a/src/weapon.cc b/src/weapon.cc
index 314b1be..3a42e80 100644
--- a/src/weapon.cc
+++ b/src/weapon.cc
@@ -1,4 +1,3 @@
-#include "json.hpp"
#include "weapon.h"
#include "creature.h"
#include <string>
@@ -7,7 +6,7 @@
using namespace std;
-namespace item {
+namespace entry {
int Weapon::getDamageDieSides(bool versatile) const {
if(versatile && getProperties().count("versatile")) {
return damageDieSides + 2;
@@ -15,14 +14,19 @@ namespace item {
return damageDieSides;
}
- std::string genActionText(const Weapon& w, const creature::Creature& c) {
+ string Weapon::getText(const creature::Creature& c) const {
+ return genText(*this, c);
+ }
+
+ string genText(const Weapon& w, const creature::Creature& c) {
stringstream text;
+ text << genText(static_cast<const Item&>(w), c);
// Determine best ability bonus
int abilityBonus = c.getBonus("str");
if(w.getProperties().count("finesse")) {
abilityBonus = max(abilityBonus, c.getBonus("dex"));
}
- text << "+" << abilityBonus + c.getProficiency() << " to hit, ";
+ text << ": +" << abilityBonus + c.getProficiency() << " to hit, ";
if(w.getReach() > 0) {
text << "reach " << w.getReach() << " ft.";
if(w.getRange().second > 0) {
@@ -32,7 +36,7 @@ namespace item {
if(w.getRange().second > 0) {
text << "range " << w.getRange().first << "/" << w.getRange().second << " ft.";
}
- text << "\nHit: " << w.getDamageDieCount() << "d" << w.getDamageDieSides() << " + " << abilityBonus << " " << w.getDamageType() << " damage";
+ text << " Hit: " << w.getDamageDieCount() << "d" << w.getDamageDieSides() << " + " << abilityBonus << " " << w.getDamageType() << " damage";
if(w.getProperties().count("versatile")) {
text << " (or " << w.getDamageDieCount() << "d" << w.getDamageDieSides(true) << " + " << abilityBonus << " " << w.getDamageType() << " damage if two-handed)";
}
@@ -42,11 +46,9 @@ namespace item {
props.erase("finesse");
props.erase("versatile");
if(! props.empty()) {
- text << "\nAdditional properties:\n";
- for(string prop : props) {
- text << "\t" << prop << "\n";
- }
+ text << " Additional properties: " << utils::join(props, ", ") << ".";
}
+ text << " " << genText(static_cast<const Substantial&>(w));
return text.str();
}
}
diff --git a/src/weapon.h b/src/weapon.h
index e4755df..9ee2e8a 100644
--- a/src/weapon.h
+++ b/src/weapon.h
@@ -7,8 +7,8 @@ namespace creature {
class Creature;
}
-namespace item {
- class Weapon : public Item {
+namespace entry {
+ class Weapon : public Item, public Substantial {
public:
Weapon(const nlohmann::json& data, const nlohmann::json& base) : Item(base), damageType(data["damage"]["dmg_type"]), damageDieCount(data["damage"]["dmg_die_count"]), damageDieSides(data["damage"]["dmg_die_sides"]), properties(data["properties"]), weaponType(data["type"]), range(data["range"][0], data["range"][1]), reach(data["reach"]), cost(data["cost"]), weight(data["weight"]) {}
@@ -22,6 +22,8 @@ namespace item {
int getCost(void) const {return cost;}
double getWeight(void) const {return weight;}
+ virtual std::string getText(const creature::Creature& c) const;
+
/*virtual nlohmann::json toJson(void) const {
auto data = Item::toJson();
data["damage"]["dmg_type"] = damageType;
@@ -48,5 +50,5 @@ namespace item {
const double weight;
};
- std::string genActionText(const Weapon& w, const creature::Creature& c);
+ std::string genText(const Weapon& w, const creature::Creature& c);
}