Family Expansions

This commit is contained in:
2026-04-13 23:49:59 +02:00
parent 129602a482
commit 0c63dfc711
8 changed files with 722 additions and 374 deletions
+20 -71
View File
@@ -500,35 +500,11 @@ func validateFeatGeneratedFile(path string, obj map[string]any, report *Validati
})
return
}
if !slices.Contains([]string{
"skill_focus",
"greater_skill_focus",
"weapon_focus",
"weapon_specialization",
"greater_weapon_focus",
"greater_weapon_specialization",
"improved_critical",
"overwhelming_critical",
"proficiencies",
"special_attacks",
}, family) {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("unsupported feat generated family %q", family),
})
if isFamilyExpansionObject(obj) {
validateFeatFamilyExpansionFile(path, obj, report)
return
}
switch family {
case "skill_focus", "greater_skill_focus":
validateFeatCompactGeneratorFile(path, obj, report, true)
case "weapon_focus",
"weapon_specialization",
"greater_weapon_focus",
"greater_weapon_specialization",
"improved_critical",
"overwhelming_critical":
validateFeatCompactGeneratorFile(path, obj, report, false)
default:
_, hasEntries := obj["entries"]
_, hasOverrides := obj["overrides"]
@@ -549,69 +525,42 @@ func validateFeatGeneratedFile(path string, obj map[string]any, report *Validati
}
}
func validateFeatCompactGeneratorFile(path string, obj map[string]any, report *ValidationReport, skillsDriven bool) {
familyKey, ok := obj["family_key"].(string)
if !ok || strings.TrimSpace(familyKey) == "" {
func validateFeatFamilyExpansionFile(path string, obj map[string]any, report *ValidationReport) {
spec, err := parseFamilyExpansionSpec(path, obj)
if err != nil {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "compact feat generated file must contain a non-empty family_key string",
Message: err.Error(),
})
return
}
template, ok := obj["template"].(string)
if !ok || strings.TrimSpace(template) == "" {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "compact feat generated file must contain a non-empty template string",
})
} else if !strings.HasPrefix(template, "masterfeats:") {
if !strings.HasPrefix(spec.Template, "masterfeats:") {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "compact feat generated template must start with masterfeats:",
})
}
childSource, err := parseFamilyExpansionSource(obj["child_source"])
if err != nil {
if spec.NamePrefix == "" {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("compact feat generated file %v", err),
})
return
}
if skillsDriven {
if childSource.Dataset != "skills" {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "skill feat generated child_source.dataset must be skills",
})
}
if raw, ok := obj["overrides"]; ok {
if _, ok := raw.(map[string]any); !ok {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "compact feat generated overrides must be an object keyed by skills:*",
})
}
}
return
}
if childSource.Dataset != "baseitems" {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "weapon feat generated child_source.dataset must be baseitems",
Message: "family expansion file must contain a non-empty name_prefix",
})
}
if childSource.Column == "" {
if spec.LabelPrefix == "" {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "weapon feat generated child_source.column must be a non-empty string",
Message: "family expansion file must contain a non-empty label_prefix",
})
}
if spec.ConstantPrefix == "" {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "family expansion file must contain a non-empty constant_prefix",
})
}
if raw, ok := obj["overrides"]; ok {
@@ -619,7 +568,7 @@ func validateFeatCompactGeneratorFile(path string, obj map[string]any, report *V
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: "weapon feat generated overrides must be an object keyed by baseitems:*",
Message: "family expansion overrides must be an object keyed by source dataset key",
})
}
}