refactor(fight): 重构战斗流程实现并完善效果处理机制

This commit is contained in:
1
2025-08-27 03:59:46 +00:00
parent 5ba6f1b8ef
commit 79cff5d85b
11 changed files with 112 additions and 75 deletions

View File

@@ -2,9 +2,60 @@ package fight
import "blazing/logic/service/fight/info"
func Rmain() {
func NewBattle(i info.NoteReadyToFightInfo) {
//调用技能产生effect参数后创建effect实例而非技能创建
t := info.BattleSkillEntity{} //
c := info.NewBattleContainer1v1(i) //创建战斗容器
t := info.BattleSkillEntity{} //
t.SideEffectArgs = []int{1, 2, 3}
//先提交effecet后然后计算伤害
//物理和特殊,百分比和固定伤害也算,真实伤害不分类别,故直接扣血就行,不需要计算
if t.Category() == info.Category.PHYSICAL || t.Category() == info.Category.SPECIAL {
c.Effects.Exec(func(e info.Effect) bool {
return e.PreDamage() //执行预处理效果
})
// Apply pre-damage effects for pet sources
// battle.applyEffects(context, EffectTrigger.PreDamage)
// if (context.crit) {
// battle.applyEffects(context, EffectTrigger.OnCritPreDamage) // Trigger crit pre-damage effects
// }
//假如说这里需要能力提升
// c.Exec(func(e Effect) func() {
// return e.OnBeforeAddMark()
// })
//添加印记前的效果如果有任何一个false,说明组织了添加效果
//这里能力提升
// c.Exec(func(e Effect) bool {
// return e.OnAnyMarkAdded()
// })
// var candidates []*Effect
// for _, eff := range c.Effects {
// if eff.Trigger == trigger {
// candidates = append(candidates, eff)
// }
// }
// // 按优先级排序
// sort.SliceStable(candidates, func(i, j int) bool {
// return candidates[i].Priority > candidates[j].Priority
// })
// // 执行
// for _, eff := range candidates {
// ctx.Effect = eff
// keep := eff.Apply(ctx)
// if !keep {
// // 持续回合结束 / 返回 false 的 effect 删除
// c.removeEffect(eff)
// }
// if ctx.Done {
// break // 被拦截
// }
// }
}
}

View File

@@ -3,6 +3,8 @@ package effect
import (
"blazing/logic/service/fight/battle/node"
"blazing/logic/service/fight/info"
"github.com/shopspring/decimal"
)
/**
@@ -13,21 +15,19 @@ type Effect1 struct {
}
func init() {
info.NodeM.AddEffect(&Effect1{})
}
// 重写EFFectID
func (this *Effect1) ID() int {
this.EffectNode.ParamSize(0) //设置参数个数
return 1
}
// 重写POST_DAMAGE ,伤害结束后触发回血
func (this *Effect1) PostDamage() bool {
//获取技能+PET上下文然后修改
//但是这里会产生循环依赖问题
off := this.GetSkill().DamageValue.Div(decimal.NewFromInt(2)) //伤害的一半
this.GetOwnerPet().Hp += uint32(off.IntPart()) //这里是effect在对方挂载,故回血给自己回血
return true
}

View File

@@ -64,8 +64,34 @@ func (this *EffectNode) ParamSize(t int) int {
return this.paramSize
}
func (this *EffectNode) GetSkill(t int) *info.BattleSkillEntity {
pet, _ := this.ctx.Value(info.BattleSkillEntityCtx).(*info.BattleSkillEntity)
func (this *EffectNode) GetSkill() *info.BattleSkillEntity {
pet, ok := this.ctx.Value(info.BattleSkillEntityCtx).(*info.BattleSkillEntity)
if !ok { //effect不一定来自技能,也有特性 能量珠 boss effect
return nil
}
return pet
}
// 获取对方精灵
func (this *EffectNode) GetBattle() *info.BattleContainer1V1 {
pet, _ := this.ctx.Value(info.BattleContainerCtx).(*info.BattleContainer1V1)
return pet
}
// 获取自身精灵
func (this *EffectNode) GetOwnerPet() *info.BattlePetEntity {
pet, _ := this.ctx.Value(info.Pet_O_Ctx).(*info.BattlePetEntity)
return pet
}
func (this *EffectNode) GetTargetPet() *info.BattlePetEntity {
pet, _ := this.ctx.Value(info.Pet_T_Ctx).(*info.BattlePetEntity)
return pet

View File

@@ -23,7 +23,7 @@ var PlayerOperations = enum.New[struct {
type BattleAction struct {
Priority EnumPlayerOperation //优先级本质上是action的itoa
ctx context.Context
ctx context.Context
}
// Compare 比较两个1v1战斗动作的执行优先级核心逻辑
@@ -48,8 +48,8 @@ func (c *BattleAction) Compare(a *BattleAction) *BattleAction {
} else if p2 < 0 {
return c
}
peto, _ := a.ctx.Value(BattlePetEntityCtx).(*BattlePetEntity)
pett, _ := a.ctx.Value(BattlePetEntityCtx).(*BattlePetEntity)
peto, _ := a.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
pett, _ := a.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
p2 = int(peto.UnitAttributes[AttrType.Speed].Value()) - int(pett.UnitAttributes[AttrType.Speed].Value()) // 假设 Use1v1SkillAction 有 SkillPriority() 方法
if p2 > 0 {

View File

@@ -4,10 +4,13 @@ import (
"context"
)
const Input_ctx = "player"
type BattleInputSourceEntity struct {
FightUserInfo
ctx context.Context //输入源的上下文
effects NodeManager //挂载effect
FightUserInfo //用户信息
PetEntities []*BattlePetEntity //宠物信息
ctx context.Context //输入源的上下文
}
// 新建一个宠物
@@ -17,7 +20,7 @@ func (u *BattleInputSourceEntity) NewBattlePetEntity(ctx context.Context) {
ret.UnitAttributes = make(map[EnumAttrType]*Attribute)
//todo 待实现精灵特性+加成的封装
ctx = context.WithValue(ctx, "player", &ret) //添加用户到上下文
ctx = context.WithValue(ctx, Input_ctx, &ret) //添加用户到上下文
ret.ctx = ctx
}
@@ -26,7 +29,7 @@ func (u *BattleInputSourceEntity) NewBattleAction(ctx context.Context, actiontyp
ret := BattleAction{
Priority: actiontype,
}
ctx = context.WithValue(ctx, "player", &ret) //添加用户到上下文
ctx = context.WithValue(ctx, Input_ctx, &ret) //添加用户到上下文
ret.ctx = ctx
}

View File

@@ -12,7 +12,9 @@ import (
// 战斗属性类型
type EnumAttrType int
const BattlePetEntityCtx = "battle_pet_entity_ctx"
// 精灵
const Pet_O_Ctx = "PET_O"
const Pet_T_Ctx = "PET_T"
var AttrType = enum.New[struct {
Attack EnumAttrType `enum:"1"` //`enum:"攻击"`

View File

@@ -44,6 +44,7 @@ type BattleSkillEntity struct {
DamageZone map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值
isCritical bool //技能是否暴击
ATTACK_COUNT_ZONE int //攻击次数
DamageValue decimal.Decimal // 伤害值
// 技能类型属性
//SkillType EnumCategory // 技能类型(物理/特殊/状态)
@@ -252,7 +253,7 @@ func (s *BattleSkillEntity) PutDamageZone(e EnumCategory, dtype EnumsZoneType, v
}
func (s *BattleSkillEntity) Pet() (*BattlePetEntity, bool) {
pet, ok := s.ctx.Value(BattlePetEntityCtx).(*BattlePetEntity)
pet, ok := s.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
return pet, ok

View File

@@ -12,6 +12,7 @@ type BattleContext struct {
Round int //回合数
BattleMode EnumBattleMode //战斗模式
opposite []BattleInputSourceEntity //不同阵营
Effects NodeManager //挂载effect
}
// 执行下一回合

View File

@@ -9,7 +9,7 @@ import (
type BattleContainer1V1 struct {
BattleContext
ownerid uint32 // 房主ID
Ownerid uint32 // 房主ID
FirstPerson uint32 //先手方ID
}
@@ -33,13 +33,15 @@ func NewBattleContainer1v1(i NoteReadyToFightInfo) *BattleContainer1V1 {
ret.same = append(ret.same, BattleInputSourceEntity{
FightUserInfo: i.OurInfo,
//todo 待初始化精灵实体
}) //添加战斗实体
ret.opposite = append(ret.same, BattleInputSourceEntity{
FightUserInfo: i.OpponentInfo,
})
ret.ownerid = i.OwnerID //房主ID
ret.Ownerid = i.OwnerID //房主ID
ret.Rand = random.NewRandomXS128WithTwoSeeds(uint64(ret.ownerid), uint64(time.Now().Unix()))
ret.Rand = random.NewRandomXS128WithTwoSeeds(uint64(ret.Ownerid), uint64(time.Now().Unix()))
ctx := context.Background()
context.WithValue(ctx, BattleContainerCtx, &ret) //传入容器的上下文

View File

@@ -1,7 +1,5 @@
package info
type Effect interface {
PreBattleStart() bool //战斗开始前
OnBattleStart() bool //战斗开始
@@ -78,6 +76,7 @@ type Effect interface {
Stack(int) int
MaxStack() int
//GetSkill() *BattleSkillEntity //获得技能ctx
}
// ========================
@@ -110,54 +109,6 @@ func (c *NodeManager) AddEffect(e Effect) {
c.Effects = append(c.Effects, e)
}
// 触发执行
func (c *NodeManager) Trigger() {
PreBattleStart := c.Exec(func(e Effect) bool {
return e.PreBattleStart()
}) //回合开始
if PreBattleStart { //说明上一步骤没有阻止执行
}
//假如说这里需要能力提升
// c.Exec(func(e Effect) func() {
// return e.OnBeforeAddMark()
// })
//添加印记前的效果如果有任何一个false,说明组织了添加效果
//这里能力提升
// c.Exec(func(e Effect) bool {
// return e.OnAnyMarkAdded()
// })
// var candidates []*Effect
// for _, eff := range c.Effects {
// if eff.Trigger == trigger {
// candidates = append(candidates, eff)
// }
// }
// // 按优先级排序
// sort.SliceStable(candidates, func(i, j int) bool {
// return candidates[i].Priority > candidates[j].Priority
// })
// // 执行
// for _, eff := range candidates {
// ctx.Effect = eff
// keep := eff.Apply(ctx)
// if !keep {
// // 持续回合结束 / 返回 false 的 effect 删除
// c.removeEffect(eff)
// }
// if ctx.Done {
// break // 被拦截
// }
// }
}
// 每回合结束时调用,用于处理持续时间
func (c *NodeManager) Tick() {
var remain []Effect

View File

@@ -13,19 +13,19 @@ var (
mu sync.Mutex // 保护标志位的互斥锁
)
// 当A完成后调用的函数
// 当A 战斗准备完成
func onAFinished() {
fmt.Println("A已完成触发onAFinished")
checkBothFinished() // 检查是否两者都完成
}
// 当B完成后调用的函数
// 当B 战斗准备完成
func onBFinished() {
fmt.Println("B已完成触发onBFinished")
checkBothFinished() // 检查是否两者都完成
}
// 当A和B都完成后调用的函数
// 当A和B都 这时候给双方回复开始战斗包
func onBothFinished() {
fmt.Println("A和B都已完成触发onBothFinished")
}