diff options
author | Your Name <you@example.com> | 2021-05-18 16:26:49 -0400 |
---|---|---|
committer | Your Name <you@example.com> | 2021-05-18 16:26:49 -0400 |
commit | 38e33d8756a5b652965be8ada478b5c4238b857c (patch) | |
tree | d4e3b166103c4c0cc8d3a4ed963333a2982bb366 | |
parent | e044fc4255aa64ef1dbc3d20ed87ed6e2f61a6bd (diff) | |
download | dmtool-38e33d8756a5b652965be8ada478b5c4238b857c.tar.gz dmtool-38e33d8756a5b652965be8ada478b5c4238b857c.tar.bz2 dmtool-38e33d8756a5b652965be8ada478b5c4238b857c.zip |
Added spellcasting command
-rw-r--r-- | files/dmtool.bash | 12 | ||||
-rw-r--r-- | src/cmd.h | 1 | ||||
-rw-r--r-- | src/cmd_manipulate.cc | 42 | ||||
-rw-r--r-- | src/cmd_usage.cc | 5 | ||||
-rw-r--r-- | src/creature.cc | 8 | ||||
-rw-r--r-- | src/creature.h | 1 | ||||
-rw-r--r-- | src/dmtool.cc | 2 | ||||
-rw-r--r-- | src/entry.h | 3 | ||||
-rw-r--r-- | src/feature.h | 2 | ||||
-rw-r--r-- | src/spellcasting.h | 2 |
10 files changed, 76 insertions, 2 deletions
diff --git a/files/dmtool.bash b/files/dmtool.bash index ffc75f7..f683e05 100644 --- a/files/dmtool.bash +++ b/files/dmtool.bash @@ -81,7 +81,7 @@ _dmtool() { COMPREPLY=() local cur="${COMP_WORDS[COMP_CWORD]}" - local commands="ls cp mkdir mv rm attacks roll damage heal reset set edit add del help" + local commands="ls cp mkdir mv rm attacks roll damage heal reset set edit add del spellcasting help" if [[ $COMP_CWORD -gt 1 ]]; then local lastarg="${COMP_WORDS[$COMP_CWORD-1]}" case "${COMP_WORDS[1]}" in @@ -93,7 +93,7 @@ _dmtool() _dmtool_complete_entries fi ;; - attacks|roll|damage|heal|set|edit|del) + attacks|roll|damage|heal|set|edit|del|spellcasting) if [[ $COMP_CWORD -le 2 ]]; then _dmtool_complete_entries else @@ -126,6 +126,14 @@ _dmtool() #TODO: Add items and spells _dmtool_complete_skills_abilities ;; + spellcasting) + if [[ $COMP_CWORD -eq 3 ]]; then + COMPREPLY+=($(compgen -W "init ability level" -- ${cur})) + elif [[ "$lastarg" == "ability" ]]; then + local IFS=$'\n' + COMPREPLY+=($(compgen -W "$(_dmtool_abilities)" -- ${cur})) + fi + ;; esac fi ;; @@ -24,6 +24,7 @@ namespace cmd { std::string add(std::vector<std::string> args); std::string del(std::vector<std::string> args); std::string edit(std::vector<std::string> args); + std::string spellcasting(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 1300008..9fc019e 100644 --- a/src/cmd_manipulate.cc +++ b/src/cmd_manipulate.cc @@ -204,4 +204,46 @@ namespace cmd { utils::saveJson(*e, p); return ""; } + + std::string spellcasting(std::vector<std::string> args) { + std::stringstream text; + auto p = getTruePath(args[0]); + auto c = utils::instantiate<creature::Creature>(p); + auto subcommand = args[1]; + if(subcommand != "init" && subcommand != "ability" && subcommand != "level") { + throw std::runtime_error("Unknown option \"" + subcommand + "\""); + } + if(subcommand == "init") { + c->addSpellcasting(); + } else { + auto sc = c->getSpellcasting(); + if(! sc) { + throw std::runtime_error("Creature " + c->getName() + " has no spellcasting"); + } + text << "Added spellcasting to " << c->getName() << std::endl; + if(subcommand == "ability") { + if(args.size() != 3) { + throw std::runtime_error("Subcommand \"spellcasting ability\" requires an additional parameter, but none was given"); + } + sc->setAbility(args[2]); + text << "Set " << c->getName() << " spellcasting ability to " << args[2] << std::endl; + } else { // subcommand == "level" + if(args.size() != 4) { + throw std::runtime_error("Subcommand \"spellcasting level\" requires more parameters"); + } + int level = utils::parseInt(args[2]); + int slots = utils::parseInt(args[3]); + if(level <= 0 || slots < 0) { + throw std::runtime_error("Spellcasting target out of range"); + } + while(sc->getSlotLevels().size() <= (std::size_t) level) { + sc->addSlotLevel(); + } + sc->getSlotLevels()[level]->numSlots = slots; + text << "Gave " << c->getName() << " " << slots << " " << utils::toOrdinal(level) << " level spell slots" << std::endl; + } + } + utils::saveJson(*c, p); + return text.str(); + } } diff --git a/src/cmd_usage.cc b/src/cmd_usage.cc index 03dae56..53e9d01 100644 --- a/src/cmd_usage.cc +++ b/src/cmd_usage.cc @@ -40,6 +40,11 @@ namespace cmd { text << indDesc << "Add entry to creature, where entry is an item or spell." << std::endl; text << indOpt << "del path entry" << std::endl; text << indDesc << "Delete entry from creature, where entry is an item or spell." << std::endl; + text << indOpt << "spellcasting path SUBCOMMAND" << std::endl; + text << indDesc << "Manipulate creature's spellcasting feature, where subcommand is any of:" << std::endl; + 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 << "help" << std::endl; text << indDesc << "Show this help." << std::endl; return text.str(); diff --git a/src/creature.cc b/src/creature.cc index 9366bac..7060c10 100644 --- a/src/creature.cc +++ b/src/creature.cc @@ -80,6 +80,14 @@ namespace creature { inventory.push_back(item); } + void Creature::addSpellcasting() { + if(getSpellcasting()) { + throw runtime_error("Creature " + getName() + " already has spellcasting"); + } + std::shared_ptr<entry::Feature> sc(new entry::Spellcasting()); + features.push_back(sc); + } + shared_ptr<entry::Spellcasting> Creature::getSpellcasting() const { for(auto f : getFeatures()) { if(f->getType() == "spells") { diff --git a/src/creature.h b/src/creature.h index c6697ce..b2a01e6 100644 --- a/src/creature.h +++ b/src/creature.h @@ -85,6 +85,7 @@ namespace creature { void setProfLevel(const rules::Skill& skill, int level); void setProficiency(int p) {prof = p;} void addInventoryItem(std::shared_ptr<entry::Item> item); + void addSpellcasting(void); void addSpell(std::shared_ptr<entry::Spell> spell); void removeSpell(std::shared_ptr<entry::Spell> spell); void removeInventoryItem(std::shared_ptr<entry::Item> item); diff --git a/src/dmtool.cc b/src/dmtool.cc index 3c5d3a1..f4fe19c 100644 --- a/src/dmtool.cc +++ b/src/dmtool.cc @@ -11,6 +11,7 @@ const std::map<std::string, std::vector<int>> nargs({ {"attacks", {1}}, {"damage", {2, 3}}, {"heal", {2}}, + {"spellcasting", {2, 3, 4}}, }); void checkArgs(std::string cmd, std::vector<std::string> args) { @@ -69,6 +70,7 @@ int main(int argc, char *argv[]) { else if(cmd == "add") std::cout << cmd::add(args); 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 == "help") std::cout << cmd::usage(exename); else std::cout << cmd::list(argsOrig); } catch(std::exception& e) { diff --git a/src/entry.h b/src/entry.h index 56fc884..9e00798 100644 --- a/src/entry.h +++ b/src/entry.h @@ -10,6 +10,9 @@ namespace creature { namespace entry { class Entry { public: + Entry() {} + // Also can be created programmatically + Entry(const std::string& entry, const std::string& name, const std::string& type, const std::string& text) : entry(entry), name(name), type(type), text(text) {} static std::shared_ptr<Entry> create(const nlohmann::json& data); virtual ~Entry() {} diff --git a/src/feature.h b/src/feature.h index 294cf1d..e3c8bdf 100644 --- a/src/feature.h +++ b/src/feature.h @@ -6,6 +6,8 @@ namespace entry { class Feature : public Entry { public: + Feature() {} + Feature(const std::string& name, const std::string& type, const std::string& text) : Entry("feature", name, type, text) {} static std::shared_ptr<Feature> create(const nlohmann::json& data); virtual ~Feature() {} }; diff --git a/src/spellcasting.h b/src/spellcasting.h index f5cebcb..aa3b3e8 100644 --- a/src/spellcasting.h +++ b/src/spellcasting.h @@ -28,8 +28,10 @@ namespace entry { class Spellcasting : public Feature { public: + Spellcasting() : Feature("spellcasting", "spells", ""), innate(false), spellcasting_ability("int") {} bool isInnate(void) const {return innate;} rules::Ability getAbility(void) const {return spellcasting_ability;} + void setAbility(const rules::Ability& ability) {spellcasting_ability = ability;} const std::vector<std::shared_ptr<SlotLevel>>& getSlotLevels(void) const {return levels;} void addSlotLevel(void) {levels.push_back(std::shared_ptr<SlotLevel>(new SlotLevel()));} std::vector<std::shared_ptr<Spell>> getSpells(void) const; |