Files
bl/logic/service/fight/input/input.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

220 lines
5.9 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 input
import (
"blazing/common/data/xmlres"
"sort"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"github.com/jinzhu/copier"
"github.com/shopspring/decimal"
)
type Input struct {
CanChange bool //是否可以死亡切换CanChange
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
Opp *Input
CanCapture int
Finished bool //是否加载完成
*info.AttackValue
FightC common.FightI
// info.BattleActionI
Effects []Effect //effects 实际上全局就是effect无限回合 //effects容器 技能的
EffectCache []Effect //这里是命中前执行的容器,也就是命中前执行的所有逻辑相关,理论上一个effect被激活,就应该同时将其他的effect取消激活
Effect_Lost []Effect
// 删掉伤害记录,可以在回调中记录,而不是每次调用记录
SumDamage decimal.Decimal //伤害
// DamageZone struct {
// Damage decimal.Decimal //伤害
// BeforeADD decimal.Decimal //攻击伤害
// BeforeMul decimal.Decimal
// BeforeFloor decimal.Decimal
// BeforeDiv decimal.Decimal
// BeforeSUB decimal.Decimal
// BeforeLock decimal.Decimal //锁伤 先锁受击方,再锁攻击方 受击方免疫也是这么锁 免疫等于锁0
// BeforeLocked decimal.Decimal
// //BeforePost decimal.Decimal
// //OldAttack int //攻击伤害被挡前伤害记录
// } //伤害容器
//First bool //是否先手
}
func NewInput(c common.FightI, p common.PlayerI) *Input {
ret := &Input{FightC: c, Player: p}
ret.Effects = make([]Effect, 0)
// t := Geteffect(EffectType.Damage, 0)
// t.Effect.SetArgs(ret)
// ret.AddEffect(t) //添加默认基类,实现继承
p.SetFightC(c) //给玩家设置战斗容器
return ret
}
func (our *Input) SortPet() {
sort.Slice(our.AllPet, func(i, j int) bool {
x, y := our.AllPet[i], our.AllPet[j]
// 若x血量>0且y血量=0则x排在前
if x.Info.Hp > 0 && y.Info.Hp <= 0 {
return true
}
// 若x血量=0且y血量>0则x排在后
if x.Info.Hp <= 0 && y.Info.Hp > 0 {
return false
}
// 同类型(都>0或都=0保持原有顺序
return i < j
})
for _, v := range our.AllPet {
if v.Info.Hp == 0 {
v.NotAlive = true
}
}
}
func (our *Input) GetPetInfo() *info.BattlePetEntity {
return our.CurrentPet
}
func (our *Input) SetOPP(t *Input) {
our.Opp = t
}
func (our *Input) GenSataus() {
our.Status = [20]int8{}
for i := 0; i < 20; i++ { //堆叠状态剩余回合
t := our.GetEffect(EffectType.Status, i)
if t != nil && t.Alive() { //状态都是叠层类的
our.Status[i] = int8(t.Duration())
}
}
}
func (our *Input) GenInfo() {
our.RemainHp = int32(our.CurrentPet.Info.Hp)
our.SkillList = our.CurrentPet.Info.SkillList
// f.Second.SkillList = f.Second.CurrentPet.Info.SkillList
// f.Second.RemainHp = int32(f.Second.CurrentPet.Info.Hp)
// ret.FAttack = *f.First.AttackValue
// ret.SAttack = *f.Second.AttackValue
}
func (our *Input) ResetAttackValue() {
our.AttackValue.SkillID = 0
our.AttackValue.IsCritical = 0
our.AttackValue.GainHp = 0
our.AttackValue.LostHp = 0
our.SumDamage = decimal.NewFromInt(0)
//our.CanUseSkill = true
}
// 这个每回合都会调用
func (our *Input) InitAttackValue() {
our.AttackValue = info.NewAttackValue(our.Player.GetInfo().UserID)
}
func (our *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) {
for _, v := range our.AllPet {
if v.Info.CatchTime == uint32(id) {
copier.Copy(&Reason, &v.Info)
Reason.UserId = our.Player.GetInfo().UserID
ii = v
}
}
return
}
// GetStatusBonus 获取最高的状态倍率
// 遍历状态数组返回存在的状态中最高的倍率无状态则返回1.0
func (our *Input) GetStatusBonus() float64 {
// 异常状态倍率映射表(状态索引 -> 倍率)
var statusBonuses = map[info.EnumPetStatus]float64{
info.PetStatus.Paralysis: 1.5,
info.PetStatus.Poisoned: 1.5,
info.PetStatus.Sleep: 2.0,
// /info.BattleStatus.Frozen: 2.0,
}
maxBonus := 1.0 // 默认无状态倍率
for statusIdx := 0; statusIdx < 20; statusIdx++ {
t := Geteffect(EffectType.Status, statusIdx)
// 检查状态是否存在数组中值为1表示存在该状态
if t != nil && t.Stack() > 0 {
if bonus, exists := statusBonuses[info.EnumPetStatus(statusIdx)]; exists && bonus > maxBonus {
maxBonus = bonus
}
}
}
return maxBonus
}
// 解析并 施加effect
func (our *Input) Parseskill(skill *action.SelectSkillAction) {
if skill == nil {
return
}
if skill.SkillEntity == nil {
return
}
our.EffectCache = make([]Effect, 0) //先把上一回合数据清空,但是应该把本身延续类效果集成过来
our.Effect_Lost = make([]Effect, 0)
// our.Initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了
//i.NewEffects = make([]Effect, 0) //这里说明是新增的效果
temparg := skill.SideEffectArgS
for _, v := range skill.SideEffectS {
t := Geteffect(EffectType.Skill, v)
args := xmlres.EffectArgs[v]
//这里是给双方添加buff
if t != nil {
t.SetArgs(our, temparg[:args]...) //设置入参,施加方永远是我方
// if t.Owner() { //如果取反,说明是给对方添加的回合效果
// //实际上,owner永远为反,说明是对方给我添加的
// t.SetArgs(i, temparg[:args]...) //设置入参,施加方永远是我方
// //给双方添加
// defender.AddEffect(t)
// } else {
//t.SetArgs(i, temparg[:args]...) //设置入参
loste := our.AddEffect(our, t)
if loste != nil {
our.Effect_Lost = append(our.Effect_Lost, loste)
}
// }
//这里是临时缓存buff,后面确认命中后修改HIT状态
// t.Alive() //先让效果保持存活
our.EffectCache = append(our.EffectCache, t)
// i.NewEffects = append(i.NewEffects, t)
}
temparg = temparg[args:]
}
}