2022-12-29 19:18:08 +01:00
|
|
|
package Parser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/fatih/color"
|
|
|
|
"gitlab.com/EternalWanderer/dice-roller/Dice"
|
|
|
|
)
|
|
|
|
|
|
|
|
const exampleFile string = "/etc/sheet-parser/example.json"
|
|
|
|
|
|
|
|
var (
|
|
|
|
path, pathFlag, skillString, saveString, statString string
|
|
|
|
modifier, diceThrows, surfaces int
|
|
|
|
X, Y int
|
|
|
|
char Character
|
|
|
|
skillMap = make(map[string]int)
|
|
|
|
statMap = make(map[string]int)
|
|
|
|
advantage, disadvantage, stat_list, skill_list, verbose, trivia bool
|
|
|
|
)
|
|
|
|
|
|
|
|
func handleError(err error) {
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-30 23:21:46 +01:00
|
|
|
func ReadJson(envVar string) {
|
|
|
|
envPath, isSet := os.LookupEnv(envVar)
|
2022-12-29 19:18:08 +01:00
|
|
|
switch {
|
|
|
|
case len(pathFlag) > 0:
|
|
|
|
path = pathFlag
|
|
|
|
case isSet:
|
|
|
|
path = envPath
|
|
|
|
default:
|
|
|
|
path = exampleFile
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("Opening file:", path)
|
|
|
|
var file, err = os.Open(path)
|
|
|
|
handleError(err)
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
byteValue, _ := ioutil.ReadAll(file)
|
|
|
|
|
|
|
|
err = json.Unmarshal(byteValue, &char)
|
|
|
|
handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func initMaps() {
|
|
|
|
for i := 0; i < len(char.Skills); i++ {
|
|
|
|
skillMap[char.Skills[i].SkillName] = i
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(char.Stats); i++ {
|
|
|
|
statMap[char.Stats[i].StatName] = i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetProficiency() int {
|
|
|
|
// https://worldbuildersjunction.com/what-is-proficiency-bonus-in-dd-5e-how-it-works-calculated/
|
|
|
|
return (char.Misc.Level-1)/4 + 2
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetSkill(skillName string) Skill {
|
|
|
|
return char.Skills[skillMap[skillName]]
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetStat(statName string) Stat {
|
|
|
|
return char.Stats[statMap[statName]]
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetModifier(stat Stat) int {
|
|
|
|
// https://worldbuildersjunction.com/dungeon-and-dragons-ability-scores-explained-for-beginners/
|
|
|
|
return (stat.Score - 10) / 2
|
|
|
|
}
|
|
|
|
|
|
|
|
func rollDice() int {
|
|
|
|
var die int
|
|
|
|
switch {
|
|
|
|
case advantage:
|
|
|
|
die, X, Y = Dice.Advantage()
|
|
|
|
case disadvantage:
|
|
|
|
die, X, Y = Dice.Disadvantage()
|
|
|
|
default:
|
|
|
|
die = Dice.SimpleCast()
|
|
|
|
}
|
|
|
|
switch die {
|
|
|
|
case 20:
|
|
|
|
color.Magenta("Natural 20!\n")
|
|
|
|
case 1:
|
|
|
|
color.Magenta("Natural 1!\n")
|
|
|
|
}
|
|
|
|
return die
|
|
|
|
}
|
2022-12-30 15:09:39 +01:00
|
|
|
|
2022-12-29 19:18:08 +01:00
|
|
|
func badCheck(errorMessage string, err error) {
|
|
|
|
if err == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fmt.Println(err)
|
|
|
|
fmt.Println(errorMessage)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func statErrorCheck() error {
|
|
|
|
for i := 0; i < len(char.Stats); i++ {
|
|
|
|
if statString == char.Stats[i].StatName || saveString == char.Stats[i].StatName {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("Unknown stat:")
|
|
|
|
}
|
|
|
|
|
|
|
|
func skillErrorCheck() error {
|
|
|
|
for i := 0; i < len(char.Skills); i++ {
|
|
|
|
if skillString == char.Skills[i].SkillName {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("Unknown skill:")
|
|
|
|
}
|
|
|
|
|
|
|
|
func statCheck(stat Stat) (int, int, error) {
|
|
|
|
die := rollDice()
|
|
|
|
return die + GetModifier(stat), die, statErrorCheck()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func savingThrow(stat Stat) (int, int, error) {
|
|
|
|
die := rollDice()
|
|
|
|
plainDie := die
|
|
|
|
|
|
|
|
if stat.Proficient {
|
|
|
|
die += GetProficiency()
|
|
|
|
}
|
|
|
|
return die + GetModifier(stat), plainDie, statErrorCheck()
|
|
|
|
}
|
|
|
|
|
2022-12-30 23:21:46 +01:00
|
|
|
func SkillCheck(skill Skill) (int, int, error) {
|
2022-12-29 19:18:08 +01:00
|
|
|
die := rollDice()
|
|
|
|
if char.Misc.ReliableTalent && skill.Proficient && die < 10 {
|
|
|
|
die = 10
|
|
|
|
}
|
|
|
|
plainDie := die
|
|
|
|
|
|
|
|
die += GetModifier(GetStat(skill.BaseStat))
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case skill.Expertise:
|
|
|
|
die += GetProficiency() * 2
|
|
|
|
case skill.Proficient:
|
|
|
|
die += GetProficiency()
|
|
|
|
case !skill.Proficient && char.Misc.JackOfAllTrades:
|
|
|
|
die += (GetProficiency() / 2)
|
|
|
|
}
|
|
|
|
return die, plainDie, skillErrorCheck()
|
|
|
|
}
|
|
|
|
|
2022-12-30 23:21:46 +01:00
|
|
|
func PrintStatList(verbose bool) {
|
2022-12-29 19:18:08 +01:00
|
|
|
color.Magenta("Listing stats...")
|
|
|
|
if verbose {
|
|
|
|
var proficiency string
|
|
|
|
for i := 0; i < len(char.Stats); i++ {
|
|
|
|
name := char.Stats[i].StatName
|
|
|
|
isProficient := char.Stats[i].Proficient
|
|
|
|
if isProficient {
|
|
|
|
proficiency = "Proficient"
|
|
|
|
} else {
|
|
|
|
proficiency = "Not proficient"
|
|
|
|
}
|
|
|
|
score := char.Stats[i].Score
|
|
|
|
fmt.Printf("Stat: %13s\t%s\tStat score: %2d\tStat modifier: %2d\n", name, proficiency, score, GetModifier(char.Stats[i]))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for i := 0; i < len(char.Stats); i++ {
|
|
|
|
fmt.Println(char.Stats[i].StatName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-30 23:21:46 +01:00
|
|
|
func PrintSkillList(verbose bool) {
|
2022-12-29 19:18:08 +01:00
|
|
|
color.Magenta("Listing skills...")
|
|
|
|
var proficiency string
|
|
|
|
var expertise string
|
|
|
|
if verbose {
|
|
|
|
for i := 0; i < len(char.Skills); i++ {
|
|
|
|
name := char.Skills[i].SkillName
|
|
|
|
localModifier := GetModifier(GetStat(char.Skills[i].BaseStat))
|
|
|
|
if char.Skills[i].Proficient {
|
|
|
|
proficiency = "Proficient"
|
|
|
|
localModifier += GetProficiency()
|
|
|
|
} else {
|
|
|
|
proficiency = "Not proficient"
|
|
|
|
}
|
|
|
|
if char.Skills[i].Expertise {
|
|
|
|
expertise = "Has expertise"
|
|
|
|
localModifier += GetProficiency()
|
|
|
|
} else {
|
|
|
|
expertise = "Doesn't have expertise"
|
|
|
|
}
|
|
|
|
fmt.Printf("Skill:%16s\tSkill modifier:%3d\t%s\t%s\n", name, localModifier, proficiency, expertise)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for i := 0; i < len(char.Skills); i++ {
|
|
|
|
fmt.Println(char.Skills[i].SkillName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|