Files
bl/logic/controller/pet_skill.go
昔念 3ee1283a2c ```
feat(pet): 新增精灵可学习技能查询功能

新增 GetPetLearnableSkills 接口用于查询当前精灵可学习技能(包含等级技能和额外技能ExtSKill),
优化 SetPetSkill 和 SortPetSkills 方法中的技能处理逻辑,提升技能管理和排序的准确性。

同时修复了宠物存储信息查询时缺少参数验证的问题,在管理后台接口中增加 free 参数支持。

BREAKING CHANGE: 管理后台
2026-04-05 12:45:00 +08:00

182 lines
4.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 controller
import (
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"blazing/common/utils"
"blazing/logic/service/fight"
"blazing/logic/service/pet"
"blazing/logic/service/player"
"blazing/modules/player/model"
)
type GetPetLearnableSkillsOutboundInfo struct {
SkillListLen uint32 `struc:"sizeof=SkillList"`
SkillList []uint32 `json:"skillList"`
}
func collectPetLearnableSkillList(currentPet *model.PetInfo) []uint32 {
skillSet := make(map[uint32]struct{})
skills := make([]uint32, 0)
appendSkill := func(skillID uint32) {
if skillID == 0 {
return
}
if _, exists := skillSet[skillID]; exists {
return
}
skillSet[skillID] = struct{}{}
skills = append(skills, skillID)
}
for _, skillID := range currentPet.GetLevelRangeCanLearningSkills(1, currentPet.Level) {
appendSkill(skillID)
}
for _, skillID := range currentPet.ExtSKill {
appendSkill(skillID)
}
for _, skill := range currentPet.SkillList {
delete(skillSet, skill.ID)
}
result := make([]uint32, 0, len(skillSet))
for _, skillID := range skills {
if _, exists := skillSet[skillID]; exists {
result = append(result, skillID)
}
}
return result
}
// GetPetLearnableSkills 查询当前精灵可学习技能(等级技能 + 额外技能ExtSKill
func (h Controller) GetPetLearnableSkills(
data *GetPetLearnableSkillsInboundInfo,
c *player.Player,
) (result *GetPetLearnableSkillsOutboundInfo, err errorcode.ErrorCode) {
_, currentPet, ok := c.FindPet(data.CatchTime)
if !ok {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
return &GetPetLearnableSkillsOutboundInfo{
SkillList: collectPetLearnableSkillList(currentPet),
}, 0
}
// SetPetSkill 设置宠物技能消耗50赛尔豆
func (h Controller) SetPetSkill(data *ChangeSkillInfo, c *player.Player) (result *pet.ChangeSkillOutInfo, err errorcode.ErrorCode) {
const setSkillCost = 50
if !c.GetCoins(setSkillCost) {
return nil, errorcode.ErrorCodes.ErrSunDouInsufficient10016
}
c.Info.Coins -= setSkillCost
_, currentPet, ok := c.FindPet(data.CatchTime)
if !ok {
return nil, errorcode.ErrorCodes.ErrSystemBusy
}
canLearnSkillSet := make(map[uint32]struct{})
for _, skillID := range collectPetLearnableSkillList(currentPet) {
canLearnSkillSet[skillID] = struct{}{}
}
if _, exists := canLearnSkillSet[data.ReplaceSkill]; !exists {
return nil, errorcode.ErrorCodes.ErrSystemBusy
}
skillInfo, exists := xmlres.SkillMap[int(data.ReplaceSkill)]
if !exists {
return nil, errorcode.ErrorCodes.ErrSystemBusy
}
_, _, ok = utils.FindWithIndex(currentPet.SkillList, func(item model.SkillInfo) bool { //已经存在技能
return item.ID == data.ReplaceSkill
})
if ok {
return nil, errorcode.ErrorCodes.ErrSystemBusy
}
maxPP := uint32(skillInfo.MaxPP)
if data.HasSkill != 0 {
// 查找要学习的技能并替换
_, targetSkill, found := utils.FindWithIndex(currentPet.SkillList, func(item model.SkillInfo) bool {
return item.ID == data.HasSkill
})
if !found {
return nil, errorcode.ErrorCodes.ErrSystemBusy
}
targetSkill.ID = data.ReplaceSkill
targetSkill.PP = maxPP
} else {
if len(currentPet.SkillList) >= 4 {
return nil, errorcode.ErrorCodes.ErrSystemBusy
}
currentPet.SkillList = append(currentPet.SkillList, model.SkillInfo{
ID: data.ReplaceSkill,
PP: maxPP,
})
}
return &pet.ChangeSkillOutInfo{
CatchTime: data.CatchTime,
}, 0
}
// SortPetSkills 排序宠物技能消耗50赛尔豆
func (h Controller) SortPetSkills(data *C2S_Skill_Sort, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
const skillSortCost = 50
if !c.GetCoins(skillSortCost) {
return nil, errorcode.ErrorCodes.ErrSunDouInsufficient10016
}
c.Info.Coins -= skillSortCost
_, currentPet, ok := c.FindPet(data.CapTm)
if !ok {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
usedSkillSet := make(map[uint32]struct{})
newSkillList := make([]model.SkillInfo, 0, 4)
for _, skillID := range data.Skill {
if skillID == 0 {
continue
}
if _, used := usedSkillSet[skillID]; used {
continue
}
_, skill, found := utils.FindWithIndex(currentPet.SkillList, func(item model.SkillInfo) bool {
return item.ID == skillID
})
if !found {
continue
}
newSkillList = append(newSkillList, *skill)
usedSkillSet[skillID] = struct{}{}
}
for _, skill := range currentPet.SkillList {
if skill.ID == 0 {
continue
}
if _, used := usedSkillSet[skill.ID]; used {
continue
}
newSkillList = append(newSkillList, skill)
usedSkillSet[skill.ID] = struct{}{}
}
if len(newSkillList) > 4 {
newSkillList = newSkillList[:4]
}
currentPet.SkillList = newSkillList
return nil, 0
}