aboutsummaryrefslogtreecommitdiff
path: root/src/cmd_manipulate.cc
diff options
context:
space:
mode:
authorYour Name <you@example.com>2022-01-16 21:32:01 -0500
committerYour Name <you@example.com>2022-01-16 21:32:01 -0500
commitd0e356d09e30a11c1e072415a5088f829d5c0a04 (patch)
tree1e64d37b9b424cd74c30ad4c8225828c7a76874e /src/cmd_manipulate.cc
parent3f78a7e1647ba94129236bd2bf4fc855c109628a (diff)
downloaddmtool-d0e356d09e30a11c1e072415a5088f829d5c0a04.tar.gz
dmtool-d0e356d09e30a11c1e072415a5088f829d5c0a04.tar.bz2
dmtool-d0e356d09e30a11c1e072415a5088f829d5c0a04.zip
Worked on features
Diffstat (limited to 'src/cmd_manipulate.cc')
-rw-r--r--src/cmd_manipulate.cc348
1 files changed, 0 insertions, 348 deletions
diff --git a/src/cmd_manipulate.cc b/src/cmd_manipulate.cc
deleted file mode 100644
index aa6407d..0000000
--- a/src/cmd_manipulate.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-#include "cmd.h"
-#include "utils.h"
-#include "creature.h"
-#include "item.h"
-#include "spellcasting.h"
-#include "settings.h"
-#include "weapon.h"
-#include "dice.h"
-#include "armor.h"
-#include <sstream>
-#include <memory>
-#include <cstdlib>
-#include <fstream>
-#include <iterator>
-#include <algorithm>
-
-namespace fs = std::filesystem;
-
-namespace cmd {
- // Call after applying to format printing
- std::string formatHealingDamage(const std::shared_ptr<creature::Creature>& c, int initHP, bool heal, int amnt, const std::string& dmgType, const std::vector<rules::Qualifier>& qualifiers) {
- std::stringstream text;
- text << (heal? "Healing " : "Damaging ") << c->getGivenName() << " the " << c->getCreatureName() << " by " << amnt;
- if(! heal) {
- std::string qualsString;
- std::vector<std::string> positiveQuals;
- for(auto qual : qualifiers) {
- positiveQuals.push_back(qual.getPositive());
- }
- if(! positiveQuals.empty()) {
- qualsString = " " + utils::join(positiveQuals, ", ");
- }
- text << qualsString << " " << dmgType << " damage";
- }
- text << ". HP: " << initHP << " -> " << c->getHP() << "." << std::endl;
- return text.str();
- }
-
- std::string healOrDamageProgrammatic(fs::path p, bool heal, int amnt, std::string dmgType, const std::vector<rules::Qualifier>& qualifiers) {
- auto c = utils::instantiate<creature::Creature>(p);
- int initHP = c->getHP();
- if(heal) {
- c->applyHealing(amnt);
- } else {
- c->applyDamage(amnt, dmgType, qualifiers);
- }
- utils::saveJson(*c, p);
- return formatHealingDamage(c, initHP, heal, amnt, dmgType, qualifiers);
- }
-
- std::string healOrDamage(bool heal, std::vector<std::string> args, std::map<std::string, std::string> flags) {
- auto qualifiers = parseQualifiers(flags);
- fs::path p = getTruePath(args[0]);
- int amnt = utils::parseInt(args[1]);
- std::string dmgType = "force";
- if(args.size() == 3) {
- dmgType = args[2];
- }
- return healOrDamageProgrammatic(p, heal, amnt, dmgType, qualifiers);
- }
-
- std::string attack(std::vector<std::string> args, std::map<std::string, std::string> flags) {
- std::stringstream text;
- bool is2h = flags.find("2") != flags.end();
- bool is1h = flags.find("1") != flags.end();
- if(is2h and is1h) {
- text << "ERROR: Cannot be both 1 handed and 2 handed!" << std::endl;
- return text.str();
- }
- auto c1 = utils::instantiate<creature::Creature>(getTruePath(args[0]));
- args.erase(args.begin());
- fs::path p2 = getTruePath(args.back());
- auto c2 = utils::instantiate<creature::Creature>(p2);
- args.erase(args.end()-1);
- std::string attackName = utils::join(args, " ");
- utils::lower(attackName);
- std::shared_ptr<entry::Weapon> w;
- for(auto weap : creature::getAttacks(*c1)) {
- if(weap->getName() == attackName) {
- w = weap;
- break;
- }
- }
- text << w->getText(*c1) << std::endl;
- int rolled = dice::roll(20);
- int bonus = w->getToHitBonus(*c1);
- text << formatRoll(w->getName(), "attack", rolled, bonus);
- int ac = creature::getAC(*c2);
- if(rolled + bonus >= ac) {
- text << " Hit (" << (rolled + bonus) << " to hit >= " << ac << " ac): ";
- bool wants2h = true;
- for(auto a : utils::castPtrs<entry::Item, entry::Armor>(c1->getInventory())) {
- if(a->getArmorType() == "shield") {
- wants2h = false;
- }
- }
- if(is2h) {
- wants2h = true;
- } else if(is1h) {
- wants2h = false;
- }
- auto dmg = entry::rollDmg(*w, wants2h);
- text << entry::formatDmg(*w, *c1, dmg) << std::endl;
- for(auto d : dmg) {
- text << " " << healOrDamageProgrammatic(p2, false, d.rolled, d.dmg_type, {});
- }
- } else {
- text << " Miss (" << (rolled + bonus) << " to hit < " << ac << " ac)" << std::endl;
- }
- return text.str();
- }
-
- std::string heal(std::vector<std::string> args) {
- return healOrDamage(true, args, {});
- }
-
- std::string damage(std::vector<std::string> args, std::map<std::string, std::string> flags) {
- return healOrDamage(false, args, flags);
- }
-
- std::string save(std::vector<std::string> args, std::map<std::string, std::string> flags) {
- if(args.size() < 3) {
- throw std::runtime_error("Subcommand 'save' requires at least 3 arguments");
- }
- std::stringstream text;
- rules::Ability ability = rules::tryGetAbilityOrSkill<rules::Ability>(args[0]);
- if(! ability) {
- throw std::runtime_error("Requires a valid ability name but received \"" + args[0] + "\".");
- }
- args.erase(args.begin());
- int DC = utils::parseInt(args[0]);
- args.erase(args.begin());
- // Now iterate over the paths
- for(std::string s : args) {
- fs::path p = getTruePath(s);
- auto c = utils::instantiate<creature::Creature>(p);
- int initHP = c->getHP();
- int rolled = dice::roll(20);
- int bonus = c->getAbilitySaveBonus(ability);
- int damage = 0;
- std::string type = "force";
- bool halves = flags.find("halves") != flags.end();
- if(flags.find("damage") != flags.end()) {
- damage = utils::parseInt(flags.at("damage"));
- if(flags.find("type") != flags.end()) type = flags.at("type");
- auto qualifiers = parseQualifiers(flags);
- rolled = c->saveOrDamage(ability, DC, damage, type, qualifiers, halves);
- rolled -= bonus; // It's combined in creature
- }
- bool passed = rolled + bonus >= DC;
- text << c->getName() << " " << (passed? "PASS" : "FAIL") << ": ";
- text << formatRoll(ability.getFull(), "save", rolled, bonus);
- if(flags.find("damage") != flags.end() and (halves or ! passed)) {
- text << formatHealingDamage(c, initHP, false, damage, type, parseQualifiers(flags));
- }
- utils::saveJson(*c, p);
- }
- return text.str();
- }
-
- std::string reset(std::vector<std::string> args) {
- for(std::string s : args) {
- fs::path p = getTruePath(s);
- auto c = utils::instantiate<creature::Creature>(p);
- c->longRest();
- utils::saveJson(*c, p);
- }
- return "";
- }
-
- std::string set(std::vector<std::string> args) {
- if(args.size() < 3) {
- throw std::runtime_error("Subcommand 'set' requires at least 3 arguments");
- }
- fs::path p = getTruePath(args[0]);
- args.erase(args.begin()); // remove path from args
- auto c = utils::instantiate<creature::Creature>(p);
- if(args[0] == "name") {
- args.erase(args.begin()); // remove "name" from args
- c->setGivenName(utils::join(args, " "));
- } else if(args[0] == "proficiency") {
- c->setProficiency(utils::parseInt(args[1]));
- } else {
- // Either an ability or a skill. If skill, then it could be multiple words long.
- std::string toSet = args.back();
- args.erase(--args.end());
- std::string abilityOrSkill = utils::join(args, " ");
- rules::Skill skill = rules::tryGetAbilityOrSkill<rules::Skill>(abilityOrSkill);
- rules::Ability ability = rules::tryGetAbilityOrSkill<rules::Ability>(abilityOrSkill);
- if(skill) {
- // ensure lower case
- utils::lower(toSet);
- int level = -1;
- if(toSet == "none") level = 0;
- else if(toSet == "proficient") level = 1;
- else if(toSet == "expert") level = 2;
- if(level == -1) {
- throw std::runtime_error("Skill levels can be set to none, proficient, or expert, but " + toSet + " was given.");
- }
- c->setProfLevel(skill, level);
- } else if(ability) {
- c->setScore(ability, utils::parseInt(toSet));
- } else {
- throw std::runtime_error("Subcommand 'set' expected an ability, skill, proficiency, or name field to set, but was given " + abilityOrSkill);
- }
- }
- utils::saveJson(*c, p);
- return "";
- }
-
- std::string add(std::vector<std::string> args) {
- std::stringstream text;
- fs::path p = getTruePath(args[0]);
- args.erase(args.begin()); // remove path from args
- auto c = utils::instantiate<creature::Creature>(p);
- std::string addName = utils::join(args, " ");
- std::shared_ptr<entry::Entry> ent;
- fs::path path = getTruePath(addName);
- if(fs::directory_entry(path).exists()) {
- ent = utils::instantiate<entry::Entry>(path);
- } else {
- ent = entry::Entry::create(utils::findByName(addName));
- }
- // Determine if it is an item or a spell
- auto i = std::dynamic_pointer_cast<entry::Item>(ent);
- if(i) {
- c->addInventoryItem(i);
- } else {
- auto s = std::dynamic_pointer_cast<entry::Spell>(ent);
- if(s) {
- c->addSpell(s);
- } else {
- throw std::runtime_error("Could not add the " + ent->getType() + " " + ent->getName() + " to " + c->getGivenName() + " the " + c->getName() + ": Requires a weapon, armor, or spell, but received object of type " + ent->getType());
- }
- }
- utils::saveJson(*c, p);
- text << "Added the " << ent->getType() << " " << ent->getName() << " to " << c->getGivenName() << " the " << c->getName() << std::endl;
- return text.str();
- }
-
- std::string del(std::vector<std::string> args) {
- std::stringstream text;
- fs::path p = getTruePath(args[0]);
- args.erase(args.begin()); // remove path from args
- auto c = utils::instantiate<creature::Creature>(p);
- //Atempt to load the item if it's a path
- std::string itemName = utils::join(args, " ");
- try {
- auto i = utils::instantiate<entry::Entry>(getTruePath(itemName));
- if(i) {
- itemName = i->getName();
- }
- } catch(std::exception& e) {} // eat.
- utils::lower(itemName);
- // Loop through all of c's stuff, searching for itemName
- std::shared_ptr<entry::Entry> removed;
- for(auto item : c->getInventory()) {
- std::string name = item->getName();
- if(utils::lower(name) == itemName) {
- c->removeInventoryItem(item);
- removed = item;
- break;
- }
- }
- if(! removed) {
- for(auto spell : c->getSpellcasting()->getSpells()) {
- std::string name = spell->getName();
- if(utils::lower(name) == itemName) {
- c->removeSpell(spell);
- removed = spell;
- break;
- }
- }
- }
- utils::saveJson(*c, p);
- if(removed) {
- text << "Successfully removed the " << removed->Entry::getType() << " " << removed->getName() << std::endl;
- } else {
- text << "Could not find any inventory item nor spell by that name" << std::endl;
- }
- return text.str();
- }
-
- std::string edit(std::vector<std::string> args) {
- auto p = getTruePath(args[0]);
- auto e = utils::instantiate<entry::Entry>(p);
- auto editor = settings::getString("editor");
- // General workflow: copy notes (text) from e to a temp file, edit it, then copy back.
- fs::path tmp("/tmp/dmtool.tmp");
- std::ofstream out(tmp);
- out << e->Entry::getText();
- out.close();
- std::system((editor + " " + tmp.string()).c_str());
- std::ifstream in(tmp);
- std::string newText(std::istreambuf_iterator<char>{in}, {});
- e->setText(newText);
- utils::saveJson(e->serialize(), 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();
- }
-
- std::string git(std::vector<std::string> args) {
- std::string root = getTruePath("").string();
- std::system(("cd " + root + " && " + utils::join(args, " ")).c_str());
- return "";
- }
-}