- 移除 BattleStateMachine 和 BattleUnit 相关代码 - 新增 BattleContainer 和 DamageContext 结构体 - 重构伤害计算逻辑,使用高精度 decimal 进行计算 - 更新随机数生成器,支持基于用户和时间的种子生成 - 优化战斗信息结构,增加 OwnerID 字段
149 lines
3.9 KiB
Go
149 lines
3.9 KiB
Go
package effect
|
||
|
||
import (
|
||
"blazing/logic/service/fight/battle/node"
|
||
"sort"
|
||
|
||
"github.com/tnnmigga/enum"
|
||
)
|
||
|
||
// ========================
|
||
// 上下文:一次效果执行环境
|
||
// ========================
|
||
type EffectContext struct {
|
||
Parent string // 上下文来源(比如 "Skill"、"Buff"、"Passive")
|
||
Trigger node.EnumEffectTrigger // 当前触发的节点
|
||
Container *EffectContainer // 效果容器(通常挂在 Actor 身上)
|
||
Effect *Effect // 当前正在执行的 Effect
|
||
Available bool // 是否可用
|
||
Success bool // 是否执行成功
|
||
Done bool // 是否中止后续执行
|
||
}
|
||
|
||
// ========================
|
||
// Effect: 单个效果
|
||
// ========================
|
||
type Effect struct {
|
||
ID uint32 // 唯一标识
|
||
Trigger node.EnumEffectTrigger // 触发节点
|
||
Priority int // 执行优先级,数值越大越先执行
|
||
LifeType EnumLifeType //回合效果 是否可持续 继承到下一直精灵
|
||
Duration int // 持续回合/次(0 = 即时生效,>0 = 回合数 ,负数是永久)
|
||
Stacks int // 当前层数
|
||
MaxStack int // 最大叠加层数
|
||
Handler func(ctx *EffectContext, next func()) bool // 执行逻辑,返回 true 表示继续保留 //TODO 内部判断是否切换了精灵,是否满足条件
|
||
|
||
}
|
||
|
||
// ================= LifeType =================
|
||
type EnumLifeType int
|
||
|
||
var LifeType = enum.New[struct {
|
||
TurnBased EnumLifeType `enum:"1"` // 回合数限制
|
||
CountBased EnumLifeType `enum:"2"` // 次数限制
|
||
}]()
|
||
|
||
// ========================
|
||
// 容器:存放多个效果
|
||
// ========================
|
||
type EffectContainer struct {
|
||
//GlobalEffects []*Effect // 全局常驻/回合/次数效果
|
||
Effects []*Effect //effects 实际上全局就是effect无限回合
|
||
}
|
||
|
||
// 添加效果
|
||
func (c *EffectContainer) AddEffect(e *Effect) {
|
||
// 如果已有同 ID 的效果,尝试叠加
|
||
for _, eff := range c.Effects {
|
||
if eff.ID == e.ID {
|
||
if eff.Stacks < eff.MaxStack {
|
||
eff.Stacks++
|
||
}
|
||
return
|
||
}
|
||
}
|
||
// 否则新加入
|
||
c.Effects = append(c.Effects, e)
|
||
}
|
||
|
||
// 添加全局效果
|
||
func (c *EffectContainer) AddGlobalEffects(e *Effect) {
|
||
// 如果已有同 ID 的效果,尝试叠加
|
||
for _, eff := range c.GlobalEffects {
|
||
if eff.ID == e.ID {
|
||
if eff.Stacks < eff.MaxStack {
|
||
eff.Stacks++
|
||
}
|
||
return
|
||
}
|
||
}
|
||
// 否则新加入
|
||
c.GlobalEffects = append(c.GlobalEffects, e)
|
||
}
|
||
|
||
// 触发执行
|
||
func (c *EffectContainer) Trigger(trigger node.EnumEffectTrigger, ctx *EffectContext) {
|
||
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 *EffectContainer) Tick() {
|
||
var remain []*Effect
|
||
for _, eff := range c.Effects {
|
||
if eff.Duration > 0 {
|
||
eff.Duration--
|
||
}
|
||
if eff.Duration != 0 { // 保留 (负数表示永久)
|
||
remain = append(remain, eff)
|
||
}
|
||
}
|
||
c.Effects = remain
|
||
}
|
||
|
||
// 删除
|
||
func (c *EffectContainer) removeEffect(e *Effect) {
|
||
var remain []*Effect
|
||
for _, eff := range c.Effects {
|
||
if eff != e {
|
||
remain = append(remain, eff)
|
||
}
|
||
}
|
||
c.Effects = remain
|
||
}
|
||
|
||
// 清理过期效果
|
||
func (c *EffectContainer) Cleanup() {
|
||
var alive []*Effect
|
||
for _, e := range c.Effects {
|
||
if e.Duration != 0 {
|
||
alive = append(alive, e)
|
||
}
|
||
}
|
||
c.Effects = alive //挂载到普通effect
|
||
}
|