diff options
Diffstat (limited to 'src/cmd_manipulate.cc')
-rw-r--r-- | src/cmd_manipulate.cc | 348 |
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 ""; - } -} |