diff options
Diffstat (limited to 'src/cmd_manipulate.cc')
-rw-r--r-- | src/cmd_manipulate.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/cmd_manipulate.cc b/src/cmd_manipulate.cc new file mode 100644 index 0000000..fe59ebf --- /dev/null +++ b/src/cmd_manipulate.cc @@ -0,0 +1,186 @@ +#include "cmd.h" +#include "utils.h" +#include "creature.h" +#include "item.h" +#include "spellcasting.h" +#include <sstream> +#include <memory> + +namespace fs = std::filesystem; + +namespace cmd { + std::string healOrDamage(bool heal, std::vector<std::string> args, std::vector<std::string> flags) { + std::stringstream text; + std::vector<rules::Qualifier> qualifiers; + if(! heal) { + for(auto flag : flags) { + if(flag == "m" || flag == "magical") { + qualifiers.push_back(rules::Qualifier::Magical()); + } else if(flag == "s" || flag == "silvered") { + qualifiers.push_back(rules::Qualifier::Silvered()); + } else if(flag == "a" || flag == "adamantine") { + qualifiers.push_back(rules::Qualifier::Adamantine()); + } + } + } + fs::path p = getTruePath(args[0]); + auto c = utils::instantiate<creature::Creature>(p); + int amnt = utils::parseInt(args[1]); + int initHP = c->getHP(); + std::string dmgType = "force"; + if(heal) { + c->applyHealing(amnt); + } else { + if(args.size() == 3) { + dmgType = args[2]; + } + c->applyDamage(amnt, dmgType, qualifiers); + } + 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; + utils::saveJson(*c, p); + return text.str(); + } + + std::string heal(std::vector<std::string> args) { + return healOrDamage(true, args, {}); + } + + std::string damage(std::vector<std::string> args, std::vector<std::string> flags) { + return healOrDamage(false, args, flags); + } + + 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(); + } +} |