Class feat injections moved to yaml
This commit is contained in:
@@ -709,6 +709,7 @@ func TestResolveNativeDatasetPreservesScalarTableReferenceBehavior(t *testing.T)
|
||||
map[string]map[string]any{"classes:barbarian": dataset.Rows[0]},
|
||||
tableRegistry,
|
||||
nil,
|
||||
project.TopDataClassFeatInjectionConfig{},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("resolveNativeDataset failed: %v", err)
|
||||
@@ -1243,6 +1244,95 @@ func TestBuildNativeExpandsClassesFeatClassskillsFilter(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildNativeAppliesConfiguredClassFeatInjections(t *testing.T) {
|
||||
root := testProjectRoot(t)
|
||||
mkdirAll(t, filepath.Join(root, "topdata", "data", "classes", "feats"))
|
||||
mkdirAll(t, filepath.Join(root, "topdata", "data", "classes", "skills"))
|
||||
mkdirAll(t, filepath.Join(root, "topdata", "data", "feat"))
|
||||
mkdirAll(t, filepath.Join(root, "topdata", "data", "masterfeats"))
|
||||
writeFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "classes", "feats", "fighter.json"), `{
|
||||
"key": "classes/feats:fighter",
|
||||
"output": "cls_feat_fighter.2da",
|
||||
"columns": ["FeatLabel", "FeatIndex", "List", "GrantedOnLevel", "OnMenu"],
|
||||
"rows": [
|
||||
{"FeatIndex": {"id": "feat:illiterate"}, "List": "3", "GrantedOnLevel": "1", "OnMenu": "0"}
|
||||
]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "classes", "skills", "fighter.json"), `{
|
||||
"key": "classes/skills:fighter",
|
||||
"output": "cls_skill_fighter.2da",
|
||||
"columns": ["SkillLabel", "SkillIndex", "ClassSkill"],
|
||||
"rows": [
|
||||
{"key": "skills:athletics", "SkillLabel": "Athletics", "SkillIndex": {"id": "skills:athletics"}, "ClassSkill": "1"},
|
||||
{"key": "skills:persuade", "SkillLabel": "Persuade", "SkillIndex": {"id": "skills:persuade"}, "ClassSkill": "1"},
|
||||
{"key": "skills:alchemy", "SkillLabel": "Alchemy", "SkillIndex": {"id": "skills:alchemy"}, "ClassSkill": "0"}
|
||||
]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "base.json"), `{
|
||||
"output": "feat.2da",
|
||||
"columns": ["LABEL", "FEAT", "DESCRIPTION", "MASTERFEAT", "REQSKILL", "SUCCESSOR"],
|
||||
"rows": [
|
||||
{"id": 1, "key": "feat:illiterate", "LABEL": "Illiterate", "FEAT": "100", "DESCRIPTION": "101", "MASTERFEAT": "****", "REQSKILL": "****", "SUCCESSOR": "****"},
|
||||
{"id": 2, "key": "feat:literate", "LABEL": "Literate", "FEAT": "102", "DESCRIPTION": "103", "MASTERFEAT": "****", "REQSKILL": "****", "SUCCESSOR": "****"},
|
||||
{"id": 3, "key": "feat:customglobal", "LABEL": "CustomGlobal", "FEAT": "104", "DESCRIPTION": "105", "MASTERFEAT": "****", "REQSKILL": "****", "SUCCESSOR": "****"},
|
||||
{"id": 10, "key": "feat:skillfocus_athletics", "LABEL": "SkillFocusAthletics", "FEAT": "200", "DESCRIPTION": "201", "MASTERFEAT": "4", "REQSKILL": "skills:athletics", "SUCCESSOR": "****"},
|
||||
{"id": 11, "key": "feat:skillfocus_persuade", "LABEL": "SkillFocusPersuade", "FEAT": "202", "DESCRIPTION": "203", "MASTERFEAT": "4", "REQSKILL": "skills:persuade", "SUCCESSOR": "****"},
|
||||
{"id": 12, "key": "feat:skillfocus_alchemy", "LABEL": "SkillFocusAlchemy", "FEAT": "204", "DESCRIPTION": "205", "MASTERFEAT": "4", "REQSKILL": "skills:alchemy", "SUCCESSOR": "****"}
|
||||
]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "lock.json"), `{
|
||||
"feat:illiterate": 1,
|
||||
"feat:literate": 2,
|
||||
"feat:customglobal": 3,
|
||||
"feat:skillfocus_athletics": 10,
|
||||
"feat:skillfocus_persuade": 11,
|
||||
"feat:skillfocus_alchemy": 12
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "masterfeats", "base.json"), `{
|
||||
"output": "masterfeats.2da",
|
||||
"columns": ["LABEL", "STRREF", "DESCRIPTION", "ICON"],
|
||||
"rows": [
|
||||
{"id": 4, "key": "masterfeats:skillfocus", "LABEL": "SkillFocus", "STRREF": "6493", "DESCRIPTION": "426", "ICON": "ife_skfoc"}
|
||||
]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "masterfeats", "lock.json"), `{"masterfeats:skillfocus": 4}`+"\n")
|
||||
|
||||
p := testProject(root)
|
||||
p.Config.TopData.ReferenceBuilder = ""
|
||||
p.Config.TopData.ClassFeatInjections = project.TopDataClassFeatInjectionConfig{
|
||||
GlobalFeats: []project.TopDataClassFeatGlobalRule{
|
||||
{Feat: "feat:literate", List: "3", GrantedOnLevel: "1", OnMenu: "0", UnlessPresent: []string{"feat:ill_iterate"}},
|
||||
{Feat: "feat:custom_global", List: "3", GrantedOnLevel: "2", OnMenu: "1"},
|
||||
},
|
||||
ClassSkillMasterfeats: []project.TopDataClassFeatMasterfeatRule{
|
||||
{Masterfeat: "masterfeats:skillfocus", List: "1", GrantedOnLevel: "2", OnMenu: "0"},
|
||||
},
|
||||
}
|
||||
result, err := BuildNative(p, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildNative failed: %v", err)
|
||||
}
|
||||
|
||||
got, err := os.ReadFile(filepath.Join(result.Output2DADir, "cls_feat_fighter.2da"))
|
||||
if err != nil {
|
||||
t.Fatalf("read cls_feat_fighter.2da: %v", err)
|
||||
}
|
||||
text := string(got)
|
||||
if !strings.Contains(text, "CustomGlobal\t3\t3\t2\t1\n") {
|
||||
t.Fatalf("expected configured global feat injection, got:\n%s", text)
|
||||
}
|
||||
if strings.Contains(text, "Literate\t2\t3\t1\t0\n") {
|
||||
t.Fatalf("expected literate injection to be skipped when illiterate is present, got:\n%s", text)
|
||||
}
|
||||
if !strings.Contains(text, "SkillFocusAthletics\t10\t1\t2\t0\n") || !strings.Contains(text, "SkillFocusPersuade\t11\t1\t2\t0\n") {
|
||||
t.Fatalf("expected configured class-skill masterfeat expansion, got:\n%s", text)
|
||||
}
|
||||
if strings.Contains(text, "SkillFocusAlchemy") {
|
||||
t.Fatalf("expected non-class skill focus to be filtered out, got:\n%s", text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCanonicalDatasetKeyMatchesMasterfeatAliases(t *testing.T) {
|
||||
keyToID := map[string]int{
|
||||
"masterfeats:skill_focus": 4,
|
||||
|
||||
Reference in New Issue
Block a user