This commit is contained in:
2025-09-30 18:32:15 +08:00
parent 91d0d29ec9
commit 3aa0362cfe
9 changed files with 135 additions and 145 deletions

View File

@@ -15,4 +15,6 @@ type FightI interface {
Capture(c PlayerI, id uint32)
GetRand() *rand.Rand
LoadPercent(c PlayerI, percent int32)
IsFirst(c PlayerI) bool
}

View File

@@ -13,17 +13,16 @@ type EnumPlayerOperation int
// 定义读秒倒计时期间玩家可执行的操作枚举
var PlayerOperations = enum.New[struct {
SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP)
SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6
ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切)
UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等)
Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线)
PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线
//SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP)
//系统放弃出手就是SKILL ID=0
SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6
ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切)
UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等)
Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线)
PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线
// BeExpelledSwitch EnumPlayerOperation `enum:"6"` // 被驱逐切换
}]()
// BattleActionI 战斗动作接口
type BattleActionI interface {
GetPlayerID() uint32
@@ -33,14 +32,10 @@ type BattleActionI interface {
// SelectSkillAction 选择技能的战斗动作
type SelectSkillAction struct {
PlayerID uint32 // 玩家ID
Skill *info.SkillEntity // 使用的技能
PetInfo *info.BattlePetEntity // 使用技能的宠物
Attack info.AttackValue
}
func (s *SelectSkillAction) GetPlayerID() uint32 {
return s.PlayerID
BaseAction
Skill *info.SkillEntity // 使用的技能
//PetInfo *info.BattlePetEntity // 使用技能的宠物
Attack info.AttackValue
}
// Priority 返回动作优先级
@@ -126,18 +121,6 @@ func (e *OverTimeAction) Priority() int {
return int(PlayerOperations.PlayerOffline)
}
// SystemGiveUpAction 系统强制放弃出手的动作
type SystemGiveUpAction struct {
BaseAction
Reason string // 放弃原因如没有PP值、宠物全部倒下等
LastPet info.BattlePetEntity // 最后在场的宠物
}
// Priority 返回动作优先级
func (s *SystemGiveUpAction) Priority() int {
return int(PlayerOperations.SystemGiveUp)
}
// PlayerOfflineAction 玩家掉线的战斗动作
type PlayerOfflineAction struct {
BaseAction

View File

@@ -1,7 +1,6 @@
package fight
import (
"blazing/common/data/xmlres"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
@@ -78,6 +77,17 @@ func (f *FightC) GetRand() *rand.Rand {
}
// 获取随机数
func (f *FightC) IsFirst(play common.PlayerI) bool {
if f.First.Player == play {
return true
}
return false
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
f.GetInputByPlayer(c, true).Player.SendLoadPercent(info.LoadPercentOutboundInfo{
@@ -323,8 +333,8 @@ func (f *FightC) battleLoop() {
f.closefight = true
case *action.ActiveSwitchAction: //切换上场的,切换方放弃出手
f.enterturn(BattleActionI[1],
&action.SystemGiveUpAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
f.enterturn(BattleActionI[1].(*action.SelectSkillAction),
&action.SelectSkillAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
case *action.UseItemAction: //使用道具
//fmt.Println(faction.ItemID)
@@ -333,7 +343,7 @@ func (f *FightC) battleLoop() {
case faction.ItemID >= 30001 && faction.ItemID <= 300010: //胶囊
//todo 将血量和技能pp传回enterturn
tt, ok := f.Our.Player.(*player.Player)
//tt, ok := f.Our.Player.(*player.Player)
mo, ism := f.Opp.Player.(*player.AI_player)
if ok && ism && mo.CanCapture { //如果获取玩家
@@ -369,11 +379,11 @@ func (f *FightC) battleLoop() {
// 其他情况
fmt.Println("ItemID 不在指定范围内")
}
f.enterturn(BattleActionI[1], &action.SystemGiveUpAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
f.enterturn(BattleActionI[1].(*action.SelectSkillAction), &action.SelectSkillAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
default: //选择技能或者放弃出手
//回合前操作,比如挂载buff
f.enterturn(BattleActionI[0], BattleActionI[1])
f.enterturn(BattleActionI[0].(*action.SelectSkillAction), BattleActionI[1].(*action.SelectSkillAction))
//回合后操作
}
@@ -382,67 +392,25 @@ func (f *FightC) battleLoop() {
}
// 解析并 施加effect
func (f *FightC) parseskill(attacker, defender *input.Input, id *action.SelectSkillAction) {
temparg := id.Skill.SideEffectArgS
for _, v := range id.Skill.SideEffectS {
t := input.Geteffect(input.EffectType.Skill, v)
args := xmlres.EffectArgs[v]
if t.ID != 0 {
if t.Effect.GetOwner() { //如果取反,说明是给对方添加的回合效果
//实际上,owner永远为反,说明是对方给我添加的
t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参,施加方永远是我方
//给双方添加
defender.AddEffect(t)
} else {
t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参
attacker.AddEffect(t)
}
}
temparg = temparg[args:]
}
}
func (f *FightC) initAttackers(fattack action.BattleActionI) {
// 伤害值
// 根据攻击方归属设置当前战斗的主/次攻击方属性
if fattack.GetPlayerID() == f.ownerID {
f.First, f.Second = f.Our, f.Opp // 攻击方为我方时,主攻击方是我方
} else {
f.First, f.Second = f.Opp, f.Our // 攻击方为对方时,主攻击方是对方
}
fmt.Println("先手", f.First.CurrentPet.Info.CatchTime, "后手", f.Second.CurrentPet.Info.CatchTime)
// TODO: 在这里调用技能结算逻辑
}
// 处理技能攻击逻辑
func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.SelectSkillAction) {
f.parseskill(attacker, defender, a) //是否miss都应该施加解析effect
attacker.Exec(func(t input.Effect) bool { //计算命中
t.Skill_Pre(input.Ctx{
a.Skill.AttackTimeC(attacker.GetProp(5, true)) //计算命中
defender.Exec(func(t input.Effect) bool { //计算闪避 ,然后修改对方命中),同时相当于计算属性无效这种
t.Skill_Hit_to(input.Ctx{
Input: attacker,
SkillEntity: a.Skill,
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
SkillEntity: a.Skill, //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
})
return true
})
attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
a.Skill.AttackTimeC(attacker.GetProp(5, true)) //计算命中
defender.Exec(func(t input.Effect) bool { //计算闪避 ,然后修改对方命中),同时相当于计算属性无效这种
t.Skill_PreUse(input.Ctx{
t.Skill_Hit(input.Ctx{ //计算变威力
Input: attacker,
SkillEntity: a.Skill,
})
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
return true
})
@@ -468,6 +436,7 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
}
attacker.Exec(func(t input.Effect) bool {
//这里实现应该参考本地技能是否命中,然后
t.Hit(true) //我方效果命中
return true
@@ -510,24 +479,55 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
//回合有先手方和后手方,同时有攻击方和被攻击方
func (f *FightC) enterturn(fattack, sattack action.BattleActionI) {
func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
if f.closefight { //战斗结束
return
}
f.initAttackers(fattack) //初始化先后手
var attacker, defender *input.Input
// 伤害值
// 根据攻击方归属设置当前战斗的主/次攻击方属性
if fattack.GetPlayerID() == f.ownerID {
f.First, f.Second = f.Our, f.Opp // 攻击方为我方时,主攻击方是我方
} else {
f.First, f.Second = f.Opp, f.Our // 攻击方为对方时,主攻击方是对方
}
fmt.Println("先手", f.First.CurrentPet.Info.CatchTime, "后手", f.Second.CurrentPet.Info.CatchTime)
//是否miss都应该施加解析effect
f.First.Parseskill(f.Second, fattack)
f.First.Exec(func(t input.Effect) bool { //回合开始前
//结算状态
t.Compare_Pre(fattack, sattack) //先结算技能的优先级
return true
})
switch {
case fattack.Skill.Priority < sattack.Skill.Priority:
fattack, sattack = sattack, fattack //互换先手权
case fattack.Skill.Priority == sattack.Skill.Priority:
if f.Second.GetProp(4, false) > f.First.GetProp(4, false) {
fattack, sattack = sattack, fattack //互换先手权
}
}
f.First.First = true
f.Second.First = false
//开始回合操作
for i := 0; i < 2; i++ {
var attackeraction action.BattleActionI
if i == 0 { //
attacker, defender = f.First, f.Second
attackeraction = fattack
attacker.First = true //先手技能
} else {
if i != 0 {
attacker, defender = f.Second, f.First
attackeraction = sattack
attacker.First = false //先手技能
@@ -554,7 +554,7 @@ func (f *FightC) enterturn(fattack, sattack action.BattleActionI) {
canuseskillok := attacker.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
//然后这里还可以处理自爆类
return t.Skill_Can(input.Ctx{
return t.Skill_Hit_Pre(input.Ctx{
Input: attacker,
SkillEntity: skill.Skill,
}) //返回本身结算,如果false,说明不能使用技能了

View File

@@ -85,4 +85,3 @@ func (u *BattlePetEntity) Type() *element.ElementCombination {
return ff
}

View File

@@ -6,14 +6,17 @@ import (
)
type Effect interface {
Compare_Pre(fattack, sattack *action.SelectSkillAction) bool
Fight_Start(ctx Ctx) bool //战斗开始
Turn_Start(ctx Ctx) //回合开始,注入特性
Skill_Pre(ctx Ctx) //技能修改,比如变威力 行动开始前,注入视为等参数在这里实现
Skill_PreUse(ctx Ctx) // 技能命中前触发//预处理受击技能 被攻击方效果,比如受击时无效技能这样
OnSkill(ctx Ctx) // 触发on miss onhit
//技能命中前的返回值代表是否可以出手 ,对命中本身的修改应该是对上下文本身的修改
Skill_Hit_Pre(ctx Ctx) bool //技能修改 行动开始前,注入视为等参数在这里实现
Skill_Hit(ctx Ctx) bool //这是是命中后的对技能的修改,比如变威力
Skill_Hit_to(ctx Ctx) bool // 技能命中前触发//预处理受击技能 被攻击方效果,比如受击时无效技能这样
OnSkill(ctx Ctx) bool // 触发on miss onhit
Skill_Can(ctx Ctx) bool //使用技能 可以取消用技能节点 技能无效节点锁定伤害加上
//Skill_Can(ctx Ctx) bool //使用技能 可以取消用技能节点 技能无效节点锁定伤害加上
Damage_ADD(ctx Ctx) bool // 攻击前触发 ,这时候就是+区间
Damage_Mul(ctx Ctx) bool // 攻击触发

View File

@@ -19,7 +19,7 @@ func (u *Input) UseSkill(opp *Input, skill *info.SkillEntity) {
CritRate := utils.Max(skill.CritRate, 1)
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
if skill.CritAtkFirst != 0 && u.First {
if skill.CritAtkFirst != 0 && u.FightC {
CritRate = 16
}
//CritAtkSecond: 后出手时必定致命一击; 默认: 0

View File

@@ -1,8 +1,10 @@
package input
import (
"blazing/common/data/xmlres"
"blazing/common/utils"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"github.com/jinzhu/copier"
@@ -10,11 +12,12 @@ import (
)
type Input struct {
CanChange bool //是否可以死亡切换CanChange
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
Finished bool //是否加载完成
CanChange bool //是否可以死亡切换CanChange
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
EffectCache []Effect
Finished bool //是否加载完成
*info.AttackValue
FightC common.FightI
// info.BattleActionI
@@ -32,7 +35,7 @@ type Input struct {
//OldAttack int //攻击伤害被挡前伤害记录
} //伤害容器
First bool //是否先手
//First bool //是否先手
}
func NewInput(c common.FightI, p common.PlayerI) *Input {
@@ -97,3 +100,33 @@ func (i *Input) GetStatusBonus() float64 {
return maxBonus
}
// 解析并 施加effect
func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
temparg := skill.Skill.SideEffectArgS
for _, v := range skill.Skill.SideEffectS {
t := Geteffect(EffectType.Skill, v)
args := xmlres.EffectArgs[v]
if t.ID != 0 {
t.Effect.SetArgs(i, temparg[:args]...) //设置入参,施加方永远是我方
// if t.Effect.GetOwner() { //如果取反,说明是给对方添加的回合效果
// //实际上,owner永远为反,说明是对方给我添加的
// t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参,施加方永远是我方
// //给双方添加
// defender.AddEffect(t)
// } else {
// t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参
// attacker.AddEffect(t)
// }
//ret = append(ret, t.Effect)
i.EffectCache = append(i.EffectCache, t.Effect)
}
temparg = temparg[args:]
}
}

View File

@@ -5,15 +5,15 @@ import (
"blazing/logic/service/fight/input"
)
func (e *EffectNode) Skill_Pre(ctx input.Ctx) {
func (e *EffectNode) Skill_Pre(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) Skill_PreUse(ctx input.Ctx) {
func (e *EffectNode) Skill_PreUse(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) OnSkill(ctx input.Ctx) {
func (e *EffectNode) OnSkill(ctx input.Ctx) bool {
if e.Effect != nil {
if e.Hit() { //没命中
e.OnHit(ctx.Input, ctx.SkillEntity)
@@ -21,7 +21,7 @@ func (e *EffectNode) OnSkill(ctx input.Ctx) {
e.OnMiss(ctx.Input, ctx.SkillEntity)
}
}
return true
}
func (e *EffectNode) Skill_Can(ctx input.Ctx) bool {

View File

@@ -23,32 +23,6 @@ func (f *FightC) Compare(a, b action.BattleActionI) (action.BattleActionI, actio
} else if p1 < 0 {
return a, b
}
_, ok := b.(*action.SystemGiveUpAction)
if ok {
if _, ok := a.(*action.SystemGiveUpAction); ok {
return b, a
}
return a, b
}
bskill := b.(*action.SelectSkillAction)
askill := a.(*action.SelectSkillAction)
// 如果是选择技能操作,进一步比较技能优先级和宠物属性
p2 := bskill.Skill.Priority - askill.Skill.Priority
if p2 > 0 {
return b, a
} else if p2 < 0 {
return a, b
}
p2 = int(f.Opp.GetProp(4, false)) - int(f.Our.GetProp(4, false))
if p2 > 0 {
return b, a
} else if p2 < 0 {
return a, b
}
return a, b // 速度相同时,发起方优先
}
@@ -108,16 +82,12 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
// 玩家使用技能
func (f *FightC) UseSkill(c common.PlayerI, id int32) {
if id == 0 {
f.actionChan <- &action.SystemGiveUpAction{BaseAction: action.NewBaseAction(c.GetInfo().UserID)}
return
}
ret := &action.SelectSkillAction{
PlayerID: c.GetInfo().UserID,
}
ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
//ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
for _, v := range ret.PetInfo.Skills {
for _, v := range f.GetInputByPlayer(c, false).CurrentPet.Skills {
if v != nil && v.ID == int(id) {
ret.Skill = v