commit 17c0c246ce8908671870fc8e00c17aaf844547f6
parent 4765933a119c88357dfd695c88fc8a6e76414da4
Author: Skylar Hill <stellarskylark@posteo.net>
Date: Thu, 2 Jun 2022 02:07:24 -0500
Add dnd5e template, make small bugfixes and improvements
Diffstat:
5 files changed, 398 insertions(+), 43 deletions(-)
diff --git a/examplesheet.yaml b/examplesheet.yaml
@@ -1,39 +0,0 @@
-name: Cragthar
-class: Paladin (Oath of Failure)
-level: 3
-tabs:
- - main:
- - ability-scores
- - ability-modifiers
- - skills
- - misc
- - attacks:
- - weapons
-expressions:
- dexterity:
- modifier: 16
- tab: main
- window: ability-scores
- DEX:
- modifier: "(dexterity-10)/2"
- tab: main
- window: ability-modifiers
- proficiency:
- modifier: 2
- tab: main
- window: misc
- sleight-of-hand:
- dice: d20
- modifier: "DEX+proficiency"
- tab: main
- window: skills
- shortsword-attack:
- dice: d20
- modifier: "DEX+proficiency"
- tab: attacks
- window: weapons
- shortsword-damage:
- dice: d6
- modifier: "DEX"
- tab: attacks
- window: weapons
diff --git a/src/rpgsheet.nim b/src/rpgsheet.nim
@@ -42,6 +42,8 @@ proc main(): void =
else:
quit(usage)
+ if arg == 1: # Assume interactive mode is desired if only one argument is provided
+ verb = Tui
if arg < 2 and verb != Tui:
quit(usage)
diff --git a/src/tui.nim b/src/tui.nim
@@ -1,13 +1,15 @@
import
illwill,
os,
+ strutils,
strformat,
tables,
+ std/wordwrap,
yaml
import utils, verb
-proc placeWindows(tb: TerminalBuffer, windows: seq[YamlNode]): Table[string, (int, int, int, int)] =
+proc placeWindows(tb: TerminalBuffer, windows: seq[YamlNode], descY: int): Table[string, (int, int, int, int)] =
result = initTable[string, (int, int, int, int)]()
let windowWidth =
if windows.len == 1:
@@ -17,7 +19,7 @@ proc placeWindows(tb: TerminalBuffer, windows: seq[YamlNode]): Table[string, (in
var currentX = 1
for win in windows:
- result[win.content] = (currentX, 3, currentX + windowWidth - 1, tb.height - 1)
+ result[win.content] = (currentX, 3, currentX + windowWidth - 1, descY - 1)
currentX += windowWidth
proc exitProc() {.noconv.} =
@@ -43,6 +45,8 @@ proc runTui*(sheet: YamlDocument): void =
var bb = newBoxBuffer(tb.width, tb.height)
var sbb = newBoxBuffer(tb.width, tb.height)
+ let descY = tb.height - 7
+
var currentTabName: string
var currentTabWindows: seq[YamlNode]
# There should only be one item, but because
@@ -52,7 +56,7 @@ proc runTui*(sheet: YamlDocument): void =
currentTabName = n.content
currentTabWindows = w.elems
- let windowPositions = placeWindows(tb, currentTabWindows)
+ let windowPositions = placeWindows(tb, currentTabWindows, descY)
for win in currentTabWindows:
if win.content notin itemsByWindow:
@@ -174,6 +178,27 @@ proc runTui*(sheet: YamlDocument): void =
tb.setForegroundColor(fgNone)
itemsbyWindow[win] = currentItems
+ # Write description
+ bb.drawRect(1, descY, tb.width - 1, tb.height - 1, doubleStyle = true)
+ let selWin = currentTabWindows[selectedWindowIndex].content
+ let sel = itemsByWindow[selWin][selectedByWindow[selWin]]
+ let item = sheet.root["expressions"][sel]
+ let desc = item.getContent("desc")
+ let val = (item.getContent("dice") & " " & item.getContent("modifier")).strip
+ let roll =
+ if not item.contains("dice"):
+ let rolled = doVerb(sel, Roll, sheet)
+ if rolled != item.getContent("modifier"):
+ rolled
+ else: "hardcoded"
+ else: "Press ENTER to roll"
+ tb.write(3, descY + 1, fmt"Value: {val} [{roll}]")
+ if desc != "":
+ let formattedDesc = desc.wrapWords(maxLineWidth = tb.width - 6)
+ let lines = formattedDesc.splitLines
+ for i in 0..lines.high:
+ tb.write(3, descY + 2 + i, lines[i])
+
tb.write(bb)
tb.setForegroundColor(fgBlue)
tb.write(sbb)
diff --git a/src/verb.nim b/src/verb.nim
@@ -66,7 +66,11 @@ proc roll(action: string, sheet: YamlNode): string =
"" # the minus is the negative sign in the int
else:
"+"
- let rollexp = dice & op & modifier
+ let rollexp =
+ if modifier == "0":
+ dice
+ else:
+ dice & op & modifier
let (output, code) = execCmdEx("rolldice -s", input = rollexp)
if code == 0:
# rolldice returns its input; the actual roll is the second line
diff --git a/templates/dnd5e.yaml b/templates/dnd5e.yaml
@@ -0,0 +1,363 @@
+# Change name, class, level
+name: Character Name
+class: Character Class
+level: 1
+tabs:
+ - main:
+ - stats
+ - ability-modifiers
+ - skills
+ - features
+ - inventory-and-attacks:
+ - attacks
+ - equipment
+ - wallet
+ - spells: # You can remove this section if you're not a caster
+ - spell-slots
+ - spellcasting-stats
+ - spells
+expressions:
+ # Change "race" to your character's race
+ race:
+ desc: Description of your character's race here
+ tab: main
+ window: features
+ # Add as many more of these as you want. Make the key
+ # like this; if you have Unarmored Defense, add an
+ # unarmored-defense field.
+ your-feature:
+ desc: Your character's awesome feature
+ tab: main
+ window: features
+ # Set these equal to your stats
+ max-health:
+ modifier: 10
+ tab: main
+ window: stats
+ current-health:
+ modifier: 10
+ tab: main
+ window: stats
+ temporary-health:
+ modifier: 0
+ tab: main
+ window: stats
+ speed:
+ modifier: 30
+ tab: main
+ window: stats
+ armor-class:
+ modifier: 10
+ tab: main
+ window: stats
+ proficiency:
+ modifier: 2
+ tab: main
+ window: stats
+ strength:
+ modifier: 10
+ tab: main
+ window: stats
+ dexterity:
+ modifier: 10
+ tab: main
+ window: stats
+ constitution:
+ modifier: 10
+ tab: main
+ window: stats
+ intelligence:
+ modifier: 10
+ tab: main
+ window: stats
+ wisdom:
+ modifier: 10
+ tab: main
+ window: stats
+ charisma:
+ modifier: 10
+ tab: main
+ window: stats
+ # Add your tool and language proficiencies here
+ other-proficiencies:
+ tab: main
+ window: stats
+ desc: Common, Simple weapons
+ # You probably don't want to change these
+ STR:
+ modifier: "(strength-10)/2"
+ tab: main
+ window: ability-modifiers
+ DEX:
+ modifier: "(dexterity-10)/2"
+ tab: main
+ window: ability-modifiers
+ CON:
+ modifier: "(constitution-10)/2"
+ tab: main
+ window: ability-modifiers
+ INT:
+ modifier: "(intelligence-10)/2"
+ tab: main
+ window: ability-modifiers
+ WIS:
+ modifier: "(wisdom-10)/2"
+ tab: main
+ window: ability-modifiers
+ CHA:
+ modifier: "(charisma-10)/2"
+ tab: main
+ window: ability-modifiers
+ # Add "+proficiency" to the skills you are proficient in,
+ # and "+(proficiency*2)" if you hvae expertise
+ passive-perception:
+ modifier: 10+WIS
+ tab: main
+ window: skills
+ strength-saving-throw:
+ dice: d20
+ modifier: STR
+ tab: main
+ window: skills
+ dexterity-saving-throw:
+ dice: d20
+ modifier: DEX
+ tab: main
+ window: skills
+ constitution-saving-throw:
+ dice: d20
+ modifier: CON
+ tab: main
+ window: skills
+ intelligence-saving-throw:
+ dice: d20
+ modifier: INT
+ tab: main
+ window: skills
+ wisdom-saving-throw:
+ dice: d20
+ modifier: WIS
+ tab: main
+ window: skills
+ charisma-saving-throw:
+ dice: d20
+ modifier: CHA
+ tab: main
+ window: skills
+ acrobatics:
+ dice: d20
+ modifier: DEX
+ tab: main
+ window: skills
+ animal-handling:
+ dice: d20
+ modifier: WIS
+ tab: main
+ window: skills
+ arcana:
+ dice: d20
+ modifier: INT
+ tab: main
+ window: skills
+ athletics:
+ dice: d20
+ modifier: STR
+ tab: main
+ window: skills
+ deception:
+ dice: d20
+ modifier: CHA
+ tab: main
+ window: skills
+ history:
+ dice: d20
+ modifier: INT
+ tab: main
+ window: skills
+ insight:
+ dice: d20
+ modifier: WIS
+ tab: main
+ window: skills
+ intimidation:
+ dice: d20
+ modifier: CHA
+ tab: main
+ window: skills
+ investigation:
+ dice: d20
+ modifier: INT
+ tab: main
+ window: skills
+ medicine:
+ dice: d20
+ modifier: WIS
+ tab: main
+ window: skills
+ nature:
+ dice: d20
+ modifier: INT
+ tab: main
+ window: skills
+ perception:
+ dice: d20
+ modifier: WIS
+ tab: main
+ window: skills
+ performance:
+ dice: d20
+ modifier: CHA
+ tab: main
+ window: skills
+ persuasion:
+ dice: d20
+ modifier: CHA
+ tab: main
+ window: skills
+ religion:
+ dice: d20
+ modifier: INT
+ tab: main
+ window: skills
+ sleight-of-hand:
+ dice: d20
+ modifier: DEX
+ tab: main
+ window: skills
+ stealth:
+ dice: d20
+ modifier: DEX
+ tab: main
+ window: skills
+ survival:
+ dice: d20
+ modifier: WIS
+ tab: main
+ window: skills
+ # Attacks; add two items for every way you have to attack,
+ # one for the attack roll, and the second for damage
+ unarmed-strike:
+ dice: d20
+ modifier: STR+proficiency
+ tab: inventory-and-attacks
+ window: attacks
+ desc: A simple attack with the body
+ unarmed-strike-damage:
+ modifier: 1+STR
+ tab: inventory-and-attacks
+ window: attacks
+ # Inventory; add an item for whatever you happen to have
+ common-clothes:
+ desc: Simple, common clothes for a simple, common person. Nothing wrong with that.
+ tab: inventory-and-attacks
+ window: equipment
+ copper-pieces:
+ modifier: 0
+ tab: inventory-and-attacks
+ window: wallet
+ silver-pieces:
+ modifier: 0
+ tab: inventory-and-attacks
+ window: wallet
+ gold-pieces:
+ modifier: 0
+ tab: inventory-and-attacks
+ window: wallet
+ electrum-pieces:
+ modifier: 0
+ tab: inventory-and-attacks
+ window: wallet
+ platinum-pieces:
+ modifier: 0
+ tab: inventory-and-attacks
+ window: wallet
+ # You can remove these if you're not a caster
+ first-level-spell-slots:
+ modifier: 1
+ tab: spells
+ window: spell-slots
+ second-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ third-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ fourth-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ fifth-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ sixth-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ seventh-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ eighth-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ ninth-level-spell-slots:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ first-level-slots-expended:
+ modifier: 1
+ tab: spells
+ window: spell-slots
+ second-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ third-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ fourth-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ fifth-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ sixth-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ seventh-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ eighth-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ ninth-level-slots-expended:
+ modifier: 0
+ tab: spells
+ window: spell-slots
+ spellcasting-ability:
+ modifier: CHA # set this appropriately
+ tab: spells
+ window: spellcasting-stats
+ spell-save-dc:
+ modifier: 8+spellcasting-ability+proficiency
+ tab: spells
+ window: spellcasting-stats
+ spell-attack-bonus:
+ dice: 1d20
+ modifier: spellcasting-ability+proficiency
+ tab: spells
+ window: spellcasting-stats
+ prestidigitation:
+ desc: "Cantrip. This spell is a minor magical trick that novice spellcasters use for practice. You create one of the following magical effects within range: 1) You create an instantaneous, harmless sensory effect, such as a shower of sparks, a puff of wind, faint musical notes, or an odd odor. 2) You instantaneously light or snuff out a candle, a torch, or a small campfire. 3) You instantaneously clean or soil an object no larger than 1 cubic foot. 4) You chill, warm, or flavor up to 1 cubic foot of nonliving material for 1 hour. 5) You make a color, a small mark, or a symbol appear on an object or a surface for 1 hour. 6) You create a nonmagical trinket or an illusory image that can fit in your hand and that lasts until the end of your next turn. If you cast this spell multiple times, you can have up to three of its non-instantaneous effects active at a time, and you can dismiss such an effect as an action."
+ tab: spells
+ window: spells