Files
bl/logic/service/fight/effect/effect_status.go
昔念 6455455992 feat(fight): 增加Boss精灵特效索引解析与空列表校验
在挑战Boss逻辑中,新增对Boss怪物NewSeIdxs字段的解析,将其分割并转换为EffectInfo添加到宠物信息中。同时增加对PetList为空时的错误处理,返回精灵不存在错误码。

refactor(effect): 调整技能属性判断方式及方法命名

将部分战斗效果和技能实体中的Type()方法重命名为GetType(),统一接口调用方式,并修改属性类型比较逻辑,直接通过整型值进行判断,提升代码一致性与可维护性。

fix(xml): 补充地图Boss配置项Id字段

更新地图配置文件中Boss节点缺失的Id属性,确保Boss数据结构完整性和唯一标识正确加载。

chore(input): 增加技能实体非空检查防止panic

在输入处理模块中加入对SelectSkillAction.SkillEntity的空指针检查,避免因未初始化技能导致运行时异常。
2025-11-25 18:25:52 +08:00

230 lines
6.4 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/shopspring/decimal"
)
// 修正拼写错误BaseSataus -> BaseStatus
type BaseStatus struct {
node.EffectNode
Status info.EnumPetStatus // 状态类型枚举
}
// 重写切换事件:我方单位切换时清除状态
func (e *BaseStatus) Switch(in *input.Input, _ info.AttackValue, _ *info.BattlePetEntity) bool {
// 我方单位下场时,状态失效
if in == e.Ctx().Our {
e.Alive(false)
}
return true
}
// 不能出手的基础状态(如麻痹、疲惫等)
type StatusCannotAct struct {
BaseStatus
}
// 技能命中前拦截:阻止出手
func (e *StatusCannotAct) Action_start(attacker, defender *action.SelectSkillAction) bool {
return false
}
// 睡眠状态:受击后解除
type StatusSleep struct {
StatusCannotAct
hasTriedAct bool // 标记是否尝试过行动
}
// 尝试出手时标记状态
func (e *StatusSleep) Action_start(attacker, defender *action.SelectSkillAction) bool {
e.hasTriedAct = true
return e.StatusCannotAct.Action_start(attacker, defender)
}
// 技能使用后处理:非状态类技能触发后解除睡眠
func (e *StatusSleep) Skill_Use_ex() bool {
if !e.hasTriedAct {
return true
}
// 技能实体存在且非状态类型技能,解除睡眠
if e.Ctx().SkillEntity != nil && e.Ctx().Category() != info.Category.STATUS {
e.Alive(false)
}
return true
}
// 持续伤害状态基类(中毒、冻伤、烧伤等)
type ContinuousDamage struct {
BaseStatus
}
// 技能命中前触发伤害1/8最大生命值真实伤害
func (e *ContinuousDamage) Action_start(attacker, defender *action.SelectSkillAction) bool {
damage := e.calculateDamage()
e.Ctx().Our.Damage(e.Input, &info.DamageZone{
Type: info.DamageType.True,
Damage: damage,
})
return true
}
// 计算伤害最大生命值的1/8
func (e *ContinuousDamage) calculateDamage() decimal.Decimal {
return decimal.NewFromUint64(uint64(e.Ctx().Our.CurrentPet.Info.MaxHp)).
Div(decimal.NewFromInt(8))
}
type Burned struct {
ContinuousDamage //继承扣血类
}
func (e *Burned) Skill_Hit() bool {
e.Ctx().SkillEntity.Power /= 2
return true
}
// 寄生种子状态:扣血同时给对方回血
type ParasiticSeed struct {
BaseStatus
}
// 技能命中前触发寄生效果
func (e *ParasiticSeed) Action_start_ex(attacker, defender *action.SelectSkillAction) bool {
// 过滤特定类型单位假设1是植物类型使用枚举替代魔法数字
damage := decimal.NewFromUint64(uint64(e.Ctx().Our.CurrentPet.Info.MaxHp)).
Div(decimal.NewFromInt(8))
// 对我方造成真实伤害
e.Ctx().Our.Damage(e.Input, &info.DamageZone{
Type: info.DamageType.True,
Damage: damage,
})
// 给对方回血(不受回血限制影响)
e.Ctx().Opp.Heal(e.Ctx().Our, nil, damage)
return true
}
type Flammable struct {
BaseStatus
}
func (e *Flammable) Action_start(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return true
}
e.Ctx().SkillEntity.Accuracy -= 30
return true
}
func (e *Flammable) Skill_Use_ex() bool {
if e.Ctx().SkillEntity == nil {
return true
}
if e.Ctx().SkillEntity.Type != int(element.ElementTypeFire) {
return true
}
// 获取状态效果
eff := input.Geteffect(input.EffectType.Status, info.PetStatus.Burned)
if eff == nil {
return true
}
duration := int(e.Input.FightC.GetRand().Int31n(2)) // 默认随机 2~3 回合
eff.Duration(duration)
eff.SetArgs(e.Ctx().Our) //输入参数是对方
e.Ctx().Our.AddEffect(e.Ctx().Our, eff)
return true
}
type Confused struct {
BaseStatus
}
func (e *Confused) Action_start(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return true
}
e.Ctx().SkillEntity.Accuracy -= 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: decimal.NewFromInt(50),
})
return true
}
type Weakened struct {
BaseStatus
}
func (e *Weakened) Damage_DIV_ex(t *info.DamageZone) bool {
// 1. 定义衰弱等级对应的倍率表索引对应等级0级无倍率
// 索引0: 0%未衰弱、1:25%、2:50%、3:100%、4:250%、5:500%
weakenedMultiples := []decimal.Decimal{
decimal.NewFromInt(0), // 0级
decimal.NewFromFloat(0.25), // 1级25%
decimal.NewFromFloat(0.5), // 2级50%
decimal.NewFromFloat(1.0), // 3级100%
decimal.NewFromFloat(2.5), // 4级250%
decimal.NewFromFloat(5.0), // 5级500%
}
// 2. 校验并限制衰弱等级≤0 直接返回≥5 按5级算
level := e.Status
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.Weakened), &Weakened{}) // 衰弱
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Confused), &Confused{}) // 混乱
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Flammable), &Flammable{}) // 易燃
// 批量注册不能行动的状态
nonActingStatuses := []info.EnumPetStatus{
info.PetStatus.Paralysis, // 麻痹
info.PetStatus.Tired, // 疲惫
info.PetStatus.Fear, // 害怕
info.PetStatus.Petrified, // 石化
}
for _, status := range nonActingStatuses {
effect := &StatusCannotAct{}
effect.Status = status
input.InitEffect(input.EffectType.Status, int(status), effect)
}
// 注册睡眠状态使用枚举常量替代硬编码8
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Sleep), &StatusSleep{})
}