feat(fight): 优化战斗逻辑与精灵切换流程

- 在多个战斗控制器方法中添加 defer 调用,确保战斗操作正确延迟执行
- 修改 ChangePet 方法返回值类型,增强接口一致性
- 修复战斗准备阶段逻辑,重构战斗开始信息构建过程
- 移除冗余广播调用,调整 PVE 战斗初始化流程
- 更新 README 中的 pprof 命令地址并完善项目介绍部分

fix(effect): 修复效果叠加逻辑与ID解析问题

- 效果叠加时默认增加一层,而非直接相加参数
- 修正 EffectIDCombiner 类型、CatchTime 的掩码偏移计算错误
- 添加重复效果日志输出,便于调试追踪

feat(boss): 完善BOSS特性实现逻辑

- 修正 NewSel17 特性
This commit is contained in:
2025-11-29 19:26:56 +08:00
parent f1c75abde6
commit 11f6817d62
23 changed files with 7269 additions and 6572 deletions

View File

@@ -2,13 +2,14 @@
这是骄阳号开发团队的开源项目请勿用于商业用途 这是骄阳号开发团队的开源项目请勿用于商业用途
在软件开发中repoimplmapper model 是常见的分层架构组件 在软件开发中repoimplmapper model 是常见的分层架构组件
## 项目介绍 ## 项目介绍
## seer-project ## seer-project
项目结构: 项目结构:
go tool pprof -http :8081 "http://125.208.20.223:54612/debug/debug/pprof/profile" go tool pprof -http :8081 "http://125.208.20.223:54612/debug/debug/pprof/profile"
go tool pprof -http :8081 "http://127.0.0.1:9909/debug/debug/pprof/profile" go tool pprof -http :8081 "http://127.0.0.1:9909/debug/pprof/profile"
详情查看 [文档](./docs) 详情查看 [文档](./docs)

View File

@@ -14,7 +14,7 @@ func (h Controller) OnReadyToFight(data *fight.ReadyToFightInboundInfo, c *playe
if c.FightC == nil { if c.FightC == nil {
return nil, errorcode.ErrorCodes.ErrBattleEnded return nil, errorcode.ErrorCodes.ErrBattleEnded
} }
c.FightC.ReadyFight(c) defer c.FightC.ReadyFight(c)
return nil, -1 return nil, -1
} }
@@ -23,7 +23,7 @@ func (h Controller) UseSkill(data *fight.UseSkillInInfo, c *player.Player) (resu
if c.FightC == nil { if c.FightC == nil {
return nil, errorcode.ErrorCodes.ErrBattleEnded return nil, errorcode.ErrorCodes.ErrBattleEnded
} }
c.FightC.UseSkill(c, (data.SkillId)) defer c.FightC.UseSkill(c, data.SkillId)
return nil, 0 return nil, 0
} }
@@ -42,17 +42,17 @@ func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *player.Player)
return nil, errorcode.ErrorCodes.ErrCannotFleePlayerBattle return nil, errorcode.ErrorCodes.ErrCannotFleePlayerBattle
} }
c.FightC.Over(c, info.BattleOverReason.PlayerEscape) defer c.FightC.Over(c, info.BattleOverReason.PlayerEscape)
return nil, 0 return nil, 0
} }
// 切换精灵 // 切换精灵
func (h Controller) ChangePet(data *fight.ChangePetInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { func (h Controller) ChangePet(data *fight.ChangePetInboundInfo, c *player.Player) (result *info.ChangePetInfo, err errorcode.ErrorCode) {
if c.FightC == nil { if c.FightC == nil {
return nil, errorcode.ErrorCodes.ErrBattleEnded return nil, errorcode.ErrorCodes.ErrBattleEnded
} }
c.FightC.ChangePet(c, data.CatchTime) defer c.FightC.ChangePet(c, data.CatchTime)
return nil, -1 return nil, -1
} }
@@ -61,7 +61,7 @@ func (h Controller) Capture(data *fight.CatchMonsterInboundInfo, c *player.Playe
if c.FightC == nil { if c.FightC == nil {
return nil, errorcode.ErrorCodes.ErrBattleEnded return nil, errorcode.ErrorCodes.ErrBattleEnded
} }
c.FightC.Capture(c, data.CapsuleId) defer c.FightC.Capture(c, data.CapsuleId)
return nil, -1 return nil, -1
} }
@@ -71,7 +71,7 @@ func (h Controller) LoadPercent(data *fight.LoadPercentInboundInfo, c *player.Pl
return nil, -1 return nil, -1
} }
c.FightC.LoadPercent(c, int32(data.Percent)) defer c.FightC.LoadPercent(c, int32(data.Percent))
return nil, -1 return nil, -1
} }
func (h Controller) UsePetItemInboundInfo(data *fight.UsePetItemInboundInfo, c *player.Player) (result *info.UsePetIteminfo, err errorcode.ErrorCode) { func (h Controller) UsePetItemInboundInfo(data *fight.UsePetItemInboundInfo, c *player.Player) (result *info.UsePetIteminfo, err errorcode.ErrorCode) {
@@ -80,7 +80,7 @@ func (h Controller) UsePetItemInboundInfo(data *fight.UsePetItemInboundInfo, c *
return nil, errorcode.ErrorCodes.ErrBattleEnded return nil, errorcode.ErrorCodes.ErrBattleEnded
} }
c.FightC.UseItem(c, data.CatchTime, data.ItemId) defer c.FightC.UseItem(c, data.CatchTime, data.ItemId)
return nil, -1 return nil, -1
} }
@@ -89,7 +89,7 @@ func (h Controller) FightChat(data *fight.ChatInfo, c *player.Player) (result *f
return nil, errorcode.ErrorCodes.ErrBattleEnded return nil, errorcode.ErrorCodes.ErrBattleEnded
} }
c.FightC.Chat(c, data.Message) defer c.FightC.Chat(c, data.Message)
return nil, -1 return nil, -1
} }

