package element import ( _ "embed" "encoding/json" "fmt" "strings" ) //go:embed data/skillTypes.json var skillTypesJSON []byte //go:embed data/typesRelation.json var typesRelationJSON []byte type skillTypesFile struct { Root struct { Item []skillTypeItem `json:"item"` } `json:"root"` } type skillTypeItem struct { ID int `json:"id"` CN string `json:"cn"` Att string `json:"att"` IsDou int `json:"is_dou"` EN []string `json:"en"` } type typeRelationFile struct { Root struct { Relation []typeRelationItem `json:"relation"` } `json:"root"` } type typeRelationItem struct { Type string `json:"type"` Opponent []typeRelationOpponent `json:"opponent"` } type typeRelationOpponent struct { Type string `json:"type"` Multiple float64 `json:"multiple"` } // 初始化全属性克制矩阵。数据来自 seer-types-relation,默认关系为 1.0。 func initFullTableMatrix() { for i := 0; i < maxMatrixSize; i++ { for j := 0; j < maxMatrixSize; j++ { matrix[i][j] = 1.0 } } enToID := initSkillTypes() initTypeRelations(enToID) } func initSkillTypes() map[string]int { var cfg skillTypesFile mustUnmarshalJSON(skillTypesJSON, &cfg, "skillTypes.json") enToID := make(map[string]int, len(cfg.Root.Item)) for _, item := range cfg.Root.Item { mustValidElementID(item.ID, "skill type") if len(item.EN) == 0 { panic(fmt.Sprintf("skill type %d has no en name", item.ID)) } elementNameMap[item.ID] = strings.ToUpper(strings.Join(item.EN, "_")) if item.IsDou == 0 { validSingleElementIDs[item.ID] = true enToID[item.EN[0]] = item.ID } } for _, item := range cfg.Root.Item { if item.IsDou == 0 { continue } if len(item.EN) != 2 { panic(fmt.Sprintf("dual skill type %d must have two en names", item.ID)) } primaryID, ok := enToID[item.EN[0]] if !ok { panic(fmt.Sprintf("dual skill type %d references unknown primary type %q", item.ID, item.EN[0])) } secondaryID, ok := enToID[item.EN[1]] if !ok { panic(fmt.Sprintf("dual skill type %d references unknown secondary type %q", item.ID, item.EN[1])) } dualElementMap[item.ID] = [2]int{primaryID, secondaryID} } return enToID } func initTypeRelations(enToID map[string]int) { var cfg typeRelationFile mustUnmarshalJSON(typesRelationJSON, &cfg, "typesRelation.json") for _, relation := range cfg.Root.Relation { attackerID, ok := enToID[relation.Type] if !ok { panic(fmt.Sprintf("type relation references unknown attacker type %q", relation.Type)) } for _, opponent := range relation.Opponent { defenderID, ok := enToID[opponent.Type] if !ok { panic(fmt.Sprintf("type relation references unknown defender type %q", opponent.Type)) } matrix[attackerID][defenderID] = opponent.Multiple } } } func mustUnmarshalJSON(data []byte, target any, name string) { if err := json.Unmarshal(data, target); err != nil { panic(fmt.Sprintf("parse %s: %v", name, err)) } } func mustValidElementID(id int, kind string) { if id <= 0 || id >= maxMatrixSize { panic(fmt.Sprintf("%s id out of range: %d", kind, id)) } }