Files
bl/logic/service/fight/input/input.go
2026-04-11 09:39:00 +08:00

394 lines
9.8 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"
"blazing/cool"
"blazing/modules/player/model"
"fmt"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"github.com/alpacahq/alpacadecimal"
"github.com/jinzhu/copier"
)
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,
}
type Input struct {
CanChange uint32 //是否可以死亡切换CanChange
// CanAction bool //是否可以行动
CurPet []*info.BattlePetEntity //当前上场精灵
AllPet []*info.BattlePetEntity
Team []*Input
OppTeam []*Input
Player common.PlayerI
Opp *Input
CanCapture int
Finished bool //是否加载完成
// info.BattleActionI
Effects []Effect //effects 实际上全局就是effect无限回合 //effects容器 技能的
EffectCache []Effect //这里是命中前执行的容器,也就是命中前执行的所有逻辑相关,理论上一个effect被激活,就应该同时将其他的effect取消激活
EffectLost []Effect
effectsByBase map[int64][]Effect
indexedEffects int
// 删掉伤害记录,可以在回调中记录,而不是每次调用记录
*model.AttackValue
FightC common.FightI
SumDamage alpacadecimal.Decimal //伤害
ShieldDamageTaken alpacadecimal.Decimal
// 记录上一回合结束时的能力等级供效果727等回溯使用。
LastTurnEndProp [6]int8
// 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)
ret.CurPet = make([]*info.BattlePetEntity, 0)
ret.effectsByBase = make(map[int64][]Effect)
// t := Geteffect(EffectType.Damage, 0)
// t.Effect.SetArgs(ret)
// ret.AddEffect(t) //添加默认基类,实现继承
p.SetFightC(c) //给玩家设置战斗容器
return ret
}
func (our *Input) CurPetAt(index int) *info.BattlePetEntity {
if our == nil || index < 0 || index >= len(our.CurPet) {
return nil
}
return our.CurPet[index]
}
func (our *Input) PrimaryCurPet() *info.BattlePetEntity {
return our.CurPetAt(0)
}
// CurrentPet 返回“当前输入槽位”的出战精灵。
// 注意Input 本身已对应一个 actor 槽位,这里不是“整队的 0 号主位”。
func (our *Input) CurrentPet() *info.BattlePetEntity {
return our.PrimaryCurPet()
}
func (our *Input) IsCurrentPetCatchTime(catchTime uint32) bool {
current := our.CurrentPet()
if current == nil {
return false
}
return current.Info.CatchTime == catchTime
}
func (our *Input) ControlledBy(userID uint32) bool {
return our != nil && our.Player != nil && our.Player.GetInfo().UserID == userID
}
// BenchPets 返回当前站位后备精灵(不含当前出战精灵)。
func (our *Input) BenchPets() []*info.BattlePetEntity {
if our == nil {
return nil
}
current := our.CurrentPet()
if current == nil {
return append([]*info.BattlePetEntity(nil), our.AllPet...)
}
bench := make([]*info.BattlePetEntity, 0, len(our.AllPet))
for _, pet := range our.AllPet {
if pet == nil || pet.Info.CatchTime == current.Info.CatchTime {
continue
}
bench = append(bench, pet)
}
return bench
}
func (our *Input) HasLivingBench() bool {
if our == nil {
return false
}
current := our.CurrentPet()
currentCatchTime := uint32(0)
if current != nil {
currentCatchTime = current.Info.CatchTime
}
for _, pet := range our.AllPet {
if pet == nil || pet.Info.Hp == 0 {
continue
}
if current != nil && pet.Info.CatchTime == currentCatchTime {
continue
}
return true
}
return false
}
func (our *Input) OpponentSlots() []*Input {
if our == nil {
return nil
}
if len(our.OppTeam) == 0 {
if our.Opp != nil {
return []*Input{our.Opp}
}
return nil
}
slots := make([]*Input, 0, len(our.OppTeam))
for _, in := range our.OppTeam {
if in == nil {
continue
}
slots = append(slots, in)
}
return slots
}
func (our *Input) SetCurPetAt(index int, pet *info.BattlePetEntity) {
if our == nil || index < 0 {
return
}
for len(our.CurPet) <= index {
our.CurPet = append(our.CurPet, nil)
}
our.CurPet[index] = pet
}
// 非原地交换收集非0血量精灵 + 0血量精灵拼接后返回
func (our *Input) SortPet() {
var nonZeroHP []*info.BattlePetEntity // 收集血量>0的精灵保持原顺序
var zeroHP []*info.BattlePetEntity // 收集血量=0的精灵保持原顺序
// 线性遍历一次,分类收集
for _, s := range our.AllPet {
if s.Info.Hp > 0 {
for _, e1 := range s.Info.EffectInfo {
t := our.InitEffect(EffectType.NewSel, int(e1.EID), e1.Args...)
if t != nil {
ef := t.ID()
if cool.Config.ServerInfo.IsDebug != 0 {
fmt.Println("初始化特性", ef.Suffix())
}
ef.SetCatchTime(s.Info.CatchTime)
t.ID(ef)
t.Duration(-1)
s.ApplyInitEffectBonus(e1)
our.AddEffect(our, t)
}
}
nonZeroHP = append(nonZeroHP, s)
} else {
zeroHP = append(zeroHP, s)
}
}
// 拼接非0血量精灵在前0血量精灵在后
our.AllPet = append(nonZeroHP, zeroHP...)
}
func (our *Input) GetPetInfo() *info.BattlePetEntity {
return our.PrimaryCurPet()
}
func (our *Input) SetOPP(t *Input) {
our.Opp = t
}
func (our *Input) RecoverEffect() {
//println("恢复效果",our.UserID)
//根本没释放技能,这些效果全部失效
for _, e := range our.EffectCache {
e.Alive(false)
}
//这时候将被覆盖的效果全部装回来enterturn
for _, e := range our.EffectLost {
if e.Duration() > 0 || e.Duration() == -1 {
// e.Alive(true)
our.AddEffect(e.GetInput(), e)
}
}
}
func (our *Input) ReactvieEffect() {
//根本没释放技能,这些效果全部失效
for _, e := range our.EffectLost {
e.Alive(false)
// our.AddEffect(e.GetInput(), e)
}
//这时候将被覆盖的效果全部装回来enterturn
for _, e := range our.EffectCache {
// e.Alive(true)
//因为后手方实际上是到了他出手阶段重新添加的结果,而非后手方重新激活效果
our.AddEffect(e.GetInput(), e)
}
}
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() {
currentPet := our.PrimaryCurPet()
if currentPet == nil {
return
}
our.RemainHp = int32(currentPet.Info.Hp)
our.SkillList = currentPet.Info.SkillList
// f.Second.SkillList = f.Second.CurPet.Info.SkillList
// f.Second.RemainHp = int32(f.Second.CurPet.Info.Hp)
// ret.FAttack = *f.First.AttackValue
// ret.SAttack = *f.Second.AttackValue
}
func (our *Input) SnapshotTurnProp() {
our.LastTurnEndProp = our.AttackValue.Prop
}
func (our *Input) ResetAttackValue() {
our.AttackValue.SkillID = 0
our.AttackValue.IsCritical = 0
our.AttackValue.GainHp = 0
our.AttackValue.LostHp = 0
our.SumDamage = alpacadecimal.Zero
//our.CanUseSkill = true
}
// 这个每回合都会调用
func (our *Input) InitAttackValue() {
our.AttackValue = info.NewAttackValue(our.Player.GetInfo().UserID)
our.LastTurnEndProp = [6]int8{}
}
func (our *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) {
for _, v := range our.AllPet {
if v.Info.CatchTime == uint32(id) && v.Info.Hp > 0 {
copier.Copy(&Reason, &v.Info)
Reason.UserId = our.Player.GetInfo().UserID
ii = v
return ii, Reason
}
}
return
}
// GetStatusBonus 获取最高的状态倍率
// 遍历状态数组返回存在的状态中最高的倍率无状态则返回1.0
func (our *Input) GetStatusBonus() float64 {
maxBonus := 1.0 // 默认无状态倍率
for statusIdx := 0; statusIdx < 20; statusIdx++ {
t := our.GetEffect(EffectType.Status, statusIdx)
if t != nil && t.Alive() {
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.Initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了
//i.NewEffects = make([]Effect, 0) //这里说明是新增的效果
temparg := skill.XML.SideEffectArgS
for _, v := range skill.XML.SideEffectS {
args := xmlres.EffectArgs[v]
t := our.InitEffect(EffectType.Skill, v, temparg[:args]...)
//这里是给双方添加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.EffectLost = append(our.EffectLost, loste)
}
// }
//这里是临时缓存buff,后面确认命中后修改HIT状态
// t.Alive() //先让效果保持存活
our.EffectCache = append(our.EffectCache, t)
// i.NewEffects = append(i.NewEffects, t)
} else {
fmt.Println("技能效果不存在", v)
}
temparg = temparg[args:]
}
}