Files
bl/modules/blazing/model/pet.go
昔念 ea1148039e ```
refactor(login): 重构登录重置逻辑,使用 defer 替代 goroutine

将每日任务重置逻辑从 goroutine 改为 defer 执行,确保在函数结束时正确重置任务状态。
同时将 TaskInfo 中的 Info 字段重命名为 Data,保持结构一致性。

refactor(task): 统一任务数据字段名为 Data

将 task 相关结构体中的 Info 字段统一
2025-09-23 13:24:40 +08:00

288 lines
8.6 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 model
import (
"blazing/common/data/xmlres"
"blazing/cool"
"math/rand"
"time"
"github.com/gogf/gf/v2/util/gconv"
)
// 除数数组放大100倍
// 数组按递增顺序排列,用于判断个体值等级
var divisors = []int{
600, 1200, 1900, 2700, 3600, 4600, 5700, 6900, 8200, 9600,
11100, 12700, 14400, 16200, 18100, 20100, 22100, 24000,
25800, 27500, 29100, 30600, 32000, 33300, 34500, 35600,
36600, 37500, 38300, 39000, 39600,
}
// CalculateIndividual 根据给定的a值计算个体值
// 返回值表示a大于等于多少个除数范围0-31
func CalculateIndividual(a int) int {
individual := 0
for _, divisor := range divisors {
if a >= divisor {
individual++
} else {
break // 数组是递增的,可提前跳出循环
}
}
return individual
}
// CalculateIndividualValue 计算个体值0-31
// 接收外部随机数生成器,便于控制随机性和复用
func CalculateIndividualValue(random *rand.Rand) int {
// 生成0-40000的随机数作为个体值计算的输入
a := random.Intn(40001)
return CalculateIndividual(a)
}
const TableNamePet = "pet"
// Pet mapped from table <pet>
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"`
}
type PetS struct {
Pet
Data []PetInfo `orm:"data" dc:"资源规格"`
}
func LastFourElements[T any](s []T) []T {
n := len(s)
if n <= 4 {
// 切片长度小于等于4时返回整个切片
return s
}
// 切片长度大于4时返回最后4个元素从n-4索引到末尾
return s[n-4:]
}
// -1是随机
// * @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 {
// 设置随机数种子,确保每次运行生成不同的随机数序列
rand.Seed(time.Now().UnixNano())
p := &PetInfo{ID: uint32(id),
EffectInfo: make([]PetEffectInfo, 0),
CatchTime: uint32(time.Now().Unix()),
Level: uint32(level)} //等级
if shinyid != -1 {
p.Shiny = uint32(shinyid)
} else {
}
if natureId != -1 {
p.Nature = uint32(natureId)
} else {
p.Nature = uint32(rand.Intn(25))
}
if dv != -1 {
p.Dv = uint32(dv)
} else {
p.Dv = uint32(CalculateIndividualValue(rand.New(rand.NewSource(time.Now().UnixNano()))))
}
if abilityTypeEnum != -1 {
if abilityTypeEnum != 0 {
v := xmlres.PlayerEffectMAP[int(abilityTypeEnum)]
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
Idx: uint16(gconv.Int16(v.Idx)),
Status: 1,
EID: uint16(gconv.Int16(v.Eid)),
Args: v.ArgsS,
})
}
} else {
for i, v := range xmlres.PlayerEffectMAP {
if rand.Intn(len(xmlres.PlayerEffectMAP)) == i {
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
Idx: uint16(gconv.Int16(v.Idx)),
Status: 1,
EID: uint16(gconv.Int16(v.Eid)),
Args: v.ArgsS,
})
}
}
}
tttt := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) //获取最后四个技能,如果不足,那就取全部技能
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))
p.CalculatePetPane()
p.Hp = p.MaxHp
return p
}
// 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:"最大生命" `
// * battle_lv: atk(0), def(1), sp_atk(2), sp_def(3), spd(4), accuracy(5)
Prop [5]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 → uint320=否1=是)
Shiny uint32 `fieldDesc:"是不是闪" `
// AbilityType uint32 `struc:"skip"` //特性
}
// PetEffectInfo 精灵特性信息结构
// <!-- NewSeIdx: 精灵特效索引 (默认0: 无效) -->
// <!-- Type: 0 - 仅单人战斗; 1 - 仅组队战斗; 2 - both; (默认0: 仅单人) -->
// <!-- Eid: 精灵特效eid (默认0: 无效) -->
// <!-- Stat: 精灵特效Stat: 0: 无效(默认值), 1: 永久, 2: 有`有效次数'的特效 3: 爆发特效 4: 异能精灵特质-->
// <!-- Times: 精灵特效可使用次数: 当type==2时有效 (默认值:0) -->
// <!-- Args: 特效参数, 不超过8个 (注意: 每个参数不能超过 65535) -->
// <!-- AdditionType:特效加成类型 1 种族值加成 2 技能威力加成 -->
type PetEffectInfo struct {
ItemID uint32 `struc:"uint32" json:"item_id"` //如果是能量珠,就显示
Idx uint16 `struc:"skip" json:"new_se_idx"`
Status byte `struc:"byte" json:"status"` //特性为1,能量珠为2
LeftCount byte `struc:"byte" json:"left_count"` //剩余次数
EID uint16 `struc:"uint16" json:"effect_id"` //特效ID
ArgsLen uint32 `struc:"sizeof=Args"`
Args []int ` json:"Args"` //自定义参数装载
}
// 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)
}