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) }