Files
bl/logic/service/fight/effect/effect_status.go
xinian 803aa71771
Some checks failed
ci/woodpecker/push/my-first-workflow Pipeline failed
更新说明
2026-04-14 15:55:28 +08:00

316 lines
8.5 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 (
element "blazing/common/data/Element"
"blazing/common/utils"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/fight/node"
"github.com/alpacahq/alpacadecimal"
)
// 修正拼写错误BaseSataus -> BaseStatus
type BaseStatus struct {
node.EffectNode
Status info.EnumPetStatus // 状态类型枚举
}
// 重写切换事件:我方单位切换时清除状态
func (e *BaseStatus) SwitchOut(in *input.Input) bool {
// 我方单位下场时,状态失效
if in == e.CarrierInput() {
e.Alive(false)
}
return true
}
// 不能出手的基础状态(如麻痹、疲惫等)
type StatusCannotAct struct {
BaseStatus
}
// 技能命中前拦截:阻止出手
func (e *StatusCannotAct) ActionStart(attacker, defender *action.SelectSkillAction) bool {
return false
}
// 疲惫状态:仅限制攻击技能,本回合属性技能仍可正常使用。
type StatusTired struct {
BaseStatus
}
func (e *StatusTired) ActionStart(attacker, defender *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return false
}
return e.Ctx().SkillEntity.Category() == info.Category.STATUS
}
// 睡眠状态:受击后解除
type StatusSleep struct {
StatusCannotAct
hasTriedAct bool
}
// 睡眠在“被攻击且未 miss”后立即解除而不是等到技能使用后节点。
func (e *StatusSleep) DamageSubEx(zone *info.DamageZone) bool {
if zone == nil || e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Category() != info.Category.STATUS {
e.Alive(false)
}
return true
}
func (e *StatusSleep) ActionStart(attacker, defender *action.SelectSkillAction) bool {
if e.Duration() <= 0 {
e.hasTriedAct = false
return true
}
e.hasTriedAct = true
return e.StatusCannotAct.ActionStart(attacker, defender)
}
func (e *StatusSleep) Skill_Use_ex() bool {
if !e.hasTriedAct {
return true
}
if e.Duration() <= 0 && e.Ctx().SkillEntity != nil && e.Ctx().Category() != info.Category.STATUS {
e.Alive(false)
}
e.hasTriedAct = false
return true
}
func (e *StatusSleep) TurnEnd() {
e.hasTriedAct = false
e.StatusCannotAct.TurnEnd()
}
// 持续伤害状态基类(中毒、冻伤、烧伤等)
type ContinuousDamage struct {
BaseStatus
isheal bool //是否回血
}
// 回合开始触发持续伤害,保证吃药/空过回合时也会正常结算。
func (e *ContinuousDamage) TurnStart(attacker, defender *action.SelectSkillAction) {
carrier := e.CarrierInput()
source := e.SourceInput()
opp := e.TargetInput()
if carrier == nil {
return
}
damage := e.calculateDamage()
carrier.Damage(source, &info.DamageZone{
Type: info.DamageType.True,
Damage: damage,
})
if len(e.SideEffectArgs) == 0 {
return
}
// 额外效果
carrier.Damage(source, &info.DamageZone{
Type: info.DamageType.True,
Damage: damage,
})
if opp == nil || opp.CurPet[0].GetHP().IntPart() == 0 {
return
}
// 给对方回血(不受回血限制影响)
opp.Heal(carrier, nil, damage)
}
// 计算伤害最大生命值的1/8
func (e *ContinuousDamage) calculateDamage() alpacadecimal.Decimal {
carrier := e.CarrierInput()
if carrier == nil || carrier.CurPet[0] == nil {
return alpacadecimal.Zero
}
return alpacadecimal.NewFromInt(int64(carrier.CurPet[0].Info.MaxHp)).
Div(alpacadecimal.NewFromInt(8))
}
type Burned struct {
ContinuousDamage //继承扣血类
}
func (e *Burned) SkillHit() bool {
e.Ctx().SkillEntity.XML.Power /= 2
return true
}
// 寄生种子状态:扣血同时给对方回血
type ParasiticSeed struct {
node.EffectNode
Status info.EnumPetStatus // 状态类型枚举
}
func (e *ParasiticSeed) SwitchOut(in *input.Input) bool {
//如果我放切换
if in == e.CarrierInput() {
e.Alive(false)
}
return true
}
// 回合开始触发寄生效果。寄生属于完整回合流程的一部分,不依赖本回合是否成功出手。
func (e *ParasiticSeed) TurnStart(attacker, defender *action.SelectSkillAction) {
carrier := e.CarrierInput()
source := e.SourceInput()
if carrier == nil {
return
}
damage := alpacadecimal.NewFromInt(int64(carrier.CurPet[0].Info.MaxHp)).
Div(alpacadecimal.NewFromInt(8))
// 对我方造成真实伤害
carrier.Damage(source, &info.DamageZone{
Type: info.DamageType.True,
Damage: damage,
})
if source == nil || source.CurPet[0] == nil || source.CurPet[0].GetHP().IntPart() == 0 {
return
}
// 给寄生种子的施放者回血(不受回血限制影响)
source.Heal(carrier, nil, damage)
}
type Flammable struct {
BaseStatus
}
func (e *Flammable) ActionStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return true
}
e.Ctx().SkillEntity.Accuracy.Sub(alpacadecimal.NewFromInt(30))
return true
}
func (e *Flammable) Skill_Use_ex() bool {
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.XML.Type != int(element.ElementTypeFire) {
return true
}
// 获取状态效果
eff := e.Ctx().Our.InitEffect(input.EffectType.Status, int(info.PetStatus.Burned))
if eff == nil {
return true
}
e.Ctx().Our.AddEffect(e.Ctx().Our, eff)
return true
}
type Confused struct {
BaseStatus
}
func (e *Confused) ActionStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return true
}
e.Ctx().SkillEntity.Accuracy.Sub(alpacadecimal.NewFromInt(80))
ok, _, _ := e.Input.Player.Roll(5, 100)
if !ok {
return true
}
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
Type: info.DamageType.Fixed,
Damage: alpacadecimal.NewFromInt(50),
})
return true
}
type Blind struct {
BaseStatus
}
func (e *Blind) ActionStart(fattack, sattack *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return true
}
e.Ctx().SkillEntity.Accuracy = e.Ctx().SkillEntity.Accuracy.Mul(alpacadecimal.NewFromFloat(0.5))
return true
}
type Weakened struct {
BaseStatus
}
func (e *Weakened) DamageDivEx(t *info.DamageZone) bool {
// 1. 定义衰弱等级对应的倍率表索引对应等级0级无倍率
// 索引0: 0%未衰弱、1:25%、2:50%、3:100%、4:250%、5:500%
weakenedMultiples := []alpacadecimal.Decimal{
alpacadecimal.Zero, // 0级
alpacadecimal.NewFromFloat(0.25), // 1级25%
alpacadecimal.NewFromFloat(0.5), // 2级50%
alpacadecimal.NewFromFloat(1.0), // 3级100%
alpacadecimal.NewFromFloat(2.5), // 4级250%
alpacadecimal.NewFromFloat(5.0), // 5级500%
}
// 2. 校验并限制衰弱等级≤0 直接返回≥5 按5级算
level := e.Stack()
if level <= 0 {
return true
}
// 等级上限限制为5避免越界
level = utils.Min(level, 5)
// 3. 获取对应等级的倍率,计算最终伤害
multiple := weakenedMultiples[level]
// 伤害计算公式:原伤害 + 原伤害 × 倍率(等价于 原伤害 × (1+倍率)
t.Damage = t.Damage.Add(t.Damage.Mul(multiple))
return true
}
func init() {
// 注册持续伤害类状态
input.InitEffect(input.EffectType.Status, int(info.PetStatus.DrainedHP), &ParasiticSeed{}) // 寄生种子
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Poisoned), &ContinuousDamage{}) // 中毒
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Frozen), &ContinuousDamage{}) // 冻伤
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Burned), &Burned{}) // 烧伤
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Bleeding), &ContinuousDamage{}) // 流血
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Weakened), &Weakened{}) // 衰弱
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Confused), &Confused{}) // 混乱
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Blind), &Blind{}) // 失明
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Flammable), &Flammable{}) // 易燃
// 批量注册不能行动的状态
nonActingStatuses := []info.EnumPetStatus{
info.PetStatus.Paralysis, // 麻痹
info.PetStatus.Fear, // 害怕
info.PetStatus.Petrified, // 石化
}
for _, status := range nonActingStatuses {
effect := &StatusCannotAct{}
effect.Status = status
input.InitEffect(input.EffectType.Status, int(status), effect)
}
tired := &StatusTired{}
tired.Status = info.PetStatus.Tired
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Tired), tired)
// 注册睡眠状态使用枚举常量替代硬编码8
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Sleep), &StatusSleep{})
}