feat(fight): 重构战斗模块并添加新功能

- 重构了战斗动作处理逻辑,增加了新的战斗动作类型
- 新增了逃跑、使用药剂、系统放弃等战斗动作
- 优化了战斗回合循环和动作执行顺序
- 增加了战斗结束处理逻辑
- 调整了玩家和AI的战斗行为
-增加精灵捕捉
This commit is contained in:
2025-09-05 22:40:36 +08:00
parent a86b69dd1e
commit 52d35119c8
10 changed files with 386 additions and 126 deletions

View File

@@ -44,6 +44,10 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn
if err1 != nil {
panic(err)
}
if c.FightC != nil {
return nil, -1
}
c.FightC = &service.FightC{}
c.FightC.NewFight(&ttt, c) //把两个玩家都传进去
c.FightC.OwnerID = c.Info.UserID
@@ -72,15 +76,6 @@ func (h Controller) UseSkill(data *fight.UseSkillInboundInfo, c *service.Player)
// 战斗逃跑
func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *service.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
defer func() {
//战斗结束Escape
ttt := service.NewTomeeHeader(2506, c.Info.UserID)
c.SendPack(ttt.Pack(&fight.FightOverInfo{
Reason: 0,
}))
c.FightC = nil
}()
c.FightC.Escape(c)
return nil, 0
}

View File

