refactor(fight): 重构战斗系统
- 移除 NodeManager 相关代码,改为使用 input 包中的 Effect - 重构 FightC 结构,添加 GetRand 方法 - 新增 BaseAction 结构和 NewBaseAction 函数 - 更新 effect 包中的 Effect 结构和相关方法 - 调整 BattleSkillEntity 中的 AttackTime 方法,增加 Hit 字段 - 更新 AttackValue 结构,保留原有的 AttackTime 字段 - 重构战斗逻辑,包括回合开始前的处理、技能使用、伤害计算等
This commit is contained in:
46
.history/logic/service/fight/input/input_20250914031345.go
Normal file
46
.history/logic/service/fight/input/input_20250914031345.go
Normal file
@@ -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
|
||||
|
||||
}
|
||||
46
.history/logic/service/fight/input/input_20250914033625.go
Normal file
46
.history/logic/service/fight/input/input_20250914033625.go
Normal file
@@ -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
|
||||
|
||||
}
|
||||
218
.history/logic/service/fight/input/nodemanger_20250914033301.go
Normal file
218
.history/logic/service/fight/input/nodemanger_20250914033301.go
Normal file
@@ -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
|
||||
// }
|
||||
218
.history/logic/service/fight/input/nodemanger_20250914033625.go
Normal file
218
.history/logic/service/fight/input/nodemanger_20250914033625.go
Normal file
@@ -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
|
||||
// }
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
122
logic/service/fight/action.go
Normal file
122
logic/service/fight/action.go
Normal file
@@ -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()
|
||||
}
|
||||
@@ -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{})
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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) { //然后检查是否战斗结束
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:"我方剩余血量"`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user