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 } // 持续伤害状态基类(中毒、冻伤、烧伤等) 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{}) }