@@ -33,10 +33,23 @@ func (f *AI_player) SendPack(b []byte) error {
func (f *AI_player) SendReadyToFightInfo(gg info.FightStartOutboundInfo) {
fmt.Println(gg)
f.FightC.UseSkill(f, f.fightinfo.OpponentPetList[0].SkillList[0].ID) //使用1#技能,实际上要按照四个技能权重去使用
// f.FightC.UseSkill(f, f.fightinfo.OpponentPetList[0].SkillList[0].ID) //使用1#技能,实际上要按照四个技能权重去使用
//这时候给个出招
}
func (f *AI_player) SendNoteReadyToFightInfo(_ info.NoteReadyToFightInfo) {
panic("not implemented") // TODO: Implement
}
func (f *AI_player) SendFightEndInfo(_ info.FightOverInfo) {
fmt.Println("战斗结束")
}
func (f *AI_player) GetAction() {
f.FightC.UseSkill(f, f.fightinfo.OpponentPetList[0].SkillList[0].ID) //使用1#技能,实际上要按照四个技能权重去使用
}
func (p *AI_player) End() {
p.FightC = nil
return
}

View File

@@ -19,7 +19,7 @@ type EffectNode struct {
SideEffectArgs []int // 附加效果参数
Success bool // 是否执行成功 成功XXX失败XXX
efftype int // 传出作用对象,默认0是自身,1是作用于对面
target int // 传出作用对象,默认0是自身,1是作用于对面
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
//增加owner target如果owner target都为自身就回合效果结束后再使用回合效果
}
@@ -31,9 +31,14 @@ func (this *EffectNode) ID() int {
}
// 传出作用对象,默认0是自身,1是作用于对面
func (this *EffectNode) Type() int {
func (this *EffectNode) Target() int {
return this.efftype
return this.target
}
func (this *EffectNode) SetTarget(t int) {
this.target = t
}
func (this *EffectNode) Stack(t int) int {

View File

@@ -25,17 +25,6 @@ type EscapeFightInboundInfo struct {
Head service.TomeeHeader `cmd:"2410" struc:"[0]pad"`
}
// FightOverInfo 战斗结束信息结构体 2506
type FightOverInfo struct {
Reason uint32 // 固定值0
WinnerId uint32 // 胜者的米米号 野怪为0
TwoTimes uint32 // 双倍经验剩余次数
ThreeTimes uint32 // 三倍经验剩余次数
AutoFightTimes uint32 // 自动战斗剩余次数
EnergyTimes uint32 // 能量吸收器剩余次数
LearnTimes uint32 // 双倍学习器剩余次数
}
// HandleFightInviteInboundInfo 处理战斗邀请的入站消息
// 回空包就行
type HandleFightInviteInboundInfo struct {

View File

@@ -1,6 +1,9 @@
package info
import (
"fmt"
"time"
"github.com/tnnmigga/enum"
)
@@ -9,54 +12,178 @@ type EnumPlayerOperation int
// 定义读秒倒计时期间玩家可执行的操作枚举
var PlayerOperations = enum.New[struct {
SystemGiveUp EnumPlayerOperation `enum:"-1"` //`enum:"系统选择放弃出手"`比如没有PP,
SelectSkill EnumPlayerOperation `enum:"0"` //`enum:"选择技能"`
ActiveSwitch EnumPlayerOperation `enum:"2"` //`enum:"主动切换(中切)"`
UsePotion EnumPlayerOperation `enum:"3"` //`enum:"使用药剂"` 捕捉 逃跑
Escape EnumPlayerOperation `enum:"4"` //`enum:"使用药剂"` 逃跑 等级最高 ,以及掉线
//DeathSwitch EnumPlayerOperation `enum:"4"` //`enum:"死亡切换"` 这两个本质上还是对action的比较
// ExpelledSwitch EnumPlayerOperation `enum:"5"` //`enum:"(被)驱逐切换"`
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"` // 玩家掉线
}]()
type BattleAction struct {
PlayerID uint32
Priority EnumPlayerOperation //优先级本质上是action的itoa
Skill BattleSkillEntity
PetInfo BattlePetEntity
//ctx context.Context
}
// Compare 比较两个1v1战斗动作的执行优先级核心逻辑
func (c *BattleAction) Compare(a *BattleAction) *BattleAction {
//player, _ := a.ctx.Value("player").(*BattleInputSourceEntity)
// 动作本身的优先级 技能的优先级是0,
p1 := a.Priority - c.Priority
if p1 > 0 { //说明对手快
return a
func Compare(a, b BattleActionI) BattleActionI {
// 动作本身的优先级比较
p1 := b.Priority() - a.Priority()
if p1 > 0 { // 对手优先级更高
return b
} else if p1 < 0 {
return c
return a
}
if a.Priority == 0 {
p2 := a.Skill.Priority - c.Skill.Priority //对方减自己
if p2 > 0 {
return a
} else if p2 < 0 {
return c
}
p2 = int(a.PetInfo.Value(4)) - int(c.PetInfo.Value(4)) // 假设 Use1v1SkillAction 有 SkillPriority() 方法
if p2 > 0 {
return a
} else if p2 < 0 {
return c
}
bskill := b.(*SelectSkillAction)
askill := a.(*SelectSkillAction)
// 如果是选择技能操作,进一步比较技能优先级和宠物属性
p2 := bskill.Skill.Priority - askill.Skill.Priority
if p2 > 0 {
return b
} else if p2 < 0 {
return a
}
return c // 3.3 速度相同时 ,发起方优先
// 比较宠物相关属性(假设Value(4)返回速度相关值)
p2 = int(bskill.PetInfo.Value(4)) - int(askill.PetInfo.Value(4))
if p2 > 0 {
return b
} else if p2 < 0 {
return a
}
return a // 速度相同时,发起方优先
}
// BattleActionI 战斗动作接口
type BattleActionI interface {
GetPlayerID() uint32
Priority() int // 优先级
}
// SelectSkillAction 选择技能的战斗动作
type SelectSkillAction struct {
PlayerID uint32 // 玩家ID
Skill *BattleSkillEntity // 使用的技能
PetInfo *BattlePetEntity // 使用技能的宠物
}
func (s *SelectSkillAction) GetPlayerID() uint32 {
return s.PlayerID
}
// Priority 返回动作优先级
func (s *SelectSkillAction) Priority() int {
return int(PlayerOperations.SelectSkill)
}
// Broadcast 广播选择技能的动作信息
func (s *SelectSkillAction) Broadcast() {
fmt.Printf("玩家[%d]选择使用技能:%sID%d执行者%s\n",
s.PlayerID, s.Skill.Name, s.Skill.ID, s.PetInfo.ID)
}
// ActiveSwitchAction 主动切换宠物的战斗动作
type ActiveSwitchAction struct {
PlayerID uint32 // 玩家ID
CurrentPet BattlePetEntity // 当前在场宠物
TargetPet BattlePetEntity // 要切换上场的宠物
SwitchReason string // 切换原因
}
// Priority 返回动作优先级
func (a *ActiveSwitchAction) Priority() int {
return int(PlayerOperations.ActiveSwitch)
}
// Broadcast 广播切换宠物的动作信息
func (a *ActiveSwitchAction) Broadcast() {
// fmt.Printf("玩家[%d]主动切换宠物:从%s切换到%s原因%s\n",
// // a.PlayerID, a.CurrentPet.Name, a.TargetPet.Name, a.SwitchReason)
}
// UsePotionAction 使用药剂的战斗动作
type UsePotionAction struct {
PlayerID uint32 // 玩家ID
PotionID uint32 // 药剂ID
PotionName string // 药剂名称
TargetPet BattlePetEntity // 药剂作用目标宠物
}
type PlayerI interface {
SendPack(b []byte) error
}
// Priority 返回动作优先级
func (u *UsePotionAction) Priority() int {
return int(PlayerOperations.UsePotion)
}
// Broadcast 广播使用药剂的动作信息
func (u *UsePotionAction) Broadcast() {
// fmt.Printf("玩家[%d]使用药剂:%sID%d目标%s\n",
// u.PlayerID, u.PotionName, u.PotionID, u.TargetPet.Name)
}
// EscapeAction 逃跑的战斗动作
type EscapeAction struct {
PlayerID uint32 // 玩家ID
Reason FightOverInfo
Our PlayerI
Opp PlayerI
}
func (e *EscapeAction) GetPlayerID() uint32 {
return e.PlayerID
}
func (e *EscapeAction) GetInfo() FightOverInfo {
return e.Reason
}
// Priority 返回动作优先级
func (e *EscapeAction) Priority() int {
return int(PlayerOperations.Escape)
}
// SystemGiveUpAction 系统强制放弃出手的动作
type SystemGiveUpAction struct {
PlayerID uint32 // 玩家ID
Reason string // 放弃原因如没有PP值、宠物全部倒下等
LastPet BattlePetEntity // 最后在场的宠物
}
func (s *SystemGiveUpAction) GetPlayerID() uint32 {
return s.PlayerID
}
// Priority 返回动作优先级
func (s *SystemGiveUpAction) Priority() int {
return int(PlayerOperations.SystemGiveUp)
}
// Broadcast 广播系统放弃的动作信息
func (s *SystemGiveUpAction) Broadcast() {
// fmt.Printf("玩家[%d]被系统强制放弃出手,原因:%s最后在场宠物%s\n",
// s.PlayerID, s.Reason, s.LastPet.Name)
}
// PlayerOfflineAction 玩家掉线的战斗动作
type PlayerOfflineAction struct {
PlayerID uint32 // 掉线玩家ID
OfflineTime time.Time // 掉线时间
CurrentPet BattlePetEntity // 掉线时在场的宠物
IsReconnect bool // 是否后续重连(预留字段)
}
// Priority 返回动作优先级
func (p *PlayerOfflineAction) Priority() int {
return int(PlayerOperations.PlayerOffline)
}
// Broadcast 广播玩家掉线信息
func (p *PlayerOfflineAction) Broadcast() {
// /status := "未重连"
// if p.IsReconnect {
// status = "已重连"
// }
// fmt.Printf("玩家[%d]在[%s]掉线,当前在场宠物:%s状态%s\n",
// p.PlayerID, p.OfflineTime.Format("2006-01-02 15:04:05"),
// p.CurrentPet.Name, status)
}

View File

@@ -4,7 +4,6 @@ import (
element "blazing/common/data/Element"
"blazing/common/data/xmlres"
"blazing/modules/blazing/model"
"context"
"sync"
"unsafe"
)
@@ -36,16 +35,26 @@ func (a *BattlePetEntity) Value(tt uint32) uint32 {
type BattlePetEntity struct {
xmlres.PetInfo
info model.PetInfo //通过偏移赋值
ctx context.Context
Capturable bool // 是否可捕获
statusConditions sync.Map // key: StatusCondition, value: int (剩余回合)
skills [4]*BattleSkillEntity // 技能槽最多4个技能
Status StatusDict //精灵的状态
info model.PetInfo //通过偏移赋值
Capturable bool // 是否可捕获
statusConditions sync.Map // key: StatusCondition, value: int (剩余回合)
Skills [4]BattleSkillEntity // 技能槽最多4个技能
Status StatusDict //精灵的状态
//能力提升属性
Prop PropDict
}
// 创建精灵实例
func CreateBattlePetEntity(info ReadyFightPetInfo) *BattlePetEntity {
ret := &BattlePetEntity{}
ret.PetInfo = xmlres.PetMAP[int(info.ID)] //注入精灵信息
return ret
}
// calculateRealValue 计算实际属性值根据状态变化计算实际值
// value 基础属性值
// stat 状态变化值(可正可负)

View File

@@ -179,3 +179,14 @@ type ReadyFightPetInfo struct {
SkinID uint32 `fieldDesc:"精灵皮肤ID" `
Shiny uint32 `fieldDesc:"精灵是否闪" `
}
// FightOverInfo 战斗结束信息结构体 2506
type FightOverInfo struct {
Reason uint32 // 固定值0
WinnerId uint32 // 胜者的米米号 野怪为0
TwoTimes uint32 // 双倍经验剩余次数
ThreeTimes uint32 // 三倍经验剩余次数
AutoFightTimes uint32 // 自动战斗剩余次数
EnergyTimes uint32 // 能量吸收器剩余次数
LearnTimes uint32 // 双倍学习器剩余次数
}

View File

@@ -13,16 +13,18 @@ type Effect interface {
PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等)
OnBeforeCalculateDamage() bool // 最终伤害计算前触发
OnDamage() bool // 造成伤害时触发
Shield() bool // 护盾值变化时触发
PostDamage() bool // 伤害结算后触发(血量扣除后)
SetParam(param []int) //设置参数
GetParam() int //获取参数
Shield() bool // 护盾值变化时触发
PostDamage() bool // 伤害结算后触发(血量扣除后)
OnCritPostDamage() bool // 暴击伤害结算后触发
OnHit() bool // 技能命中时触发
OnMiss() bool // 技能未命中时触发
AfterAttacked() bool // 被攻击后触发(受击判定)
Type() int // 技能效果类型
Target() bool // 技能效果类型
SetTarget(bool) // 技能效果类型
OnDefeat() bool // 精灵被击败时触发
TurnEnd() bool // 回合结束
@@ -71,6 +73,7 @@ type NodeManager struct {
var NodeM = &NodeManager{}
func (c *NodeManager) AddEffect(e Effect) {
// 如果已有同 ID 的效果,尝试叠加
for _, eff := range c.Effects {
if eff.ID() == e.ID() {
@@ -115,12 +118,12 @@ func (c *NodeManager) Exec(fn func(Effect) bool) bool {
return results
}
// 消除回合类效果 efftype 输入是消对方的还是自己的
func (c *NodeManager) CancelTurn(efftype int) {
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
func (c *NodeManager) CancelTurn(efftype bool) {
var remain []Effect
for _, eff := range c.Effects {
if eff.Duration(0) <= 0 && eff.Type() != efftype {
if eff.Duration(0) <= 0 && eff.Target() == efftype { //false是自身,true是对方,反转后为真就是自己的
remain = append(remain, eff)
}
}

View File

@@ -1,44 +1,72 @@
package service
import (
"blazing/common/data/xmlres"
"blazing/common/utils"
"blazing/logic/service/fight/info"
"fmt"
"math/rand"
"time"
"github.com/gogf/gf/v2/util/gconv"
"github.com/jinzhu/copier"
)
type PlayerI interface {
ID() uint32
MapID() uint32
//GetInfo() info.BattlePetEntity
GetAction()
End() //结束战斗
SendPack(b []byte) error
SendReadyToFightInfo(info.FightStartOutboundInfo)
SendNoteReadyToFightInfo(info.NoteReadyToFightInfo)
SendFightEndInfo(info.FightOverInfo)
}
type FightC struct {
Info *info.NoteReadyToFightInfo
Our PlayerI
Opp PlayerI
MAXPET uint32 // 最大精灵数
OwnerID uint32 // 战斗发起者ID
AFinished bool
BFinished bool
Info *info.NoteReadyToFightInfo
Our PlayerI
OurCurrentPet *info.BattlePetEntity //我方精灵
Opp PlayerI
OppCurrentPet *info.BattlePetEntity //对方当前精灵
MAXPET uint32 // 最大精灵数
OwnerID uint32 // 战斗发起者ID
AFinished bool
BFinished bool
//random *rand.Rand //随机数种子
StartTime time.Time
actionChan chan info.BattleAction // 所有操作统一从这里进入
Round int //回合数
actionChan chan info.BattleActionI // 所有操作统一从这里进入
Round int //回合数
EffectS info.NodeManager //effects容器
}
// 玩家逃跑
func (f *FightC) Escape(c PlayerI) {
ret := &info.EscapeAction{
PlayerID: c.ID(),
Reason: info.FightOverInfo{
Reason: uint32(info.BattleOverReason.PlayerEscape),
},
}
f.actionChan <- ret
}
// 玩家使用技能
func (f *FightC) UseSkill(c PlayerI, id uint32) {
ret := info.BattleAction{
ret := &info.SelectSkillAction{
PlayerID: c.ID(),
Priority: info.PlayerOperations.SelectSkill,
// Skill: info.CreateBattleSkillWithInfinity(id),
Skill: info.CreateBattleSkillWithInfinity(id),
}
if c == f.Our {
ret.PetInfo = f.OurCurrentPet //存入自己的精灵信息
} else {
ret.PetInfo = f.OppCurrentPet
}
f.actionChan <- ret
@@ -49,30 +77,40 @@ func (f *FightC) ReadyFight(c 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.SendReadyToFightInfo(rett)
f.Opp.SendReadyToFightInfo(rett)
}
switch f.Info.FightId {
case 1: // 1v1
if c == f.Our {
f.AFinished = true
f.OurCurrentPet = info.CreateBattlePetEntity(f.Info.OurPetList[0])
if f.BFinished {
copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0])
f.Our.SendReadyToFightInfo(rett)
f.Opp.SendReadyToFightInfo(rett)
rrsult()
}
} else {
f.Opp = c
f.BFinished = true
if f.AFinished {
copier.Copy(&rett.Info2, &f.Info.OurPetList[0])
f.Our.SendReadyToFightInfo(rett)
f.Opp.SendReadyToFightInfo(rett)
rrsult()
}
}
case 3: // 野怪战斗
copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0])
rett.Info1.UserID = f.Info.OurInfo.UserID
f.Our.SendReadyToFightInfo(rett)
f.Opp.SendReadyToFightInfo(rett)
//判断捕捉率大于0
if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 {
rett.Info2.Catchable = 1
}
rrsult()
}
}
func (f *FightC) Random() {
@@ -90,49 +128,74 @@ func (f *FightC) NewFight(i *info.NoteReadyToFightInfo, plays PlayerI) {
f.Our = plays
f.Info = i
f.StartTime = time.Now()
f.actionChan = make(chan info.BattleAction, 2) // 初始化全局操作通道
f.actionChan = make(chan info.BattleActionI, 2) // 初始化全局操作通道
switch i.FightId {
case 1:
// 1v1等双方进入
case 3: // 野怪战斗
plays.SendNoteReadyToFightInfo(*i)
f.Opp = &AI_player{fightinfo: *i, FightC: f} // 创建虚拟对手
plays.SendNoteReadyToFightInfo(*i)
}
go f.battleLoop() // 起战斗循环
}
// 广播,并是否结束回合
func (f *FightC) Broadcast(t info.BattleActionI) bool {
switch ff := t.(type) {
case *info.SelectSkillAction:
case *info.EscapeAction:
f.Our.SendFightEndInfo(ff.Reason)
f.Opp.SendFightEndInfo(ff.Reason)
return true
default:
}
return false
}
// 战斗回合循环
func (f *FightC) battleLoop() {
for {
f.Round++ //回合数自增
actions := make(map[uint32]info.BattleAction) // 每个玩家一条记录
f.Round++ //回合数自增
if f.Round > 250 { //回合数超过250,战斗平局结束
}
actions := make(map[uint32]info.BattleActionI) // 每个玩家一条记录
timeout := time.After(60 * time.Second)
for len(actions) < 2 {
select {
case action := <-f.actionChan:
// 只接受有效玩家 ID
if action.PlayerID != f.Our.ID() && action.PlayerID != f.Opp.ID() {
continue
}
// 如果该玩家已经提交过,就忽略重复动作
if _, exists := actions[uint32(action.PlayerID)]; exists {
fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", action.PlayerID)
if action.GetPlayerID() != f.Our.ID() && action.GetPlayerID() != f.Opp.ID() {
continue
}
actions[uint32(action.PlayerID)] = action
fmt.Printf("玩家%d 执行动作", action.PlayerID)
if action.GetPlayerID() == f.Our.ID() && f.Info.FightId == 3 {
go f.Opp.GetAction() //获取AI的动作
}
// 如果该玩家已经提交过,就忽略重复动作
if _, exists := actions[uint32(action.GetPlayerID())]; exists {
fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", action.GetPlayerID())
continue
}
actions[uint32(action.GetPlayerID())] = action
fmt.Printf("玩家%d 执行动作", action.GetPlayerID())
case <-timeout:
fmt.Println("回合操作超时")
if _, exists := actions[f.Our.ID()]; !exists {
actions[f.Our.ID()] = info.BattleAction{PlayerID: f.Our.ID(), Priority: info.PlayerOperations.SystemGiveUp} //系统选择出手
actions[f.Our.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.ID()} //系统选择出手
}
if _, exists := actions[f.Opp.ID()]; !exists {
actions[f.Opp.ID()] = info.BattleAction{PlayerID: f.Our.ID(), Priority: info.PlayerOperations.SystemGiveUp} //系统选择出手
actions[f.Opp.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.ID()} //系统选择出手
}
}
}
@@ -140,19 +203,50 @@ func (f *FightC) battleLoop() {
// 双方动作齐了,取出来结算
p1Action := actions[f.Our.ID()]
p2Action := actions[f.Opp.ID()]
fmt.Printf("开始结算回合")
fmt.Println("开始结算回合")
fmt.Println(p1Action)
fmt.Println(p2Action)
firstaction := info.Compare(p1Action, p2Action)
if firstaction.Priority() > 0 { //如果优先级大于0,说明是在技能之上的
t := f.Broadcast(firstaction)
if t {
break
}
}
// TODO: 在这里调用技能结算逻辑
if isBattleEnd() {
fmt.Println("战斗结束")
return
firstskill, _ := firstaction.(*info.SelectSkillAction)
temparg := firstskill.Skill.SideEffectArgS
for _, v := range firstskill.Skill.SideEffectS {
t, ok := effectmap[v]
if ok {
args := t.GetParam()
t.SetParam(temparg[:args]) //设置入参
//如果不是是房主方,说明施加的对象是反的,比如本来是false,实际上是给邀请方施加的
//所以这里要对target取反
if firstaction.GetPlayerID() != f.OwnerID {
t.SetTarget(!t.Target())
}
temparg = temparg[args:]
}
}
}
close(f.actionChan) //关闭战斗通道
//取消战斗信息
f.Our.End()
f.Opp.End()
}
// 判断战斗是否结束
func isBattleEnd() bool {
return false
}
var effectmap = utils.ToMap[info.Effect, int](info.NodeM.Effects,
func(t info.Effect) int {
return t.ID()
})

View File

@@ -124,6 +124,15 @@ func (p *Player) GetInfo() model.PlayerInfo {
return *p.Info
}
func (p *Player) GetAction() {
return
}
func (p *Player) End() {
p.FightC = nil
return
}
func (p *Player) ID() uint32 {
return p.Info.UserID
@@ -154,6 +163,11 @@ func (p *Player) SendNoteReadyToFightInfo(b info.NoteReadyToFightInfo) {
p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样
}
func (p *Player) SendFightEndInfo(b info.FightOverInfo) {
t1 := NewTomeeHeader(2506, p.Info.UserID)
p.SendPack(t1.Pack(&b))
}
// Save 保存玩家数据
func (p *Player) Save() {