All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
feat(fight): 添加效果工厂模式支持以解决闭包变量捕获问题 - 新增initskillFactory函数用于注册效果工厂 - 修改技能效果注册逻辑从直接实例化改为工厂模式 - 解决循环中闭包捕获变量导致的潜在问题 feat(fight): 实现对手输入获取逻辑优化回合处理 - 添加roundOpponentInput方法获取对手输入 - 重构enterturn方法中的先后手逻辑 - 确保攻击方和被攻击
549 lines
14 KiB
Go
549 lines
14 KiB
Go
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
|
||
}
|