feat(fight): 重构战斗模块并添加新功能
- 重构了战斗动作处理逻辑,增加了新的战斗动作类型 - 新增了逃跑、使用药剂、系统放弃等战斗动作 - 优化了战斗回合循环和动作执行顺序 - 增加了战斗结束处理逻辑 - 调整了玩家和AI的战斗行为 -增加精灵捕捉
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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]选择使用技能:%s(ID:%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]使用药剂:%s(ID:%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)
|
||||
}
|
||||
|
||||
@@ -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 状态变化值(可正可负)
|
||||
|
||||
@@ -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 // 双倍学习器剩余次数
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user