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" ) 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 // 删掉伤害记录,可以在回调中记录,而不是每次调用记录 *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) // 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) 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 { // 异常状态倍率映射表(状态索引 -> 倍率) 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 := our.InitEffect(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.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:] } }