fix(topdata): encode spell radial feat IDs (#37)
## Summary
- add explicit `{"spellradial": {"id": "feat:key"}}` authoring syntax for `spells.2da` `FeatID`
- resolve spell and feat rows dynamically and emit NWN:EE packed subradial values
- reject malformed or misplaced spell-radial references
## Verification
- `go test ./internal/topdata`
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Reviewed-on: #37
Reviewed-by: archvillainette <vickydotbat@tutamail.com>
Reviewed-by: xtul <mpiasecki720@protonmail.com>
Co-authored-by: gitea-bot <gitea-bot@noreply.git.westgate.pw>
Co-committed-by: gitea-bot <gitea-bot@noreply.git.westgate.pw>
This commit is contained in:
@@ -4712,6 +4712,24 @@ func (r *valueResolver) resolveValue(row map[string]any, field string, value any
|
||||
|
||||
switch typed := value.(type) {
|
||||
case map[string]any:
|
||||
if radial, ok := typed["spellradial"].(map[string]any); ok && len(typed) == 1 {
|
||||
if r.dataset.Name != "spells" || field != "FeatID" {
|
||||
return tlkCompiledValue{}, fmt.Errorf("spellradial reference is only valid for spells.FeatID")
|
||||
}
|
||||
radialKey, ok := radial["id"].(string)
|
||||
if !ok || len(radial) != 1 {
|
||||
return tlkCompiledValue{}, fmt.Errorf("spellradial reference requires exactly one id")
|
||||
}
|
||||
featID, ok := r.keyToID[radialKey]
|
||||
if !ok {
|
||||
return tlkCompiledValue{}, fmt.Errorf("unknown spellradial feat reference: %s", radialKey)
|
||||
}
|
||||
spellID, ok := row["id"].(int)
|
||||
if !ok {
|
||||
return tlkCompiledValue{}, fmt.Errorf("spellradial reference requires a numeric spell row id")
|
||||
}
|
||||
return tlkCompiledValue{Value: spellID<<16 + featID}, nil
|
||||
}
|
||||
if encoding, ok := r.valueEncodingForField(field); ok {
|
||||
mode := strings.TrimSpace(encoding.Mode)
|
||||
_, hasList := typed["list"]
|
||||
|
||||
@@ -11887,7 +11887,7 @@ func TestBuildSupportsCanonicalSpells(t *testing.T) {
|
||||
"spells:disarm": {
|
||||
"Label": "Disarm",
|
||||
"Name": "501",
|
||||
"FeatID": {"id": "feat:disarm"},
|
||||
"FeatID": {"spellradial": {"id": "feat:specialattacks"}},
|
||||
"Master": {"id": "spells:specialattacks"},
|
||||
"Category": {"ref": "spells:specialattacks", "field": "Category"}
|
||||
}
|
||||
@@ -11939,7 +11939,7 @@ func TestBuildSupportsCanonicalSpells(t *testing.T) {
|
||||
!strings.Contains(text, "\t1000\t") ||
|
||||
!strings.Contains(text, "841\tDisarm\t501") ||
|
||||
!strings.Contains(text, "\t840\t") ||
|
||||
!strings.Contains(text, "\t1001\t") ||
|
||||
!strings.Contains(text, "\t55116776\t") ||
|
||||
!strings.Contains(text, "849\tBard_Fascinate\t600") ||
|
||||
!strings.Contains(text, "\t601\t") ||
|
||||
!strings.Contains(text, "\t602\t") ||
|
||||
|
||||
Reference in New Issue
Block a user