aboutsummaryrefslogtreecommitdiff
path: root/src/spellcasting.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/spellcasting.cc')
-rw-r--r--src/spellcasting.cc68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/spellcasting.cc b/src/spellcasting.cc
new file mode 100644
index 0000000..62af6de
--- /dev/null
+++ b/src/spellcasting.cc
@@ -0,0 +1,68 @@
+#include "spellcasting.h"
+#include "creature.h"
+#include "utils.h"
+#include <string>
+#include <sstream>
+#include <vector>
+
+using namespace std;
+
+namespace entry {
+ string Spellcasting::getText(const creature::Creature& c) const {
+ return genText(*this, c);
+ }
+
+ string toOrdinal(size_t number) {
+ string suffix = "th";
+ if (number % 100 < 11 || number % 100 > 13) {
+ switch (number % 10) {
+ case 1:
+ suffix = "st";
+ break;
+ case 2:
+ suffix = "nd";
+ break;
+ case 3:
+ suffix = "rd";
+ break;
+ }
+ }
+ return to_string(number) + suffix;
+ }
+
+ string genText(const Spellcasting& s, const creature::Creature& c) {
+ stringstream text;
+ text << genText(static_cast<const Feature&>(s), c);
+ text << ": Spellcasting ability: " << s.getAbility();
+ text << " (spell save DC " << 8 + c.getBonus(s.getAbility()) + c.getProficiency();
+ text << ", +" << c.getBonus(s.getAbility()) + c.getProficiency() << " to hit with spell attacks).";
+ if(s.isInnate()) {
+ text << " (spellcasting is innate).";
+ }
+ int levelNumber = 0;
+ for(auto level : s.getSpellsBySlot()) {
+ text << "\n";
+ if(level.numSlots == 0) {
+ if(s.isInnate()) {
+ text << "At will: ";
+ } else {
+ text << "Cantrips: ";
+ }
+ } else {
+ if(s.isInnate()) {
+ text << level.numSlots << "/day each: ";
+ } else {
+ text << toOrdinal(levelNumber) << " level (" << level.numSlots << " slots): ";
+ }
+ }
+ vector<string> names;
+ for(auto spell : level.spells) {
+ names.push_back(spell.getName());
+ }
+ text << utils::join(names, ", ");
+ levelNumber++;
+ }
+
+ return text.str();
+ }
+}