Spellcasting expansion

This commit is contained in:
2026-05-27 10:28:44 +02:00
parent bd9d2c6da0
commit a2d9820f8d
2 changed files with 81 additions and 0 deletions
+51
View File
@@ -1740,6 +1740,57 @@ tables:
} }
} }
func TestWikiTemplateRendersClassProgressionSpellcastingAdvancementNotes(t *testing.T) {
ctx := testWikiTableContext(t, `
tables:
ClassProgression:
source: class_progression
rows:
levels: 1-4
columns:
- key: level
label: Lvl
value: "{{Level}}"
- key: notes
label: Notes
value: "{{SpellcastingAdvancementNote + if(present(SpellcastingAdvancementNote) && present(Notes), \" \", \"\") + Notes}}"
empty: ""
`)
page := wikiTemplatePage{
PageID: "classes:pale_master",
Category: "classes",
Key: "classes:pale_master",
Title: "Pale Master",
Row: map[string]any{
"SpellCaster": 0,
"ArcSpellLvlMod": 2,
"DivSpellLvlMod": 0,
"meta": map[string]any{
"wiki": map[string]any{
"progression_notes": map[string]any{
"3": "Manual level note.",
},
},
},
},
}
got, err := ctx.renderWikiTemplateString("classes.html", `{{table:ClassProgression}}`, page)
if err != nil {
t.Fatalf("render table template: %v", err)
}
for _, expected := range []string{
`<tr><td>1</td><td>+1 level of existing arcane spellcasting class</td></tr>`,
`<tr><td>2</td><td></td></tr>`,
`<tr><td>3</td><td>+1 level of existing arcane spellcasting class Manual level note.</td></tr>`,
`<tr><td>4</td><td></td></tr>`,
} {
if !strings.Contains(got, expected) {
t.Fatalf("expected %q in rendered table:\n%s", expected, got)
}
}
}
func TestWikiTemplateHidesUnusedConfiguredClassSpellColumns(t *testing.T) { func TestWikiTemplateHidesUnusedConfiguredClassSpellColumns(t *testing.T) {
ctx := testWikiTableContext(t, ` ctx := testWikiTableContext(t, `
tables: tables:
+30
View File
@@ -452,6 +452,7 @@ func (ctx *wikiContext) classProgressionRows(levels string, projections map[stri
row["HasSpellProgression"] = hasSpellProgression(classRow) row["HasSpellProgression"] = hasSpellProgression(classRow)
row["HasSpellsPerDay"] = hasPerDay row["HasSpellsPerDay"] = hasPerDay
row["HasSpellsKnown"] = hasKnown row["HasSpellsKnown"] = hasKnown
row["SpellcastingAdvancementNote"] = classSpellcastingAdvancementNote(classRow, level)
populateClassSpellProgressionFields(row, "SpellsPerDay", spellsPerDayByLevel[level]) populateClassSpellProgressionFields(row, "SpellsPerDay", spellsPerDayByLevel[level])
populateClassSpellProgressionFields(row, "SpellsKnown", spellsKnownByLevel[level]) populateClassSpellProgressionFields(row, "SpellsKnown", spellsKnownByLevel[level])
out = append(out, row) out = append(out, row)
@@ -459,6 +460,35 @@ func (ctx *wikiContext) classProgressionRows(levels string, projections map[stri
return out, nil return out, nil
} }
func classSpellcastingAdvancementNote(classRow map[string]any, level int) string {
if level < 1 || isClassSpellcaster(classRow) {
return ""
}
notes := []string{}
if advancesSpellcastingAtLevel(classRow, "ArcSpellLvlMod", level) {
notes = append(notes, "+1 level of existing arcane spellcasting class")
}
if advancesSpellcastingAtLevel(classRow, "DivSpellLvlMod", level) {
notes = append(notes, "+1 level of existing divine spellcasting class")
}
return strings.Join(notes, "; ")
}
func advancesSpellcastingAtLevel(classRow map[string]any, field string, level int) bool {
mod, err := asInt(fieldValue(classRow, field))
if err != nil || mod <= 0 {
return false
}
return roundedSpellcastingLevelAdvancement(level, mod) > roundedSpellcastingLevelAdvancement(level-1, mod)
}
func roundedSpellcastingLevelAdvancement(level, mod int) int {
if level <= 0 || mod <= 0 {
return 0
}
return (level*2 + mod) / (mod * 2)
}
func (ctx *wikiContext) classProgressionNote(classRow map[string]any, level int) string { func (ctx *wikiContext) classProgressionNote(classRow map[string]any, level int) string {
meta, err := parseExistingMetadata(classRow) meta, err := parseExistingMetadata(classRow)
if err != nil || meta == nil { if err != nil || meta == nil {