Files
bl/common/data/xmlres/skill.go
昔念 3739c2a6f9
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(xmlres): 使用rawFlexibleString替换字符串类型以支持灵活解析

- 将EffectArg结构体中的SideEffectArg字段类型从string改为rawFlexibleString
- 将Move结构体中的Name字段类型从string改为rawFlexibleString,并更新反序列化逻辑
- 统一配置文件解析方式,移除磁盘回退机制并简化readConfigContent函数
- 移除不再使用的导入包和变量

fix(fight): 修复战斗系统中的空技能和无效数据问题

- 在
2026-04-13 11:28:30 +08:00

218 lines
7.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package xmlres
import (
"encoding/json"
"encoding/xml"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
)
func ParseSideEffectArgs(argsStr string) []int {
if argsStr == "" {
return []int{}
}
parts := strings.Fields(argsStr)
args := make([]int, 0, len(parts))
for _, part := range parts {
if num, err := strconv.Atoi(part); err == nil {
args = append(args, num)
}
}
return args
}
// MovesTbl 定义 XML 根元素
type MovesTbl struct {
XMLName xml.Name `xml:"MovesTbl"`
Moves []Move `xml:"Moves>Move"`
EFF []SideEffect `xml:"SideEffects>SideEffect"`
}
type MovesJSON struct {
MovesTbl MovesJSONRoot `json:"MovesTbl"`
}
type MovesJSONRoot struct {
Moves struct {
Move []Move `json:"Move"`
} `json:"Moves"`
SideEffects struct {
SideEffect []SideEffect `json:"SideEffect"`
} `json:"SideEffects"`
}
type MovesMap struct {
XMLName xml.Name `xml:"MovesTbl"`
Moves map[int]Move
EFF []SideEffect `xml:"SideEffects>SideEffect"`
}
type rawFlexibleString string
func (s *rawFlexibleString) UnmarshalJSON(data []byte) error {
text := strings.TrimSpace(string(data))
if text == "" || text == "null" {
*s = ""
return nil
}
if len(text) >= 2 && text[0] == '"' && text[len(text)-1] == '"' {
var decoded string
if err := json.Unmarshal(data, &decoded); err != nil {
return err
}
*s = rawFlexibleString(decoded)
return nil
}
*s = rawFlexibleString(text)
return nil
}
// Move 定义单个技能的结构
type Move struct {
ID int `xml:"ID,attr" json:"ID"`
Name string `xml:"Name,attr" json:"Name"`
Category int `xml:"Category,attr" json:"Category"` //属性
Type int `xml:"Type,attr" json:"Type"` //类型
Power int `xml:"Power,attr" json:"Power"` //威力
MaxPP int `xml:"MaxPP,attr" json:"MaxPP"` //最大PP
Accuracy int `xml:"Accuracy,attr" json:"Accuracy"` //命中率
CritRate int `xml:"CritRate,attr,omitempty" json:"CritRate,omitempty"` //暴击率
Priority int `xml:"Priority,attr,omitempty" json:"Priority,omitempty"` //优先级
MustHit int `xml:"MustHit,attr,omitempty" json:"MustHit,omitempty"` //是否必中
SwapElemType int `xml:"SwapElemType,attr,omitempty" json:"SwapElemType,omitempty"` //技能交换属性
CopyElemType int `xml:"CopyElemType,attr,omitempty" json:"CopyElemType,omitempty"` // 技能复制属性
CritAtkFirst int `xml:"CritAtkFirst,attr,omitempty" json:"CritAtkFirst,omitempty"` // 先出手时必定致命一击
CritAtkSecond int `xml:"CritAtkSecond,attr,omitempty" json:"CritAtkSecond,omitempty"` //后出手时必定致命一击
CritSelfHalfHp int `xml:"CritSelfHalfHp,attr,omitempty" json:"CritSelfHalfHp,omitempty"` //自身体力低于一半时必定致命一击
CritFoeHalfHp int `xml:"CritFoeHalfHp,attr,omitempty" json:"CritFoeHalfHp,omitempty"` //对方体力低于一半时必定致命一击
DmgBindLv int `xml:"DmgBindLv,attr,omitempty" json:"DmgBindLv,omitempty"` //使对方受到的伤害值等于自身的等级
PwrBindDv int `xml:"PwrBindDv,attr,omitempty" json:"PwrBindDv,omitempty"` //威力power取决于自身的潜力个体值
PwrDouble int `xml:"PwrDouble,attr,omitempty" json:"PwrDouble,omitempty"` //攻击时,若对方处于异常状态, 则威力翻倍;
DmgBindHpDv int `xml:"DmgBindHpDv,attr,omitempty" json:"DmgBindHpDv,omitempty"` //使对方受到的伤害值等于自身的体力值
SideEffect string `xml:"SideEffect,attr,omitempty" json:"SideEffect,omitempty"`
SideEffectArg string `xml:"SideEffectArg,attr,omitempty" json:"SideEffectArg,omitempty"`
SideEffectS []int
SideEffectArgS []int
AtkNum int `xml:"AtkNum,attr,omitempty" json:"AtkNum,omitempty"`
AtkType int `xml:"AtkType,attr,omitempty" json:"AtkType,omitempty"` // 0:所有人 1:仅己方 2:仅对方 3:仅自己
Url string `xml:"Url,attr,omitempty" json:"Url,omitempty"`
Info string `xml:"info,attr,omitempty" json:"info,omitempty"`
CD *int `xml:"CD,attr" json:"CD"`
}
func (m *Move) UnmarshalJSON(data []byte) error {
type moveAlias struct {
ID int `json:"ID"`
Name rawFlexibleString `json:"Name"`
Category int `json:"Category"`
Type int `json:"Type"`
Power int `json:"Power"`
MaxPP int `json:"MaxPP"`
Accuracy int `json:"Accuracy"`
CritRate int `json:"CritRate,omitempty"`
Priority int `json:"Priority,omitempty"`
MustHit int `json:"MustHit,omitempty"`
SwapElemType int `json:"SwapElemType,omitempty"`
CopyElemType int `json:"CopyElemType,omitempty"`
CritAtkFirst int `json:"CritAtkFirst,omitempty"`
CritAtkSecond int `json:"CritAtkSecond,omitempty"`
CritSelfHalfHp int `json:"CritSelfHalfHp,omitempty"`
CritFoeHalfHp int `json:"CritFoeHalfHp,omitempty"`
DmgBindLv int `json:"DmgBindLv,omitempty"`
PwrBindDv int `json:"PwrBindDv,omitempty"`
PwrDouble int `json:"PwrDouble,omitempty"`
DmgBindHpDv int `json:"DmgBindHpDv,omitempty"`
SideEffect rawFlexibleString `json:"SideEffect,omitempty"`
SideEffectArg rawFlexibleString `json:"SideEffectArg,omitempty"`
AtkNum int `json:"AtkNum,omitempty"`
AtkType int `json:"AtkType,omitempty"`
Url string `json:"Url,omitempty"`
Info string `json:"info,omitempty"`
CD *int `json:"CD"`
}
var aux moveAlias
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
*m = Move{
ID: aux.ID,
Name: string(aux.Name),
Category: aux.Category,
Type: aux.Type,
Power: aux.Power,
MaxPP: aux.MaxPP,
Accuracy: aux.Accuracy,
CritRate: aux.CritRate,
Priority: aux.Priority,
MustHit: aux.MustHit,
SwapElemType: aux.SwapElemType,
CopyElemType: aux.CopyElemType,
CritAtkFirst: aux.CritAtkFirst,
CritAtkSecond: aux.CritAtkSecond,
CritSelfHalfHp: aux.CritSelfHalfHp,
CritFoeHalfHp: aux.CritFoeHalfHp,
DmgBindLv: aux.DmgBindLv,
PwrBindDv: aux.PwrBindDv,
PwrDouble: aux.PwrDouble,
DmgBindHpDv: aux.DmgBindHpDv,
SideEffect: string(aux.SideEffect),
SideEffectArg: string(aux.SideEffectArg),
AtkNum: aux.AtkNum,
AtkType: aux.AtkType,
Url: aux.Url,
Info: aux.Info,
CD: aux.CD,
}
return nil
}
type SideEffect struct {
ID int `xml:"ID,attr" json:"ID"`
Help string `xml:"help,attr" json:"help"`
Des string `xml:"des,attr" json:"des"`
}
// ReadHTTPFile 通过HTTP GET请求获取远程文件内容
// url: 远程文件的URL地址
// 返回文件内容字节流和可能的错误
func ReadHTTPFile(url string) ([]byte, error) {
// 创建HTTP客户端并设置超时时间避免无限等待
client := &http.Client{
Timeout: 30 * time.Second, // 30秒超时
}
// 发送GET请求
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close() // 确保响应体被关闭
// 检查响应状态码
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("请求返回非成功状态码: %d", resp.StatusCode)
}
// 读取响应体内容
content, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取内容失败: %w", err)
}
return content, nil
}