Skill focus identity resolution
This commit is contained in:
@@ -9594,6 +9594,143 @@ func TestBuildGeneratedSkillFocusUsesOverriddenCanonicalSkillKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildGeneratedSkillFocusReusesHardcodedSkillFeatRowsForRenamedSkills(t *testing.T) {
|
||||
root := testProjectRoot(t)
|
||||
writeFeatGeneratedHarness(t, root, map[string]string{
|
||||
"skill_focus.json": `{
|
||||
"family": "skill_focus",
|
||||
"family_key": "skill_focus",
|
||||
"template": "masterfeats:skillfocus",
|
||||
"name_prefix": "Skill Focus",
|
||||
"label_prefix": "FEAT_SKILL_FOCUS",
|
||||
"constant_prefix": "FEAT_SKILL_FOCUS",
|
||||
"default_fields": {
|
||||
"CRValue": "0.5",
|
||||
"ReqSkillMinRanks": "1",
|
||||
"ALLCLASSESCANUSE": "1",
|
||||
"TOOLSCATEGORIES": "6",
|
||||
"PreReqEpic": "0",
|
||||
"ReqAction": "1"
|
||||
},
|
||||
"apply_after_modules": true,
|
||||
"child_ref_field": "REQSKILL",
|
||||
"child_source": {
|
||||
"dataset": "skills",
|
||||
"predicate": "accessible"
|
||||
},
|
||||
"overrides": {
|
||||
"skills:craft_woodworking": {
|
||||
"ICON": "ife_X1SFCrTrap"
|
||||
}
|
||||
}
|
||||
}` + "\n",
|
||||
"greater_skill_focus.json": `{
|
||||
"family": "greater_skill_focus",
|
||||
"family_key": "greater_skill_focus",
|
||||
"template": "masterfeats:greaterskillfocus",
|
||||
"name_prefix": "Greater Skill Focus",
|
||||
"label_prefix": "FEAT_GREATER_SKILL_FOCUS",
|
||||
"constant_prefix": "FEAT_GREATER_SKILL_FOCUS",
|
||||
"legacy_family_keys": ["epic_skill_focus"],
|
||||
"default_fields": {
|
||||
"CRValue": "0.2",
|
||||
"ReqSkillMinRanks": "15",
|
||||
"ALLCLASSESCANUSE": "1",
|
||||
"TOOLSCATEGORIES": "6",
|
||||
"PreReqEpic": "0",
|
||||
"ReqAction": "1"
|
||||
},
|
||||
"apply_after_modules": true,
|
||||
"child_ref_field": "REQSKILL",
|
||||
"child_source": {
|
||||
"dataset": "skills",
|
||||
"predicate": "accessible"
|
||||
},
|
||||
"overrides": {
|
||||
"skills:craft_woodworking": {
|
||||
"ICON": "ife_X2EpSkFCrTr"
|
||||
}
|
||||
}
|
||||
}` + "\n",
|
||||
}, map[string]int{
|
||||
"feat:skill_focus_craft_trap": 407,
|
||||
"feat:skill_focus_craft_woodworking": 1372,
|
||||
"feat:greater_skill_focus_craft_trap": 590,
|
||||
"feat:greater_skill_focus_craft_woodworking": 1314,
|
||||
})
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "skills", "base.json"), `{
|
||||
"output": "skills.2da",
|
||||
"columns": ["Label", "Name", "Description", "Icon", "Untrained", "KeyAbility", "ArmorCheckPenalty", "AllClassesCanUse", "Category", "MaxCR", "Constant", "HostileSkill", "HideFromLevelUp"],
|
||||
"rows": [
|
||||
{"id": 22, "key": "skills:craft_woodworking", "Label": "CraftWoodworking", "Name": "2000", "Description": "2001", "Icon": "isk_craftwood", "Untrained": "1", "KeyAbility": "INT", "ArmorCheckPenalty": "0", "AllClassesCanUse": "1", "Category": "****", "MaxCR": "****", "Constant": "SKILL_CRAFT_WOODWORKING", "HostileSkill": "0", "HideFromLevelUp": "0"}
|
||||
]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "skills", "lock.json"), `{"skills:craft_woodworking":22}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "base.json"), `{
|
||||
"output": "feat.2da",
|
||||
"compare_reference": false,
|
||||
"columns": [
|
||||
"LABEL","FEAT","DESCRIPTION","ICON","MINATTACKBONUS","MINSTR","MINDEX","MININT","MINWIS","MINCON","MINCHA",
|
||||
"MINSPELLLVL","PREREQFEAT1","PREREQFEAT2","GAINMULTIPLE","EFFECTSSTACK","ALLCLASSESCANUSE","CATEGORY","MAXCR",
|
||||
"SPELLID","SUCCESSOR","CRValue","USESPERDAY","MASTERFEAT","TARGETSELF","OrReqFeat0","OrReqFeat1","OrReqFeat2",
|
||||
"OrReqFeat3","OrReqFeat4","REQSKILL","ReqSkillMinRanks","REQSKILL2","ReqSkillMinRanks2","Constant","TOOLSCATEGORIES",
|
||||
"HostileFeat","MinLevel","MinLevelClass","MaxLevel","MinFortSave","PreReqEpic","ReqAction"
|
||||
],
|
||||
"rows": [
|
||||
{"id": 407, "key": "feat:skill_focus_craft_trap", "LABEL": "FEAT_SKILL_FOCUS_CRAFT_TRAP", "REQSKILL": 22, "MASTERFEAT": 4, "Constant": "FEAT_SKILL_FOCUS_CRAFT_TRAP"},
|
||||
{"id": 590, "key": "feat:epic_skill_focus_craft_trap", "LABEL": "FEAT_EPIC_SKILL_FOCUS_CRAFT_TRAP", "REQSKILL": 22, "MASTERFEAT": 5, "Constant": "FEAT_EPIC_SKILL_FOCUS_CRAFT_TRAP"}
|
||||
]
|
||||
}`+"\n")
|
||||
|
||||
result, err := BuildNative(testProject(root), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildNative failed: %v", err)
|
||||
}
|
||||
got, err := os.ReadFile(filepath.Join(result.Output2DADir, "feat.2da"))
|
||||
if err != nil {
|
||||
t.Fatalf("read feat.2da: %v", err)
|
||||
}
|
||||
text := string(got)
|
||||
if !strings.Contains(text, "407\tFEAT_SKILL_FOCUS_CRAFT_WOODWORKING\t") {
|
||||
t.Fatalf("expected generated skill focus woodworking to reuse hardcoded Craft Trap row 407, got:\n%s", text)
|
||||
}
|
||||
if !strings.Contains(text, "590\tFEAT_GREATER_SKILL_FOCUS_CRAFT_WOODWORKING\t") {
|
||||
t.Fatalf("expected generated greater skill focus woodworking to reuse hardcoded epic Craft Trap row 590, got:\n%s", text)
|
||||
}
|
||||
for _, unexpected := range []string{
|
||||
"1372\tFEAT_SKILL_FOCUS_CRAFT_WOODWORKING\t",
|
||||
"1314\tFEAT_GREATER_SKILL_FOCUS_CRAFT_WOODWORKING\t",
|
||||
"FEAT_SKILL_FOCUS_CRAFT_TRAP\t",
|
||||
"FEAT_EPIC_SKILL_FOCUS_CRAFT_TRAP\t",
|
||||
} {
|
||||
if strings.Contains(text, unexpected) {
|
||||
t.Fatalf("expected no duplicate stale skill focus row %q, got:\n%s", unexpected, text)
|
||||
}
|
||||
}
|
||||
lockRaw, err := os.ReadFile(filepath.Join(root, "topdata", "data", "feat", "lock.json"))
|
||||
if err != nil {
|
||||
t.Fatalf("read feat lock: %v", err)
|
||||
}
|
||||
lockText := string(lockRaw)
|
||||
for _, expected := range []string{
|
||||
`"feat:skill_focus_craft_woodworking": 407`,
|
||||
`"feat:greater_skill_focus_craft_woodworking": 590`,
|
||||
} {
|
||||
if !strings.Contains(lockText, expected) {
|
||||
t.Fatalf("expected lock to contain %s, got:\n%s", expected, lockText)
|
||||
}
|
||||
}
|
||||
for _, stale := range []string{
|
||||
"feat:skill_focus_craft_trap",
|
||||
"feat:greater_skill_focus_craft_trap",
|
||||
"feat:epic_skill_focus_craft_trap",
|
||||
} {
|
||||
if strings.Contains(lockText, stale) {
|
||||
t.Fatalf("expected stale lock %s to be pruned, got:\n%s", stale, lockText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeatGeneratedContextIgnoresExplicitlyRetiredFeatKeys(t *testing.T) {
|
||||
root := testProjectRoot(t)
|
||||
writeFeatGeneratedHarness(t, root, map[string]string{
|
||||
|
||||
Reference in New Issue
Block a user