Files
bl/logic/controller/pet.go
昔念 c52c409ffc feat(player): 新增玩家累计经验查询接口
新增 PlayerExp 控制器方法,用于返回玩家的累计经验值。同时调整了经验池字段类型为 uint32 并修复相关使用逻辑。

feat(pet): 实现宠物经验增加与升级逻辑

在 Player 结构体中新增 AddPetExp 方法,支持宠物经验增长、自动升级及进化判断。升级后会重新计算面板属性并推送更新包。

feat(fight): 重构战斗伤害计算与效果系统

引入 DamageZone 和 EnumDamageType 类型,统一红伤处理流程;移除旧有的 Pet/Skill/Prop 属性获取临时修改机制,改为直接访问真实属性。更新多个技能效果实现以适配新结构。

refactor(effect): 优化技能效果初始化和生命周期方法

统一技能效果初始化方式,明确各阶段回调函数职责,如 PreActionStart、PreAttacked 等。删除已废弃的属性修改钩子函数,并更新状态类效果实现。

refactor(input): 移除 deepcopy 依赖并替换为 go-deepcopy

将原先使用的 mohae/deepcopy 替换为 barkimedes/go-deepcopy,用于战斗节点中的 effect 拷贝逻辑,提升性能和安全性。

refactor(model): 调整玩家信息字段类型

将 PlayerInfo 中的 GoldBean 字段由 int32 改为 uint32,ExpPool 字段由 int64 改为 uint32,确保数据类型一致性与合理性。

feat(nono): 增加 Nono 跟随/收回协议结构定义

新增 NonoFollowOrHomeInInfo 和 NonoFollowOutInfo 结构体,用于处理 Nono 宠物的跟随与收回操作指令。

chore(deps): 添加 go-deepcopy 依赖

在 go.mod 中引入 github.com/barkimedes/go-deepcopy 依赖库,用于替代原有的 deepcopy 工具。
2025-09-26 13:33:55 +08:00

187 lines
4.7 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 controller
import (
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"blazing/logic/service/pet"
"blazing/logic/service/player"
"blazing/modules/blazing/model"
"github.com/jinzhu/copier"
)
// 获取精灵信息
func (h *Controller) GetPetInfo(
data *pet.InInfo,
c *player.Player) (result *pet.OutInfo,
err errorcode.ErrorCode) { //这个时候player应该是空的
for _, pi := range c.Info.PetList {
if pi.CatchTime == data.CatchTime {
result = &pet.OutInfo{
PetInfo: pi,
}
}
}
if result == nil {
result = &pet.OutInfo{
PetInfo: c.Service.PetInfo_One(data.CatchTime).Data,
}
}
return result, 0
}
// 获取仓库列表
func (h *Controller) GetPetList(
data *pet.GetPetListInboundEmpty,
c *player.Player) (result *pet.GetPetListOutboundInfo,
err errorcode.ErrorCode) { //这个时候player应该是空的
result = &pet.GetPetListOutboundInfo{}
tt := c.Service.PetInfo(0) //获得未放生的精灵
result.ShortInfoList = make([]pet.PetShortInfo, len(tt))
for i, v := range tt {
copier.Copy(&result.ShortInfoList[i], &v)
}
return result, 0
}
// 精灵背包仓库切换
func (h *Controller) PetRelease(
data *pet.PetReleaseInboundInfo,
c *player.Player) (
result *pet.PetReleaseOutboundInfo,
err errorcode.ErrorCode) { //这个时候player应该是空的
//放入背包=数据库置1+添加到背包+pet release发包 仓库=数据库置0+移除背包 设置首发等于取到首发精灵后重新排序
//这里只修改,因为添加和移除背包在宠物获取时已经做了
result = &pet.PetReleaseOutboundInfo{}
result.Flag = uint32(data.Flag)
c.Service.PetInfo_One_exec(data.CatchTime, func(t *model.PetEX) {
t.InBag = int(data.Flag)
})
switch data.Flag {
case 0:
removeIndex := -1
for i, v := range c.Info.PetList {
if v.CatchTime == uint32(data.CatchTime) {
removeIndex = i
break // 只移除第一个匹配值,若需移除所有,可省略 break 继续循环
}
}
if removeIndex != -1 {
c.Info.PetList = append(c.Info.PetList[:removeIndex], c.Info.PetList[removeIndex+1:]...)
}
case 1:
//todo 背包
c.Service.PetInfo_One_exec(data.CatchTime, func(t *model.PetEX) {
c.Info.PetList = append(c.Info.PetList, t.Data)
result.PetInfo = t.Data
})
}
if len(c.Info.PetList) > 0 {
result.FirstPetTime = c.Info.PetList[0].CatchTime //设置首发
}
//service.NewUserService(c.Info.UserID).PetAdd( *r)
return result, 0
}
// 精灵展示
func (h *Controller) PlayerShowPet(
data *pet.PetShowInboundInfo, c *player.Player) (result *pet.PetShowOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
results := pet.PetShowOutboundInfo{}
for _, pi := range c.Info.PetList {
if pi.CatchTime == data.CatchTime {
copier.Copy(&results, pi)
results.Flag = data.Flag
results.UserID = data.Head.UserID
data.Broadcast(c.Info.MapID, results) //同步广播
}
}
return result, -1
}
func (h *Controller) PetOneCure(
data *pet.PetOneCureInboundInfo, c *player.Player) (result *pet.PetOneCureOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
_, onpet, ok := FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
return item.CatchTime == data.CatchTime
})
if ok {
onpet.Hp = onpet.MaxHp
for i := 0; i < 4; i++ {
maxPP, ok := xmlres.SkillMap[int(onpet.SkillList[i].ID)]
// 恢复至最大PP值从配置表获取
if onpet.SkillList[i].ID != 0 && ok {
onpet.SkillList[i].PP = uint32(maxPP.MaxPP)
}
}
}
return &pet.PetOneCureOutboundInfo{
CatchTime: data.CatchTime,
}, 0
}
// 精灵首发
func (h *Controller) PetFirst(
data *pet.PetDefaultInboundInfo, c *player.Player) (result *pet.PetDefaultOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
result = &pet.PetDefaultOutboundInfo{}
var ttt []model.PetInfo
for index, pi := range c.Info.PetList {
if pi.CatchTime == data.CatchTime {
ttt = append(ttt, pi)
ttt = append(ttt, c.Info.PetList[:index]...)
ttt = append(ttt, c.Info.PetList[index+1:]...)
result.IsDefault = 1
break
}
}
c.Info.PetList = ttt
return result, 0
}
// FindWithIndex 遍历slice找到第一个满足条件的元素
// 返回:索引、元素指针、是否找到
func FindWithIndex[T any](slice []T, predicate func(item T) bool) (int, *T, bool) {
for i := range slice {
if predicate(slice[i]) {
return i, &slice[i], true
}
}
return -1, nil, false
}
func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, c *player.Player) (result *pet.PetSetExpOutboundInfo, err errorcode.ErrorCode) {
_, onpet, ok := FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
return item.CatchTime == data.CatchTime
})
if ok {
c.AddPetExp(onpet, data.Exp)
}
return &pet.PetSetExpOutboundInfo{}, 0
}