Files
bl/logic/service/fight/effect/effect_status.go

315 lines
8.5 KiB
Go
Raw Normal View History

package effect
import (
2025-11-16 20:30:17 +00:00
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"
feat(player): 新增玩家累计经验查询接口 新增 PlayerExp 控制器方法,用于返回玩家的累计经验值。同时调整了经验池字段类型为 uint32 并修复相关使用逻辑。 feat(pet): 实现宠物经验增加与升级逻辑 在 Player 结构体中新增 AddPetExp 方法,支持宠物经验增长、自动升级及进化判断。升级后会重新计算面板属性并推送更新包。 feat(fight): 重构战斗伤害计算与效果系统 引入 DamageZone 和 EnumDamageType 类型,统一红伤处理流程;移除旧有的 Pet/Skill/Prop 属性获取临时修改机制,改为直接访问真实属性。更新多个技能效果实现以适配新结构。 refactor(effect): 优化技能效果初始化和生命周期方法 统一技能效果初始化方式,明确各阶段回调函数职责,如 PreActionStart、PreAttacked 等。删除已废弃的属性修改钩子函数,并更新状态类效果实现。 refactor(input): 移除 deepcopy 依赖并替换为 go-deepcopy 将原先使用的 mohae/deepcopy 替换为 barkimedes/go-deepcopy,用于战斗节点中的 effect 拷贝逻辑,提升性能和安全性。 refactor(model): 调整玩家信息字段类型 将 PlayerInfo 中的 GoldBean 字段由 int32 改为 uint32,ExpPool 字段由 int64 改为 uint32,确保数据类型一致性与合理性。 feat(nono): 增加 Nono 跟随/收回协议结构定义 新增 NonoFollowOrHomeInInfo 和 NonoFollowOutInfo 结构体,用于处理 Nono 宠物的跟随与收回操作指令。 chore(deps): 添加 go-deepcopy 依赖 在 go.mod 中引入 github.com/barkimedes/go-deepcopy 依赖库,用于替代原有的 deepcopy 工具。
2025-09-26 13:33:55 +08:00
"github.com/alpacahq/alpacadecimal"
)
2025-11-16 20:30:17 +00:00
// 修正拼写错误BaseSataus -> BaseStatus
type BaseStatus struct {
node.EffectNode
2025-11-16 20:30:17 +00:00
Status info.EnumPetStatus // 状态类型枚举
}
2025-11-16 20:30:17 +00:00
// 重写切换事件:我方单位切换时清除状态
func (e *BaseStatus) SwitchOut(in *input.Input) bool {
2025-11-16 20:30:17 +00:00
// 我方单位下场时,状态失效
2026-04-04 06:27:15 +08:00
if in == e.CarrierInput() {
e.Alive(false)
}
return true
}
2025-11-16 20:30:17 +00:00
// 不能出手的基础状态(如麻痹、疲惫等)
type StatusCannotAct struct {
BaseStatus
}
2025-11-16 20:30:17 +00:00
// 技能命中前拦截:阻止出手
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
}
2025-11-16 20:30:17 +00:00
// 睡眠状态:受击后解除
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
}
2025-11-16 20:30:17 +00:00
e.hasTriedAct = true
return e.StatusCannotAct.ActionStart(attacker, defender)
}
2025-11-16 20:30:17 +00:00
2025-11-11 05:54:24 +00:00
func (e *StatusSleep) Skill_Use_ex() bool {
2025-11-16 20:30:17 +00:00
if !e.hasTriedAct {
return true
}
if e.Duration() <= 0 && e.Ctx().SkillEntity != nil && e.Ctx().Category() != info.Category.STATUS {
``` refactor(socket): 移除未使用的网络相关导入和注释掉的 RST 攻击检测逻辑 移除了 `ServerEvent.go` 中未使用的 `net` 和 `strings` 包导入。同时, 将原有的 RST 攻击检测及防护逻辑代码注释掉,便于后续重新设计或彻底删除。 fix(logic): 调整 fight pool 初始化与释放策略 将 `fight/action.go` 中的 `Fightpool` 类型从 `*ants.MultiPool` 改为 `*ants.Pool`,并调整其初始化方式为 `NewPool(-1)` 以适应动态扩容。 此外,在 `main.go` 中将 `ReleaseTimeout` 参数由 100 调整为 0, 确保立即清理超时任务。 feat(fight): 优化战斗输入状态重置逻辑 在 `fight/action.go` 的 `ReadyFight` 方法中提前设置 `GetInputByPlayer(c, false).Finished = true`,避免重复赋值。 同时更新了状态睡眠效果的处理流程,并简化了输入模块的状态缓存机制, 移除了冗余的 `Initeffectcache` 函数调用及相关逻辑。 perf(fight): 动态计算玩家动作等待时间 在 `loop.go` 的 `collectPlayerActions` 方法中, 将固定超时时间替换为基于 `waittime` 的动态等待时间计算公式, 提高响应灵活性。同时修复通道关闭判断条件以增强稳定性。 refactor(fight): 更新技能效果解析和状态持续逻辑 修改 `input.go` 中 `GenSataus` 方法以正确初始化状态数组; 在 `Turn.go` 中重构 `Turn_End` 方法内的执行逻辑, 确保仅在我方后手时增加回合数,提升战斗流程准确性。 chore(service): 删除废弃文件 SocketHandler_Tomee.go 完全移除已弃用的 `SocketHandler_Tomee.go` 文件及其全部内容, 减少项目冗余代码。 ```
2025-11-13 05:05:05 +08:00
e.Alive(false)
}
e.hasTriedAct = false
return true
}
func (e *StatusSleep) TurnEnd() {
e.hasTriedAct = false
}
2025-11-16 20:30:17 +00:00
// 持续伤害状态基类(中毒、冻伤、烧伤等)
type ContinuousDamage struct {
BaseStatus
isheal bool //是否回血
}
// 回合开始触发持续伤害,保证吃药/空过回合时也会正常结算。
func (e *ContinuousDamage) TurnStart(attacker, defender *action.SelectSkillAction) {
2026-04-04 06:27:15 +08:00
carrier := e.CarrierInput()
source := e.SourceInput()
opp := e.TargetInput()
2026-04-04 06:27:15 +08:00
if carrier == nil {
return
2026-04-04 06:27:15 +08:00
}
2025-11-16 20:30:17 +00:00
damage := e.calculateDamage()
2026-04-04 06:27:15 +08:00
carrier.Damage(source, &info.DamageZone{
2025-11-11 05:54:24 +00:00
Type: info.DamageType.True,
2025-11-16 20:30:17 +00:00
Damage: damage,
2025-11-11 05:54:24 +00:00
})
if len(e.SideEffectArgs) == 0 {
return
}
// 额外效果
2026-04-04 06:27:15 +08:00
carrier.Damage(source, &info.DamageZone{
Type: info.DamageType.True,
Damage: damage,
})
2026-04-04 06:27:15 +08:00
if opp == nil || opp.CurPet[0].GetHP().IntPart() == 0 {
return
}
// 给对方回血(不受回血限制影响)
2026-04-04 06:27:15 +08:00
opp.Heal(carrier, nil, damage)
}
2025-11-16 20:30:17 +00:00
// 计算伤害最大生命值的1/8
func (e *ContinuousDamage) calculateDamage() alpacadecimal.Decimal {
2026-04-04 06:27:15 +08:00
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
}
2025-11-16 20:30:17 +00:00
// 寄生种子状态:扣血同时给对方回血
type ParasiticSeed struct {
node.EffectNode
Status info.EnumPetStatus // 状态类型枚举
2025-11-16 20:30:17 +00:00
}
func (e *ParasiticSeed) SwitchOut(in *input.Input) bool {
2026-02-01 01:01:16 +08:00
//如果我放切换
2026-04-04 06:27:15 +08:00
if in == e.CarrierInput() {
e.Alive(false)
}
return true
}
// 回合开始触发寄生效果。寄生属于完整回合流程的一部分,不依赖本回合是否成功出手。
func (e *ParasiticSeed) TurnStart(attacker, defender *action.SelectSkillAction) {
2026-04-04 06:27:15 +08:00
carrier := e.CarrierInput()
source := e.SourceInput()
if carrier == nil {
return
2026-04-04 06:27:15 +08:00
}
2026-04-04 06:27:15 +08:00
damage := alpacadecimal.NewFromInt(int64(carrier.CurPet[0].Info.MaxHp)).
Div(alpacadecimal.NewFromInt(8))
feat(player): 新增玩家累计经验查询接口 新增 PlayerExp 控制器方法,用于返回玩家的累计经验值。同时调整了经验池字段类型为 uint32 并修复相关使用逻辑。 feat(pet): 实现宠物经验增加与升级逻辑 在 Player 结构体中新增 AddPetExp 方法,支持宠物经验增长、自动升级及进化判断。升级后会重新计算面板属性并推送更新包。 feat(fight): 重构战斗伤害计算与效果系统 引入 DamageZone 和 EnumDamageType 类型,统一红伤处理流程;移除旧有的 Pet/Skill/Prop 属性获取临时修改机制,改为直接访问真实属性。更新多个技能效果实现以适配新结构。 refactor(effect): 优化技能效果初始化和生命周期方法 统一技能效果初始化方式,明确各阶段回调函数职责,如 PreActionStart、PreAttacked 等。删除已废弃的属性修改钩子函数,并更新状态类效果实现。 refactor(input): 移除 deepcopy 依赖并替换为 go-deepcopy 将原先使用的 mohae/deepcopy 替换为 barkimedes/go-deepcopy,用于战斗节点中的 effect 拷贝逻辑,提升性能和安全性。 refactor(model): 调整玩家信息字段类型 将 PlayerInfo 中的 GoldBean 字段由 int32 改为 uint32,ExpPool 字段由 int64 改为 uint32,确保数据类型一致性与合理性。 feat(nono): 增加 Nono 跟随/收回协议结构定义 新增 NonoFollowOrHomeInInfo 和 NonoFollowOutInfo 结构体,用于处理 Nono 宠物的跟随与收回操作指令。 chore(deps): 添加 go-deepcopy 依赖 在 go.mod 中引入 github.com/barkimedes/go-deepcopy 依赖库,用于替代原有的 deepcopy 工具。
2025-09-26 13:33:55 +08:00
2025-11-16 20:30:17 +00:00
// 对我方造成真实伤害
2026-04-04 06:27:15 +08:00
carrier.Damage(source, &info.DamageZone{
2025-11-16 20:30:17 +00:00
Type: info.DamageType.True,
Damage: damage,
})
if source == nil || source.CurPet[0] == nil || source.CurPet[0].GetHP().IntPart() == 0 {
return
2026-02-02 01:01:01 +08:00
}
// 给寄生种子的施放者回血(不受回血限制影响)
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
}
2025-11-16 20:30:17 +00:00
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{}) // 易燃
2025-11-16 20:30:17 +00:00
// 批量注册不能行动的状态
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)
}
2025-11-16 20:30:17 +00:00
tired := &StatusTired{}
tired.Status = info.PetStatus.Tired
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Tired), tired)
2025-11-16 20:30:17 +00:00
// 注册睡眠状态使用枚举常量替代硬编码8
input.InitEffect(input.EffectType.Status, int(info.PetStatus.Sleep), &StatusSleep{})
}