Files
bl/logic/service/fight/effect/selfkill.go
昔念 e1a994ba11
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(fight): 添加效果工厂模式支持以解决闭包变量捕获问题

- 新增initskillFactory函数用于注册效果工厂
- 修改技能效果注册逻辑从直接实例化改为工厂模式
- 解决循环中闭包捕获变量导致的潜在问题

feat(fight): 实现对手输入获取逻辑优化回合处理

- 添加roundOpponentInput方法获取对手输入
- 重构enterturn方法中的先后手逻辑
- 确保攻击方和被攻击
2026-04-12 22:44:13 +08:00

549 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package effect
import (
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/fight/node"
"github.com/alpacahq/alpacadecimal"
"github.com/gogf/gf/v2/util/grand"
)
type SelfKill struct {
node.EffectNode
can bool
}
func (e *SelfKill) SetArgs(t *input.Input, a ...int) {
// e.CanStack(-1)//后续的不会顶掉这个效果
e.EffectNode.SetArgs(t, a...)
e.Duration(-1) // 次数类,无限回合
}
func (e *SelfKill) OnSkill() bool {
if e.can {
return true
}
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: alpacadecimal.NewFromInt(int64(e.Ctx().Our.CurPet[0].Info.MaxHp)),
})
e.can = true
return true
}
// 自杀,所以效果不消除
func (e *SelfKill) SwitchOut(in *input.Input) bool {
return true
}
type skillHitRegistrarEffect struct {
node.EffectNode
handler func(*skillHitRegistrarEffect) bool
}
func newSkillHitRegistrarEffect(handler func(*skillHitRegistrarEffect) bool) *skillHitRegistrarEffect {
return &skillHitRegistrarEffect{handler: handler}
}
func (e *skillHitRegistrarEffect) SkillHit() bool {
if e.handler == nil {
return true
}
return e.handler(e)
}
type onSkillRegistrarEffect struct {
node.EffectNode
handler func(*onSkillRegistrarEffect) bool
}
func newOnSkillRegistrarEffect(handler func(*onSkillRegistrarEffect) bool) *onSkillRegistrarEffect {
return &onSkillRegistrarEffect{handler: handler}
}
func (e *onSkillRegistrarEffect) OnSkill() bool {
if e.handler == nil {
return true
}
return e.handler(e)
}
type skillUseRegistrarEffect struct {
node.EffectNode
handler func(*skillUseRegistrarEffect) bool
}
func newSkillUseRegistrarEffect(handler func(*skillUseRegistrarEffect) bool) *skillUseRegistrarEffect {
return &skillUseRegistrarEffect{handler: handler}
}
func (e *skillUseRegistrarEffect) Skill_Use() bool {
if e.handler == nil {
return true
}
return e.handler(e)
}
type comparePreOnSkillRegistrarEffect struct {
node.EffectNode
comparePreHandler func(*comparePreOnSkillRegistrarEffect, *action.SelectSkillAction, *action.SelectSkillAction) bool
onSkillHandler func(*comparePreOnSkillRegistrarEffect) bool
}
func newComparePreOnSkillRegistrarEffect(comparePre func(*comparePreOnSkillRegistrarEffect, *action.SelectSkillAction, *action.SelectSkillAction) bool, onSkill func(*comparePreOnSkillRegistrarEffect) bool) *comparePreOnSkillRegistrarEffect {
return &comparePreOnSkillRegistrarEffect{
comparePreHandler: comparePre,
onSkillHandler: onSkill,
}
}
func (e *comparePreOnSkillRegistrarEffect) ComparePre(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if e.comparePreHandler == nil {
return true
}
return e.comparePreHandler(e, fattack, sattack)
}
func (e *comparePreOnSkillRegistrarEffect) OnSkill() bool {
if e.onSkillHandler == nil {
return true
}
return e.onSkillHandler(e)
}
func init() {
registerSelfKillEffects()
registerSelfDamageSkillHitEffects()
registerSelfDamageOnSkillEffects()
registerSelfDamageSkillUseEffects()
registerSelfDamageComparePreOnSkillEffects()
registerSelfDamageSubEffects()
}
func registerSelfKillEffects() {
builders := map[int]func() input.Effect{
59: func() input.Effect { return &Effect59{} },
71: func() input.Effect { return &Effect71{count: 2} },
144: func() input.Effect { return &Effect144{} },
435: func() input.Effect { return &Effect435{} },
574: func() input.Effect { return &Effect574{} },
618: func() input.Effect { return &Effect618{} },
}
for effectID, builder := range builders {
initskill(effectID, builder())
}
}
func registerSelfDamageSkillHitEffects() {
handlers := map[int]func(*skillHitRegistrarEffect) bool{
72: func(e *skillHitRegistrarEffect) bool {
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().AttackTime != 0 {
return true
}
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.True,
Damage: alpacadecimal.NewFromInt(int64(e.Ctx().Our.CurPet[0].Info.Hp)),
})
return true
},
}
for effectID, handler := range handlers {
currentHandler := handler
initskillFactory(effectID, func() input.Effect {
return newSkillHitRegistrarEffect(currentHandler)
})
}
}
func registerSelfDamageOnSkillEffects() {
handlers := map[int]func(*onSkillRegistrarEffect) bool{
79: func(e *onSkillRegistrarEffect) bool {
e.Ctx().Our.SetProp(e.Ctx().Our, 2, 2)
e.Ctx().Our.SetProp(e.Ctx().Our, 4, 1)
e.Ctx().Our.SetProp(e.Ctx().Our, 5, 1)
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: e.Ctx().Our.CurPet[0].GetHP().Div(alpacadecimal.NewFromInt(2)),
})
return true
},
137: func(e *onSkillRegistrarEffect) bool {
currentHP := e.Ctx().Our.CurPet[0].GetHP()
halfHP := currentHP.Div(alpacadecimal.NewFromInt(2))
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: halfHP,
})
e.Ctx().Our.SetProp(e.Ctx().Our, 4, 2)
e.Ctx().Our.SetProp(e.Ctx().Our, 0, 2)
return true
},
479: func(e *onSkillRegistrarEffect) bool {
selfDamage := alpacadecimal.NewFromInt(int64(e.Args()[0].IntPart()))
opponentDamage := alpacadecimal.NewFromInt(int64(e.Args()[1].IntPart()))
currentHP := e.Ctx().Our.CurPet[0].GetHP()
minHP := alpacadecimal.NewFromInt(200)
if currentHP.Cmp(minHP) < 0 {
damageToTake := currentHP.Sub(alpacadecimal.NewFromInt(1))
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: damageToTake,
})
} else {
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: selfDamage,
})
}
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: opponentDamage,
})
return true
},
556: func(e *onSkillRegistrarEffect) bool {
currentHP := e.Ctx().Our.CurPet[0].Info.Hp
if currentHP > 1 {
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: alpacadecimal.NewFromInt(int64(currentHP - 1)),
})
}
return true
},
}
for effectID, handler := range handlers {
currentHandler := handler
initskillFactory(effectID, func() input.Effect {
return newOnSkillRegistrarEffect(currentHandler)
})
}
}
func registerSelfDamageSkillUseEffects() {
handlers := map[int]func(*skillUseRegistrarEffect) bool{
80: func(e *skillUseRegistrarEffect) bool {
damage := e.Ctx().Our.CurPet[0].GetMaxHP().Div(alpacadecimal.NewFromInt(2))
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: damage,
})
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: damage,
})
return true
},
112: func(e *skillUseRegistrarEffect) bool {
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: alpacadecimal.NewFromInt(int64(e.Ctx().Our.CurPet[0].Info.MaxHp)),
})
damage := int64(grand.N(250, 300))
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: alpacadecimal.Min(alpacadecimal.NewFromInt(damage), e.Ctx().Opp.CurPet[0].GetHP().Sub(alpacadecimal.NewFromInt(1))),
})
return true
},
617: func(e *skillUseRegistrarEffect) bool {
if len(e.Args()) < 2 {
return true
}
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: e.Ctx().Our.CurPet[0].GetMaxHP(),
})
minDamage := int(e.Args()[0].IntPart())
maxDamage := int(e.Args()[1].IntPart())
if maxDamage < minDamage {
minDamage, maxDamage = maxDamage, minDamage
}
randomDamage := minDamage
if maxDamage > minDamage {
randomDamage = grand.N(minDamage, maxDamage)
}
remainHP := e.Ctx().Opp.CurPet[0].GetHP().Sub(alpacadecimal.NewFromInt(1))
if remainHP.Cmp(alpacadecimal.Zero) <= 0 {
return true
}
damage := alpacadecimal.Min(alpacadecimal.NewFromInt(int64(randomDamage)), remainHP)
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: damage,
})
return true
},
1380: func(e *skillUseRegistrarEffect) bool {
if len(e.Args()) < 3 {
return true
}
applyAllPropDown(e.Ctx().Our, e.Ctx().Opp, int8(e.Args()[0].IntPart()))
sub := e.Ctx().Our.InitEffect(input.EffectType.Sub, 1380, int(e.Args()[1].IntPart()), int(e.Args()[2].IntPart()))
if sub != nil {
e.Ctx().Opp.AddEffect(e.Ctx().Our, sub)
}
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: e.Ctx().Our.CurPet[0].GetHP(),
})
return true
},
}
for effectID, handler := range handlers {
currentHandler := handler
initskillFactory(effectID, func() input.Effect {
return newSkillUseRegistrarEffect(currentHandler)
})
}
}
func registerSelfDamageComparePreOnSkillEffects() {
effects := map[int]*comparePreOnSkillRegistrarEffect{
142: newComparePreOnSkillRegistrarEffect(
func(e *comparePreOnSkillRegistrarEffect, fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if fattack == nil {
return true
}
if fattack.PlayerID == e.Ctx().Our.UserID {
return true
}
if sattack == nil || sattack.SkillEntity == nil {
return true
}
sattack.SkillEntity.XML.Priority += 1
return true
},
func(e *comparePreOnSkillRegistrarEffect) bool {
maxHP := e.Ctx().Our.CurPet[0].GetMaxHP()
damageAmount := maxHP.Div(e.Args()[0])
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: damageAmount,
})
return true
},
),
}
for effectID, effect := range effects {
currentEffect := effect
initskillFactory(effectID, func() input.Effect {
return newComparePreOnSkillRegistrarEffect(currentEffect.comparePreHandler, currentEffect.onSkillHandler)
})
}
}
func registerSelfDamageSubEffects() {
input.InitEffect(input.EffectType.Sub, 618, &Effect618Sub{})
input.InitEffect(input.EffectType.Sub, 1380, &Effect1380Sub{})
}
// Effect 59: 消耗自身全部体力(体力降到0),使下一只出战精灵的{0}和{1}能力提升1个等级
type Effect59 struct {
SelfKill
}
func (e *Effect59) TurnStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) {
if !e.can {
return
}
e.Ctx().Our.SetProp(e.Ctx().Our, int8(e.Args()[0].IntPart()), 1)
e.Ctx().Our.SetProp(e.Ctx().Our, int8(e.Args()[1].IntPart()), 1)
e.Alive(false)
}
// Effect 71: 消耗自身全部体力己方下2次攻击技能必定打出致命一击
type Effect71 struct {
SelfKill
count int
}
func (e *Effect71) ActionStart(a, b *action.SelectSkillAction) bool {
if !e.can {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.XML.CritRate = 16
e.count--
if e.count <= 0 {
e.Alive(false)
}
return true
}
// Effect 144: 消耗自己所有体力,使下一个出战的精灵{0}回合免疫异常状态
type Effect144 struct {
SelfKill
count int
}
func (e *Effect144) EFFect_Befer(in *input.Input, effEffect input.Effect) bool {
if !e.can {
return true
}
if int(e.Input.FightC.GetOverInfo().Round) >= e.count+e.SideEffectArgs[0] {
e.Alive(false)
}
if e.count == 0 {
e.count = int(e.Input.FightC.GetOverInfo().Round)
}
if in != e.Ctx().Opp {
return true
}
if input.IS_Stat(effEffect) {
return false
}
return true
}
// Effect 435: 牺牲自己,使下回合出场的精灵首次攻击必定命中,必定先手
type Effect435 struct {
SelfKill
}
func (e *Effect435) ComparePre(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if !e.can {
return true
}
if fattack == nil {
return true
}
if fattack.PlayerID == e.Ctx().Our.UserID {
return true
}
if sattack == nil || sattack.SkillEntity == nil {
return true
}
sattack.SkillEntity.XML.Priority += 7
e.Alive(false)
return true
}
func (e *Effect435) ActionStart(a, b *action.SelectSkillAction) bool {
if !e.can {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.XML.MustHit = 1
return true
}
// Effect 574: 消耗自身全部体力,令己方下次使用的技能必定先手、必定命中,下次命中的攻击技能必定打出致命一击
type Effect574 struct {
SelfKill
}
func (e *Effect574) ComparePre(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if !e.can {
return true
}
if fattack == nil {
return true
}
if fattack.PlayerID == e.Ctx().Our.UserID {
return true
}
if sattack == nil || sattack.SkillEntity == nil {
return true
}
sattack.SkillEntity.XML.Priority += 7
e.Alive(false)
return true
}
func (e *Effect574) ActionStart(a, b *action.SelectSkillAction) bool {
if !e.can {
return true
}
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.XML.MustHit = 1
e.Ctx().SkillEntity.XML.CritRate = 16
return true
}
// Effect 618: 消耗自身所有体力,使下一只出战精灵{0}回合内每回合恢复{1}点体力
type Effect618 struct {
SelfKill
}
func (e *Effect618) SwitchIn(in *input.Input) bool {
if !e.can || in != e.Ctx().Our {
return true
}
effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 618, e.SideEffectArgs...)
if effect != nil {
e.Ctx().Our.AddEffect(e.Ctx().Our, effect)
}
e.Alive(false)
return true
}
type Effect618Sub struct {
RoundEffectArg0Base
}
func (e *Effect618Sub) TurnEnd() {
if len(e.Args()) > 1 && e.Ctx().Our.CurPet[0].Info.Hp > 0 {
e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Args()[1])
}
e.EffectNode.TurnEnd()
}
type Effect1380Sub struct {
RoundEffectArg0Base
}
func (e *Effect1380Sub) ComparePre(fattack, sattack *action.SelectSkillAction) bool {
current := actionByPlayer(fattack, sattack, e.Ctx().Our.UserID)
if current == nil || current.SkillEntity == nil || len(e.Args()) < 2 {
return true
}
current.SkillEntity.XML.Priority -= int(e.Args()[1].IntPart())
return true
}