Files
bl/logic/service/fight/battle/skill/effect/effect.go
昔念 d7b4fb88c8 refactor(logic): 删除战斗系统相关代码
- 移除 battle 目录下的所有文件
- 删除 fight/battle 目录及其内容
- 更新 go.mod 和 go.sum 文件,移除相关依赖
2025-08-25 01:48:42 +08:00

216 lines
4.8 KiB
Go

package effect
import (
"fmt"
"sort"
"github.com/badu/bus"
"github.com/tnnmigga/enum"
)
// ========================
// BattleMode 枚举
// ========================
type EnumBattleMode string
var BattleMode = enum.New[struct {
PVE EnumBattleMode `enum:"3"`
PVP EnumBattleMode `enum:"1"`
}]()
// ========================
// Effect 框架
// ========================
type ContextType interface {
SourceID() string
}
type EffectContext struct {
Parent ContextType
Trigger EnumEffectTrigger
Container *EffectContainer
Effect *Effect
Available bool
Success bool
Done bool
}
func (c *EffectContext) Stop() { c.Done = true }
func (c *EffectContext) SourceID() string {
if c.Container != nil {
return c.Container.ID
}
return "unknown"
}
type EffectFunc func(ctx *EffectContext, next func())
type Effect struct {
ID string
Priority int
Triggers []EnumEffectTrigger
Condition func(*EffectContext) bool
Apply EffectFunc
}
type EffectContainer struct {
ID string
Effects []*Effect
Subs []*bus.Listener[*EffectContext]
Battle *Battle
Parent ContextType
}
func NewEffectContainer(id string, effects []*Effect, battle *Battle, parent ContextType) *EffectContainer {
c := &EffectContainer{
ID: id,
Effects: effects,
Battle: battle,
Parent: parent,
}
// 自动订阅 triggers
for _, e := range effects {
for _, trig := range e.Triggers {
sub := battle.GetTopic(trig).Sub(func(ctx *EffectContext) {
if ctx.Available && e.Apply != nil {
ctx.Effect = e
c.executeWithPriority([]*EffectContext{ctx})
}
})
c.Subs = append(c.Subs, sub)
}
}
return c
}
// done/next 执行队列,按优先级
func (c *EffectContainer) executeWithPriority(queue []*EffectContext) {
sort.SliceStable(queue, func(i, j int) bool {
return queue[i].Effect.Priority > queue[j].Effect.Priority
})
var runNext func(idx int)
runNext = func(idx int) {
if idx >= len(queue) {
return
}
ctx := queue[idx]
if ctx.Available {
ctx.Effect.Apply(ctx, func() {
runNext(idx + 1)
})
} else {
runNext(idx + 1)
}
}
runNext(0)
}
// ========================
// Battle
// ========================
type Battle struct {
Turn int
topics map[EnumEffectTrigger]*bus.Topic[*EffectContext]
}
func NewBattle() *Battle {
allTriggers := []EnumEffectTrigger{
EffectTrigger.OnBattleStart,
EffectTrigger.BeforeSort,
EffectTrigger.BeforeUseSkillCheck,
EffectTrigger.AfterUseSkillCheck,
EffectTrigger.BeforeMultiHit,
EffectTrigger.BeforeHit,
EffectTrigger.OnCritPreDamage,
EffectTrigger.PreDamage,
EffectTrigger.OnHit,
EffectTrigger.OnMiss,
EffectTrigger.AfterAttacked,
EffectTrigger.OnDefeat,
EffectTrigger.SkillUseEnd,
EffectTrigger.OnBeforeCalculateDamage,
EffectTrigger.OnDamage,
EffectTrigger.Shield,
EffectTrigger.PostDamage,
EffectTrigger.OnCritPostDamage,
EffectTrigger.OnTransform,
EffectTrigger.OnTransformEnd,
EffectTrigger.BeforeTransform,
EffectTrigger.AfterTransform,
EffectTrigger.TurnStart,
EffectTrigger.TurnEnd,
EffectTrigger.OnBeforeAddMark,
EffectTrigger.OnAnyMarkAdded,
EffectTrigger.OnRemoveMark,
EffectTrigger.OnMarkCreated,
EffectTrigger.OnMarkDestroy,
EffectTrigger.OnMarkDurationEnd,
EffectTrigger.OnStackBefore,
EffectTrigger.OnStack,
EffectTrigger.OnBeforeConsumeStack,
EffectTrigger.OnConsumeStack,
EffectTrigger.OnBeforeHeal,
EffectTrigger.OnHeal,
EffectTrigger.BeforeRageGain,
EffectTrigger.BeforeRageLoss,
EffectTrigger.OnRageGain,
EffectTrigger.OnRageLoss,
EffectTrigger.OnSwitchIn,
EffectTrigger.OnSwitchOut,
EffectTrigger.OnOwnerSwitchIn,
EffectTrigger.OnOwnerSwitchOut,
EffectTrigger.BeforeEffect,
EffectTrigger.AfterEffect,
}
topics := make(map[EnumEffectTrigger]*bus.Topic[*EffectContext])
for _, trig := range allTriggers {
topics[trig] = bus.NewTopic[*EffectContext]()
}
return &Battle{Turn: 0, topics: topics}
}
func (b *Battle) GetTopic(trig EnumEffectTrigger) *bus.Topic[*EffectContext] {
return b.topics[trig]
}
func (b *Battle) NextTurn(containers []*EffectContainer) {
b.Turn++
fmt.Printf("=== 回合 %d 开始 ===\n", b.Turn)
b.PublishTrigger(EffectTrigger.TurnStart, containers)
fmt.Println("=== 玩家操作阶段 ===")
b.PublishTrigger(EffectTrigger.TurnEnd, containers)
fmt.Printf("=== 回合 %d 结束 ===\n\n", b.Turn)
}
func (b *Battle) PublishTrigger(trigger EnumEffectTrigger, containers []*EffectContainer) {
for _, c := range containers {
for _, e := range c.Effects {
for _, t := range e.Triggers {
if t == trigger {
ctx := &EffectContext{
Parent: c.Parent,
Trigger: trigger,
Container: c,
Effect: e,
Available: true,
}
b.GetTopic(trigger).Pub(ctx)
}
}
}
}
}
// ========================
// 示例
// ========================
type Player struct {
ID string
}
func (p *Player) SourceID() string { return p.ID }