package model import ( "blazing/common/data/xmlres" "blazing/cool" "math" "math/rand" "time" ) const TableNamePet = "pet" // Pet mapped from table type Pet struct { *cool.Model 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"` // Owner uint32 `struc:"skip"` //仅作为存储 // FreedTime uint32 `struc:"skip"` //放生时间 //是否可交易,这里应该定义在精灵ID里 //是否上架 Data string `gorm:"type:text;not null;comment:'精灵全部数据'" json:"data"` } func GetGaussRandomNum(min, max int64) int64 { σ := (float64(min) + float64(max)) / 2 μ := (float64(max) - σ) / 3 rand.Seed(time.Now().UnixNano()) x := rand.Float64() x1 := rand.Float64() a := math.Cos(2*math.Pi*x) * math.Sqrt((-2)*math.Log(x1)) result := a*μ + σ return int64(result) } // RandomInRange 从切片表示的范围中返回对应结果: // - 切片包含1个元素时,返回该元素本身 // - 切片包含2个元素时,从[min, max]闭区间随机生成一个整数(自动调整min和max顺序) // - 其他情况返回0 func RandomInRange(rangeSlice []int) int { rand.Seed(time.Now().UnixNano()) switch len(rangeSlice) { case 1: // 只有一个元素时返回自身 return rangeSlice[0] case 2: // 两个元素时处理为范围 min, max := rangeSlice[0], rangeSlice[1] // 确保 min ≤ max if min > max { min, max = max, min } // 生成 [min, max] 区间的随机整数 return int(GetGaussRandomNum(int64(min), int64(max))) //(rand.Intn(int(max-min+1)) + int(min)) default: // 其他长度返回0 return 0 } } func LastFourElements[T any](s []T) []T { n := len(s) if n <= 4 { // 切片长度小于等于4时,返回整个切片 return s } // 切片长度大于4时,返回最后4个元素(从n-4索引到末尾) return s[n-4:] } // * @param petTypeId 精灵类型ID // * @param individualValue 个体值 // * @param natureId 性格ID // * @param abilityTypeEnum 特性类型 // * @param isShiny 是否为闪光 // * @param level 等级 // * @return 生成的精灵实体 func GenPetInfo(id int, dv, natureId, abilityTypeEnum, shinyid, level []int) *PetInfo { p := &PetInfo{ID: uint32(id), Shiny: uint32(RandomInRange(shinyid)), //闪光 Nature: uint32(RandomInRange(natureId)), //性格 Dv: uint32(RandomInRange(dv)), EffectInfo: make([]PetEffectInfo, 0), CatchTime: uint32(time.Now().Unix()), Level: uint32(RandomInRange(level))} //等级 p.EffectInfo = append(p.EffectInfo, PetEffectInfo{ItemID: uint32(RandomInRange(abilityTypeEnum))}) naxml := xmlres.NatureRootMap[int(p.Nature)] petxml := xmlres.PetMAP[int(id)] tttt := make([]uint32, 0) for _, v := range petxml.LearnableMoves.Moves { if p.Level >= uint32(v.LearningLv) { tttt = append(tttt, uint32(v.ID)) } } tttt = LastFourElements(tttt) //获取最后四个技能,如果不足,那就取全部技能 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( uint32(petxml.Atk), p.Dv, p.Level, p.EvAttack, naxml.AttackCorrect, ) defense := p.CalculatePetPanelSize( uint32(petxml.Def), p.Dv, p.Level, p.EvDefence, naxml.DefenseCorrect, ) specialAttack := p.CalculatePetPanelSize( uint32(petxml.SpAtk), p.Dv, p.Level, p.EvSpecialAttack, naxml.SaCorrect, ) specialDefense := p.CalculatePetPanelSize( uint32(petxml.SpDef), p.Dv, p.Level, p.EvSpecialDefense, naxml.SdCorrect, ) speed := p.CalculatePetPanelSize( uint32(petxml.Spd), 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面板值(无性格修正) func (c *PetInfo) CalculatePetHPPanelSize(base, dv, level, ev uint32) uint32 { return uint32((float64(base)*2+float64(ev)/4.0+float64(dv))*(float64(level)/100.0) + float64(level) + 10) } // 计算其他属性面板值(带性格修正) func (c *PetInfo) CalculatePetPanelSize(base, dv, level, ev uint32, natureCorrect float64) uint32 { base1 := float64((float64(base)*2+float64(ev)/4.0+float64(dv))*(float64(level)/100.0) + 5) return uint32(float64(base1) * natureCorrect) } // PetInfo 精灵信息结构(合并后的优化版本) type PetInfo struct { // 精灵编号(@UInt long → uint32) ID uint32 `fieldDesc:"精灵编号" ` // 名字:默认为全0,补齐到16字节(固定长度 → [16]byte) Name string `struc:"[16]byte" ` // 个体值(@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”) SkillList [4]SkillInfo // 捕捉时间(@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=是) Shiny uint32 `fieldDesc:"是不是闪" ` // AbilityType uint32 `struc:"skip"` //特性 } // PetEffectInfo 精灵特性信息结构 type PetEffectInfo struct { 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"` } // SkillInfo 精灵技能信息结构(SkillInfo) type SkillInfo struct { ID uint32 PP uint32 } // 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) }