```
feat(item): 出售物品后减少背包中对应物品数量 在处理物品出售逻辑时,增加调用 SubItem 方法以正确扣减玩家背包中的物品数量。 feat(map): 玩家离开地图时重置 Canmon 标志位 通过 atomic.StoreUint32 将玩家的 Canmon 状态设置为 0,确保线程安全。 fix(pet): 调整宠物经验增加逻辑并修复技能学习问题 重构 AddPetExp 方法逻辑,优化升级流程、技能学习机制,并修正经验显示
This commit is contained in:
30
logic/controller/fight_tawor.go
Normal file
30
logic/controller/fight_tawor.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/common/utils"
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/player"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
func (h Controller) FRESH_CHOICE_FIGHT_LEVEL(data *fight.C2S_FRESH_CHOICE_FIGHT_LEVEL, c *player.Player) (result *fight.S2C_FreshChoiceLevelRequestInfo, err errorcode.ErrorCode) {
|
||||
|
||||
result = &fight.S2C_FreshChoiceLevelRequestInfo{}
|
||||
|
||||
switch data.Head.CMD {
|
||||
case 2428: //试炼之塔
|
||||
c.Info.CurrentFreshStage = utils.Max(c.Info.CurrentFreshStage, 1)
|
||||
result.CurFightLevel = uint(c.Info.CurrentFreshStage)
|
||||
case 2414: //勇者之塔
|
||||
c.Info.CurrentStage = utils.Max(c.Info.CurrentStage, 1)
|
||||
result.CurFightLevel = uint(c.Info.CurrentStage)
|
||||
}
|
||||
result.BossId = []uint32{10}
|
||||
atomic.StoreUint32(&c.Canmon, 0)
|
||||
return result, 0
|
||||
}
|
||||
func (h Controller) FRESH_LEAVE_FIGHT_LEVEL(data *fight.FRESH_LEAVE_FIGHT_LEVEL, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
return result, 0
|
||||
}
|
||||
@@ -17,5 +17,6 @@ func (h Controller) ITEM_SALE(data *item.C2S_ITEM_SALE, c *player.Player) (resul
|
||||
c.Info.Coins += uint32(int64(data.Amount) * int64(xmlres.ItemsMAP[int(data.ItemId)].SellPrice))
|
||||
|
||||
}
|
||||
c.Service.Item.SubItem(data.ItemId, data.Amount)
|
||||
return result, 0
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *mapho
|
||||
return
|
||||
}
|
||||
func (h *Controller) MapLeave(data *space.LeaveMapInboundInfo, c *player.Player) (result *info.LeaveMapOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||
|
||||
atomic.StoreUint32(&c.Canmon, 0)
|
||||
//data.Broadcast(c.Info.MapID, info.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播
|
||||
result = &info.LeaveMapOutboundInfo{
|
||||
UserID: c.Info.UserID,
|
||||
|
||||
@@ -229,7 +229,7 @@ func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, c *player.Player)
|
||||
_, onpet, ok := c.FindPet(data.CatchTime)
|
||||
if ok && onpet.Level < 100 {
|
||||
|
||||
defer c.AddPetExp(onpet, data.Exp)
|
||||
c.AddPetExp(onpet, data.Exp)
|
||||
return &pet.PetSetExpOutboundInfo{
|
||||
Exp: c.Info.ExpPool,
|
||||
}, 0
|
||||
|
||||
@@ -124,3 +124,23 @@ type ChatInfo struct {
|
||||
MessageLen uint32 `struc:"sizeof=Message"`
|
||||
Message string `json:"message" fieldDescription:"消息内容, 结束符为utf-8的数字0"` // 消息内容,包含utf-8空字符('\x00')作为结束符
|
||||
}
|
||||
type C2S_FRESH_CHOICE_FIGHT_LEVEL struct {
|
||||
Head common.TomeeHeader `cmd:"2428|2414" struc:"skip"`
|
||||
// Level 挑战层数选择标识
|
||||
// 0: 继续挑战(从数据库存储的当前通关层数开始)
|
||||
// 1: 从1层开始
|
||||
// 2: 从11层开始
|
||||
// 3: 从21层开始
|
||||
// 4: 从31层开始
|
||||
Level uint `json:"level"` // 若使用JSON序列化,添加tag;若用protobuf可替换为对应的tag
|
||||
}
|
||||
type S2C_FreshChoiceLevelRequestInfo struct {
|
||||
// CurFightLevel 当前战斗层数(对应前端 curFightLevel 字段)
|
||||
CurFightLevel uint `json:"curFightLevel"` // JSON序列化tag,保证字段名与前端一致
|
||||
BossIdLen uint32 `struc:"sizeof=BossId"`
|
||||
// BossId 当前层数的精灵ID数组(对应前端 bossId 字段,C# List<uint> 对应Go []uint切片)
|
||||
BossId []uint32 `json:"bossId"`
|
||||
}
|
||||
type FRESH_LEAVE_FIGHT_LEVEL struct {
|
||||
Head common.TomeeHeader `cmd:"2430|2416" struc:"skip"`
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ func init() {
|
||||
|
||||
onpet.Downgrade(1)
|
||||
onpet.NextLvExp = 0
|
||||
onpet.Update_EXP()
|
||||
onpet.Update(false)
|
||||
onpet.Ev = [6]uint32{}
|
||||
onpet.Dv = uint32(grand.Intn(32))
|
||||
onpet.Nature = (onpet.Nature + uint32(grand.Intn(25))) % 25
|
||||
|
||||
@@ -18,23 +18,22 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
|
||||
addExp = utils.Min(addExp, p.Info.ExpPool)
|
||||
originalLevel := petinfo.Level
|
||||
Exp := petinfo.Exp + addExp
|
||||
|
||||
petinfo.Update_EXP()
|
||||
petinfo.Update()
|
||||
p.Info.ExpPool -= addExp //减去已使用的经验
|
||||
gainexp := Exp //已获得的经验
|
||||
for Exp >= petinfo.NextLvExp {
|
||||
|
||||
petinfo.Level++
|
||||
petinfo.Update_EXP()
|
||||
petinfo.Update()
|
||||
petinfo.Update(true)
|
||||
Exp -= petinfo.LvExp
|
||||
|
||||
if originalLevel < 100 && petinfo.Level == 100 { //升到100了
|
||||
p.Info.ExpPool += Exp //减去已使用的经验
|
||||
gainexp -= Exp
|
||||
Exp = 0
|
||||
break //停止升级
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
petinfo.Exp = Exp
|
||||
// 重新计算面板
|
||||
if originalLevel != petinfo.Level {
|
||||
@@ -42,27 +41,26 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
|
||||
|
||||
petinfo.Cure()
|
||||
p.Info.PetMaxLevel = utils.Max(petinfo.Level, p.Info.PetMaxLevel)
|
||||
}
|
||||
// 处理技能学习
|
||||
canLearnSkillList := utils.LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level), 4) //获取最后四个技能,如果不足,那就取全部技能
|
||||
|
||||
// 处理技能学习
|
||||
canLearnSkillList := utils.LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level), 4) //获取最后四个技能,如果不足,那就取全部技能
|
||||
for i := 0; i < 4; i++ {
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
if len(canLearnSkillList) != 0 {
|
||||
skid := canLearnSkillList[len(canLearnSkillList)-1]
|
||||
petinfo.SkillList = append(petinfo.SkillList, model.SkillInfo{
|
||||
|
||||
if len(canLearnSkillList) != 0 {
|
||||
skid := canLearnSkillList[len(canLearnSkillList)-1]
|
||||
petinfo.SkillList = append(petinfo.SkillList, model.SkillInfo{
|
||||
ID: skid,
|
||||
PP: uint32(xmlres.SkillMap[int(skid)].MaxPP),
|
||||
})
|
||||
|
||||
ID: skid,
|
||||
PP: uint32(xmlres.SkillMap[int(skid)].MaxPP),
|
||||
})
|
||||
canLearnSkillList = canLearnSkillList[:len(canLearnSkillList)-1]
|
||||
}
|
||||
|
||||
canLearnSkillList = canLearnSkillList[:len(canLearnSkillList)-1]
|
||||
}
|
||||
|
||||
}
|
||||
if len(petinfo.SkillList) > 4 {
|
||||
petinfo.SkillList = petinfo.SkillList[:4] //归正到4
|
||||
if len(petinfo.SkillList) > 4 {
|
||||
petinfo.SkillList = petinfo.SkillList[:4] //归正到4
|
||||
}
|
||||
}
|
||||
|
||||
t1 := common.NewTomeeHeader(2508, p.Info.UserID)
|
||||
@@ -71,6 +69,7 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
|
||||
var petinfwo info.UpdatePropInfo
|
||||
|
||||
copier.Copy(&petinfwo, petinfo)
|
||||
petinfwo.Exp = gainexp
|
||||
rrr.Data = append(rrr.Data, petinfwo)
|
||||
p.SendPack(t1.Pack(rrr)) //准备包由各自发,因为协议不一样
|
||||
// 发送经验更新消息
|
||||
|
||||
@@ -270,8 +270,8 @@ func (pet *PetInfo) Downgrade(level uint32) {
|
||||
|
||||
}
|
||||
|
||||
// 执行进化逻辑
|
||||
func (petinfo *PetInfo) Update() {
|
||||
// 执行进化逻辑 ,是否进化
|
||||
func (petinfo *PetInfo) Update(isup bool) {
|
||||
|
||||
// 最大进化次数限制(防止配置表闭环导致死循环)
|
||||
maxEvolveTimes := 10
|
||||
@@ -283,14 +283,18 @@ func (petinfo *PetInfo) Update() {
|
||||
if evolveCount >= maxEvolveTimes {
|
||||
break
|
||||
}
|
||||
|
||||
// 进化完成后,统一更新经验(原逻辑保留)
|
||||
petinfo.LvExp = petinfo.NextLvExp
|
||||
// 获取当前宠物形态的配置
|
||||
basic, ok := xmlres.PetMAP[int(petinfo.ID)]
|
||||
// 配置不存在,直接退出循环
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
petinfo.NextLvExp = calculateExperience(petinfo.Level, basic.GetBasic())
|
||||
if !isup {
|
||||
return
|
||||
}
|
||||
// 检查是否满足进化条件
|
||||
canEvolve := basic.EvolvesTo != 0 && // 有明确的进化目标
|
||||
int(petinfo.Level) >= basic.EvolvingLv && // 等级达到进化要求
|
||||
@@ -308,19 +312,6 @@ func (petinfo *PetInfo) Update() {
|
||||
|
||||
}
|
||||
|
||||
// 传入bool则不升级
|
||||
// Update 改造为循环进化:直到宠物无法再进化为止,再更新经验
|
||||
// t ...bool:原参数逻辑,len(t)==0时触发进化检查,否则仅更新经验
|
||||
|
||||
func (petinfo *PetInfo) Update_EXP() {
|
||||
|
||||
// 进化完成后,统一更新经验(原逻辑保留)
|
||||
petinfo.LvExp = petinfo.NextLvExp
|
||||
// 获取最终形态的宠物配置,计算下一等级经验
|
||||
basic := xmlres.PetMAP[int(petinfo.ID)]
|
||||
petinfo.NextLvExp = calculateExperience(petinfo.Level, basic.GetBasic())
|
||||
}
|
||||
|
||||
// calculateExperience 计算指定等级和种族值所需的经验值
|
||||
// level: 当前等级
|
||||
// baseValue: 种族值
|
||||
@@ -485,7 +476,7 @@ func GenPetInfo(
|
||||
// ---- 属性计算 ----
|
||||
p.CalculatePetPane(true)
|
||||
|
||||
p.Update_EXP()
|
||||
p.Update(false)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package model
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/utils"
|
||||
)
|
||||
|
||||
// 实现获取等级范围内可学习的技能
|
||||
@@ -35,7 +34,16 @@ func (c *PetInfo) calculatePetPanelSize(base, ev uint32, natureCorrect float64)
|
||||
// 计算生成面板,只允许第一次生成超过100,比如boss,不允许额外超过
|
||||
func (p *PetInfo) CalculatePetPane(frist bool) {
|
||||
if !frist {
|
||||
p.Level = utils.Min(p.Level, 100)
|
||||
|
||||
if p.Level > 100 {
|
||||
|
||||
oldlveel := p.Level
|
||||
p.Level = 100
|
||||
defer func() {
|
||||
p.Level = oldlveel
|
||||
}()
|
||||
}
|
||||
|
||||
}
|
||||
naxml := xmlres.NatureRootMap[int(p.Nature)]
|
||||
petxml := xmlres.PetMAP[int(p.ID)]
|
||||
|
||||
@@ -158,7 +158,7 @@ type PlayerInfo struct {
|
||||
AllPetNumber uint32 `struc:"uint32" json:"all_pet_number"` // 精灵数量
|
||||
MonKingWin uint32 `struc:"uint32" json:"mon_king_win"` // 精灵王胜场
|
||||
MessWin uint32 `struc:"skip" json:"mess_win"` // 大乱斗胜场
|
||||
CurrentStage uint32 `struc:"uint32" json:"current_stage"` // 勇者之塔层数
|
||||
CurrentStage uint32 `struc:"uint32" default:"1" json:"current_stage"` // 勇者之塔层数
|
||||
MaxStage uint32 `struc:"uint32" json:"max_stage"` // 试炼之塔最高层
|
||||
CurrentFreshStage uint32 `struc:"uint32" json:"current_fresh_stage"` // 当前试炼层数
|
||||
MaxFreshStage uint32 `struc:"uint32" json:"max_fresh_stage"` // 最高试炼层
|
||||
|
||||
@@ -151,6 +151,8 @@ func NewInfoService(id uint32) *InfoService {
|
||||
|
||||
Service: &cool.Service{Model: model.NewPlayer(), UniqueKey: map[string]string{
|
||||
"player_id": "角色名称不能重复",
|
||||
}, PageQueryOp: &cool.QueryOp{
|
||||
FieldEQ: []string{"player_id"},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user