```
feat(fight): 调整战斗逻辑与伤害计算流程 - 移除 `Over` 方法中的冗余回调参数 `fn` - 修复部分技能效果中错误的伤害目标对象(Our/Opp) - 优化战斗循环逻辑,使用 `over` channel 替代 `quit` 作为战斗结束信号 - 增加回合效果执行前的存活状态判断 - 修正伤害计算过程中对血量扣减的逻辑错误 -
This commit is contained in:
@@ -170,7 +170,7 @@ func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *player.Player)
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
c.FightC.Over(c, info.BattleOverReason.PlayerEscape, nil)
|
||||
c.FightC.Over(c, info.BattleOverReason.PlayerEscape)
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
)
|
||||
|
||||
type FightI interface {
|
||||
Over(c PlayerI, id info.EnumBattleOverReason, fn func()) //逃跑
|
||||
UseSkill(c PlayerI, id int32) //使用技能
|
||||
GetCurrPET(c PlayerI) *info.BattlePetEntity //当前精灵
|
||||
Over(c PlayerI, id info.EnumBattleOverReason) //逃跑
|
||||
UseSkill(c PlayerI, id int32) //使用技能
|
||||
GetCurrPET(c PlayerI) *info.BattlePetEntity //当前精灵
|
||||
|
||||
Ownerid() uint32
|
||||
ReadyFight(c PlayerI) //是否准备战斗
|
||||
@@ -19,5 +19,5 @@ type FightI interface {
|
||||
UseItem(c PlayerI, cacthid, itemid uint32)
|
||||
CanEscape() bool
|
||||
IsFirst(c PlayerI) bool
|
||||
//GetOverChan() chan struct{}
|
||||
GetOverChan() chan struct{}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func (f *FightC) Compare(a, b action.BattleActionI) (action.BattleActionI, actio
|
||||
}
|
||||
|
||||
// 玩家逃跑/无响应/掉线
|
||||
func (f *FightC) Over(c common.PlayerI, res info.EnumBattleOverReason, fn func()) {
|
||||
func (f *FightC) Over(c common.PlayerI, res info.EnumBattleOverReason) {
|
||||
if f.closefight {
|
||||
cool.Loger.Debug(context.Background(), " 战斗chan已关闭")
|
||||
return
|
||||
@@ -48,9 +48,6 @@ func (f *FightC) Over(c common.PlayerI, res info.EnumBattleOverReason, fn func()
|
||||
f.Reason = res
|
||||
f.WinnerId = f.GetInputByPlayer(c, true).UserID
|
||||
close(f.quit)
|
||||
if fn != nil {
|
||||
fn()
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ func (e *Effect28) OnSkill() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
e.Ctx().Opp.Damage(&info.DamageZone{
|
||||
e.Ctx().Our.Damage(&info.DamageZone{
|
||||
Type: info.DamageType.Fixed,
|
||||
Damage: decimal.NewFromInt(int64(e.Ctx().Opp.CurrentPet.Info.Hp)).Div(decimal.NewFromInt(int64(e.SideEffectArgs[0]))),
|
||||
})
|
||||
|
||||
@@ -28,7 +28,7 @@ func (e *Effect29) OnSkill() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
e.Ctx().Opp.Damage(&info.DamageZone{
|
||||
e.Ctx().Our.Damage(&info.DamageZone{
|
||||
|
||||
Type: info.DamageType.Fixed,
|
||||
Damage: decimal.NewFromInt(int64(e.SideEffectArgs[0])),
|
||||
|
||||
@@ -32,8 +32,8 @@ func (e *Effect62_sub) OnSkill() bool {
|
||||
//defer e.Alive(false)
|
||||
if e.Duration() == 0 { //说明对方没有切换精灵
|
||||
//直接扣除所有血量OnSkill
|
||||
|
||||
e.Ctx().Our.Damage(&info.DamageZone{
|
||||
//相当于对方给自己的伤害
|
||||
e.Ctx().Opp.Damage(&info.DamageZone{
|
||||
Type: info.DamageType.Fixed,
|
||||
Damage: decimal.NewFromInt(int64(e.Ctx().Our.CurrentPet.Info.MaxHp)),
|
||||
})
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
"fmt"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
@@ -34,10 +35,11 @@ func (e *Effect7) Damage_Floor() bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
fmt.Println("Effect7_old", e.Ctx().DamageZone.Damage.IntPart())
|
||||
if e.Ctx().DamageZone.Type == info.DamageType.Red {
|
||||
e.Ctx().DamageZone.Damage = decimal.NewFromInt(int64(e.Ctx().Our.CurrentPet.Info.Hp - e.Ctx().Opp.CurrentPet.Info.Hp))
|
||||
|
||||
}
|
||||
|
||||
fmt.Println("Effect7_new", e.Ctx().DamageZone.Damage.IntPart())
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -49,12 +49,12 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski
|
||||
if attacker.AttackTime > 0 { //如果命中
|
||||
|
||||
attacker.CalculateCrit(defender, a) //暴击计算
|
||||
attacker.AttackValue.IsCritical = a.Crit
|
||||
attacker.IsCritical = a.Crit
|
||||
|
||||
attacker.DamageZone.Damage = attacker.CalculatePower(defender, a)
|
||||
//睡眠受击消除
|
||||
|
||||
if attacker.AttackValue.IsCritical == 1 {
|
||||
if attacker.IsCritical == 1 {
|
||||
//暴击破防
|
||||
if a.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 {
|
||||
|
||||
@@ -74,11 +74,6 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski
|
||||
//这里实现应该参考本地技能是否命中,然后
|
||||
e.Hit(a.AttackTime != 0) //我方效果命中
|
||||
}
|
||||
// for _, t := range defender.EffectCache {
|
||||
// if t.GetInput() == attacker { //如果取反,说明是给对方添加的回合效果
|
||||
// t.Hit(a.AttackTime != 0)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 扣减防御方血量
|
||||
attacker.Exec(func(t input.Effect) bool {
|
||||
@@ -89,7 +84,7 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski
|
||||
return true
|
||||
})
|
||||
|
||||
defender.Damage(&info.DamageZone{
|
||||
attacker.Damage(&info.DamageZone{
|
||||
|
||||
Damage: attacker.DamageZone.Damage,
|
||||
},
|
||||
@@ -216,7 +211,9 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
currentskill = oldskill
|
||||
attacker.Initeffectcache()
|
||||
// fmt.Println("开始攻击威力", oldskill.Power)
|
||||
|
||||
if oldskill != nil {
|
||||
fmt.Println("开始攻击威力", oldskill.Power)
|
||||
}
|
||||
canuseskill := attacker.ExecCace(func(t input.Effect) bool { //这个是能否使用技能
|
||||
//结算状态
|
||||
//然后这里还可以处理自爆类
|
||||
@@ -232,8 +229,11 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
|
||||
f.processSkillAttack(attacker, defender, currentskill)
|
||||
currentskill = oldskill //还原技能
|
||||
// fmt.Println("结束攻击1", oldskill.Power)
|
||||
// fmt.Println("结束攻击", currentskill.Power)
|
||||
if oldskill != nil {
|
||||
fmt.Println("结束攻击_old", oldskill.Power)
|
||||
fmt.Println("结束攻击_new", currentskill.Power)
|
||||
}
|
||||
|
||||
_, skill, ok := utils.FindWithIndex(attacker.CurrentPet.Info.SkillList, func(item model.SkillInfo) bool {
|
||||
return item.ID == currentskill.Info.ID
|
||||
})
|
||||
|
||||
@@ -28,6 +28,7 @@ type FightC struct {
|
||||
actionChan chan action.BattleActionI // 所有操作统一从这里进入
|
||||
Round int //回合数
|
||||
quit chan struct{}
|
||||
over chan struct{}
|
||||
First *input.Input
|
||||
Second *input.Input
|
||||
closefight bool
|
||||
@@ -165,8 +166,7 @@ func (f *FightC) initplayer(c common.PlayerI, opp bool) bool {
|
||||
}
|
||||
|
||||
}
|
||||
f.Opp.SetOPP(f.Our)
|
||||
f.Our.SetOPP(f.Opp)
|
||||
|
||||
temp.CurrentPet = temp.AllPet[0]
|
||||
return true
|
||||
}
|
||||
@@ -176,6 +176,7 @@ func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.Pla
|
||||
f := &FightC{}
|
||||
f.ownerID = p1.GetInfo().UserID
|
||||
f.quit = make(chan struct{})
|
||||
f.over = make(chan struct{})
|
||||
f.StartTime = time.Now()
|
||||
seed := f.StartTime.UnixNano() ^ int64(p1.GetInfo().UserID) ^ int64(p2.GetInfo().UserID) // ^ int64(f.Round) // 用异或运算混合多维度信息
|
||||
f.rand = rand.New(rand.NewSource(seed))
|
||||
@@ -194,6 +195,8 @@ func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.Pla
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
f.Our.SetOPP(f.Opp)
|
||||
f.Opp.SetOPP(f.Our)
|
||||
i := Fightpool.Free()
|
||||
if i <= 0 {
|
||||
Fightpool.Tune(Fightpool.Cap() + 1)
|
||||
@@ -246,3 +249,8 @@ func (f *FightC) Broadcast(t func(ff *input.Input)) {
|
||||
t(f.Opp)
|
||||
|
||||
}
|
||||
|
||||
func (f *FightC) GetOverChan() chan struct{} {
|
||||
return f.over
|
||||
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ func (our *Input) AddEffect(e Effect) {
|
||||
if v.ID() == e.ID() && //找到相同的效果id
|
||||
v.Alive() && //如果之前的效果还存活
|
||||
equalInts(v.GetArgs(), e.GetArgs()) { //如果层数可以叠加或者是无限层数
|
||||
|
||||
|
||||
if v.MaxStack() == 0 {
|
||||
v.Alive(false) //不允许叠层,取消效果
|
||||
e.Duration(utils.Max(e.Duration(), v.Duration()))
|
||||
@@ -202,13 +202,14 @@ func (our *Input) ExecCace(fn func(Effect) bool) bool {
|
||||
result := true
|
||||
|
||||
for _, value := range our.EffectCache {
|
||||
value.Ctx().Our = our
|
||||
value.Ctx().Opp = our.Opp
|
||||
value.Ctx().DamageZone = &info.DamageZone{}
|
||||
if !fn(value) { //存在false,但是仍然要向下执行
|
||||
result = false //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果
|
||||
if value.Alive() {
|
||||
value.Ctx().Our = our
|
||||
value.Ctx().Opp = our.Opp
|
||||
value.Ctx().DamageZone = &info.DamageZone{}
|
||||
if !fn(value) { //存在false,但是仍然要向下执行
|
||||
result = false //如果是false,说明存在阻止向下执行的effect,比如免疫能力提升效果
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -92,6 +92,7 @@ func (our *Input) DelPP(value int) {
|
||||
}
|
||||
|
||||
// /红伤只允许调用一次来保持锁伤
|
||||
// 这个方法是对对方造成伤害
|
||||
// 伤害落实 // 血量扣减节点比如触发回神,反弹也在这里实现
|
||||
func (our *Input) Damage(sub *info.DamageZone) {
|
||||
// sub := deep.MustCopy(ctx.DamageZone) //拷贝伤害,避免直接上下文传递,便于附加伤害
|
||||
@@ -166,15 +167,15 @@ func (our *Input) Damage(sub *info.DamageZone) {
|
||||
}
|
||||
|
||||
if sub.Type == info.DamageType.Red { //红才会产生造成伤害
|
||||
our.DamageZone.Damage.Add(sub.Damage) // 叠加总伤害
|
||||
our.AttackValue.LostHp = uint32(sub.Damage.IntPart()) //红伤落实
|
||||
our.DamageZone.Damage = sub.Damage // 叠加总伤害
|
||||
our.AttackValue.LostHp = uint32(our.DamageZone.Damage.IntPart()) //红伤落实
|
||||
}
|
||||
|
||||
if uint32(sub.Damage.IntPart()) > our.CurrentPet.Info.Hp {
|
||||
if uint32(our.DamageZone.Damage.IntPart()) > our.Opp.CurrentPet.Info.Hp {
|
||||
|
||||
our.CurrentPet.Info.Hp = 0
|
||||
our.Opp.CurrentPet.Info.Hp = 0
|
||||
} else {
|
||||
our.CurrentPet.Info.Hp = our.CurrentPet.Info.Hp - uint32(sub.Damage.IntPart())
|
||||
our.Opp.CurrentPet.Info.Hp = our.Opp.CurrentPet.Info.Hp - uint32(our.DamageZone.Damage.IntPart())
|
||||
}
|
||||
|
||||
//todo 待实现死亡effet
|
||||
|
||||
@@ -143,7 +143,6 @@ func (our *Input) GetStatusBonus() float64 {
|
||||
}
|
||||
|
||||
func (our *Input) Initeffectcache() {
|
||||
our.EffectCache = make([]Effect, 0) //先把上一回合数据清空,但是应该把本身延续类效果集成过来
|
||||
|
||||
for _, v := range our.Effects {
|
||||
|
||||
@@ -160,7 +159,8 @@ func (our *Input) Initeffectcache() {
|
||||
|
||||
// 解析并 施加effect
|
||||
func (our *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
|
||||
our.Initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了
|
||||
our.EffectCache = make([]Effect, 0) //先把上一回合数据清空,但是应该把本身延续类效果集成过来
|
||||
our.Initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了
|
||||
//i.NewEffects = make([]Effect, 0) //这里说明是新增的效果
|
||||
temparg := skill.SideEffectArgS
|
||||
|
||||
@@ -183,7 +183,7 @@ func (our *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
|
||||
//i.AddEffect(t)
|
||||
// }
|
||||
//这里是临时缓存buff,后面确认命中后修改HIT状态
|
||||
// t.Alive() //先让效果保持存活
|
||||
t.Alive() //先让效果保持存活
|
||||
our.EffectCache = append(our.EffectCache, t)
|
||||
// i.NewEffects = append(i.NewEffects, t)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (f *FightC) battleLoop() {
|
||||
ourID := f.Our.Player.GetInfo().UserID
|
||||
oppID := f.Opp.Player.GetInfo().UserID
|
||||
|
||||
for {
|
||||
for !f.closefight {
|
||||
|
||||
f.Round++
|
||||
fmt.Printf("—— 第 %d 回合开始 ——\n", f.Round)
|
||||
@@ -37,7 +37,6 @@ func (f *FightC) battleLoop() {
|
||||
|
||||
}
|
||||
|
||||
fmt.Println("战斗循环结束")
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
//todo 将血量和技能pp传回enterturn
|
||||
|
||||
@@ -45,7 +44,8 @@ func (f *FightC) battleLoop() {
|
||||
|
||||
})
|
||||
close(f.actionChan)
|
||||
close(f.quit)
|
||||
fmt.Println("战斗循环结束")
|
||||
close(f.over)
|
||||
}
|
||||
|
||||
// 收集玩家动作(含超时判定)
|
||||
@@ -252,9 +252,3 @@ func (f *FightC) getPlayerByID(id uint32) common.PlayerI {
|
||||
}
|
||||
return f.Opp.Player
|
||||
}
|
||||
|
||||
// 根据玩家ID返回对应对象
|
||||
func (f *FightC) GetOverChan() chan struct{} {
|
||||
|
||||
return f.quit
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@ func (e *EffectNode) Turn_End() {
|
||||
e.Alive(false)
|
||||
|
||||
} else {
|
||||
e.trunl.Do(func() {
|
||||
// e.trunl.Do(func() {
|
||||
|
||||
if e.Ctx().Opp.FightC.IsFirst(e.Ctx().Opp.Player) { //如果对方先手
|
||||
e.duration++
|
||||
// e.Alive(true)
|
||||
}
|
||||
// if e.Ctx().Opp.FightC.IsFirst(e.Ctx().Opp.Player) { //如果对方先手
|
||||
// e.duration++
|
||||
// // e.Alive(true)
|
||||
// }
|
||||
|
||||
})
|
||||
// })
|
||||
e.duration--
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ type EffectNode struct {
|
||||
id int
|
||||
maxStack int // 最大叠加层数 ,正常都是不允许叠加的,除了衰弱特殊效果 ,异常和能力的叠层
|
||||
SideEffectArgs []int // 附加效果参数
|
||||
owner bool //是否作用自身
|
||||
Success bool // 是否执行成功 成功XXX,失败XXX
|
||||
arget bool // 传出作用对象,默认0是自身,1是作用于对面
|
||||
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
|
||||
alive bool // 是否失效 effect返回值是否被取消,是否被删除
|
||||
hit bool
|
||||
trunl sync.Once
|
||||
ctx input.Ctx
|
||||
// owner bool //是否作用自身
|
||||
Success bool // 是否执行成功 成功XXX,失败XXX
|
||||
arget bool // 传出作用对象,默认0是自身,1是作用于对面
|
||||
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
|
||||
alive bool // 是否失效 effect返回值是否被取消,是否被删除
|
||||
hit bool
|
||||
trunl sync.Once
|
||||
ctx input.Ctx
|
||||
//增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果
|
||||
}
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ func (p *Player) Save() {
|
||||
|
||||
}
|
||||
if p.FightC != nil {
|
||||
ov := make(chan struct{})
|
||||
//ov := make(chan struct{})
|
||||
go func() {
|
||||
|
||||
defer func() {
|
||||
@@ -330,13 +330,12 @@ func (p *Player) Save() {
|
||||
|
||||
}
|
||||
}()
|
||||
p.FightC.Over(p, info.BattleOverReason.PlayerOffline, func() {
|
||||
<-ov
|
||||
}) //玩家逃跑,但是不能锁线程
|
||||
p.FightC.Over(p, info.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程
|
||||
}()
|
||||
|
||||
//<-p.FightC.GetOverChan() //等待结束
|
||||
//<-ov
|
||||
<-p.FightC.GetOverChan() //等待结束
|
||||
}
|
||||
|
||||
p.Info.TimeToday = p.Info.TimeToday + uint32(time.Now().Unix()) - uint32(p.Onlinetime) //保存电池时间
|
||||
p.Onlinetime = uint32(time.Now().Unix())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user