package noteButtons
import (
"bytes"
"html/template"
"log"
"strings"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
)
type InfluenceBlock struct {
ast.BaseBlock
Campaign string
Name string
Level int
Rarity string
Size string
Traits []string
CreatureType string
Perception int
Will int
Discovery []InfluenceDiscovery
Skills []InfluenceSkill
Thresholds []InfluenceThreshold
Resistance string
Weakness string
Background string
Appearance string
Personality string
Penalty string
}
type ToMap interface {
ToMap() map[string]interface{}
}
type InfluenceDiscovery struct {
Skill string
SkillLabel string
Dc int
}
func (i InfluenceDiscovery) ToMap() map[string]interface{} {
out := make(map[string]interface{})
out["skill"] = i.Skill
out["dc"] = i.Dc
out["skillLabel"] = i.SkillLabel
return out
}
type InfluenceSkill struct {
Skill string
SkillLabel string
Dc int
Reason string
}
func (i InfluenceSkill) ToMap() map[string]interface{} {
out := make(map[string]interface{})
out["skill"] = i.Skill
out["dc"] = i.Dc
out["skillLabel"] = i.SkillLabel
return out
}
type InfluenceThreshold struct {
Value int
Text template.HTML
}
var KindInfluenceBlock = ast.NewNodeKind("InfluenceBlock")
func (b *InfluenceBlock) Kind() ast.NodeKind {
return KindInfluenceBlock
}
func (b *InfluenceBlock) Dump(source []byte, level int) {
ast.DumpHelper(b, source, level, nil, nil)
}
type InfluenceBlockParser struct{}
func (p *InfluenceBlockParser) Trigger() []byte {
return []byte{'{'}
}
func (p *InfluenceBlockParser) Parse(parent ast.Node, reader text.Reader, pc parser.Context) ast.Node {
line, _ := reader.PeekLine()
if !bytes.HasPrefix(line, []byte("{{")) {
return nil
}
// Find the closing }}
end := bytes.Index(line[2:], []byte("}}"))
if end < 0 {
return nil
}
end += 2
contents := strings.TrimSpace(string(line[2:end]))
if !strings.HasPrefix(contents, "influence") {
return nil
}
contents = strings.TrimSpace(strings.TrimPrefix(contents, "influence"))
args, err := parseArgs(contents)
if err != nil {
log.Default().Print(err)
return nil
}
id := args["id"]
jsData, _ := pc.Get(InfluencesContextKey).(map[string]map[string]interface{})[id]
traitsRaw := jsData["traits"].([]interface{})
traits := make([]string, 0)
for _, trait := range traitsRaw {
traits = append(traits, trait.(string))
}
campaign, _ := pc.Get(CampaignContextKey).(string)
block := &InfluenceBlock{
Name: jsData["name"].(string),
Level: int(jsData["level"].(float64)),
Rarity: jsData["rarity"].(string),
Size: jsData["size"].(string),
Traits: traits,
CreatureType: jsData["type"].(string),
Perception: int(jsData["perception"].(float64)),
Will: int(jsData["will"].(float64)),
Resistance: jsData["resistance"].(string),
Weakness: jsData["weakness"].(string),
Background: jsData["background"].(string),
Appearance: jsData["appearance"].(string),
Personality: jsData["personality"].(string),
Discovery: make([]InfluenceDiscovery, 0),
Skills: make([]InfluenceSkill, 0),
Thresholds: make([]InfluenceThreshold, 0),
Campaign: campaign,
}
penalty, ok := jsData["penalty"].(string)
if ok {
block.Penalty = penalty
}
discoveries := jsData["discovery"].([]interface{})
for _, discovery := range discoveries {
discovery := discovery.(map[string]interface{})
block.Discovery = append(block.Discovery, InfluenceDiscovery{
Skill: discovery["skill"].(string),
Dc: int(discovery["dc"].(float64)),
SkillLabel: formatSkill(discovery["skill"].(string)),
})
}
influences := jsData["influence"].([]interface{})
for _, influence := range influences {
influence := influence.(map[string]interface{})
block.Skills = append(block.Skills, InfluenceSkill{
Skill: influence["skill"].(string),
Dc: int(influence["dc"].(float64)),
SkillLabel: formatSkill(influence["skill"].(string)),
})
}
thresholds := jsData["thresholds"].([]interface{})
for _, threshold := range thresholds {
threshold := threshold.(map[string]interface{})
block.Thresholds = append(block.Thresholds, InfluenceThreshold{
Value: int(threshold["value"].(float64)),
Text: template.HTML(strings.ReplaceAll(threshold["message"].(string), "\n\n", "
")),
})
}
reader.Advance(end + 2)
return block
}
type InfluenceBlockRenderer struct {
template *template.Template
}
func (r *InfluenceBlockRenderer) renderInfluenceBlock(writer util.BufWriter, _ []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
return ast.WalkContinue, nil
}
block := node.(*InfluenceBlock)
return ast.WalkContinue, r.template.ExecuteTemplate(writer, "influence", block)
}
func (r *InfluenceBlockRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(KindInfluenceBlock, r.renderInfluenceBlock)
}