rpgsheet

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 52d1c5cab0df5f8e62c758c412494684435fc39f
Author: Skylar Hill <stellarskylark@posteo.net>
Date:   Mon, 30 May 2022 20:12:06 -0500

First commit

Diffstat:
AREADME.md | 12++++++++++++
Aexamplesheet.yaml | 34++++++++++++++++++++++++++++++++++
Arpgsheet.nimble | 14++++++++++++++
Asrc/rpgsheet.nim | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,12 @@ +# rpgsheets + +`rpgsheets` is a CLI/TUI character sheet application for tabletop RPGs. + +## Features +* **System-agnostic:** Character sheets are stored as YAML files, and the data structure is not designed with a particular TTRPG system (ie DnD5e). You can make a template for your favorite system! +* **Auto-rolling:** As long as your system uses dice rolls that can be represented with the standard `NUMdFACES+MOD` notation, you can easily define actions which will automatically be rolled. +* **Auto-calculation:** You can define values in your character sheet which are dependent on other values. For instance, you can define a hard-coded `proficiency` value, and then define your shortsword attack modifier as `3+proficiency`. (For DnD, you probably actually want a hard-coded `strength` ability score, then a `STR` value defined as `(strength-10)/2`, then define your shortsword attack as `STR+proficiency`.) + +## Dependencies: +* `rolldice` for, uh, rolling dice +* `bc` for calculations diff --git a/examplesheet.yaml b/examplesheet.yaml @@ -0,0 +1,34 @@ +tabs: + main: + - ability-scores + - ability-modifiers + - skills + - misc + attacks: + - weapons +expressions: + dexterity: + exp: "16" + tab: main + window: ability-scores + DEX: + exp: "(dexterity-10)/2" + tab: main + window: ability-modifiers + prof: + exp: "2" + tab: main + window: misc + sleight-of-hand: + dice: "d20" + exp: "DEX+prof" + shortsword-atk: + dice: "d20" + exp: "DEX+prof" + tab: attacks + window: weapons + shortsword-dmg: + dice: "d6" + exp: "DEX" + tab: attacks + window: weapons diff --git a/rpgsheet.nimble b/rpgsheet.nimble @@ -0,0 +1,14 @@ +# Package + +version = "0.0.1" +author = "Skylar Hill" +description = "CLI/TUI application for TTRPG character sheets" +license = "GPL-3.0-only" +srcDir = "src" +bin = @["rpgsheet"] + + +# Dependencies + +requires "nim >= 1.6.6" +requires "yaml >= 0.16.0" diff --git a/src/rpgsheet.nim b/src/rpgsheet.nim @@ -0,0 +1,51 @@ +import json, yaml, re, strutils, osproc, os + +let reRawExp = re"([a-zA-Z\-]+[a-zA-Z])" +let reProcessedExp = re"^[\d*+\-/()]*$" + +proc decodeExpression(exp: string, sheet: JsonNode): string = + var working = exp + if exp.contains(reProcessedExp): + # I think that execCmdEx adds whitespace in input; + # the xargs pipe first is necessary to prevent bc + # from throwing up + let (output, code) = execCmdEx("xargs | bc", input=exp) + if code == 0: + working = output.strip + return working + + if sheet["expressions"].contains exp: + working = decodeExpression(sheet["expressions"][exp]["exp"].getStr, sheet) + return working + + for match in exp.findAll reRawExp: + working = working.replace(match, decodeExpression(match, sheet)) + return decodeExpression(working, sheet) + +proc roll(action: string, sheet: JsonNode): string = + let exp = sheet["expressions"][action] + if not exp.contains "dice": + return decodeExpression(exp["exp"].getStr, sheet) + let dice = exp["dice"].getStr + var modifier = decodeExpression(exp["exp"].getStr, sheet) + var op = + if modifier.parseInt < 0: + "" # the minus is the negative sign in the int + else: + "+" + let rollexp = dice & op & modifier + let (output, code) = execCmdEx("rolldice", input = rollexp) + if code == 0: + # rolldice returns its input; the actual roll is the second line + result = output.splitLines[1] + +if paramCount() < 2: + quit( + """Usage: + ./rpgsheet sheet.yaml action + """ + ) + +let file = open(paramStr(1)) +let sheetNode = file.readAll.loadtoJson[0] +echo roll(paramStr(2), sheetNode)