From 01293baa64fa905c5763020bd6c0b4903d41fc78 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 12 Jun 2021 15:32:53 -0400 Subject: Verified some creature attacks --- src/weapon.cc | 66 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 15 deletions(-) (limited to 'src/weapon.cc') diff --git a/src/weapon.cc b/src/weapon.cc index 053dbc1..cdf4657 100644 --- a/src/weapon.cc +++ b/src/weapon.cc @@ -5,6 +5,7 @@ #include #include #include +#include using namespace std; @@ -17,9 +18,12 @@ namespace entry { int reach; int cost; double weight; + std::optional toHitOverride; + std::optional dmgBonusOverride; + std::optional abilityOverride; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(weaponImpl, damage, properties, weapon_type, range, reach, cost, weight); + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(weaponImpl, damage, properties, weapon_type, range, reach, cost, weight, toHitOverride, dmgBonusOverride, abilityOverride); NLOHMANN_FRIEND_DEFS(Item, Weapon, data); @@ -36,7 +40,7 @@ namespace entry { string getTextHelper(const Weapon& w, string toHitBonus, string damageBonus) { stringstream text; text << "+" << toHitBonus << " to hit, "; - if(w.getReach() > 0) { + if(w.getReach() > 0 or w.getRange().second == 0) { text << "reach " << w.getReach() << " ft."; if(w.getRange().second > 0) { text << " or "; @@ -49,23 +53,43 @@ namespace entry { auto dmgs = w.getDamage(); for(size_t i = 0; i < dmgs.size(); i++) { const Damage& d = dmgs[i]; - text << d.dmg_die_count << "d" << d.dmg_die_sides; - if(i == 0) { + text << d.dmg_die_count; + if(d.dmg_die_sides > 1) { + text << "d" << d.dmg_die_sides; + } + if((i == 0 or dmgs[i].is_or) and w.getType() == "weapons" and d.dmg_die_sides != 1) { if(w.getProperties().count("versatile")) { text << " (or " << d.dmg_die_count << "d" << d.dmg_die_sides + 2 << " if two-handed)"; } - text << " + " << damageBonus; + try { + int dmgBonusInt = stoi(damageBonus); + if(dmgBonusInt > 0) { + text << " + " << dmgBonusInt; + } else if(dmgBonusInt < 0) { + text << " - " << dmgBonusInt * -1; + } // Else it's zero + } catch(exception& e) { + text << " + " << damageBonus; + } } text << " " << d.dmg_type << " damage"; if(i < dmgs.size()-1) { - if(d.is_or) { + if(dmgs[i+1].is_or) { text << " or "; } else { text << " plus "; } } } - text << "."; + if(w.Entry::getText().empty()) { + text << "."; + } else { + char first = w.Entry::getText()[0]; + if('a' <= first and 'z' >= first) { + text << ' '; + } + text << w.Entry::getText(); + } auto props = w.getProperties(); // We don't care about finesse nor versatile because they're already handled props.erase("finesse"); @@ -73,10 +97,9 @@ namespace entry { if(! props.empty()) { text << " Additional properties: " << utils::join(props, ", ") << "."; } - if(! w.Entry::getText().empty()) { - text << " " << w.Entry::getText(); + if(! w.Substantial::getText().empty()) { + text << " " << w.Substantial::getText(); } - text << " " << w.Substantial::getText(); return text.str(); } @@ -103,7 +126,7 @@ namespace entry { vector dmgsVersatile = rollDmg(w, true); int abilityBonus = c.getBonus(creature::getBestAbility(getAbilityOptions(w), c)); for(size_t i = 0; i < dmgsNoVersatile.size(); i++) { - if(i == 0) { + if(i == 0 and w.getType() == "weapons" and dmgsNoVersatile[0].dmg_die_sides != 1) { text << dmgsNoVersatile[i].rolled + abilityBonus; if(w.getProperties().count("versatile")) { text << " (or " << dmgsVersatile[i].rolled + abilityBonus << " if two-handed)"; @@ -136,19 +159,25 @@ namespace entry { if(w.getRange().second > 0) { return {rules::Ability::Dex()}; } - cerr << "Error processing weapon!" << endl; + //cerr << "Error processing weapon: " << w.getName() << "!" << endl; + // Default to str return {rules::Ability::Str()}; } string Weapon::getText() const { auto abilities = getAbilityOptions(*this); string abilityString; - if(abilities.size() == 1) { + if(data->dmgBonusOverride) { + abilityString = to_string(*data->dmgBonusOverride); + } else if(data->abilityOverride) { + abilityString = data->abilityOverride->getAbbrev(); + } else if(abilities.size() == 1) { abilityString = string(abilities[0]); } else { abilityString = "max(" + utils::join(abilities, ", ") + ")"; } - return getTextHelper(*this, "(" + abilityString + " + prof)", abilityString); + string toHitString = data->toHitOverride ? to_string(*data->toHitOverride) : "(" + abilityString + " + prof)"; + return getTextHelper(*this, toHitString, abilityString); } @@ -157,7 +186,14 @@ namespace entry { text << getName() << " (" << getType() << "): "; // Determine best ability bonus int abilityBonus = c.getBonus(creature::getBestAbility(getAbilityOptions(*this), c)); - text << getTextHelper(*this, to_string(abilityBonus + c.getProficiency()), to_string(abilityBonus)); + if(data->abilityOverride) { + abilityBonus = c.getBonus(*data->abilityOverride); + } + string toHitString = data->toHitOverride ? to_string(*data->toHitOverride) : to_string(abilityBonus + c.getProficiency()); + if(data->dmgBonusOverride) { + abilityBonus = *data->dmgBonusOverride; + } + text << getTextHelper(*this, toHitString, to_string(abilityBonus)); return text.str(); } } -- cgit v1.2.3