2025-07-26 02:06:08 +00:00
|
|
|
|
package model
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-08-31 00:27:07 +08:00
|
|
|
|
"blazing/common/data/xmlres"
|
2025-07-26 02:06:08 +00:00
|
|
|
|
"blazing/cool"
|
2025-08-31 00:27:07 +08:00
|
|
|
|
|
|
|
|
|
|
"time"
|
2025-07-26 02:06:08 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const TableNamePet = "pet"
|
|
|
|
|
|
|
|
|
|
|
|
// Pet mapped from table <pet>
|
|
|
|
|
|
type Pet struct {
|
|
|
|
|
|
*cool.Model
|
2025-08-31 00:27:07 +08:00
|
|
|
|
PlayerID uint32 `gorm:"not null;index:idx_pet_by_player_id;comment:'所属玩家ID'" json:"player_id"`
|
|
|
|
|
|
InBag int `gorm:"not null;comment:'是否在背包中'" json:"in_bag"` //"0为放入仓库,1为放入背包
|
|
|
|
|
|
CatchTime uint32 `gorm:"not null;comment:'捕捉时间'" json:"catch_time"`
|
2025-08-31 06:53:42 +00:00
|
|
|
|
// Owner uint32 `struc:"skip"` //仅作为存储
|
|
|
|
|
|
// FreedTime uint32 `struc:"skip"` //放生时间
|
|
|
|
|
|
//是否可交易,这里应该定义在精灵ID里
|
|
|
|
|
|
//是否上架
|
|
|
|
|
|
Data string `gorm:"type:text;not null;comment:'精灵全部数据'" json:"data"`
|
2025-08-31 00:27:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-02 00:45:29 +08:00
|
|
|
|
func LastFourElements[T any](s []T) []T {
|
|
|
|
|
|
n := len(s)
|
|
|
|
|
|
if n <= 4 {
|
|
|
|
|
|
// 切片长度小于等于4时,返回整个切片
|
|
|
|
|
|
return s
|
|
|
|
|
|
}
|
|
|
|
|
|
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
|
|
|
|
|
return s[n-4:]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 00:27:07 +08:00
|
|
|
|
// * @param petTypeId 精灵类型ID
|
|
|
|
|
|
// * @param individualValue 个体值
|
|
|
|
|
|
// * @param natureId 性格ID
|
|
|
|
|
|
// * @param abilityTypeEnum 特性类型
|
|
|
|
|
|
// * @param isShiny 是否为闪光
|
|
|
|
|
|
// * @param level 等级
|
|
|
|
|
|
// * @return 生成的精灵实体
|
2025-09-02 00:45:29 +08:00
|
|
|
|
func GenPetInfo(id, dv, natureId, abilityTypeEnum, shinyid, level uint32) *PetInfo {
|
2025-08-31 00:27:07 +08:00
|
|
|
|
|
|
|
|
|
|
p := &PetInfo{ID: id,
|
2025-09-01 01:03:46 +08:00
|
|
|
|
Shiny: shinyid, //闪光
|
|
|
|
|
|
Nature: natureId, //性格
|
2025-09-02 00:45:29 +08:00
|
|
|
|
Dv: dv,
|
2025-09-01 01:03:46 +08:00
|
|
|
|
EffectInfo: make([]PetEffectInfo, 0),
|
|
|
|
|
|
CatchTime: uint32(time.Now().Unix()),
|
|
|
|
|
|
Level: level} //等级
|
|
|
|
|
|
|
|
|
|
|
|
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{ItemID: abilityTypeEnum})
|
2025-08-31 00:27:07 +08:00
|
|
|
|
naxml := xmlres.NatureRootMap[int(natureId)]
|
2025-09-02 00:45:29 +08:00
|
|
|
|
petxml := xmlres.PetMAP[int(id)]
|
2025-08-31 00:27:07 +08:00
|
|
|
|
tttt := make([]uint32, 0)
|
|
|
|
|
|
for _, v := range petxml.LearnableMoves.Moves {
|
|
|
|
|
|
if p.Level >= uint32(v.LearningLv) {
|
|
|
|
|
|
tttt = append(tttt, uint32(v.ID))
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-02 00:45:29 +08:00
|
|
|
|
tttt = LastFourElements(tttt) //获取最后四个技能,如果不足,那就取全部技能
|
2025-08-31 00:27:07 +08:00
|
|
|
|
for i := 0; i < len(tttt); i++ {
|
|
|
|
|
|
p.SkillList[i].ID = tttt[i]
|
|
|
|
|
|
p.SkillList[i].Pp = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
p.SkillListLen = uint32(len(tttt))
|
|
|
|
|
|
// 计算各项属性
|
|
|
|
|
|
hp := p.CalculatePetHPPanelSize(
|
|
|
|
|
|
uint32(petxml.HP),
|
|
|
|
|
|
p.Dv,
|
|
|
|
|
|
p.Level,
|
|
|
|
|
|
p.EvHp,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
attack := p.CalculatePetPanelSize(
|
2025-09-01 01:03:46 +08:00
|
|
|
|
uint32(petxml.Atk),
|
2025-08-31 00:27:07 +08:00
|
|
|
|
p.Dv,
|
|
|
|
|
|
p.Level,
|
|
|
|
|
|
p.EvAttack,
|
|
|
|
|
|
naxml.AttackCorrect,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
defense := p.CalculatePetPanelSize(
|
2025-09-01 01:03:46 +08:00
|
|
|
|
uint32(petxml.Def),
|
2025-08-31 00:27:07 +08:00
|
|
|
|
p.Dv,
|
|
|
|
|
|
p.Level,
|
|
|
|
|
|
p.EvDefence,
|
|
|
|
|
|
naxml.DefenseCorrect,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
specialAttack := p.CalculatePetPanelSize(
|
2025-09-01 01:03:46 +08:00
|
|
|
|
uint32(petxml.SpAtk),
|
2025-08-31 00:27:07 +08:00
|
|
|
|
p.Dv,
|
|
|
|
|
|
p.Level,
|
|
|
|
|
|
p.EvSpecialAttack,
|
|
|
|
|
|
naxml.SaCorrect,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
specialDefense := p.CalculatePetPanelSize(
|
2025-09-01 01:03:46 +08:00
|
|
|
|
uint32(petxml.SpDef),
|
2025-08-31 00:27:07 +08:00
|
|
|
|
p.Dv,
|
|
|
|
|
|
p.Level,
|
|
|
|
|
|
p.EvSpecialDefense,
|
|
|
|
|
|
naxml.SdCorrect,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
speed := p.CalculatePetPanelSize(
|
2025-09-01 01:03:46 +08:00
|
|
|
|
uint32(petxml.Spd),
|
2025-08-31 00:27:07 +08:00
|
|
|
|
p.Dv,
|
|
|
|
|
|
p.Level,
|
|
|
|
|
|
p.EvSpeed,
|
|
|
|
|
|
naxml.SpeedCorrect,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 设置计算结果
|
|
|
|
|
|
p.MaxHp = hp
|
|
|
|
|
|
p.Hp = hp
|
|
|
|
|
|
p.Attack = attack
|
|
|
|
|
|
p.Defence = defense
|
|
|
|
|
|
p.SpecialAttack = specialAttack
|
|
|
|
|
|
p.SpecialDefence = specialDefense
|
|
|
|
|
|
p.Speed = speed
|
|
|
|
|
|
return p
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算HP面板值(无性格修正)
|
2025-08-31 07:05:18 +00:00
|
|
|
|
func (c *PetInfo) CalculatePetHPPanelSize(base, dv, level, ev uint32) uint32 {
|
2025-09-01 01:03:46 +08:00
|
|
|
|
|
|
|
|
|
|
return uint32((float64(base)*2+float64(ev)/4.0+float64(dv))*(float64(level)/100.0) + float64(level) + 10)
|
2025-08-31 00:27:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算其他属性面板值(带性格修正)
|
2025-08-31 07:05:18 +00:00
|
|
|
|
func (c *PetInfo) CalculatePetPanelSize(base, dv, level, ev uint32, natureCorrect float64) uint32 {
|
|
|
|
|
|
|
2025-09-01 01:03:46 +08:00
|
|
|
|
base1 := float64((float64(base)*2+float64(ev)/4.0+float64(dv))*(float64(level)/100.0) + 5)
|
|
|
|
|
|
return uint32(float64(base1) * natureCorrect)
|
2025-07-26 02:06:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-10 14:19:03 +08:00
|
|
|
|
// PetInfo 精灵信息结构(合并后的优化版本)
|
2025-07-26 02:06:08 +00:00
|
|
|
|
type PetInfo struct {
|
2025-08-31 06:53:42 +00:00
|
|
|
|
|
2025-08-24 17:33:19 +08:00
|
|
|
|
// 精灵编号(@UInt long → uint32)
|
|
|
|
|
|
ID uint32 `fieldDesc:"精灵编号" `
|
|
|
|
|
|
|
|
|
|
|
|
// 名字:默认为全0,补齐到16字节(固定长度 → [16]byte)
|
2025-08-31 00:27:07 +08:00
|
|
|
|
Name string `struc:"[16]byte" `
|
2025-08-24 17:33:19 +08:00
|
|
|
|
|
|
|
|
|
|
// 个体值(@UInt long → uint32)
|
|
|
|
|
|
Dv uint32 `fieldDesc:"个体值" `
|
|
|
|
|
|
|
|
|
|
|
|
// 性格(@UInt long → uint32)
|
|
|
|
|
|
Nature uint32 `fieldDesc:"性格" `
|
|
|
|
|
|
|
|
|
|
|
|
// 等级(@UInt long → uint32)
|
|
|
|
|
|
Level uint32 `fieldDesc:"等级" `
|
|
|
|
|
|
|
|
|
|
|
|
// 当前等级已获得经验(@UInt long → uint32)
|
|
|
|
|
|
Exp uint32 `fieldDesc:"当前等级已经获得的经验 2538" `
|
|
|
|
|
|
|
|
|
|
|
|
// 当前等级所需经验(@UInt long → uint32)
|
|
|
|
|
|
LvExp uint32 `fieldDesc:"当前等级所需的经验" `
|
|
|
|
|
|
|
|
|
|
|
|
// 升到下一级的经验(@UInt long → uint32)
|
|
|
|
|
|
NextLvExp uint32 `fieldDesc:"升到下一级的经验" `
|
|
|
|
|
|
|
|
|
|
|
|
// 当前生命(@UInt long → uint32)
|
|
|
|
|
|
Hp uint32 `fieldDesc:"当前生命" `
|
|
|
|
|
|
|
|
|
|
|
|
// 最大生命(@UInt long → uint32)
|
|
|
|
|
|
MaxHp uint32 `fieldDesc:"最大生命" `
|
|
|
|
|
|
|
|
|
|
|
|
// 攻击(@UInt long → uint32)
|
|
|
|
|
|
Attack uint32 `fieldDesc:"攻击" `
|
|
|
|
|
|
|
|
|
|
|
|
// 防御(@UInt long → uint32)
|
|
|
|
|
|
Defence uint32 `fieldDesc:"防御" `
|
|
|
|
|
|
|
|
|
|
|
|
// 特攻(@UInt long → uint32)
|
|
|
|
|
|
SpecialAttack uint32 `fieldDesc:"特攻" `
|
|
|
|
|
|
|
|
|
|
|
|
// 特防(@UInt long → uint32)
|
|
|
|
|
|
SpecialDefence uint32 `fieldDesc:"特防" `
|
|
|
|
|
|
|
|
|
|
|
|
// 速度(@UInt long → uint32)
|
|
|
|
|
|
Speed uint32 `fieldDesc:"速度" `
|
|
|
|
|
|
|
|
|
|
|
|
// 生命学习力(@UInt long → uint32)
|
|
|
|
|
|
EvHp uint32 `fieldDesc:"生命学习力" `
|
|
|
|
|
|
|
|
|
|
|
|
// 攻击学习力(@UInt long → uint32)
|
|
|
|
|
|
EvAttack uint32 `fieldDesc:"攻击学习力" `
|
|
|
|
|
|
|
|
|
|
|
|
// 防御学习力(@UInt long → uint32)
|
|
|
|
|
|
EvDefence uint32 `fieldDesc:"防御学习力" `
|
|
|
|
|
|
|
|
|
|
|
|
// 特攻学习力(@UInt long → uint32)
|
|
|
|
|
|
EvSpecialAttack uint32 `fieldDesc:"特攻学习力" `
|
|
|
|
|
|
|
|
|
|
|
|
// 特防学习力(@UInt long → uint32,注意原Java拼写:evSpecialDefense)
|
|
|
|
|
|
EvSpecialDefense uint32 `fieldDesc:"特防学习力" `
|
|
|
|
|
|
|
|
|
|
|
|
// 速度学习力(@UInt long → uint32)
|
|
|
|
|
|
EvSpeed uint32 `fieldDesc:"速度学习力" `
|
|
|
|
|
|
SkillListLen uint32
|
|
|
|
|
|
// 技能信息:固定4条,空则赋值0(固定长度List → [4]SkillInfo,零值即符合“赋值0”)
|
2025-08-31 00:27:07 +08:00
|
|
|
|
SkillList [4]SkillInfo
|
2025-08-24 17:33:19 +08:00
|
|
|
|
|
|
|
|
|
|
// 捕捉时间(@UInt long → 若为时间戳用uint32;若需时间类型可改为time.Time,需配合序列化处理)
|
|
|
|
|
|
CatchTime uint32 `fieldDesc:"捕捉时间" `
|
|
|
|
|
|
|
|
|
|
|
|
// 捕捉地图(@UInt long → uint32)
|
|
|
|
|
|
CatchMap uint32 `fieldDesc:"捕捉地图" `
|
|
|
|
|
|
|
|
|
|
|
|
// 未知默认0(@UInt long → uint32)
|
|
|
|
|
|
CatchRect uint32 `fieldDesc:"未知默认为0" `
|
|
|
|
|
|
|
|
|
|
|
|
// 捕获等级默认0(@UInt long → uint32)
|
|
|
|
|
|
CatchLevel uint32 `fieldDesc:"捕获等级 默认为0" `
|
|
|
|
|
|
EffectInfoLen uint16 `struc:"sizeof=EffectInfo"`
|
|
|
|
|
|
// 特性列表:长度用UShort存储(变长List → []PetEffectInfo + 长度前缀规则)
|
|
|
|
|
|
EffectInfo []PetEffectInfo `fieldDesc:"特性列表, 长度在头部以UShort存储" serialize:"lengthFirst,lengthType=uint16,type=structArray"`
|
|
|
|
|
|
|
|
|
|
|
|
// 皮肤ID默认0(@UInt long → uint32)
|
|
|
|
|
|
SkinID uint32 `fieldDesc:"皮肤id默认为0" `
|
|
|
|
|
|
|
|
|
|
|
|
// 是否闪光(@UInt long → uint32,0=否,1=是)
|
2025-09-01 01:03:46 +08:00
|
|
|
|
Shiny uint32 `fieldDesc:"是不是闪" `
|
|
|
|
|
|
// AbilityType uint32 `struc:"skip"` //特性
|
2025-07-26 02:06:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-10 14:19:03 +08:00
|
|
|
|
// PetEffectInfo 精灵特性信息结构
|
2025-07-26 02:06:08 +00:00
|
|
|
|
type PetEffectInfo struct {
|
2025-08-10 14:19:03 +08:00
|
|
|
|
ItemID uint32 `struc:"uint32" json:"item_id"`
|
|
|
|
|
|
Status byte `struc:"byte" json:"status"`
|
|
|
|
|
|
LeftCount byte `struc:"byte" json:"left_count"`
|
|
|
|
|
|
EffectID uint16 `struc:"uint16" json:"effect_id"`
|
|
|
|
|
|
Reserve1 byte `struc:"byte" json:"reserve1"`
|
|
|
|
|
|
Reserve2 byte `struc:"byte" json:"reserve2"`
|
|
|
|
|
|
Reserve3 byte `struc:"byte" json:"reserve3"`
|
|
|
|
|
|
Reserve4 [13]byte `struc:"[13]byte" json:"reserve4"`
|
2025-07-26 02:06:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 23:22:10 +00:00
|
|
|
|
// SkillInfo 精灵技能信息结构(SkillInfo)
|
2025-08-15 08:17:43 +00:00
|
|
|
|
type SkillInfo struct {
|
2025-08-31 00:27:07 +08:00
|
|
|
|
ID uint32
|
|
|
|
|
|
Pp uint32
|
2025-08-15 08:17:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-26 02:06:08 +00:00
|
|
|
|
// TableName Pet's table name
|
|
|
|
|
|
func (*Pet) TableName() string {
|
|
|
|
|
|
return TableNamePet
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GroupName Pet's table group
|
|
|
|
|
|
func (*Pet) GroupName() string {
|
|
|
|
|
|
return "default"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewPet create a new Pet
|
|
|
|
|
|
func NewPet() *Pet {
|
|
|
|
|
|
return &Pet{
|
|
|
|
|
|
Model: cool.NewModel(),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// init 创建表
|
|
|
|
|
|
func init() {
|
|
|
|
|
|
_ = cool.CreateTable(&Pet{})
|
|
|
|
|
|
// fmt.Println(err)
|
|
|
|
|
|
}
|