package catalogs import ( "encoding/json" "os" "path/filepath" "sync" ) var _ = json.RawMessage{} var _ = sync.Mutex{} var _ = os.ReadFile var _ = filepath.Join // // One NPC profile (character-compendium entry), projected from ProfileAgentProfileConfig.json. // MaxTrust is the profile's trust ceiling. Its observed range is 1..4, which lines // up with the small NeedTrust values in ProfileRewardConfig.json (1,2,3,4); the 100..600 entries // there belong to a different reward track, so MaxTrust is the right value to stamp on // TrustNpcInfo.TrustValue. // NoTrustPop comes from the same table: rows with it set are skipped by the // client's PopUpAgentProfile, which is why we populate the login payload instead of blasting // SyncPlayerNpcProfileActivate — that S2C pushes every profile onto a popup queue. // type NpcProfileEntry4229938 struct { Id uint32 `json:"id"` Name string `json:"name"` MaxTrust uint32 `json:"maxTrust"` NoTrustPop bool `json:"noTrustPop"` WebId uint32 `json:"webId"` AgentId uint32 `json:"agentId"` TrustTarget []uint32 `json:"trustTarget"` TrustReward []uint32 `json:"trustReward"` } // One radio song, projected from RadioSongsConfig.json. type RadioSongEntry4229938 struct { Id uint32 `json:"id"` Song string `json:"song"` Singer string `json:"singer"` Mark string `json:"mark"` } // // Build-4229938 NPC profile + radio song catalogs, read from the configured client-data // directory. Neither source table ships in the v0.3 Configs folder; both come from // 补丁和工具\ConfigDump.zip. Regenerate with _gen_profile_cfg.py. // Unlike the quest list, the client really does read these two out of the login payload: // lua/LX6/Data/Player/PlayerData/PlayerInfoMinorNpcProfileData.lua // InitPlayerInfo -> info.InfoMinor.InfoNpcProfile.NpcProfiles -> npcTrustInfo[ProfileId] // PlayerRadioSongsData.SongInfoDict is read directly by the radio UI, and // GameToClientImpl.SyncAddRadioSong refuses to do anything when it is absent. // var ( NpcProfileCatalog4229938_cacheLock sync.RWMutex NpcProfileCatalog4229938_cached = false NpcProfileCatalog4229938_entries []any ) // LoadNpcProfileCatalog4229938 loads catalog records from client config directory func LoadNpcProfileCatalog4229938(configDir string) ([]any, error) { NpcProfileCatalog4229938_cacheLock.RLock() if NpcProfileCatalog4229938_cached { defer NpcProfileCatalog4229938_cacheLock.RUnlock() return NpcProfileCatalog4229938_entries, nil } NpcProfileCatalog4229938_cacheLock.RUnlock() NpcProfileCatalog4229938_cacheLock.Lock() defer NpcProfileCatalog4229938_cacheLock.Unlock() if NpcProfileCatalog4229938_cached { return NpcProfileCatalog4229938_entries, nil } filePath := filepath.Join(configDir, "NpcProfileCatalog.json.json") data, err := os.ReadFile(filePath) if err != nil { return nil, err } var raw struct { Records []json.RawMessage `json:"records"` } if err := json.Unmarshal(data, &raw); err != nil { return nil, err } var result []any for _, item := range raw.Records { var m map[string]any if err := json.Unmarshal(item, &m); err == nil { result = append(result, m) } } NpcProfileCatalog4229938_entries = result NpcProfileCatalog4229938_cached = true return result, nil } func NpcProfileCatalog4229938_Open(file string, doc any, records any) bool { // Catalog helper NpcProfileCatalog4229938_Open return false } func NpcProfileCatalog4229938_ReadIds(row any, prop string) []uint32 { // Catalog helper NpcProfileCatalog4229938_ReadIds return nil } func NpcProfileCatalog4229938_LoadProfiles() []NpcProfileEntry4229938 { // Catalog helper NpcProfileCatalog4229938_LoadProfiles return nil } func NpcProfileCatalog4229938_LoadSongs() []RadioSongEntry4229938 { // Catalog helper NpcProfileCatalog4229938_LoadSongs return nil }