View File

@@ -147,7 +147,7 @@ func (h Controller) ARENA_OWENR_ACCE(data *fight.ARENA_OWENR_ACCE, c *player.Pla
s := c.GetSpace() s := c.GetSpace()
if atomic.LoadUint32(&c.GetSpace().Owner.UserID) != c.GetInfo().UserID && c.GetInfo().UserID != atomic.LoadUint32(&c.GetSpace().Owner.ChallengerID) { //说明已经有人了 if atomic.LoadUint32(&c.GetSpace().Owner.UserID) != c.GetInfo().UserID && c.GetInfo().UserID != atomic.LoadUint32(&c.GetSpace().Owner.ChallengerID) { //说明已经有人了
return nil, errorcode.ErrorCodes.ErrChampionCannotCancel return nil, -1
} }
s.Owner.Set(c) s.Owner.Set(c)

View File

@@ -173,7 +173,7 @@ func (h *Controller) PlayerShowPet(
copier.Copy(&result, onpet) copier.Copy(&result, onpet)
result.Flag = data.Flag result.Flag = data.Flag
result.UserID = data.Head.UserID result.UserID = data.Head.UserID
c.GetSpace().Broadcast(c, data.Head.CMD, result) defer c.GetSpace().Broadcast(c, data.Head.CMD, result)
} }
return return
@@ -188,7 +188,8 @@ func (h *Controller) PetOneCure(
_, onpet, ok := c.FindPet(data.CatchTime) _, onpet, ok := c.FindPet(data.CatchTime)
if ok { if ok {
onpet.Cure() defer onpet.Cure()
} }
return &pet.PetOneCureOutboundInfo{ return &pet.PetOneCureOutboundInfo{
@@ -226,7 +227,7 @@ func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, c *player.Player)
_, onpet, ok := c.FindPet(data.CatchTime) _, onpet, ok := c.FindPet(data.CatchTime)
if ok { if ok {
c.AddPetExp(onpet, data.Exp) defer c.AddPetExp(onpet, data.Exp)
} }
return &pet.PetSetExpOutboundInfo{ return &pet.PetSetExpOutboundInfo{

View File

@@ -7,7 +7,6 @@ import (
"blazing/logic/service/fight/action" "blazing/logic/service/fight/action"
"blazing/logic/service/fight/info" "blazing/logic/service/fight/info"
"blazing/logic/service/fight/input" "blazing/logic/service/fight/input"
"blazing/logic/service/player"
"context" "context"
"log" "log"
@@ -60,15 +59,17 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
cool.Loger.Debug(context.Background(), " 战斗chan已关闭") cool.Loger.Debug(context.Background(), " 战斗chan已关闭")
return return
} }
//todo 待实现无法切精灵的情况
selfinput := f.GetInputByPlayer(c, false)
InitAttackValue := *selfinput.AttackValue
oldpet := selfinput.CurrentPet
ret := &action.ActiveSwitchAction{ ret := &action.ActiveSwitchAction{
BaseAction: action.NewBaseAction(c.GetInfo().UserID), BaseAction: action.NewBaseAction(c.GetInfo().UserID),
} }
selfinput.CurrentPet, ret.Reason = selfinput.GetPet(id)
selfinput := f.GetInputByPlayer(c, false)
selfinput.CurrentPet, ret.Reason = selfinput.GetPet(id)
c.SendPackCmd(2407, &ret.Reason)
InitAttackValue := *selfinput.AttackValue
oldpet := selfinput.CurrentPet
f.Switch = append(f.Switch, ret) f.Switch = append(f.Switch, ret)
selfinput.InitAttackValue() //切换精灵消除能力提升 selfinput.InitAttackValue() //切换精灵消除能力提升
//这时候精灵已经切换过了,可以直接给新精灵加效果 //这时候精灵已经切换过了,可以直接给新精灵加效果
@@ -83,13 +84,6 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
}) })
}) })
f.Broadcast(func(ff *input.Input) { //先给自身广播
if ff.Player.GetInfo().UserID == c.GetInfo().UserID {
ff.Player.SendPackCmd(2407, &ret.Reason)
}
})
f.actionChan <- ret f.actionChan <- ret
} }
@@ -135,31 +129,12 @@ func (f *FightC) UseItem(c common.PlayerI, cacthid, itemid uint32) {
// ReadyFight 处理玩家战斗准备逻辑,当满足条件时启动战斗循环 // ReadyFight 处理玩家战斗准备逻辑,当满足条件时启动战斗循环
func (f *FightC) ReadyFight(c common.PlayerI) { func (f *FightC) ReadyFight(c common.PlayerI) {
// 1. 构建战斗开始信息(整理双方初始宠物信息)
fightStartInfo := f.buildFightStartInfo()
// 2. 标记当前玩家已准备完成 // 2. 标记当前玩家已准备完成
input := f.GetInputByPlayer(c, false) input := f.GetInputByPlayer(c, false)
input.Finished = true input.Finished = true
// 3. 根据战斗类型判断是否满足战斗启动条件,满足则启动
switch f.Info.Status {
case info.BattleMode.FIGHT_WITH_NPC: // NPC/野怪战斗:处理捕捉相关逻辑后启动
//f.handleNPCFightSpecial(&fightStartInfo)
if f.Opp.Player.(*player.AI_player).CanCapture > 0 {
f.Opp.CanCapture = f.Opp.Player.(*player.AI_player).CanCapture
fightStartInfo.Info2.Catchable = 1 //可以捕捉就置1
}
f.Opp.AttackValue.Prop = f.Opp.Player.(*player.AI_player).Prop
fightStartInfo.Info2.Prop = f.Opp.AttackValue.Prop
f.startBattle(fightStartInfo)
default: // PVP战斗需双方都准备完成
if f.checkBothPlayersReady(c) { if f.checkBothPlayersReady(c) {
f.startBattle(fightStartInfo) f.startBattle(f.FightStartOutboundInfo)
}
} }
} }
@@ -198,12 +173,6 @@ func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) {
log.Panic(context.Background(), "战斗循环提交失败", "error", err) log.Panic(context.Background(), "战斗循环提交失败", "error", err)
} }
f.Broadcast(func(ff *input.Input) {
ff.InitEFFect(&startInfo)
})
f.Broadcast(func(ff *input.Input) { f.Broadcast(func(ff *input.Input) {
// 通知双方玩家准备完成,即将开始战斗 // 通知双方玩家准备完成,即将开始战斗

View File

@@ -27,7 +27,7 @@ type NewSel1 struct {
NewSel0 NewSel0
} }
func (e *NewSel1) BeferProp(in *input.Ctx, prop, level int8, ptype info.EnumAbilityOpType) bool { func (e *NewSel1) Prop_Befer(in *input.Input, prop int8, level int8, ptype info.EnumAbilityOpType) bool {
//魂印特性有不在场的情况,绑定时候将精灵和特性绑定 //魂印特性有不在场的情况,绑定时候将精灵和特性绑定
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime { if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
@@ -35,7 +35,7 @@ func (e *NewSel1) BeferProp(in *input.Ctx, prop, level int8, ptype info.EnumAbil
} }
//能力下降类 //能力下降类
if level > 0 && ptype == info.AbilityOpType.SUB { if ptype == info.AbilityOpType.SUB {
return false return false

View File

@@ -6,7 +6,7 @@ import (
"blazing/logic/service/fight/input" "blazing/logic/service/fight/input"
) )
// 17. 自身体力降到N以下时每次攻击必定致命一击;a1: high 32, a2: low 32 // 17. 自身体力降到N以下时每次攻击必定致命一击;a1: high 32
// TODO: 实现自身体力降到N以下时每次攻击必定致命一击;a1: high 32, a2: low 32的核心逻辑 // TODO: 实现自身体力降到N以下时每次攻击必定致命一击;a1: high 32, a2: low 32的核心逻辑
type NewSel17 struct { type NewSel17 struct {
NewSel0 NewSel0
@@ -23,8 +23,8 @@ func (e *NewSel17) Action_start(a, b *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity.Category() == info.Category.STATUS { if e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true return true
} }
full32 := int64(e.Args()[0])<<32 | int64(e.Args()[1])
if e.Ctx().Our.CurrentPet.HP <= int(full32) { if e.Ctx().Our.CurrentPet.HP <= int(e.Args()[0]) {
e.Ctx().SkillEntity.CritRate = 16 e.Ctx().SkillEntity.CritRate = 16
} }

View File

@@ -23,6 +23,9 @@ func (e *NewSel27) Damage_DIV_ex(t *info.DamageZone) bool {
if e.Ctx().SkillEntity == nil { if e.Ctx().SkillEntity == nil {
return true return true
} }
if t.Type != info.DamageType.Red {
return true
}
if e.index >= len(e.Args()) { if e.index >= len(e.Args()) {
e.index = 0 e.index = 0

View File

@@ -11,19 +11,35 @@ import (
// TODO: 实现偶数伤害(dmg) 提升到 n * dmg;a1: n的核心逻辑 // TODO: 实现偶数伤害(dmg) 提升到 n * dmg;a1: n的核心逻辑
type NewSel39 struct { type NewSel39 struct {
NewSel0 NewSel0
can bool
} }
func (e *NewSel39) Damage_DIV_ex(t *info.DamageZone) bool { func (e *NewSel39) Damage_Mul(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime { if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true return true
} }
if t.Damage.IntPart()%2 == 0 { if !e.can {
return true
}
t.Damage = t.Damage.Mul(decimal.NewFromInt(int64(e.Args()[0]))) t.Damage = t.Damage.Mul(decimal.NewFromInt(int64(e.Args()[0])))
return true
}
func (e *NewSel39) Skill_Use_ex() bool {
//fmt.Println("NewSel39", t.Damage.IntPart())
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
} }
if e.Ctx().Opp.SumDamage.IntPart()%2 == 0 {
e.can = true
} else {
e.can = false
}
return true return true
} }
func init() { func init() {

View File

@@ -11,21 +11,38 @@ import (
// TODO: 实现奇数伤害(dmg) 改为 1/n * dmg;a1: n的核心逻辑 // TODO: 实现奇数伤害(dmg) 改为 1/n * dmg;a1: n的核心逻辑
type NewSel40 struct { type NewSel40 struct {
NewSel0 NewSel0
can bool
} }
func (e *NewSel40) Damage_DIV_ex(t *info.DamageZone) bool { func (e *NewSel40) Damage_DIV_ex(t *info.DamageZone) bool {
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime { if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true return true
} }
if t.Damage.IntPart()%2 != 0 { if !e.can {
return true
t.Damage = t.Damage.Mul(decimal.NewFromInt(1 / int64(e.Args()[0])))
} }
t.Damage = t.Damage.Mul(decimal.NewFromInt(1).Div(decimal.NewFromInt(int64(e.Args()[0]))))
return true
}
func (e *NewSel40) Skill_Use_ex() bool {
//fmt.Println("NewSel39", t.Damage.IntPart())
if e.ID().GetCatchTime() != e.Ctx().Our.CurrentPet.Info.CatchTime {
return true
}
if e.Ctx().Opp.SumDamage.IntPart()%2 != 0 {
e.can = true
} else {
e.can = false
}
return true return true
} }
func init() { func init() {
input.InitEffect(input.EffectType.NewSel, 40, &NewSel40{}) input.InitEffect(input.EffectType.NewSel, 40, &NewSel40{})
} }

View File

@@ -188,7 +188,7 @@ func (e *Weakened) Damage_DIV_ex(t *info.DamageZone) bool {
} }
// 2. 校验并限制衰弱等级≤0 直接返回≥5 按5级算 // 2. 校验并限制衰弱等级≤0 直接返回≥5 按5级算
level := e.Status level := e.Stack()
if level <= 0 { if level <= 0 {
return true return true
} }

View File

@@ -12,6 +12,7 @@ import (
"blazing/logic/service/fight/action" "blazing/logic/service/fight/action"
"blazing/logic/service/fight/info" "blazing/logic/service/fight/info"
"blazing/logic/service/fight/input" "blazing/logic/service/fight/input"
"blazing/logic/service/player"
"blazing/logic/service/user" "blazing/logic/service/user"
"math/rand" "math/rand"
"sync" "sync"
@@ -22,7 +23,10 @@ import (
) )
type FightC struct { type FightC struct {
//准备战斗信息
ReadyInfo info.NoteReadyToFightInfo ReadyInfo info.NoteReadyToFightInfo
//开始战斗信息
info.FightStartOutboundInfo
Info info.Fightinfo Info info.Fightinfo
IsReady bool IsReady bool
ownerID uint32 // 战斗发起者ID ownerID uint32 // 战斗发起者ID
@@ -221,6 +225,8 @@ func NewFight(p1, p2 common.PlayerI, fn func(*info.FightOverInfo)) (*FightC, err
fmt.Println("NewFight", p1.GetInfo().UserID) fmt.Println("NewFight", p1.GetInfo().UserID)
f := &FightC{} f := &FightC{}
f.ownerID = p1.GetInfo().UserID f.ownerID = p1.GetInfo().UserID
// 1. 构建战斗开始信息(整理双方初始宠物信息)
f.callback = fn //战斗结束的回调 f.callback = fn //战斗结束的回调
f.quit = make(chan struct{}) f.quit = make(chan struct{})
f.over = make(chan struct{}) f.over = make(chan struct{})
@@ -249,19 +255,28 @@ func NewFight(p1, p2 common.PlayerI, fn func(*info.FightOverInfo)) (*FightC, err
f.ReadyInfo.OpponentInfo, f.ReadyInfo.OpponentPetList = initfightready(f.Opp) f.ReadyInfo.OpponentInfo, f.ReadyInfo.OpponentPetList = initfightready(f.Opp)
var loadtime time.Duration = 120 * time.Second var loadtime time.Duration = 120 * time.Second
//说明是PVE //说明是PVE
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
f.Opp.Finished = true //PVE 默认boss数据直接加载完成
loadtime = 60 * time.Second
}
f.Broadcast(func(ff *input.Input) { f.Broadcast(func(ff *input.Input) {
ff.SetOPP(f.GetInputByPlayer(ff.Player, true)) ff.SetOPP(f.GetInputByPlayer(ff.Player, true))
}) })
f.FightStartOutboundInfo = f.buildFightStartInfo()
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
f.Opp.Finished = true //PVE 默认boss数据直接加载完成
loadtime = 60 * time.Second
//f.handleNPCFightSpecial(&fightStartInfo)
if f.Opp.Player.(*player.AI_player).CanCapture > 0 {
f.Opp.CanCapture = f.Opp.Player.(*player.AI_player).CanCapture
f.FightStartOutboundInfo.Info2.Catchable = 1 //可以捕捉就置1
}
f.Opp.AttackValue.Prop = f.Opp.Player.(*player.AI_player).Prop
f.FightStartOutboundInfo.Info2.Prop = f.Opp.AttackValue.Prop
}
f.Broadcast(func(ff *input.Input) { f.Broadcast(func(ff *input.Input) {
//ff.InitEFFect(&f.FightStartOutboundInfo)
ff.Player.SendPackCmd(2503, &f.ReadyInfo) ff.Player.SendPackCmd(2503, &f.ReadyInfo)
}) })

View File

@@ -187,6 +187,7 @@ func (our *Input) AddEffect(in *Input, e Effect) Effect {
if v.ID().Base == e.ID().Base && //找到相同的效果id if v.ID().Base == e.ID().Base && //找到相同的效果id
v.Alive() && //如果之前的效果还存活 v.Alive() && //如果之前的效果还存活
equalInts(v.Args(), e.Args()) { //如果层数可以叠加或者是无限层数 equalInts(v.Args(), e.Args()) { //如果层数可以叠加或者是无限层数
fmt.Println("重复效果", e.ID().Suffix(), v.ID().Suffix())
if !v.CanStack() { //说明进行了替换 if !v.CanStack() { //说明进行了替换
v.Alive(false) //不允许叠层,取消效果 v.Alive(false) //不允许叠层,取消效果
@@ -194,7 +195,8 @@ func (our *Input) AddEffect(in *Input, e Effect) Effect {
our.Effects = append(our.Effects, e) our.Effects = append(our.Effects, e)
return v //这里把V替换掉了 return v //这里把V替换掉了
} else { } else {
v.Stack(v.Stack() + e.Stack()) //获取到当前叠层数然后叠加 //默认给叠一层
v.Stack(v.Stack() + 1) //获取到当前叠层数然后叠加
//这里直接返回,不再继续执行后续效果,因为这里是可以叠加的效果 //这里直接返回,不再继续执行后续效果,因为这里是可以叠加的效果
//v.Duration(e.Duration()) //回合数覆盖 //v.Duration(e.Duration()) //回合数覆盖
v.Duration(utils.Max(e.Duration(), v.Duration())) v.Duration(utils.Max(e.Duration(), v.Duration()))
@@ -264,10 +266,3 @@ func (our *Input) CancelTurn(in *Input) {
// } // }
// } // }
// 初始化魂印
func (our *Input) InitEFFect(info *info.FightStartOutboundInfo) {
//our.AttackValue = info.NewAttackValue(our.Player.GetInfo().UserID)
}

View File

@@ -54,22 +54,26 @@ func (e *EffectIDCombiner) EffectID() int64 {
return e.Base return e.Base
} }
// EffectType 读取/替换效果类型(读写一体 // SetEffectType 设置效果类型(修复掩码偏移问题
// 参数t可选,传入则替换当前效果类型;不传则仅读取 // 参数t必须传入有效值否则panic也可加len(t)==0判断
// 返回:当前的效果类型(EnumEffectType func (e *EffectIDCombiner) SetEffectType(t EnumEffectType) {
func (e *EffectIDCombiner) SetEffectType(t ...EnumEffectType) {
e.Base = (e.Base & ^prefixMask) | (int64(t[0]) << prefixOffset) // 修正掩码左移到高16位仅清空效果类型区域
clearMask := uint64(prefixMask) << prefixOffset
e.Base = (e.Base & ^int64(clearMask)) | (int64(t) << prefixOffset)
} }
// GetEffectType 读取效果类型
func (e EffectIDCombiner) GetEffectType() EnumEffectType { func (e EffectIDCombiner) GetEffectType() EnumEffectType {
return EnumEffectType((e.Base >> prefixOffset) & int64(prefixMask))
return EnumEffectType((e.Base >> prefixOffset) & 0xFFFF)
} }
// CatchTime 读取/替换CatchTime读写一体,完全保留你的写法 // SetCatchTime 设置CatchTime修复掩码偏移问题避免清空Suffix
// 参数t可选传入则替换当前CatchTime不传则仅读取 func (e *EffectIDCombiner) SetCatchTime(t uint32) {
// 返回当前的CatchTime值
func (e *EffectIDCombiner) SetCatchTime(t ...uint32) { // 修正掩码左移到中32位仅清空CatchTime区域
e.Base = (e.Base & ^catchMask) | (int64(t[0]) << catchOffset) clearMask := uint64(catchMask) << catchOffset
e.Base = (e.Base & ^int64(clearMask)) | (int64(t) << catchOffset)
} }
func (e EffectIDCombiner) GetCatchTime() uint32 { func (e EffectIDCombiner) GetCatchTime() uint32 {

View File

@@ -2,6 +2,7 @@ package input
import ( import (
"blazing/common/data/xmlres" "blazing/common/data/xmlres"
"fmt"
"sort" "sort"
"blazing/logic/service/common" "blazing/logic/service/common"
@@ -81,6 +82,7 @@ func (our *Input) SortPet() {
t := Geteffect(EffectType.NewSel, e1.EID) t := Geteffect(EffectType.NewSel, e1.EID)
if t != nil { if t != nil {
ef := t.ID() ef := t.ID()
fmt.Println("初始化特性", ef.Suffix())
ef.SetCatchTime(v.Info.CatchTime) ef.SetCatchTime(v.Info.CatchTime)
@@ -154,6 +156,8 @@ func (our *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.Chang
Reason.UserId = our.Player.GetInfo().UserID Reason.UserId = our.Player.GetInfo().UserID
ii = v ii = v
return ii, Reason
} }
} }

View File

@@ -55,7 +55,9 @@ func (e *EffectNode) Stack(t ...int) int {
} }
func (e *EffectNode) ID(t ...input.EffectIDCombiner) input.EffectIDCombiner { func (e *EffectNode) ID(t ...input.EffectIDCombiner) input.EffectIDCombiner {
if len(t) > 0 { if len(t) > 0 {
e.id = t[0] e.id = t[0]
} }

View File

@@ -3,6 +3,7 @@ package main
import ( import (
_ "github.com/gogf/gf/contrib/nosql/redis/v2" _ "github.com/gogf/gf/contrib/nosql/redis/v2"
"blazing/common/data/xmlres"
_ "blazing/contrib/files/local" _ "blazing/contrib/files/local"
"blazing/login/internal/cmd" "blazing/login/internal/cmd"
@@ -21,8 +22,21 @@ import (
"github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gctx"
) )
func init() {
xmlres.Initfile()
}
func main() { func main() {
// for _, i := range xmlres.ItemsMAP {
// cool.DBM(dict.NewDictInfoService().GetModel()).Insert(
// g.Map{"typeId": 6, "name": i.Name, "remark": i.ID, "ordernum": 1},
// )
// fmt.Println(i.ID, i.Name)
// }
//input.Test() //input.Test()
// element.TestAllScenarios() // element.TestAllScenarios()

View File

@@ -35,7 +35,7 @@ func init() {
g.Server().BindMiddleware("/admin/*/open/*", BaseAuthorityMiddlewareOpen) g.Server().BindMiddleware("/admin/*/open/*", BaseAuthorityMiddlewareOpen)
g.Server().BindMiddleware("/admin/*/comm/*", BaseAuthorityMiddlewareComm) g.Server().BindMiddleware("/admin/*/comm/*", BaseAuthorityMiddlewareComm)
g.Server().BindMiddleware("/admin/*", BaseAuthorityMiddleware) g.Server().BindMiddleware("/admin/*", BaseAuthorityMiddleware)
g.Server().BindMiddleware("/*", AutoI18n) // g.Server().BindMiddleware("/*", AutoI18n)
g.Server().BindMiddleware("/*", MiddlewareCORS) g.Server().BindMiddleware("/*", MiddlewareCORS)
} }

View File

@@ -12,7 +12,7 @@ type Task struct {
*cool.Model *cool.Model
PlayerID uint64 `gorm:"not null;index:idx_task_by_player_id;comment:'所属玩家ID'" json:"player_id"` PlayerID uint64 `gorm:"not null;index:idx_task_by_player_id;comment:'所属玩家ID'" json:"player_id"`
TaskID uint32 `gorm:"not null;comment:'任务ID'" json:"task_id"` TaskID uint32 `gorm:"not null;comment:'任务ID'" json:"task_id"`
Data string `gorm:"type:text;not null;comment:'全部数据'" json:"data"` Data string `gorm:"type:jsonb;not null;comment:'全部数据'" json:"data"`
} }
// TaskEX 单个任务的详细信息,包含任务步骤状态和整体状态 // TaskEX 单个任务的详细信息,包含任务步骤状态和整体状态

View File

@@ -45,7 +45,10 @@ func (s *TaskService) Exec(id uint32, t func(*model.TaskEX) bool) {
} }
gg.PlayerID = uint64(s.userid) gg.PlayerID = uint64(s.userid)
gg.TaskID = id gg.TaskID = id
m1.Save(gg) _, err := m1.Save(gg)
if err != nil {
panic(err)
}
} }

View File

@@ -96,6 +96,7 @@ func delChildDict(id int64) error {
func NewDictInfoService() *DictInfoService { func NewDictInfoService() *DictInfoService {
return &DictInfoService{ return &DictInfoService{
&cool.Service{ &cool.Service{
UniqueKey: map[string]string{"name": "名称不能重复"},
Model: model.NewDictInfo(), Model: model.NewDictInfo(),
ListQueryOp: &cool.QueryOp{ ListQueryOp: &cool.QueryOp{
FieldEQ: []string{"typeId"}, FieldEQ: []string{"typeId"},

View File

@@ -445,10 +445,10 @@
<NewSeIdx <NewSeIdx
Idx="75" Stat="1" Eid="16" Args="5" /> Idx="75" Stat="1" Eid="16" Args="5" />
<NewSeIdx Idx="76" Stat="1" Eid="17" Args="0 200" /> <NewSeIdx Idx="76" Stat="1" Eid="17" Args="200" />
<NewSeIdx <NewSeIdx
Idx="77" Stat="1" Eid="17" Args="0 375" /> Idx="77" Stat="1" Eid="17" Args="375" />
<NewSeIdx Idx="78" Stat="1" Eid="17" Args="0 5000" /> <NewSeIdx Idx="78" Stat="1" Eid="17" Args="5000" />
<NewSeIdx <NewSeIdx
Idx="79" Stat="1" Eid="18" Args="" /> Idx="79" Stat="1" Eid="18" Args="" />

File diff suppressed because it is too large Load Diff