From 9d87ce9e4652129f38c6a10a7de7d023bf80b32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Sun, 14 Sep 2025 03:36:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor(fight):=20=E9=87=8D=E6=9E=84=E6=88=98?= =?UTF-8?q?=E6=96=97=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 NodeManager 相关代码,改为使用 input 包中的 Effect - 重构 FightC 结构,添加 GetRand 方法 - 新增 BaseAction 结构和 NewBaseAction 函数 - 更新 effect 包中的 Effect 结构和相关方法 - 调整 BattleSkillEntity 中的 AttackTime 方法,增加 Hit 字段 - 更新 AttackValue 结构,保留原有的 AttackTime 字段 - 重构战斗逻辑,包括回合开始前的处理、技能使用、伤害计算等 --- .../fight/input/input_20250914031345.go | 46 +++ .../fight/input/input_20250914033625.go | 46 +++ .../fight/input/nodemanger_20250914033301.go | 218 +++++++++++++++ .../fight/input/nodemanger_20250914033625.go | 218 +++++++++++++++ logic/service/common/fight.go | 6 +- logic/service/fight/BattleAction.go | 6 + logic/service/fight/action.go | 122 ++++++++ logic/service/fight/effect/effect_1.go | 3 +- logic/service/fight/effect/effect_62.go | 3 +- logic/service/fight/effect/effect_67.go | 3 +- logic/service/fight/effect/effect_9.go | 3 +- logic/service/fight/effect/effect_stat.go | 7 +- logic/service/fight/fightc.go | 264 ++++++------------ logic/service/fight/info/BattleSkillEntity.go | 8 +- logic/service/fight/info/info.go | 2 +- logic/service/fight/input/input.go | 2 + .../fight/{node => input}/nodemanger.go | 92 +++--- logic/service/fight/node/Turn.go | 4 +- logic/service/fight/node/attack.go | 51 +++- 19 files changed, 858 insertions(+), 246 deletions(-) create mode 100644 .history/logic/service/fight/input/input_20250914031345.go create mode 100644 .history/logic/service/fight/input/input_20250914033625.go create mode 100644 .history/logic/service/fight/input/nodemanger_20250914033301.go create mode 100644 .history/logic/service/fight/input/nodemanger_20250914033625.go create mode 100644 logic/service/fight/action.go rename logic/service/fight/{node => input}/nodemanger.go (58%) diff --git a/.history/logic/service/fight/input/input_20250914031345.go b/.history/logic/service/fight/input/input_20250914031345.go new file mode 100644 index 000000000..46c3f9319 --- /dev/null +++ b/.history/logic/service/fight/input/input_20250914031345.go @@ -0,0 +1,46 @@ +package input + +import ( + "blazing/logic/service/common" + "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 + Finished bool //是否加载完成 + *info.AttackValue + FightC common.FightI + // info.BattleActionI + Effect NodeManager //effects容器OurEffect node.NodeManager //effects容器 + Damage decimal.Decimal //造成伤害 + First bool +} + +func (i *Input) GetPetInfo() *info.BattlePetEntity { + + return i.CurrentPet + +} +func (i *Input) InitAttackValue() { + i.AttackValue = info.NewAttackValue(i.Player.ID()) + +} +func (i *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) { + for _, v := range i.AllPet { + if v.Info.CatchTime == uint32(id) { + copier.Copy(&Reason, &v.Info) + Reason.UserId = i.Player.ID() + + ii = v + } + + } + return + +} diff --git a/.history/logic/service/fight/input/input_20250914033625.go b/.history/logic/service/fight/input/input_20250914033625.go new file mode 100644 index 000000000..46c3f9319 --- /dev/null +++ b/.history/logic/service/fight/input/input_20250914033625.go @@ -0,0 +1,46 @@ +package input + +import ( + "blazing/logic/service/common" + "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 + Finished bool //是否加载完成 + *info.AttackValue + FightC common.FightI + // info.BattleActionI + Effect NodeManager //effects容器OurEffect node.NodeManager //effects容器 + Damage decimal.Decimal //造成伤害 + First bool +} + +func (i *Input) GetPetInfo() *info.BattlePetEntity { + + return i.CurrentPet + +} +func (i *Input) InitAttackValue() { + i.AttackValue = info.NewAttackValue(i.Player.ID()) + +} +func (i *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) { + for _, v := range i.AllPet { + if v.Info.CatchTime == uint32(id) { + copier.Copy(&Reason, &v.Info) + Reason.UserId = i.Player.ID() + + ii = v + } + + } + return + +} diff --git a/.history/logic/service/fight/input/nodemanger_20250914033301.go b/.history/logic/service/fight/input/nodemanger_20250914033301.go new file mode 100644 index 000000000..fb63c155d --- /dev/null +++ b/.history/logic/service/fight/input/nodemanger_20250914033301.go @@ -0,0 +1,218 @@ +package input + +import ( + "blazing/logic/service/fight/info" + "reflect" +) + +type Effect interface { + OnBattleStart() bool //战斗开始 + + OnTurnStart(attacker, defender *Input) bool //回合开始 + + UseSkill(attacker, defender *Input) bool //使用技能 可以取消用技能节点 + // OnSkillPP() bool //技能PP减少节点 + // BeforeMultiHit() bool //多段攻击前 + // BeforeHit() bool //命中前 + // OnCritPreDamage() bool //暴击判定成功且伤害计算前触发 + // PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等) + // OnBeforeCalculateDamage() bool // 最终伤害计算前触发 + // OnDamage() bool // 造成伤害时触发 + //使用技能 可以取消用技能节点 + SetArgs(param []int) + IsCrit(attacker, defender *Input, skill *info.BattleSkillEntity) bool //是否暴击 + CalculateDamage(attacker, defender *Input, skill *info.BattleSkillEntity) //击判定成功且伤害计算前触发 + // Shield() bool // 护盾值变化时触发 + // PostDamage() bool // 伤害结算后触发(血量扣除后) + IsHit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //闪避率计算,,实际上是修改命中的判断 + TakeHit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //闪避率计算,,实际上是修改命中的判断 + //() bool // 暴击伤害结算后触发 + + // OnHit() bool // 技能命中时触发 + // OnMiss() bool // 技能未命中时触发 + // AfterAttacked() bool // 被攻击后触发(受击判定) + + // SetOwner(bool) + // OnDefeat() bool // 精灵被击败时触发 + + // TurnEnd() bool // 回合结束 + + // // 堆叠(Stack)相关触发 + // OnStackBefore() bool // 堆叠效果前触发 + // OnStack() bool // 堆叠效果触发 + // OnBeforeConsumeStack() bool // 消耗堆叠前触发 + // OnConsumeStack() bool // 消耗堆叠时触发 + + // // 治疗相关触发 + // OnBeforeHeal() bool // 治疗前触发 + // OnHeal() bool // 治疗生效时触发 + + // // // 怒气(Rage)相关触发 + // // BeforeRageGain EnumEffectTrigger enum:"37" // 增怒前触发 + // // OnRageGain EnumEffectTrigger enum:"38" // 增怒时触发 + // // BeforeRageLoss EnumEffectTrigger enum:"39" // 减怒前触发 + // // OnRageLoss EnumEffectTrigger enum:"40" // 减怒时触发 + + // // 精灵切换相关触发 + // OnSwitchIn() bool // 精灵出战 / 上场时触发 + // OnSwitchOut() bool // 精灵下场时触发 + // OnOwnerSwitchIn() bool // 所属玩家精灵出战时触发 + // OnOwnerSwitchOut() bool // 所属玩家精灵下场时触发 + + // PreBattleEnd() bool //战斗结束前 + // OnBattleEnd() bool //战斗结束 + + Duration(int) int + ID() int + GetArgSize() int + Stack(int) int + MaxStack() int + GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方) + //GetSkill() *BattleSkillEntity //获得技能ctx +} + +// ======================== +// 容器:存放多个效果 +// ======================== +type NodeManager struct { + //GlobalEffects []*Effect // 全局常驻/回合/次数效果 + Effects []Effect //effects 实际上全局就是effect无限回合 +} + +var NodeM = make(map[int]Effect, 0) + +func InitEffect(id int, t Effect) { + + NodeM[id] = t +} +func getTypeName(v interface{}) string { + // 获取类型信息 + t := reflect.TypeOf(v) + + // 如果是指针类型,需要先获取其指向的元素类型 + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + // 如果是结构体类型,返回其名称 + if t.Kind() == reflect.Struct { + return t.Name() + } + + // 非结构体类型返回空或对应的类型名 + return t.Kind().String() +} + +func (c *NodeManager) AddEffect(e Effect) { + + // 如果已有同 ID 的效果,尝试叠加 + for _, eff := range c.Effects { + if eff.ID() == e.ID() { + if eff.Stack(0) < eff.MaxStack() { //如果小于最大叠层 + eff.Stack(eff.Stack(0)) //获取到当前叠层数然后叠加 + } else { + + //这里,说明是延续回合效果 + + eff.Duration(eff.Duration(0)) + } + return + } + } + // 否则新加入 + c.Effects = append(c.Effects, e) +} + +// 删除 +func (c *NodeManager) RemoveEffect(e Effect) { + var remain []Effect + for _, eff := range c.Effects { + if eff.ID() != e.ID() { + remain = append(remain, eff) + } + } + c.Effects = remain +} + +// ForEachEffectBool 遍历所有 Effect,执行“无参数、返回 bool”的方法 +// 参数 fn:接收单个 Effect,返回 bool(如 func(e Effect) bool { return e.OnBattleStart() }) +// 返回值:所有 Effect 的方法返回值列表 +func (c *NodeManager) Exec(fn func(Effect) bool) bool { + + var results bool + for _, effect := range c.Effects { + result := fn(effect) + if !result { + results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 + } else { + break //如果是false,停止向下循环 + } + } + return results +} + +// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方 +func (c *NodeManager) CancelTurn(efftype bool) { + + var remain []Effect + for _, eff := range c.Effects { + if eff.Duration(0) <= 0 && eff.GetOwner() == efftype { //false是自身,true是对方,反转后为真就是自己的 + remain = append(remain, eff) + } + } + c.Effects = remain + +} + +// // 添加效果 +// func (c **NodeManager) AddEffect(e Effect) { +// var fff *NodeManager +// switch t := (e.Duration(0) > 1); t { //判断是否是回合类效果 +// case t: //t>0就是回合类效果了 -1和0都是非回合效果和无限效果,无法被断回合 +// fff = c.Turn +// default: +// fff = c.Mark +// } + +// fff.AddEffect(e) +// } + +// // 删除 +// func (c **NodeManager) RemoveEffect(e Effect) { + +// var fff *NodeManager +// switch t := (e.Duration(0) > 1); t { //判断是否是回合类效果 +// case t: //t>0就是回合类效果了 -1和0都是非回合效果和无限效果,无法被断回合 +// fff = c.Turn +// default: +// fff = c.Mark +// } +// fff.RemoveEffect(e) +// } + +// // ForEachEffectBool 遍历所有 Effect,执行“无参数、返回 bool”的方法 +// // 参数 fn:接收单个 Effect,返回 bool(如 func(e Effect) bool { return e.OnBattleStart() }) +// // 返回值:所有 Effect 的方法返回值列表 +// func (c *NodeManagerE) Exec(fn func(Effect) bool) bool { + +// // var results bool + +// // execfun := func(nm *NodeManager) { +// // for _, effect := range nm.Effects { +// // result := fn(effect) +// // if !result { +// // results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 +// // } +// // } +// // } +// results := true +// result := c.Mark.Exec(fn) //执行叠层 +// if !result { +// results = result +// } +// result = c.Turn.Exec(fn) //执行回合类效果 +// if !result { +// results = result +// } +// return results +// } diff --git a/.history/logic/service/fight/input/nodemanger_20250914033625.go b/.history/logic/service/fight/input/nodemanger_20250914033625.go new file mode 100644 index 000000000..773371a34 --- /dev/null +++ b/.history/logic/service/fight/input/nodemanger_20250914033625.go @@ -0,0 +1,218 @@ +package input + +import ( + "blazing/logic/service/fight/info" + "reflect" +) + +type Effect interface { + OnBattleStart() bool //战斗开始 + + OnTurnStart(attacker, defender *Input) bool //回合开始 + + UseSkill(attacker, defender *Input) bool //使用技能 可以取消用技能节点 + // OnSkillPP() bool //技能PP减少节点 + // BeforeMultiHit() bool //多段攻击前 + // BeforeHit() bool //命中前 + // OnCritPreDamage() bool //暴击判定成功且伤害计算前触发 + // PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等) + // OnBeforeCalculateDamage() bool // 最终伤害计算前触发 + // OnDamage() bool // 造成伤害时触发 + //使用技能 可以取消用技能节点 + SetArgs(param []int) + IsCrit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //是否暴击 + CalculateDamage(attacker, defender *Input, skill *info.BattleSkillEntity) //击判定成功且伤害计算前触发 + // Shield() bool // 护盾值变化时触发 + // PostDamage() bool // 伤害结算后触发(血量扣除后) + IsHit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //闪避率计算,,实际上是修改命中的判断 + TakeHit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //闪避率计算,,实际上是修改命中的判断 + //() bool // 暴击伤害结算后触发 + + // OnHit() bool // 技能命中时触发 + // OnMiss() bool // 技能未命中时触发 + // AfterAttacked() bool // 被攻击后触发(受击判定) + + // SetOwner(bool) + // OnDefeat() bool // 精灵被击败时触发 + + // TurnEnd() bool // 回合结束 + + // // 堆叠(Stack)相关触发 + // OnStackBefore() bool // 堆叠效果前触发 + // OnStack() bool // 堆叠效果触发 + // OnBeforeConsumeStack() bool // 消耗堆叠前触发 + // OnConsumeStack() bool // 消耗堆叠时触发 + + // // 治疗相关触发 + // OnBeforeHeal() bool // 治疗前触发 + // OnHeal() bool // 治疗生效时触发 + + // // // 怒气(Rage)相关触发 + // // BeforeRageGain EnumEffectTrigger enum:"37" // 增怒前触发 + // // OnRageGain EnumEffectTrigger enum:"38" // 增怒时触发 + // // BeforeRageLoss EnumEffectTrigger enum:"39" // 减怒前触发 + // // OnRageLoss EnumEffectTrigger enum:"40" // 减怒时触发 + + // // 精灵切换相关触发 + // OnSwitchIn() bool // 精灵出战 / 上场时触发 + // OnSwitchOut() bool // 精灵下场时触发 + // OnOwnerSwitchIn() bool // 所属玩家精灵出战时触发 + // OnOwnerSwitchOut() bool // 所属玩家精灵下场时触发 + + // PreBattleEnd() bool //战斗结束前 + // OnBattleEnd() bool //战斗结束 + + Duration(int) int + ID() int + GetArgSize() int + Stack(int) int + MaxStack() int + GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方) + //GetSkill() *BattleSkillEntity //获得技能ctx +} + +// ======================== +// 容器:存放多个效果 +// ======================== +type NodeManager struct { + //GlobalEffects []*Effect // 全局常驻/回合/次数效果 + Effects []Effect //effects 实际上全局就是effect无限回合 +} + +var NodeM = make(map[int]Effect, 0) + +func InitEffect(id int, t Effect) { + + NodeM[id] = t +} +func getTypeName(v interface{}) string { + // 获取类型信息 + t := reflect.TypeOf(v) + + // 如果是指针类型,需要先获取其指向的元素类型 + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + // 如果是结构体类型,返回其名称 + if t.Kind() == reflect.Struct { + return t.Name() + } + + // 非结构体类型返回空或对应的类型名 + return t.Kind().String() +} + +func (c *NodeManager) AddEffect(e Effect) { + + // 如果已有同 ID 的效果,尝试叠加 + for _, eff := range c.Effects { + if eff.ID() == e.ID() { + if eff.Stack(0) < eff.MaxStack() { //如果小于最大叠层 + eff.Stack(eff.Stack(0)) //获取到当前叠层数然后叠加 + } else { + + //这里,说明是延续回合效果 + + eff.Duration(eff.Duration(0)) + } + return + } + } + // 否则新加入 + c.Effects = append(c.Effects, e) +} + +// 删除 +func (c *NodeManager) RemoveEffect(e Effect) { + var remain []Effect + for _, eff := range c.Effects { + if eff.ID() != e.ID() { + remain = append(remain, eff) + } + } + c.Effects = remain +} + +// ForEachEffectBool 遍历所有 Effect,执行“无参数、返回 bool”的方法 +// 参数 fn:接收单个 Effect,返回 bool(如 func(e Effect) bool { return e.OnBattleStart() }) +// 返回值:所有 Effect 的方法返回值列表 +func (c *NodeManager) Exec(fn func(Effect) bool) bool { + + var results bool + for _, effect := range c.Effects { + result := fn(effect) + if !result { + results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 + } else { + break //如果是false,停止向下循环 + } + } + return results +} + +// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方 +func (c *NodeManager) CancelTurn(efftype bool) { + + var remain []Effect + for _, eff := range c.Effects { + if eff.Duration(0) <= 0 && eff.GetOwner() == efftype { //false是自身,true是对方,反转后为真就是自己的 + remain = append(remain, eff) + } + } + c.Effects = remain + +} + +// // 添加效果 +// func (c **NodeManager) AddEffect(e Effect) { +// var fff *NodeManager +// switch t := (e.Duration(0) > 1); t { //判断是否是回合类效果 +// case t: //t>0就是回合类效果了 -1和0都是非回合效果和无限效果,无法被断回合 +// fff = c.Turn +// default: +// fff = c.Mark +// } + +// fff.AddEffect(e) +// } + +// // 删除 +// func (c **NodeManager) RemoveEffect(e Effect) { + +// var fff *NodeManager +// switch t := (e.Duration(0) > 1); t { //判断是否是回合类效果 +// case t: //t>0就是回合类效果了 -1和0都是非回合效果和无限效果,无法被断回合 +// fff = c.Turn +// default: +// fff = c.Mark +// } +// fff.RemoveEffect(e) +// } + +// // ForEachEffectBool 遍历所有 Effect,执行“无参数、返回 bool”的方法 +// // 参数 fn:接收单个 Effect,返回 bool(如 func(e Effect) bool { return e.OnBattleStart() }) +// // 返回值:所有 Effect 的方法返回值列表 +// func (c *NodeManagerE) Exec(fn func(Effect) bool) bool { + +// // var results bool + +// // execfun := func(nm *NodeManager) { +// // for _, effect := range nm.Effects { +// // result := fn(effect) +// // if !result { +// // results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 +// // } +// // } +// // } +// results := true +// result := c.Mark.Exec(fn) //执行叠层 +// if !result { +// results = result +// } +// result = c.Turn.Exec(fn) //执行回合类效果 +// if !result { +// results = result +// } +// return results +// } diff --git a/logic/service/common/fight.go b/logic/service/common/fight.go index 3a222ef3a..7c52dccf8 100644 --- a/logic/service/common/fight.go +++ b/logic/service/common/fight.go @@ -1,6 +1,9 @@ package common -import "blazing/logic/service/fight/info" +import ( + "blazing/logic/service/fight/info" + "math/rand" +) type FightI interface { Escape(c PlayerI) //逃跑 @@ -10,4 +13,5 @@ type FightI interface { ReadyFight(c PlayerI) //是否准备战斗 ChangePet(c PlayerI, id uint32) Capture(c PlayerI, id uint32) + GetRand() *rand.Rand } diff --git a/logic/service/fight/BattleAction.go b/logic/service/fight/BattleAction.go index 7bc9c2c10..efc2990b1 100644 --- a/logic/service/fight/BattleAction.go +++ b/logic/service/fight/BattleAction.go @@ -91,6 +91,12 @@ type BaseAction struct { } +func NewBaseAction(t uint32) BaseAction { + return BaseAction{ + PlayerID: t, + } + +} func (a *BaseAction) GetPlayerID() uint32 { return a.PlayerID // fmt.Printf("玩家[%d]主动切换宠物:从%s切换到%s(原因:%s)\n", diff --git a/logic/service/fight/action.go b/logic/service/fight/action.go new file mode 100644 index 000000000..af01da924 --- /dev/null +++ b/logic/service/fight/action.go @@ -0,0 +1,122 @@ +package fight + +import ( + "blazing/common/data/xmlres" + "blazing/logic/service/common" + "blazing/logic/service/fight/info" + "blazing/logic/service/player" + "math" + + "github.com/gogf/gf/v2/util/gconv" + "github.com/jinzhu/copier" + "github.com/panjf2000/ants/v2" +) + +// 玩家逃跑 +func (f *FightC) Escape(c common.PlayerI) { + ret := &EscapeAction{ + BaseAction: NewBaseAction(c.GetInfo().UserID), + Reason: info.FightOverInfo{ + + Reason: uint32(info.BattleOverReason.PlayerEscape), + }, + } + + f.actionChan <- ret +} + +// 玩家掉线 +func (f *FightC) Offline(c common.PlayerI) { + ret := &PlayerOfflineAction{ + BaseAction: NewBaseAction(c.GetInfo().UserID), + Reason: info.FightOverInfo{ + + Reason: uint32(info.BattleOverReason.PlayerOffline), + }, + } + + f.actionChan <- ret +} + +// 切换精灵 主动和被驱逐 +func (f *FightC) ChangePet(c common.PlayerI, id uint32) { + ret := &ActiveSwitchAction{ + BaseAction: NewBaseAction(c.GetInfo().UserID), + } + + f.GetInputByPlayer(c, false).CurrentPet, ret.Reason = f.GetInputByPlayer(c, false).GetPet(id) + + f.actionChan <- ret +} + +// 玩家使用技能 +func (f *FightC) UseSkill(c common.PlayerI, id int32) { + + if id == 0 { + f.actionChan <- &SystemGiveUpAction{BaseAction: NewBaseAction(c.GetInfo().UserID)} + return + } + ret := &SelectSkillAction{ + PlayerID: c.ID(), + } + ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet + + for _, v := range ret.PetInfo.Skills { + + if v != nil && v.ID == int(id) { + ret.Skill = v + } + + } + f.actionChan <- ret +} + +// 玩家使用技能 +func (f *FightC) Capture(c common.PlayerI, id uint32) { + + f.actionChan <- &UseItemAction{BaseAction: NewBaseAction(c.GetInfo().UserID), ItemID: id} +} + +// 战斗准备 +func (f *FightC) ReadyFight(c common.PlayerI) { + rett := info.FightStartOutboundInfo{} + + copier.Copy(&rett.Info1, &f.Info.OurPetList[0]) // 复制自己的信息 + copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0]) + rett.Info1.UserID = f.Info.OurInfo.UserID // + rett.Info2.UserID = f.Info.OpponentInfo.UserID + + rrsult := func() { //传回函数 + + f.Our.Player.SendReadyToFightInfo(rett) + f.Opp.Player.SendReadyToFightInfo(rett) + } + + switch f.Info.FightId { + case 1: // 1v1 + + f.GetInputByPlayer(c, false).Finished = true + if f.GetInputByPlayer(c, true).Finished { + rrsult() + } + + case 3: // 野怪战斗 + + //判断捕捉率大于0 + if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 { + rett.Info2.Catchable = 1 + t, _ := f.Opp.Player.(*player.AI_player) + t.CanCapture = true + + } + + rrsult() + } +} + +var Fightpool *ants.Pool + +func init() { + Fightpool, _ = ants.NewPool(math.MaxInt32) + //defer p.Release() +} diff --git a/logic/service/fight/effect/effect_1.go b/logic/service/fight/effect/effect_1.go index fc9ca8a54..c0b76f1a5 100644 --- a/logic/service/fight/effect/effect_1.go +++ b/logic/service/fight/effect/effect_1.go @@ -1,6 +1,7 @@ package effect import ( + "blazing/logic/service/fight/input" "blazing/logic/service/fight/node" ) @@ -12,7 +13,7 @@ type Effect1 struct { } func init() { - node.InitEffect(1, &Effect1{}) + input.InitEffect(1, &Effect1{}) } diff --git a/logic/service/fight/effect/effect_62.go b/logic/service/fight/effect/effect_62.go index ac9fd4b53..fe92569ba 100644 --- a/logic/service/fight/effect/effect_62.go +++ b/logic/service/fight/effect/effect_62.go @@ -1,6 +1,7 @@ package effect import ( + "blazing/logic/service/fight/input" "blazing/logic/service/fight/node" ) @@ -13,7 +14,7 @@ type Effect62 struct { } func init() { - node.InitEffect(62, &Effect62{ + input.InitEffect(62, &Effect62{ EffectNode: node.EffectNode{ ArgSize: 1, }, diff --git a/logic/service/fight/effect/effect_67.go b/logic/service/fight/effect/effect_67.go index 61426694e..e3857ffbf 100644 --- a/logic/service/fight/effect/effect_67.go +++ b/logic/service/fight/effect/effect_67.go @@ -1,6 +1,7 @@ package effect import ( + "blazing/logic/service/fight/input" "blazing/logic/service/fight/node" ) @@ -12,7 +13,7 @@ type Effect67 struct { } func init() { - node.InitEffect(67, &Effect67{ + input.InitEffect(67, &Effect67{ EffectNode: node.EffectNode{ ArgSize: 1, }, diff --git a/logic/service/fight/effect/effect_9.go b/logic/service/fight/effect/effect_9.go index cc53418cd..f824d94f0 100644 --- a/logic/service/fight/effect/effect_9.go +++ b/logic/service/fight/effect/effect_9.go @@ -1,6 +1,7 @@ package effect import ( + "blazing/logic/service/fight/input" "blazing/logic/service/fight/node" ) @@ -9,7 +10,7 @@ import ( */ func init() { - node.InitEffect(9, &Effect9{ + input.InitEffect(9, &Effect9{ EffectNode: node.EffectNode{ ArgSize: 2, }, diff --git a/logic/service/fight/effect/effect_stat.go b/logic/service/fight/effect/effect_stat.go index f3ac04a1b..381dbaf76 100644 --- a/logic/service/fight/effect/effect_stat.go +++ b/logic/service/fight/effect/effect_stat.go @@ -1,18 +1,19 @@ package effect import ( + "blazing/logic/service/fight/input" "blazing/logic/service/fight/node" ) func init() { //技能使用成功时,m%自身XX等级+/-n - node.InitEffect(4, NewEffectStat(false)) + input.InitEffect(4, NewEffectStat(false)) //技能使用成功时,m%对方XX等级+/-n - node.InitEffect(5, NewEffectStat(true)) + input.InitEffect(5, NewEffectStat(true)) } -func NewEffectStat(b bool) node.Effect { +func NewEffectStat(b bool) input.Effect { return &EffectStat{ node.EffectNode{ diff --git a/logic/service/fight/fightc.go b/logic/service/fight/fightc.go index 600411dfc..af6ff5a54 100644 --- a/logic/service/fight/fightc.go +++ b/logic/service/fight/fightc.go @@ -1,23 +1,17 @@ package fight import ( - "blazing/common/data/xmlres" - "blazing/common/utils" "blazing/logic/service/common" "blazing/logic/service/fight/info" "blazing/logic/service/fight/input" - "blazing/logic/service/fight/node" "blazing/logic/service/player" "fmt" - "math" "math/rand" "sort" "time" - "github.com/gogf/gf/v2/util/gconv" "github.com/jinzhu/copier" "github.com/mohae/deepcopy" - "github.com/panjf2000/ants/v2" "github.com/shopspring/decimal" ) @@ -31,9 +25,9 @@ type FightC struct { StartTime time.Time actionChan chan BattleActionI // 所有操作统一从这里进入 Round int //回合数 - EffectS node.NodeManager //effects容器 - First *input.Input - Second *input.Input + + First *input.Input + Second *input.Input } func (f *FightC) Ownerid() uint32 { @@ -62,71 +56,6 @@ func (f *FightC) GetInputByAction(c BattleActionI, isOpposite bool) *input.Input return f.Opp } -// 玩家逃跑 -func (f *FightC) Escape(c common.PlayerI) { - ret := &EscapeAction{ - PlayerID: c.ID(), - Reason: info.FightOverInfo{ - - Reason: uint32(info.BattleOverReason.PlayerEscape), - }, - } - - f.actionChan <- ret -} - -// 玩家掉线 -func (f *FightC) Offline(c common.PlayerI) { - ret := &PlayerOfflineAction{ - PlayerID: c.ID(), - Reason: info.FightOverInfo{ - - Reason: uint32(info.BattleOverReason.PlayerOffline), - }, - } - - f.actionChan <- ret -} - -// 切换精灵 主动和被驱逐 -func (f *FightC) ChangePet(c common.PlayerI, id uint32) { - ret := &ActiveSwitchAction{ - PlayerID: c.ID(), - } - - f.GetInputByPlayer(c, false).CurrentPet, ret.Reason = f.GetInputByPlayer(c, false).GetPet(id) - - f.actionChan <- ret -} - -// 玩家使用技能 -func (f *FightC) UseSkill(c common.PlayerI, id int32) { - - if id == 0 { - f.actionChan <- &SystemGiveUpAction{PlayerID: c.ID()} - return - } - ret := &SelectSkillAction{ - PlayerID: c.ID(), - } - ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet - - for _, v := range ret.PetInfo.Skills { - - if v != nil && v.ID == int(id) { - ret.Skill = v - } - - } - f.actionChan <- ret -} - -// 玩家使用技能 -func (f *FightC) Capture(c common.PlayerI, id uint32) { - - f.actionChan <- &UseItemAction{PlayerID: c.ID(), ItemID: id} -} - // 玩家使用技能 func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity { if f.Our.Player.ID() == c.ID() { @@ -137,49 +66,13 @@ func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity { } -// 战斗准备 -func (f *FightC) ReadyFight(c common.PlayerI) { - rett := info.FightStartOutboundInfo{} +// 获取随机数 +func (f *FightC) GetRand() *rand.Rand { - copier.Copy(&rett.Info1, &f.Info.OurPetList[0]) // 复制自己的信息 - copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0]) - rett.Info1.UserID = f.Info.OurInfo.UserID // - rett.Info2.UserID = f.Info.OpponentInfo.UserID + return f.rand - rrsult := func() { //传回函数 - - f.Our.Player.SendReadyToFightInfo(rett) - f.Opp.Player.SendReadyToFightInfo(rett) - } - - switch f.Info.FightId { - case 1: // 1v1 - - f.GetInputByPlayer(c, false).Finished = true - if f.GetInputByPlayer(c, true).Finished { - rrsult() - } - - case 3: // 野怪战斗 - - //判断捕捉率大于0 - if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 { - rett.Info2.Catchable = 1 - t, _ := f.Opp.Player.(*player.AI_player) - t.CanCapture = true - - } - - rrsult() - } } -var Fightpool *ants.Pool - -func init() { - Fightpool, _ = ants.NewPool(math.MaxInt32) - //defer p.Release() -} func (f *FightC) initplayer(c common.PlayerI, opp bool) { temp := &input.Input{Player: c} @@ -192,15 +85,7 @@ func (f *FightC) initplayer(c common.PlayerI, opp bool) { } } - // for k, v := range c.GetPetInfo() { - // if f.Info.MAXPET == 0 || k < int(f.Info.MAXPET) { - // temppet := v //这里必须先复制,否则会导致字段混乱 - // temp.AllPet = append(temp.AllPet, info.CreateBattlePetEntity(&temppet, f.rand)) - // } - - // } - // // 排序:血量>0的放前面,血量=0的放后面,同类型保持原有顺序 sort.Slice(temp.AllPet, func(i, j int) bool { x, y := temp.AllPet[i], temp.AllPet[j] // 若x血量>0且y血量=0,则x排在前 @@ -380,10 +265,12 @@ func (f *FightC) battleLoop() { fmt.Println("回合操作超时") if _, exists := actions[f.Our.Player.ID()]; !exists { - actions[f.Our.Player.ID()] = &SystemGiveUpAction{PlayerID: f.Our.Player.ID()} //系统选择出手 + actions[f.Our.Player.ID()] = &SystemGiveUpAction{ + BaseAction: NewBaseAction(f.Our.Player.ID())} //系统选择出手 } if _, exists := actions[f.Opp.Player.ID()]; !exists { - actions[f.Opp.Player.ID()] = &SystemGiveUpAction{PlayerID: f.Opp.Player.ID()} //系统选择出手 + + actions[f.Opp.Player.ID()] = &SystemGiveUpAction{BaseAction: NewBaseAction(f.Opp.Player.ID())} //系统选择出手 } } } @@ -393,6 +280,7 @@ func (f *FightC) battleLoop() { p1Action := actions[f.Our.Player.ID()] p2Action := actions[f.Opp.Player.ID()] fmt.Println("开始结算回合") + var BattleActionI [2]BattleActionI BattleActionI[0], BattleActionI[1] = Compare(p1Action, p2Action) @@ -410,11 +298,11 @@ func (f *FightC) battleLoop() { ff.Player.SendFightEndInfo(faction.Reason) //广播逃跑原因 }) break - case *ActiveSwitchAction: //切换上场的 - f.enterturn(BattleActionI[1], nil) //切换,相当于后手直接出手 + case *ActiveSwitchAction: //切换上场的,切换方放弃出手 + f.enterturn(BattleActionI[1], &SystemGiveUpAction{BaseAction: NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手 case *UseItemAction: //使用道具 - fmt.Println(faction.ItemID) + //fmt.Println(faction.ItemID) switch { case faction.ItemID >= 30001 && faction.ItemID <= 300010: //胶囊 @@ -452,7 +340,7 @@ func (f *FightC) battleLoop() { // 其他情况 fmt.Println("ItemID 不在指定范围内") } - + f.enterturn(BattleActionI[1], &SystemGiveUpAction{BaseAction: NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手 case *SelectSkillAction: //选择技能 //回合前操作,比如挂载buff @@ -466,23 +354,28 @@ func (f *FightC) battleLoop() { } // 解析并 施加effect -func (f *FightC) parseskill(id *SelectSkillAction) { +func (f *FightC) parseskill(attacker, defender *input.Input, id *SelectSkillAction) { temparg := id.Skill.SideEffectArgS for _, v := range id.Skill.SideEffectS { - t, ok := node.NodeM[v] + t, ok := input.NodeM[v] if ok { //获取成功 args := t.GetArgSize() t.SetArgs(temparg[:args]) //设置入参 - //如果不是是房主方,说明施加的对象是反的,比如本来是false,实际上是给邀请方施加的 - //所以这里要对target取反 - if id.GetPlayerID() != f.ownerID { - t.SetOwner(!t.GetOwner()) - } + // //如果不是是房主方,说明施加的对象是反的,比如本来是false,实际上是给邀请方施加的 + // //所以这里要对target取反 + // if id.GetPlayerID() != f.ownerID { + // t.SetOwner(!t.GetOwner()) + // } temparg = temparg[args:] - f.EffectS.AddEffect(deepcopy.Copy(t).(node.Effect)) + if t.GetOwner() { //如果取反,说明是给对方添加的回合效果 + //实际上,owner永远为反,说明是对方给我添加的 + defender.Effect.AddEffect(deepcopy.Copy(t).(input.Effect)) + } else { + attacker.Effect.AddEffect(deepcopy.Copy(t).(input.Effect)) + } } @@ -514,55 +407,32 @@ func (f *FightC) initAttackers(fattack, sattack BattleActionI) { // 处理技能攻击逻辑 func (f *FightC) processSkillAttack(attacker, defender *input.Input, skill *SelectSkillAction) { - f.parseskill(skill) //解析effect // 记录技能信息 - attacker.AttackValue.SkillID = uint32(skill.Skill.ID) //获取技能ID - attacker.AttackValue.AttackTime = skill.Skill.AttackTime() //计算命中 + attacker.AttackValue.SkillID = uint32(skill.Skill.ID) //获取技能ID - f.EffectS.Exec(func(t node.Effect) bool { //计算闪避 闪避就是命中率重新计算的结果 - //闪避本质上是算对方的命中重写函数? + attacker.Effect.Exec(func(t input.Effect) bool { //计算命中 - if attacker.UserID == f.Our.Player.ID() { - - } - if !t.GetOwner() { //先获取对方的 - return t.AttackTime(attacker, defender) - } - return true + attacker.AttackValue.AttackTime = t.IsHit(attacker, defender, skill.Skill) + return attacker.AttackTime == 0 //等于0,继续处理 }) + defender.Effect.Exec(func(t input.Effect) bool { //计算命中 - if attacker.AttackValue.AttackTime == 1 { //如果命中 + attacker.AttackValue.AttackTime = t.TakeHit(attacker, defender, skill.Skill) + + return attacker.AttackTime > 0 // + }) + if attacker.AttackValue.AttackTime > 0 { //如果命中 spower := skill.Skill.CalculatePower(defender.CurrentPet) attacker.Damage = spower - CritRate := utils.Max(skill.Skill.CritRate, 1) - CritRateR := f.rand.Int31n(16) - //CritAtkFirst: 先出手时必定致命一击; 默认: 0 - if skill.Skill.CritAtkFirst != 0 && attacker == f.First { - CritRate = 16 - } - //CritAtkSecond: 后出手时必定致命一击; 默认: 0 - if skill.Skill.CritAtkSecond != 0 && attacker != f.First { - CritRate = 16 - } - // CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0 - if skill.Skill.CritSelfHalfHp != 0 && (attacker.CurrentPet.HP < int(attacker.CurrentPet.Info.MaxHp)/2) { - CritRate = 16 - } - // CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0 - if skill.Skill.CritSelfHalfHp != 0 && (defender.CurrentPet.HP < int(defender.CurrentPet.Info.MaxHp)/2) { - CritRate = 16 - } - - //todo 暴击伤害 - if CritRateR <= int32(CritRate) { - attacker.AttackValue.IsCritical = 1 - } + attacker.Effect.Exec(func(t input.Effect) bool { //计算暴击率加成 + attacker.AttackValue.IsCritical = t.IsCrit(attacker, defender, skill.Skill) + return attacker.AttackValue.IsCritical == 0 + }) if attacker.AttackValue.IsCritical == 1 { attacker.Damage.Mul(decimal.NewFromInt(2)) //暴击翻倍 } - if uint32(attacker.Damage.IntPart()) > defender.CurrentPet.Info.Hp { defender.CurrentPet.Info.Hp = 0 } else { @@ -575,23 +445,25 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, skill *Sele } func (f *FightC) enterturn(fattack, sattack BattleActionI) { + f.initAttackers(fattack, sattack) //初始化先后手 var attacker, defender *input.Input + + //**回合开始前enterturn + + attacker.Effect.Exec(func(t input.Effect) bool { //计算命中 + + //结算状态 + t.OnTurnStart(attacker, defender) + return true + }) + //开始回合操作 for i := 0; i < 2; i++ { var attackeraction BattleActionI - if i == 0 { // - attacker, defender = f.First, f.Second - attackeraction = fattack - //attacker.BattleActionI, defender.BattleActionI = fattack, sattack - - } else { - attacker, defender = f.Second, f.First - attackeraction = sattack - - } skill, ok := attackeraction.(*SelectSkillAction) - if !ok { //还有系统选择放弃出手的 + f.parseskill(attacker, defender, skill) //解析effect + if !ok { //还有系统选择放弃出手的 continue } @@ -599,13 +471,35 @@ func (f *FightC) enterturn(fattack, sattack BattleActionI) { continue } - f.processSkillAttack(attacker, defender, skill) + if i == 0 { // + attacker, defender = f.First, f.Second + attackeraction = fattack + skill.Skill.First = true //先手技能 + //attacker.BattleActionI, defender.BattleActionI = fattack, sattack + + } else { + attacker, defender = f.Second, f.First + attackeraction = sattack + skill.Skill.First = false //后手技能 + + } + canuseskill := attacker.Effect.Exec(func(t input.Effect) bool { //计算命中 + //结算状态 + return t.UseSkill(attacker, defender) //返回本身结算,如果false,说明不能使用技能了 + + }) + + if canuseskill { //可以使用技能 + + f.processSkillAttack(attacker, defender, skill) + + skill.Skill.Info.PP-- //减少PP + } fmt.Println(i, "玩家技能伤害:", attacker.Damage, "自身剩余血量:", attacker.CurrentPet.Info.Hp, "对手剩余血量:", defender.CurrentPet.Info.Hp, ) - skill.Skill.Info.PP-- //减少PP if defender.CurrentPet.Info.Hp == 0 { defender.CanChange = true //被打死就可以切精灵了 if f.IsWin(attacker, defender.CurrentPet.Info.CatchTime) { //然后检查是否战斗结束 diff --git a/logic/service/fight/info/BattleSkillEntity.go b/logic/service/fight/info/BattleSkillEntity.go index a9a9dd4e6..f4bdfebc1 100644 --- a/logic/service/fight/info/BattleSkillEntity.go +++ b/logic/service/fight/info/BattleSkillEntity.go @@ -43,6 +43,7 @@ type BattleSkillEntity struct { Rand *rand.Rand Pet *BattlePetEntity First bool + Hit uint32 } // CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP) @@ -164,14 +165,15 @@ var DamageC = enum.New[struct { // 计算是否命中 func (s *BattleSkillEntity) AttackTime() uint32 { + s.Hit = 0 //先重置上一次的 if s.MustHit != 0 { - return 1 + s.Hit = 2 } if int64(s.Pet.Accuracy(int64(s.Accuracy))) > s.Rand.Int63n(100) { - return 1 + s.Hit = 1 } - return 0 + return s.Hit } func (s *BattleSkillEntity) CriticalsameTypeBonus() decimal.Decimal { diff --git a/logic/service/fight/info/info.go b/logic/service/fight/info/info.go index 2a688a095..981dd2930 100644 --- a/logic/service/fight/info/info.go +++ b/logic/service/fight/info/info.go @@ -74,7 +74,7 @@ func NewAttackValue(userid uint32) *AttackValue { type AttackValue struct { UserID uint32 `json:"userId" fieldDescription:"玩家的米米号 与野怪对战userid = 0"` SkillID uint32 `json:"skillId" fieldDescription:"使用技能的id"` - AttackTime uint32 `json:"attackTime" fieldDescription:"是否击中 如果为0 则miss 如果为1 则击中"` + AttackTime uint32 `json:"attackTime" fieldDescription:"是否击中 如果为0 则miss 如果为1 则击中,2为必中"` LostHp uint32 `json:"lostHp" fieldDescription:"我方造成的伤害"` GainHp int32 `json:"gainHp" fieldDescription:"我方获得血量"` RemainHp int32 `json:"remainHp" fieldDescription:"我方剩余血量"` diff --git a/logic/service/fight/input/input.go b/logic/service/fight/input/input.go index 00e0e3e89..46c3f9319 100644 --- a/logic/service/fight/input/input.go +++ b/logic/service/fight/input/input.go @@ -17,7 +17,9 @@ type Input struct { *info.AttackValue FightC common.FightI // info.BattleActionI + Effect NodeManager //effects容器OurEffect node.NodeManager //effects容器 Damage decimal.Decimal //造成伤害 + First bool } func (i *Input) GetPetInfo() *info.BattlePetEntity { diff --git a/logic/service/fight/node/nodemanger.go b/logic/service/fight/input/nodemanger.go similarity index 58% rename from logic/service/fight/node/nodemanger.go rename to logic/service/fight/input/nodemanger.go index 13ff74c30..773371a34 100644 --- a/logic/service/fight/node/nodemanger.go +++ b/logic/service/fight/input/nodemanger.go @@ -1,69 +1,73 @@ -package node +package input import ( - "blazing/logic/service/fight/input" + "blazing/logic/service/fight/info" "reflect" ) type Effect interface { OnBattleStart() bool //战斗开始 - OnTurnStart() bool //回合开始 + OnTurnStart(attacker, defender *Input) bool //回合开始 - UseSkill() bool //使用技能 可以取消用技能节点 - OnSkillPP() bool //技能PP减少节点 - BeforeMultiHit() bool //多段攻击前 - BeforeHit() bool //命中前 - OnCritPreDamage() bool //暴击判定成功且伤害计算前触发 - PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等) - OnBeforeCalculateDamage() bool // 最终伤害计算前触发 - OnDamage() bool // 造成伤害时触发 - SetArgs(param []int) //设置参数 + UseSkill(attacker, defender *Input) bool //使用技能 可以取消用技能节点 + // OnSkillPP() bool //技能PP减少节点 + // BeforeMultiHit() bool //多段攻击前 + // BeforeHit() bool //命中前 + // OnCritPreDamage() bool //暴击判定成功且伤害计算前触发 + // PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等) + // OnBeforeCalculateDamage() bool // 最终伤害计算前触发 + // OnDamage() bool // 造成伤害时触发 + //使用技能 可以取消用技能节点 + SetArgs(param []int) + IsCrit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //是否暴击 + CalculateDamage(attacker, defender *Input, skill *info.BattleSkillEntity) //击判定成功且伤害计算前触发 + // Shield() bool // 护盾值变化时触发 + // PostDamage() bool // 伤害结算后触发(血量扣除后) + IsHit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //闪避率计算,,实际上是修改命中的判断 + TakeHit(attacker, defender *Input, skill *info.BattleSkillEntity) uint32 //闪避率计算,,实际上是修改命中的判断 + //() bool // 暴击伤害结算后触发 - Shield() bool // 护盾值变化时触发 - PostDamage() bool // 伤害结算后触发(血量扣除后) - AttackTime(*input.Input, *input.Input) bool //闪避率计算,,实际上是修改命中的判断 - OnCritPostDamage() bool // 暴击伤害结算后触发 + // OnHit() bool // 技能命中时触发 + // OnMiss() bool // 技能未命中时触发 + // AfterAttacked() bool // 被攻击后触发(受击判定) - OnHit() bool // 技能命中时触发 - OnMiss() bool // 技能未命中时触发 - AfterAttacked() bool // 被攻击后触发(受击判定) - GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方) - SetOwner(bool) - OnDefeat() bool // 精灵被击败时触发 + // SetOwner(bool) + // OnDefeat() bool // 精灵被击败时触发 - TurnEnd() bool // 回合结束 + // TurnEnd() bool // 回合结束 - // 堆叠(Stack)相关触发 - OnStackBefore() bool // 堆叠效果前触发 - OnStack() bool // 堆叠效果触发 - OnBeforeConsumeStack() bool // 消耗堆叠前触发 - OnConsumeStack() bool // 消耗堆叠时触发 + // // 堆叠(Stack)相关触发 + // OnStackBefore() bool // 堆叠效果前触发 + // OnStack() bool // 堆叠效果触发 + // OnBeforeConsumeStack() bool // 消耗堆叠前触发 + // OnConsumeStack() bool // 消耗堆叠时触发 - // 治疗相关触发 - OnBeforeHeal() bool // 治疗前触发 - OnHeal() bool // 治疗生效时触发 + // // 治疗相关触发 + // OnBeforeHeal() bool // 治疗前触发 + // OnHeal() bool // 治疗生效时触发 - // // 怒气(Rage)相关触发 - // BeforeRageGain EnumEffectTrigger enum:"37" // 增怒前触发 - // OnRageGain EnumEffectTrigger enum:"38" // 增怒时触发 - // BeforeRageLoss EnumEffectTrigger enum:"39" // 减怒前触发 - // OnRageLoss EnumEffectTrigger enum:"40" // 减怒时触发 + // // // 怒气(Rage)相关触发 + // // BeforeRageGain EnumEffectTrigger enum:"37" // 增怒前触发 + // // OnRageGain EnumEffectTrigger enum:"38" // 增怒时触发 + // // BeforeRageLoss EnumEffectTrigger enum:"39" // 减怒前触发 + // // OnRageLoss EnumEffectTrigger enum:"40" // 减怒时触发 - // 精灵切换相关触发 - OnSwitchIn() bool // 精灵出战 / 上场时触发 - OnSwitchOut() bool // 精灵下场时触发 - OnOwnerSwitchIn() bool // 所属玩家精灵出战时触发 - OnOwnerSwitchOut() bool // 所属玩家精灵下场时触发 + // // 精灵切换相关触发 + // OnSwitchIn() bool // 精灵出战 / 上场时触发 + // OnSwitchOut() bool // 精灵下场时触发 + // OnOwnerSwitchIn() bool // 所属玩家精灵出战时触发 + // OnOwnerSwitchOut() bool // 所属玩家精灵下场时触发 - PreBattleEnd() bool //战斗结束前 - OnBattleEnd() bool //战斗结束 + // PreBattleEnd() bool //战斗结束前 + // OnBattleEnd() bool //战斗结束 Duration(int) int ID() int GetArgSize() int Stack(int) int MaxStack() int + GetOwner() bool // 技能属主,比如寄生和镇魂歌,属主是对方) //GetSkill() *BattleSkillEntity //获得技能ctx } @@ -140,6 +144,8 @@ func (c *NodeManager) Exec(fn func(Effect) bool) bool { result := fn(effect) if !result { results = result //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果 + } else { + break //如果是false,停止向下循环 } } return results diff --git a/logic/service/fight/node/Turn.go b/logic/service/fight/node/Turn.go index 9bf0debec..d50632f81 100644 --- a/logic/service/fight/node/Turn.go +++ b/logic/service/fight/node/Turn.go @@ -1,5 +1,7 @@ package node +import "blazing/logic/service/fight/input" + // 回合开始前 func (this *EffectNode) PreTurnStart() bool { return true @@ -7,7 +9,7 @@ func (this *EffectNode) PreTurnStart() bool { } // 回合开始 -func (this *EffectNode) OnTurnStart() bool { +func (this *EffectNode) OnTurnStart(attacker, defender *input.Input) bool { return true } diff --git a/logic/service/fight/node/attack.go b/logic/service/fight/node/attack.go index e280f0404..ea69c303d 100644 --- a/logic/service/fight/node/attack.go +++ b/logic/service/fight/node/attack.go @@ -1,6 +1,23 @@ package node - -func (this *EffectNode) UseSkill() bool { + +import ( + "blazing/common/utils" + "blazing/logic/service/fight/info" + "blazing/logic/service/fight/input" +) + +// 技能命中计算 +func (this *EffectNode) IsHit(attacker, defender *input.Input, skill *info.BattleSkillEntity) uint32 { + return skill.AttackTime() //计算命中 +} + +// 被命中计算,默认直接返回,重写这个来实现闪避率 +func (this *EffectNode) TakeHit(attacker, defender *input.Input, skill *info.BattleSkillEntity) uint32 { + + return skill.Hit +} + +func (this *EffectNode) UseSkill(attacker, defender *input.Input) bool { panic("not implemented") // TODO: Implement } func (this *EffectNode) OnSkillPP() bool { @@ -26,7 +43,7 @@ func (this *EffectNode) PreDamage() bool { panic("not implemented") // TODO: Implement } -func (this *EffectNode) OnBeforeCalculateDamage() bool { +func (this *EffectNode) CalculateDamage(attacker, defender *input.Input, skill *info.BattleSkillEntity) { panic("not implemented") // TODO: Implement } @@ -42,8 +59,32 @@ func (this *EffectNode) PostDamage() bool { panic("not implemented") // TODO: Implement } -func (this *EffectNode) OnCritPostDamage() bool { - panic("not implemented") // TODO: Implement +func (this *EffectNode) IsCrit(attacker, defender *input.Input, skill *info.BattleSkillEntity) uint32 { + CritRate := utils.Max(skill.CritRate, 1) + CritRateR := attacker.FightC.GetRand().Int31n(16) + //CritAtkFirst: 先出手时必定致命一击; 默认: 0 + if skill.CritAtkFirst != 0 && skill.First { + CritRate = 16 + } + //CritAtkSecond: 后出手时必定致命一击; 默认: 0 + if skill.CritAtkSecond != 0 && !skill.First { + CritRate = 16 + } + // CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0 + if skill.CritSelfHalfHp != 0 && (attacker.CurrentPet.HP < int(attacker.CurrentPet.Info.MaxHp)/2) { + CritRate = 16 + } + // CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0 + if skill.CritSelfHalfHp != 0 && (defender.CurrentPet.HP < int(defender.CurrentPet.Info.MaxHp)/2) { + CritRate = 16 + } + + //todo 暴击伤害 + if CritRateR <= int32(CritRate) { + return 1 + } + + return 0 } func (this *EffectNode) OnHit() bool {