From 3f78a7e1647ba94129236bd2bf4fc855c109628a Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 3 Jan 2022 16:25:45 -0500 Subject: Added command to force a saving throw --- src/cmd_manipulate.cc | 88 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 27 deletions(-) (limited to 'src/cmd_manipulate.cc') diff --git a/src/cmd_manipulate.cc b/src/cmd_manipulate.cc index 294b600..aa6407d 100644 --- a/src/cmd_manipulate.cc +++ b/src/cmd_manipulate.cc @@ -17,16 +17,10 @@ namespace fs = std::filesystem; namespace cmd { - std::string healOrDamageProgrammatic(fs::path p, bool heal, int amnt, std::string dmgType, std::vector qualifiers) { + // Call after applying to format printing + std::string formatHealingDamage(const std::shared_ptr& c, int initHP, bool heal, int amnt, const std::string& dmgType, const std::vector& qualifiers) { std::stringstream text; - auto c = utils::instantiate(p); - int initHP = c->getHP(); - if(heal) { - c->applyHealing(amnt); - } else { - c->applyDamage(amnt, dmgType, qualifiers); - } - text << (heal? "Healing " : "Damaging ") << c->getGivenName() << " the " << c->getCreatureName() << " by " << amnt; + text << (heal? "Healing " : "Damaging ") << c->getGivenName() << " the " << c->getCreatureName() << " by " << amnt; if(! heal) { std::string qualsString; std::vector positiveQuals; @@ -39,23 +33,23 @@ namespace cmd { text << qualsString << " " << dmgType << " damage"; } text << ". HP: " << initHP << " -> " << c->getHP() << "." << std::endl; - utils::saveJson(*c, p); return text.str(); } - std::string healOrDamage(bool heal, std::vector args, std::vector flags) { - std::vector 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()); - } - } - } + std::string healOrDamageProgrammatic(fs::path p, bool heal, int amnt, std::string dmgType, const std::vector& qualifiers) { + auto c = utils::instantiate(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 args, std::map flags) { + auto qualifiers = parseQualifiers(flags); fs::path p = getTruePath(args[0]); int amnt = utils::parseInt(args[1]); std::string dmgType = "force"; @@ -65,10 +59,10 @@ namespace cmd { return healOrDamageProgrammatic(p, heal, amnt, dmgType, qualifiers); } - std::string attack(std::vector args, std::vector flags) { + std::string attack(std::vector args, std::map flags) { std::stringstream text; - bool is2h = std::find(flags.begin(), flags.end(), "2") != flags.end(); - bool is1h = std::find(flags.begin(), flags.end(), "1") != flags.end(); + 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(); @@ -120,9 +114,49 @@ namespace cmd { return healOrDamage(true, args, {}); } - std::string damage(std::vector args, std::vector flags) { + std::string damage(std::vector args, std::map flags) { return healOrDamage(false, args, flags); } + + std::string save(std::vector args, std::map flags) { + if(args.size() < 3) { + throw std::runtime_error("Subcommand 'save' requires at least 3 arguments"); + } + std::stringstream text; + rules::Ability ability = rules::tryGetAbilityOrSkill(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(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 args) { for(std::string s : args) { -- cgit v1.2.3