Class feat injections moved to yaml

This commit is contained in:
2026-05-24 20:23:08 +02:00
parent 5fa5246e9f
commit b2a58cb011
8 changed files with 429 additions and 86 deletions
+83
View File
@@ -191,6 +191,45 @@ topdata:
}
}
func TestEffectiveConfigIncludesTopDataClassFeatInjections(t *testing.T) {
root := t.TempDir()
writeProjectFile(t, filepath.Join(root, ConfigFile), `
module:
name: Test Module
resref: testmod
topdata:
source: topdata
class_feat_injections:
global_feats:
- feat: feat:literate
list: 3
granted_on_level: 1
on_menu: 0
unless_present: [feat:illiterate]
class_skill_masterfeats:
- masterfeat: masterfeats:skillfocus
list: 1
granted_on_level: -1
on_menu: 0
`)
proj, err := Load(root)
if err != nil {
t.Fatalf("Load returned error: %v", err)
}
injections := proj.EffectiveConfig().TopData.ClassFeatInjections
if len(injections.GlobalFeats) != 1 || len(injections.ClassSkillMasterfeats) != 1 {
t.Fatalf("expected configured class feat injections, got %#v", injections)
}
if got := injections.GlobalFeats[0]; got.Feat != "feat:literate" || got.List != "3" || got.GrantedOnLevel != "1" || got.OnMenu != "0" || len(got.UnlessPresent) != 1 || got.UnlessPresent[0] != "feat:illiterate" {
t.Fatalf("unexpected global class feat injection: %#v", got)
}
if got := injections.ClassSkillMasterfeats[0]; got.Masterfeat != "masterfeats:skillfocus" || got.List != "1" || got.GrantedOnLevel != "-1" || got.OnMenu != "0" {
t.Fatalf("unexpected class skill masterfeat injection: %#v", got)
}
}
func TestValidateLayoutRejectsInvalidTopDataValueEncodings(t *testing.T) {
root := t.TempDir()
mkdirAll(t, filepath.Join(root, "topdata"))
@@ -239,6 +278,50 @@ func TestValidateLayoutRejectsInvalidTopDataValueEncodings(t *testing.T) {
}
}
func TestValidateLayoutRejectsInvalidTopDataClassFeatInjections(t *testing.T) {
root := t.TempDir()
mkdirAll(t, filepath.Join(root, "topdata"))
mkdirAll(t, filepath.Join(root, "build"))
proj := &Project{
Root: root,
Config: Config{
Module: ModuleConfig{Name: "Test", ResRef: "test"},
Paths: PathConfig{Build: "build"},
TopData: TopDataConfig{
Source: "topdata",
ClassFeatInjections: TopDataClassFeatInjectionConfig{
GlobalFeats: []TopDataClassFeatGlobalRule{
{Feat: "literate", List: "3", GrantedOnLevel: "1", OnMenu: "0", UnlessPresent: []string{"illiterate"}},
{Feat: "feat:valid", List: "", GrantedOnLevel: "x", OnMenu: "0"},
},
ClassSkillMasterfeats: []TopDataClassFeatMasterfeatRule{
{Masterfeat: "skillfocus", List: "1", GrantedOnLevel: "-1", OnMenu: ""},
},
},
},
},
}
err := proj.ValidateLayout()
if err == nil {
t.Fatal("expected invalid class feat injection validation error")
}
text := err.Error()
for _, want := range []string{
"topdata.class_feat_injections.global_feats[0].feat",
"topdata.class_feat_injections.global_feats[0].unless_present[0]",
"topdata.class_feat_injections.global_feats[1].list",
"topdata.class_feat_injections.global_feats[1].granted_on_level",
"topdata.class_feat_injections.class_skill_masterfeats[0].masterfeat",
"topdata.class_feat_injections.class_skill_masterfeats[0].on_menu",
} {
if !strings.Contains(text, want) {
t.Fatalf("expected validation error %q, got %v", want, err)
}
}
}
func TestScanUsesYAMLMusicConvertExtensionsWithinConfiguredDatasetRoots(t *testing.T) {
root := t.TempDir()
if err := os.MkdirAll(filepath.Join(root, "assets", "audio", "westgate"), 0o755); err != nil {