refactor(fight): 重构战斗流程实现并完善效果处理机制
This commit is contained in:
@@ -2,9 +2,60 @@ package fight
|
|||||||
|
|
||||||
import "blazing/logic/service/fight/info"
|
import "blazing/logic/service/fight/info"
|
||||||
|
|
||||||
func Rmain() {
|
func NewBattle(i info.NoteReadyToFightInfo) {
|
||||||
//调用技能产生effect参数后,创建effect实例,而非技能创建
|
//调用技能产生effect参数后,创建effect实例,而非技能创建
|
||||||
t := info.BattleSkillEntity{} //
|
c := info.NewBattleContainer1v1(i) //创建战斗容器
|
||||||
|
t := info.BattleSkillEntity{} //
|
||||||
t.SideEffectArgs = []int{1, 2, 3}
|
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 // 被拦截
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package effect
|
|||||||
import (
|
import (
|
||||||
"blazing/logic/service/fight/battle/node"
|
"blazing/logic/service/fight/battle/node"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,21 +15,19 @@ type Effect1 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
info.NodeM.AddEffect(&Effect1{})
|
info.NodeM.AddEffect(&Effect1{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重写EFFectID
|
// 重写EFFectID
|
||||||
func (this *Effect1) ID() int {
|
func (this *Effect1) ID() int {
|
||||||
this.EffectNode.ParamSize(0) //设置参数个数
|
this.EffectNode.ParamSize(0) //设置参数个数
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重写POST_DAMAGE ,伤害结束后触发回血
|
// 重写POST_DAMAGE ,伤害结束后触发回血
|
||||||
func (this *Effect1) PostDamage() bool {
|
func (this *Effect1) PostDamage() bool {
|
||||||
//获取技能+PET上下文,然后修改
|
|
||||||
//但是这里会产生循环依赖问题
|
|
||||||
|
|
||||||
|
off := this.GetSkill().DamageValue.Div(decimal.NewFromInt(2)) //伤害的一半
|
||||||
|
this.GetOwnerPet().Hp += uint32(off.IntPart()) //这里是effect在对方挂载,故回血给自己回血
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,34 @@ func (this *EffectNode) ParamSize(t int) int {
|
|||||||
return this.paramSize
|
return this.paramSize
|
||||||
|
|
||||||
}
|
}
|
||||||
func (this *EffectNode) GetSkill(t int) *info.BattleSkillEntity {
|
func (this *EffectNode) GetSkill() *info.BattleSkillEntity {
|
||||||
pet, _ := this.ctx.Value(info.BattleSkillEntityCtx).(*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
|
return pet
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ var PlayerOperations = enum.New[struct {
|
|||||||
|
|
||||||
type BattleAction struct {
|
type BattleAction struct {
|
||||||
Priority EnumPlayerOperation //优先级本质上是action的itoa
|
Priority EnumPlayerOperation //优先级本质上是action的itoa
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare 比较两个1v1战斗动作的执行优先级(核心逻辑)
|
// Compare 比较两个1v1战斗动作的执行优先级(核心逻辑)
|
||||||
@@ -48,8 +48,8 @@ func (c *BattleAction) Compare(a *BattleAction) *BattleAction {
|
|||||||
} else if p2 < 0 {
|
} else if p2 < 0 {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
peto, _ := a.ctx.Value(BattlePetEntityCtx).(*BattlePetEntity)
|
peto, _ := a.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
|
||||||
pett, _ := a.ctx.Value(BattlePetEntityCtx).(*BattlePetEntity)
|
pett, _ := a.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
|
||||||
|
|
||||||
p2 = int(peto.UnitAttributes[AttrType.Speed].Value()) - int(pett.UnitAttributes[AttrType.Speed].Value()) // 假设 Use1v1SkillAction 有 SkillPriority() 方法
|
p2 = int(peto.UnitAttributes[AttrType.Speed].Value()) - int(pett.UnitAttributes[AttrType.Speed].Value()) // 假设 Use1v1SkillAction 有 SkillPriority() 方法
|
||||||
if p2 > 0 {
|
if p2 > 0 {
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const Input_ctx = "player"
|
||||||
|
|
||||||
type BattleInputSourceEntity struct {
|
type BattleInputSourceEntity struct {
|
||||||
FightUserInfo
|
FightUserInfo //用户信息
|
||||||
ctx context.Context //输入源的上下文
|
PetEntities []*BattlePetEntity //宠物信息
|
||||||
effects NodeManager //挂载effect
|
ctx context.Context //输入源的上下文
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新建一个宠物
|
// 新建一个宠物
|
||||||
@@ -17,7 +20,7 @@ func (u *BattleInputSourceEntity) NewBattlePetEntity(ctx context.Context) {
|
|||||||
|
|
||||||
ret.UnitAttributes = make(map[EnumAttrType]*Attribute)
|
ret.UnitAttributes = make(map[EnumAttrType]*Attribute)
|
||||||
//todo 待实现精灵特性+加成的封装
|
//todo 待实现精灵特性+加成的封装
|
||||||
ctx = context.WithValue(ctx, "player", &ret) //添加用户到上下文
|
ctx = context.WithValue(ctx, Input_ctx, &ret) //添加用户到上下文
|
||||||
ret.ctx = ctx
|
ret.ctx = ctx
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -26,7 +29,7 @@ func (u *BattleInputSourceEntity) NewBattleAction(ctx context.Context, actiontyp
|
|||||||
ret := BattleAction{
|
ret := BattleAction{
|
||||||
Priority: actiontype,
|
Priority: actiontype,
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, "player", &ret) //添加用户到上下文
|
ctx = context.WithValue(ctx, Input_ctx, &ret) //添加用户到上下文
|
||||||
ret.ctx = ctx
|
ret.ctx = ctx
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import (
|
|||||||
// 战斗属性类型
|
// 战斗属性类型
|
||||||
type EnumAttrType int
|
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 {
|
var AttrType = enum.New[struct {
|
||||||
Attack EnumAttrType `enum:"1"` //`enum:"攻击"`
|
Attack EnumAttrType `enum:"1"` //`enum:"攻击"`
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ type BattleSkillEntity struct {
|
|||||||
DamageZone map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值
|
DamageZone map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值
|
||||||
isCritical bool //技能是否暴击
|
isCritical bool //技能是否暴击
|
||||||
ATTACK_COUNT_ZONE int //攻击次数
|
ATTACK_COUNT_ZONE int //攻击次数
|
||||||
|
DamageValue decimal.Decimal // 伤害值
|
||||||
// 技能类型属性
|
// 技能类型属性
|
||||||
//SkillType EnumCategory // 技能类型(物理/特殊/状态)
|
//SkillType EnumCategory // 技能类型(物理/特殊/状态)
|
||||||
|
|
||||||
@@ -252,7 +253,7 @@ func (s *BattleSkillEntity) PutDamageZone(e EnumCategory, dtype EnumsZoneType, v
|
|||||||
|
|
||||||
}
|
}
|
||||||
func (s *BattleSkillEntity) Pet() (*BattlePetEntity, bool) {
|
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
|
return pet, ok
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ type BattleContext struct {
|
|||||||
Round int //回合数
|
Round int //回合数
|
||||||
BattleMode EnumBattleMode //战斗模式
|
BattleMode EnumBattleMode //战斗模式
|
||||||
opposite []BattleInputSourceEntity //不同阵营
|
opposite []BattleInputSourceEntity //不同阵营
|
||||||
|
Effects NodeManager //挂载effect
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行下一回合
|
// 执行下一回合
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type BattleContainer1V1 struct {
|
type BattleContainer1V1 struct {
|
||||||
BattleContext
|
BattleContext
|
||||||
ownerid uint32 // 房主ID
|
Ownerid uint32 // 房主ID
|
||||||
FirstPerson uint32 //先手方ID
|
FirstPerson uint32 //先手方ID
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -33,13 +33,15 @@ func NewBattleContainer1v1(i NoteReadyToFightInfo) *BattleContainer1V1 {
|
|||||||
|
|
||||||
ret.same = append(ret.same, BattleInputSourceEntity{
|
ret.same = append(ret.same, BattleInputSourceEntity{
|
||||||
FightUserInfo: i.OurInfo,
|
FightUserInfo: i.OurInfo,
|
||||||
|
//todo 待初始化精灵实体
|
||||||
|
|
||||||
}) //添加战斗实体
|
}) //添加战斗实体
|
||||||
ret.opposite = append(ret.same, BattleInputSourceEntity{
|
ret.opposite = append(ret.same, BattleInputSourceEntity{
|
||||||
FightUserInfo: i.OpponentInfo,
|
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()
|
ctx := context.Background()
|
||||||
context.WithValue(ctx, BattleContainerCtx, &ret) //传入容器的上下文
|
context.WithValue(ctx, BattleContainerCtx, &ret) //传入容器的上下文
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package info
|
package info
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Effect interface {
|
type Effect interface {
|
||||||
PreBattleStart() bool //战斗开始前
|
PreBattleStart() bool //战斗开始前
|
||||||
OnBattleStart() bool //战斗开始
|
OnBattleStart() bool //战斗开始
|
||||||
@@ -78,6 +76,7 @@ type Effect interface {
|
|||||||
|
|
||||||
Stack(int) int
|
Stack(int) int
|
||||||
MaxStack() int
|
MaxStack() int
|
||||||
|
//GetSkill() *BattleSkillEntity //获得技能ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================
|
// ========================
|
||||||
@@ -110,54 +109,6 @@ func (c *NodeManager) AddEffect(e Effect) {
|
|||||||
c.Effects = append(c.Effects, e)
|
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() {
|
func (c *NodeManager) Tick() {
|
||||||
var remain []Effect
|
var remain []Effect
|
||||||
|
|||||||
@@ -13,19 +13,19 @@ var (
|
|||||||
mu sync.Mutex // 保护标志位的互斥锁
|
mu sync.Mutex // 保护标志位的互斥锁
|
||||||
)
|
)
|
||||||
|
|
||||||
// 当A完成后调用的函数
|
// 当A 战斗准备完成
|
||||||
func onAFinished() {
|
func onAFinished() {
|
||||||
fmt.Println("A已完成,触发onAFinished")
|
fmt.Println("A已完成,触发onAFinished")
|
||||||
checkBothFinished() // 检查是否两者都完成
|
checkBothFinished() // 检查是否两者都完成
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当B完成后调用的函数
|
// 当B 战斗准备完成
|
||||||
func onBFinished() {
|
func onBFinished() {
|
||||||
fmt.Println("B已完成,触发onBFinished")
|
fmt.Println("B已完成,触发onBFinished")
|
||||||
checkBothFinished() // 检查是否两者都完成
|
checkBothFinished() // 检查是否两者都完成
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当A和B都完成后调用的函数
|
// 当A和B都 这时候给双方回复开始战斗包
|
||||||
func onBothFinished() {
|
func onBothFinished() {
|
||||||
fmt.Println("A和B都已完成,触发onBothFinished")
|
fmt.Println("A和B都已完成,触发onBothFinished")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user