diff options
author | Your Name <you@example.com> | 2021-04-16 11:23:27 -0400 |
---|---|---|
committer | Your Name <you@example.com> | 2021-04-16 11:23:27 -0400 |
commit | 4618763c0e3a723bf4bb43c7b9edbce87240e0af (patch) | |
tree | a18aa4bf7da05ac02b4e37b199aeeb82da977aea /src | |
parent | dfce4d0398a8bafbb7ad7a31345af181c0269c09 (diff) | |
download | dmtool-4618763c0e3a723bf4bb43c7b9edbce87240e0af.tar.gz dmtool-4618763c0e3a723bf4bb43c7b9edbce87240e0af.tar.bz2 dmtool-4618763c0e3a723bf4bb43c7b9edbce87240e0af.zip |
Rebased feature/item on entry
Diffstat (limited to 'src')
-rw-r--r-- | src/armor.cc | 34 | ||||
-rw-r--r-- | src/armor.h | 8 | ||||
-rw-r--r-- | src/creature.cc | 6 | ||||
-rw-r--r-- | src/creature.h | 14 | ||||
-rw-r--r-- | src/entry.cc | 15 | ||||
-rw-r--r-- | src/entry.h | 39 | ||||
-rw-r--r-- | src/feature.cc | 2 | ||||
-rw-r--r-- | src/feature.h | 29 | ||||
-rw-r--r-- | src/item.cc | 11 | ||||
-rw-r--r-- | src/item.h | 33 | ||||
-rw-r--r-- | src/spellcasting.cc | 68 | ||||
-rw-r--r-- | src/spellcasting.h | 7 | ||||
-rw-r--r-- | src/test.cc | 20 | ||||
-rw-r--r-- | src/weapon.cc | 20 | ||||
-rw-r--r-- | src/weapon.h | 8 |
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(); + } } @@ -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); } |