mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 16:02:26 +08:00
GCG流程至投掷骰子
This commit is contained in:
@@ -21,6 +21,7 @@ type GameDataConfig struct {
|
|||||||
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
|
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
|
||||||
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
|
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
|
||||||
DropGroupDataMap map[int32]*DropGroupData // 掉落组
|
DropGroupDataMap map[int32]*DropGroupData // 掉落组
|
||||||
|
GCGCharDataMap map[int32]*GCGCharData // 角色卡牌
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitGameDataConfig() {
|
func InitGameDataConfig() {
|
||||||
@@ -62,6 +63,7 @@ func (g *GameDataConfig) load() {
|
|||||||
g.loadAvatarSkillData() // 角色技能
|
g.loadAvatarSkillData() // 角色技能
|
||||||
g.loadAvatarSkillDepotData() // 角色技能库
|
g.loadAvatarSkillDepotData() // 角色技能库
|
||||||
g.loadDropGroupData() // 掉落组
|
g.loadDropGroupData() // 掉落组
|
||||||
|
g.loadGCGCharData() // 角色卡牌
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameDataConfig) readCsvFileData(fileName string) []byte {
|
func (g *GameDataConfig) readCsvFileData(fileName string) []byte {
|
||||||
|
|||||||
75
gdconf/game_data_config/csv/GCGCharData.csv
Normal file
75
gdconf/game_data_config/csv/GCGCharData.csv
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
CharId,,TagId1,TagId2,TagId3,TagId4,TagId5,,,,,SkillListStr,,HPBase,MaxElemVal,,
|
||||||
|
int32,,int32,int32,int32,int32,int32,,,,,string,,int32,int32,,
|
||||||
|
ID,卡牌类型,[卡牌标签列表]1,[卡牌标签列表]2,[卡牌标签列表]3,[卡牌标签列表]4,[卡牌标签列表]5,[卡牌变量]1类型,[卡牌变量]1值,[卡牌变量]2类型,[卡牌变量]2值,卡牌技能列表,可进构筑,角色生命值,角色充能上限,最大行动意图数,死亡后移出游戏
|
||||||
|
1001,1,303,503,502,201,,,,,,80,,50,1,1,
|
||||||
|
1002,1,301,503,502,204,,,,,,80,,50,1,1,1
|
||||||
|
1003,1,303,503,502,201,,,,,,80#1130211,,50,1,1,
|
||||||
|
1101,1,301,204,402,,,16,0,,,11011# 11012# 11013# 11014,1,10,2,2,
|
||||||
|
1102,1,301,204,401,,,,,,,11021# 11022# 11023,1,10,3,2,
|
||||||
|
1103,1,301,201,401,,,,,,,11031# 11032# 11033,1,10,2,2,
|
||||||
|
1104,1,301,203,402,,,,,,,11041# 11042# 11043,1,10,3,2,
|
||||||
|
1105,1,301,201,403,,,,,,,11051# 11052# 11053# 11054,1,10,3,2,
|
||||||
|
1201,1,302,202,401,,,,,,,12011# 12012# 12013,1,10,3,2,
|
||||||
|
1202,1,302,201,402,,,,,,,12021# 12022# 12023,1,10,2,2,
|
||||||
|
1203,1,302,202,401,,,,,,,12031# 12032# 12033# 12034,1,10,3,2,
|
||||||
|
1301,1,303,203,401,,,,,,,13011# 13012# 13013,1,10,3,2,
|
||||||
|
1302,1,303,205,402,,,,,,,13021# 13022# 13023,1,10,2,2,
|
||||||
|
1303,1,303,201,401,,,,,,,13031# 13032# 13033,1,10,2,2,
|
||||||
|
1305,1,303,204,403,,,,,,,13051# 13052# 13053,1,10,2,2,
|
||||||
|
1401,1,304,204,401,,,,,,,14011# 14012# 14013,1,10,3,2,
|
||||||
|
1402,1,304,203,401,,,,,,,14021# 14022# 14023,1,10,3,2,
|
||||||
|
1403,1,304,201,402,,,,,,,14031# 14032# 14033,1,10,3,2,
|
||||||
|
1404,1,304,205,404,,,,,,,14041# 14042# 14043# 14044,1,10,2,2,
|
||||||
|
1501,1,307,202,401,,,,,,,15011# 15012# 15013,1,10,2,2,
|
||||||
|
1502,1,307,201,401,,,,,,,15021# 15022# 15023,1,10,3,2,
|
||||||
|
1601,1,305,202,402,,,,,,,16011# 16012# 16013,1,10,3,2,
|
||||||
|
1602,1,305,203,401,,,,,,,16021# 16022# 16023,1,10,2,2,
|
||||||
|
1701,1,306,204,404,,,,,,,17011# 17012# 17013,1,10,2,2,
|
||||||
|
2201,1,302,200,503,,,,,,,22011# 22012# 22013# 22014,1,10,3,2,
|
||||||
|
2202,1,302,200,501,,,,,,,22021# 22022# 22023,1,10,2,2,
|
||||||
|
2301,1,303,200,501,,,,,,,23011# 23012# 23013# 23014,1,10,2,2,
|
||||||
|
2501,1,307,200,503,,,,,,,25011# 25012# 25013# 25014,1,10,3,2,
|
||||||
|
2601,1,305,200,503,502,,,,,,26011# 26012# 26013# 26014,1,8,2,2,
|
||||||
|
2701,1,306,200,503,,,,,,,27011# 27012# 27013# 27014,1,10,2,2,
|
||||||
|
3001,1,300,503,502,,,,,,,30011# 30012# 30013,,4,2,1,1
|
||||||
|
3002,1,300,503,502,,,,,,,30021# 30022# 30023,,3,2,1,1
|
||||||
|
3003,1,300,504,,,,,,,,30031# 30032# 30033# 30034# 30035# 30036,,6,2,1,1
|
||||||
|
3101,1,301,503,502,,,,,,,31011# 31012# 31013# 31014# 31015,,8,2,2,1
|
||||||
|
3102,1,301,503,502,,,,,,,31021# 31022# 31023,,3,2,1,1
|
||||||
|
3103,1,301,503,,,,,,,,31031# 31032# 31033# 31034# 31035,,4,2,2,1
|
||||||
|
3201,1,302,503,,,,,,,,32011# 32012# 32013# 32014# 32015,,4,3,2,1
|
||||||
|
3202,1,302,503,502,,,,,,,32021# 32022# 32023,,4,2,2,1
|
||||||
|
3203,1,302,501,,,,,,,,32031# 32032# 32033# 32034# 32035,,10,3,2,1
|
||||||
|
3204,1,302,503,,,,,,,,32041# 32042# 32043,,4,2,1,1
|
||||||
|
3301,1,303,503,,,,,,,,33011# 33012# 33013# 33014# 33015,,4,3,2,1
|
||||||
|
3302,1,303,503,502,,,,,,,33021# 33022# 33023# 33024,,8,2,2,1
|
||||||
|
3303,1,303,504,,,,,,,,33031# 33032# 33033# 33034# 33035# 33036# 33037,,10,2,2,1
|
||||||
|
3304,1,303,503,502,,,,,,,33041# 33042# 33043,,4,2,1,1
|
||||||
|
3305,1,303,504,,,,,,,,33051# 33052# 30033# 30034# 30035# 30036,,6,2,1,1
|
||||||
|
3401,1,304,504,,,,,,,,34011# 34012# 34013# 34014# 34015# 34016# 34017,,10,2,2,1
|
||||||
|
3402,1,304,503,502,,,,,,,34021# 34022# 34023,,3,2,1,1
|
||||||
|
3403,1,304,503,502,,,,,,,34031# 34032# 34033# 34034,,8,2,2,1
|
||||||
|
3405,1,304,504,,,,,,,,34051# 34052# 30033# 30034# 30035# 30036,,6,2,1,1
|
||||||
|
3406,1,304,503,,,,,,,,34061# 34062# 34063,,4,2,1,1
|
||||||
|
3501,1,307,503,502,,,,,,,35011# 35012# 35013,,4,2,2,1
|
||||||
|
3502,1,307,501,,,,,,,,35021# 35022# 35023# 35024# 35025,,10,2,2,1
|
||||||
|
3701,1,306,503,,,,,,,,37011# 37012# 37013# 37014,,6,2,2,1
|
||||||
|
3703,1,306,503,502,,,,,,,37031# 37032# 37033,,4,2,1,1
|
||||||
|
4601,1,305,200,503,502,,,,,,26011# 26012 # 26013,,12,2,2,1
|
||||||
|
4602,1,305,200,503,502,,,,,,26011# 26012 # 26013# 26014,,16,2,3,1
|
||||||
|
4603,1,305,200,503,502,,,,,,26011# 26012 # 26013# 26014,,24,2,3,1
|
||||||
|
4604,1,305,200,503,502,,,,,,26011# 26012 # 26013# 26014,,8,2,2,1
|
||||||
|
4201,1,302,200,503,,,,,,,22011# 22012 # 22013# 22014# 32043,,30,3,4,1
|
||||||
|
4202,1,302,200,503,,,,,,,22011# 22012 # 22013# 22014# 32043,,45,3,4,1
|
||||||
|
4203,1,302,200,501,,,,,,,22021# 22022 # 22023,,10,2,3,1
|
||||||
|
4204,1,302,200,501,,,,,,,22021# 22022 # 22023,,10,2,2,1
|
||||||
|
4301,1,303,200,501,,,,,,,23011# 23012 # 23013# 23014,,10,2,3,1
|
||||||
|
4302,1,303,200,501,,,,,,,23011# 23012 # 23013# 23014,,10,2,2,1
|
||||||
|
4501,1,307,200,503,,,,,,,25011# 25012 # 25013# 25014,,20,3,2,1
|
||||||
|
4502,1,307,200,503,,,,,,,25011# 25012 # 25013# 25014,,28,3,2,1
|
||||||
|
4701,1,306,200,503,,,,,,,27011# 27012 # 27013# 27014,,36,2,4,1
|
||||||
|
4702,1,306,200,503,,,,,,,27011# 27012 # 27013# 27014,,48,2,4,1
|
||||||
|
4703,1,306,200,503,,,,,,,27011# 27012 # 27013# 27014,,10,2,2,1
|
||||||
|
4704,1,306,200,503,,,,,,,27011# 27012 # 27013# 27014,,30,2,3,1
|
||||||
|
5201,1,302,503,,,,,,,,32011# 32012# 32013# 32014# 32015# 32016,,4,3,2,1
|
||||||
|
5301,1,303,503,,,,,,,,33011# 33012# 33013# 33014# 33015# 33016,,4,3,2,1
|
||||||
|
66
gdconf/gcg_char_data.go
Normal file
66
gdconf/gcg_char_data.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package gdconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"hk4e/pkg/logger"
|
||||||
|
|
||||||
|
"github.com/jszwec/csvutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 角色卡牌配置表
|
||||||
|
|
||||||
|
type GCGCharData struct {
|
||||||
|
CharId int32 `csv:"CharId"` // ID
|
||||||
|
TagId1 int32 `csv:"TagId1,omitempty"` // 卡牌标签列表1
|
||||||
|
TagId2 int32 `csv:"TagId2,omitempty"` // 卡牌标签列表2
|
||||||
|
TagId3 int32 `csv:"TagId3,omitempty"` // 卡牌标签列表3
|
||||||
|
TagId4 int32 `csv:"TagId4,omitempty"` // 卡牌标签列表4
|
||||||
|
TagId5 int32 `csv:"TagId5,omitempty"` // 卡牌标签列表5
|
||||||
|
SkillListStr string `csv:"SkillListStr,omitempty"` // 卡牌技能列表文本
|
||||||
|
HPBase int32 `csv:"HPBase,omitempty"` // 角色生命值
|
||||||
|
MaxElemVal int32 `csv:"MaxElemVal,omitempty"` // 角色充能上限
|
||||||
|
|
||||||
|
TagList []uint32 // 卡牌标签列表
|
||||||
|
SkillList []uint32 // 卡牌技能列表
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameDataConfig) loadGCGCharData() {
|
||||||
|
g.GCGCharDataMap = make(map[int32]*GCGCharData)
|
||||||
|
data := g.readCsvFileData("GCGCharData.csv")
|
||||||
|
var gcgCharDataList []*GCGCharData
|
||||||
|
err := csvutil.Unmarshal(data, &gcgCharDataList)
|
||||||
|
if err != nil {
|
||||||
|
info := fmt.Sprintf("parse file error: %v", err)
|
||||||
|
panic(info)
|
||||||
|
}
|
||||||
|
for _, gcgCharData := range gcgCharDataList {
|
||||||
|
// 将TagId整合进TagList
|
||||||
|
gcgCharData.TagList = make([]uint32, 0, 5)
|
||||||
|
tempTagList := make([]int32, 0, 5)
|
||||||
|
tempTagList = append(tempTagList, gcgCharData.TagId1, gcgCharData.TagId2, gcgCharData.TagId3, gcgCharData.TagId4, gcgCharData.TagId5)
|
||||||
|
for _, tagId := range tempTagList {
|
||||||
|
// 跳过为0的tag
|
||||||
|
if tagId == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
gcgCharData.TagList = append(gcgCharData.TagList, uint32(tagId))
|
||||||
|
}
|
||||||
|
// 技能列表读取转换
|
||||||
|
tempSkillList := strings.Split(strings.ReplaceAll(gcgCharData.SkillListStr, " ", ""), "#")
|
||||||
|
gcgCharData.SkillList = make([]uint32, 0, len(tempSkillList))
|
||||||
|
for _, s := range tempSkillList {
|
||||||
|
skillId, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("skill id to i err, %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gcgCharData.SkillList = append(gcgCharData.SkillList, uint32(skillId))
|
||||||
|
}
|
||||||
|
// list -> map
|
||||||
|
g.GCGCharDataMap[gcgCharData.CharId] = gcgCharData
|
||||||
|
}
|
||||||
|
logger.Info("GCGCharData count: %v", len(g.GCGCharDataMap))
|
||||||
|
}
|
||||||
43
gs/game/gcg_ai.go
Normal file
43
gs/game/gcg_ai.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hk4e/pkg/logger"
|
||||||
|
"hk4e/protocol/proto"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GCGAi struct {
|
||||||
|
game *GCGGame // 所在的游戏
|
||||||
|
controllerId uint32 // 操控者Id
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReceiveGCGMessagePackNotify 接收GCG消息包通知
|
||||||
|
func (g *GCGAi) ReceiveGCGMessagePackNotify(notify *proto.GCGMessagePackNotify) {
|
||||||
|
// 获取玩家的操控者对象
|
||||||
|
gameController := g.game.controllerMap[g.controllerId]
|
||||||
|
if gameController == nil {
|
||||||
|
logger.Error("ai 角色 nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pack := range notify.MsgPackList {
|
||||||
|
for _, message := range pack.MsgList {
|
||||||
|
switch message.Message.(type) {
|
||||||
|
case *proto.GCGMessage_PhaseChange:
|
||||||
|
// 阶段改变
|
||||||
|
msg := message.GetPhaseChange()
|
||||||
|
switch msg.AfterPhase {
|
||||||
|
case proto.GCGPhaseType_GCG_PHASE_TYPE_ON_STAGE:
|
||||||
|
logger.Error("请选择你的英雄 hhh")
|
||||||
|
go func() {
|
||||||
|
time.Sleep(1000 * 3)
|
||||||
|
// 默认选第一张牌
|
||||||
|
cardInfo := gameController.cardList[0]
|
||||||
|
// 操控者选择角色牌
|
||||||
|
g.game.ControllerSelectChar(gameController, cardInfo, []uint32{})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"hk4e/gdconf"
|
||||||
"hk4e/gs/model"
|
"hk4e/gs/model"
|
||||||
"hk4e/pkg/logger"
|
"hk4e/pkg/logger"
|
||||||
|
"hk4e/pkg/random"
|
||||||
|
"hk4e/protocol/cmd"
|
||||||
"hk4e/protocol/proto"
|
"hk4e/protocol/proto"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ControllerType 操控者类型
|
// ControllerType 操控者类型
|
||||||
type ControllerType uint8
|
type ControllerType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ControllerType_Player ControllerType = iota // 玩家
|
ControllerType_None ControllerType = iota
|
||||||
ControllerType_AI // AI
|
ControllerType_Player // 玩家
|
||||||
|
ControllerType_AI // AI
|
||||||
)
|
)
|
||||||
|
|
||||||
// GCGCardInfo 游戏对局内卡牌
|
// GCGCardInfo 游戏对局内卡牌
|
||||||
@@ -36,12 +42,24 @@ const (
|
|||||||
|
|
||||||
// GCGController 操控者
|
// GCGController 操控者
|
||||||
type GCGController struct {
|
type GCGController struct {
|
||||||
controllerId uint32 // 操控者Id
|
controllerId uint32 // 操控者Id
|
||||||
cardMap map[uint32]*GCGCardInfo // 卡牌列表
|
cardList []*GCGCardInfo // 卡牌列表
|
||||||
loadState ControllerLoadState // 加载状态
|
loadState ControllerLoadState // 加载状态
|
||||||
controllerType ControllerType // 操控者的类型
|
allow uint32 // 是否允许操控 0 -> 不允许 1 -> 允许
|
||||||
player *model.Player
|
selectedCharCard *GCGCardInfo // 选择的角色卡牌
|
||||||
ai uint32 // 暂时不写
|
controllerType ControllerType // 操控者的类型
|
||||||
|
player *model.Player // 玩家对象
|
||||||
|
ai *GCGAi // AI对象
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCardByGuid 通过卡牌的Guid获取卡牌
|
||||||
|
func (g *GCGController) GetCardByGuid(cardGuid uint32) *GCGCardInfo {
|
||||||
|
for _, info := range g.cardList {
|
||||||
|
if info.guid == cardGuid {
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCGManager 七圣召唤管理器
|
// GCGManager 七圣召唤管理器
|
||||||
@@ -63,14 +81,14 @@ func (g *GCGManager) CreateGame(gameId uint32, playerList []*model.Player) *GCGG
|
|||||||
guid: g.gameGuidCounter,
|
guid: g.gameGuidCounter,
|
||||||
gameId: gameId,
|
gameId: gameId,
|
||||||
roundInfo: &GCGRoundInfo{
|
roundInfo: &GCGRoundInfo{
|
||||||
roundNum: 1, // 默认以第一回合开始
|
roundNum: 1, // 默认以第一回合开始
|
||||||
allowControllerMap: make(map[uint32]uint32, 0),
|
firstController: 1, // 1号操控者为先手
|
||||||
firstController: 1, // 1号操控者为先手
|
diceSideMap: make(map[uint32][]proto.GCGDiceSideType, 2),
|
||||||
},
|
},
|
||||||
controllerMap: make(map[uint32]*GCGController, 0),
|
controllerMap: make(map[uint32]*GCGController, 2),
|
||||||
controllerMsgPackMap: make(map[uint32][]*proto.GCGMessagePack),
|
msgPackList: make([]*proto.GCGMessagePack, 0, 10),
|
||||||
historyCardList: make([]*proto.GCGCard, 0, 0),
|
historyMsgPackList: make([]*proto.GCGMessagePack, 0, 50),
|
||||||
historyMsgPackList: make([]*proto.GCGMessagePack, 0, 0),
|
historyCardList: make([]*GCGCardInfo, 0, 100),
|
||||||
}
|
}
|
||||||
// 初始化游戏
|
// 初始化游戏
|
||||||
game.InitGame(playerList)
|
game.InitGame(playerList)
|
||||||
@@ -79,20 +97,351 @@ func (g *GCGManager) CreateGame(gameId uint32, playerList []*model.Player) *GCGG
|
|||||||
return game
|
return game
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCGMsgPhaseChange GCG消息阶段改变
|
type GCGGameState uint8
|
||||||
func (g *GCGManager) GCGMsgPhaseChange(game *GCGGame, afterPhase proto.GCGPhaseType) *proto.GCGMessage {
|
|
||||||
gcgMsgPhaseChange := &proto.GCGMsgPhaseChange{
|
const (
|
||||||
BeforePhase: game.roundInfo.phaseType,
|
GCGGameState_None GCGGameState = iota
|
||||||
AfterPhase: afterPhase,
|
GCGGameState_Waiting // 等待玩家加载
|
||||||
AllowControllerMap: make([]*proto.Uint32Pair, 0, len(game.controllerMap)),
|
GCGGameState_Running // 游戏运行中
|
||||||
|
GCGGameState_Stoped // 游戏已结束
|
||||||
|
)
|
||||||
|
|
||||||
|
// 阶段对应的处理函数
|
||||||
|
var phaseFuncMap = map[proto.GCGPhaseType]func(game *GCGGame){
|
||||||
|
proto.GCGPhaseType_GCG_PHASE_TYPE_START: PhaseStartReady,
|
||||||
|
proto.GCGPhaseType_GCG_PHASE_TYPE_ON_STAGE: PhaseSelectChar,
|
||||||
|
proto.GCGPhaseType_GCG_PHASE_TYPE_DICE: PhaseRollDice,
|
||||||
|
proto.GCGPhaseType_GCG_PHASE_TYPE_PRE_MAIN: PhasePreMain,
|
||||||
|
}
|
||||||
|
|
||||||
|
// PhaseStartReady 阶段开局准备
|
||||||
|
func PhaseStartReady(game *GCGGame) {
|
||||||
|
// 客户端更新操控者
|
||||||
|
game.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, game.GCGMsgUpdateController())
|
||||||
|
// 分配先手
|
||||||
|
game.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_PHASE_EXIT, game.GCGMsgClientPerform(proto.GCGClientPerformType_GCG_CLIENT_PERFORM_TYPE_FIRST_HAND, []uint32{game.roundInfo.firstController}))
|
||||||
|
// 游戏绘制卡牌阶段 应该
|
||||||
|
game.GameChangePhase(proto.GCGPhaseType_GCG_PHASE_TYPE_DRAW)
|
||||||
|
// 游戏选择角色卡牌阶段
|
||||||
|
game.GameChangePhase(proto.GCGPhaseType_GCG_PHASE_TYPE_ON_STAGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PhaseSelectChar 阶段选择角色卡牌
|
||||||
|
func PhaseSelectChar(game *GCGGame) {
|
||||||
|
// 该阶段确保每位玩家都选择了角色
|
||||||
|
for _, controller := range game.controllerMap {
|
||||||
|
if controller.selectedCharCard == nil {
|
||||||
|
// 如果有没选择角色卡牌的则不执行后面
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 开始阶段所有玩家允许操作
|
// 回合信息
|
||||||
if afterPhase == proto.GCGPhaseType_GCG_PHASE_TYPE_START || afterPhase == proto.GCGPhaseType_GCG_PHASE_TYPE_ON_STAGE || afterPhase == proto.GCGPhaseType_GCG_PHASE_TYPE_MAIN {
|
game.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_SEND_MESSAGE, game.GCGMsgDuelDataChange())
|
||||||
for controllerId := range game.controllerMap {
|
// 游戏投掷骰子阶段
|
||||||
gcgMsgPhaseChange.AllowControllerMap = append(gcgMsgPhaseChange.AllowControllerMap, &proto.Uint32Pair{
|
game.GameChangePhase(proto.GCGPhaseType_GCG_PHASE_TYPE_DICE)
|
||||||
Key: controllerId,
|
}
|
||||||
Value: 1,
|
|
||||||
})
|
// PhaseRollDice 阶段投掷骰子
|
||||||
|
func PhaseRollDice(game *GCGGame) {
|
||||||
|
// 给每位玩家投掷骰子
|
||||||
|
for _, controller := range game.controllerMap {
|
||||||
|
diceSideList := make([]proto.GCGDiceSideType, 0, 8)
|
||||||
|
rand.Seed(time.Now().UnixNano()) // 随机数种子
|
||||||
|
// 玩家需要8个骰子
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
diceSide := proto.GCGDiceSideType(random.GetRandomInt32(1, 8))
|
||||||
|
diceSideList = append(diceSideList, diceSide)
|
||||||
|
}
|
||||||
|
// 存储该回合玩家的骰子
|
||||||
|
game.roundInfo.diceSideMap[controller.controllerId] = diceSideList
|
||||||
|
game.AddMsgPack(controller.controllerId, proto.GCGActionType_GCG_ACTION_TYPE_ROLL, game.GCGMsgDiceRoll(controller.controllerId, uint32(len(diceSideList)), diceSideList))
|
||||||
|
}
|
||||||
|
game.GameChangePhase(proto.GCGPhaseType_GCG_PHASE_TYPE_REROLL)
|
||||||
|
// g.controllerMap[1].allow = 1
|
||||||
|
// g.controllerMap[2].allow = 0
|
||||||
|
// msgPackInfo := g.CreateMsgPackInfo()
|
||||||
|
// msgPackInfo.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, g.GCGMsgPVEIntention(&proto.GCGMsgPVEIntention{CardGuid: g.controllerMap[2].cardList[0].guid, SkillIdList: []uint32{g.controllerMap[2].cardList[0].skillIdList[1]}}, &proto.GCGMsgPVEIntention{CardGuid: g.controllerMap[2].cardList[1].guid, SkillIdList: []uint32{g.controllerMap[2].cardList[1].skillIdList[0]}}))
|
||||||
|
// g.BroadcastMsgPackInfo(msgPackInfo, false)
|
||||||
|
// msgPackInfo1 := g.CreateMsgPackInfo()
|
||||||
|
// msgPackInfo1.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, g.GCGMsgUpdateController())
|
||||||
|
// msgPackInfo1.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_SEND_MESSAGE, g.GCGMsgPhaseContinue())
|
||||||
|
// g.BroadcastMsgPackInfo(msgPackInfo1, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PhasePreMain 阶段战斗开始
|
||||||
|
func PhasePreMain(game *GCGGame) {
|
||||||
|
game.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_TRIGGER_SKILL, game.GCGMsgUseSkill(195, 33024), game.GCGMsgUseSkillEnd(195, 33024))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCGRoundInfo 游戏对局回合信息
|
||||||
|
type GCGRoundInfo struct {
|
||||||
|
roundNum uint32 // 游戏当前回合数
|
||||||
|
phaseType proto.GCGPhaseType // 现在所处的阶段类型
|
||||||
|
firstController uint32 // 当前回合先手的操控者
|
||||||
|
diceSideMap map[uint32][]proto.GCGDiceSideType // 操控者骰子列表 uint32 -> controllerId
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCGGame 游戏对局
|
||||||
|
type GCGGame struct {
|
||||||
|
guid uint32 // 唯一Id
|
||||||
|
gameId uint32 // 游戏Id
|
||||||
|
gameState GCGGameState // 游戏运行状态
|
||||||
|
gameTick uint32 // 游戏tick
|
||||||
|
serverSeqCounter uint32 // 请求序列生成计数器
|
||||||
|
controllerIdCounter uint32 // 操控者Id生成器
|
||||||
|
cardGuidCounter uint32 // 卡牌guid生成计数器
|
||||||
|
roundInfo *GCGRoundInfo // 游戏回合信息
|
||||||
|
controllerMap map[uint32]*GCGController // 操控者列表 uint32 -> controllerId
|
||||||
|
msgPackList []*proto.GCGMessagePack // 消息包待发送区
|
||||||
|
historyMsgPackList []*proto.GCGMessagePack // 历史消息包列表
|
||||||
|
historyCardList []*GCGCardInfo // 历史卡牌列表
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPlayer GCG游戏添加玩家
|
||||||
|
func (g *GCGGame) AddPlayer(player *model.Player) {
|
||||||
|
// 创建操控者
|
||||||
|
g.controllerIdCounter++
|
||||||
|
controller := &GCGController{
|
||||||
|
controllerId: g.controllerIdCounter,
|
||||||
|
cardList: make([]*GCGCardInfo, 0, 50),
|
||||||
|
loadState: ControllerLoadState_None,
|
||||||
|
controllerType: ControllerType_Player,
|
||||||
|
player: player,
|
||||||
|
}
|
||||||
|
// 生成卡牌信息
|
||||||
|
g.GiveCharCard(controller, 1301)
|
||||||
|
g.GiveCharCard(controller, 1103)
|
||||||
|
// 记录操控者
|
||||||
|
g.controllerMap[g.controllerIdCounter] = controller
|
||||||
|
player.GCGCurGameGuid = g.guid
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAI GCG游戏添加AI
|
||||||
|
func (g *GCGGame) AddAI() {
|
||||||
|
// 创建操控者
|
||||||
|
g.controllerIdCounter++
|
||||||
|
controller := &GCGController{
|
||||||
|
controllerId: g.controllerIdCounter,
|
||||||
|
cardList: make([]*GCGCardInfo, 0, 50),
|
||||||
|
loadState: ControllerLoadState_InitFinish,
|
||||||
|
controllerType: ControllerType_AI,
|
||||||
|
ai: &GCGAi{
|
||||||
|
game: g,
|
||||||
|
controllerId: g.controllerIdCounter,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// 生成卡牌信息
|
||||||
|
g.GiveCharCard(controller, 3001)
|
||||||
|
g.GiveCharCard(controller, 3302)
|
||||||
|
// 记录操控者
|
||||||
|
g.controllerMap[g.controllerIdCounter] = controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// GameChangePhase 游戏更改阶段
|
||||||
|
func (g *GCGGame) GameChangePhase(phase proto.GCGPhaseType) {
|
||||||
|
beforePhase := g.roundInfo.phaseType
|
||||||
|
// 修改游戏的阶段
|
||||||
|
g.roundInfo.phaseType = phase
|
||||||
|
switch phase {
|
||||||
|
case proto.GCGPhaseType_GCG_PHASE_TYPE_ON_STAGE, proto.GCGPhaseType_GCG_PHASE_TYPE_DICE:
|
||||||
|
// 该阶段允许所有玩家行动
|
||||||
|
for _, controller := range g.controllerMap {
|
||||||
|
controller.allow = 1
|
||||||
|
}
|
||||||
|
case proto.GCGPhaseType_GCG_PHASE_TYPE_PRE_MAIN:
|
||||||
|
// 该阶段不允许所有玩家行动
|
||||||
|
for _, controller := range g.controllerMap {
|
||||||
|
controller.allow = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NEXT_PHASE, g.GCGMsgPhaseChange(beforePhase, phase))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GiveCharCard 给予操控者角色卡牌
|
||||||
|
func (g *GCGGame) GiveCharCard(controller *GCGController, charId uint32) {
|
||||||
|
// 读取角色卡牌配置表
|
||||||
|
gcgCharConfig, ok := gdconf.CONF.GCGCharDataMap[int32(charId)]
|
||||||
|
if !ok {
|
||||||
|
logger.Error("gcg char config error, charId: %v", charId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 生成卡牌信息
|
||||||
|
g.cardGuidCounter++
|
||||||
|
controller.cardList = append(controller.cardList, &GCGCardInfo{
|
||||||
|
cardId: charId,
|
||||||
|
guid: g.cardGuidCounter,
|
||||||
|
faceType: 0, // 1为金卡
|
||||||
|
tagList: gcgCharConfig.TagList,
|
||||||
|
tokenMap: map[uint32]uint32{
|
||||||
|
1: uint32(gcgCharConfig.HPBase), // 血量
|
||||||
|
2: uint32(gcgCharConfig.HPBase), // 最大血量(不确定)
|
||||||
|
4: 0, // 充能
|
||||||
|
5: uint32(gcgCharConfig.MaxElemVal), // 充能条
|
||||||
|
},
|
||||||
|
skillIdList: gcgCharConfig.SkillList,
|
||||||
|
skillLimitList: []uint32{},
|
||||||
|
isShow: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControllerSelectChar 操控者选择角色卡牌
|
||||||
|
func (g *GCGGame) ControllerSelectChar(controller *GCGController, cardInfo *GCGCardInfo, costDiceIndexList []uint32) {
|
||||||
|
// 判断选择角色卡牌消耗的点数是否正确
|
||||||
|
if controller.selectedCharCard != nil && len(costDiceIndexList) == 0 {
|
||||||
|
// 首次选择角色牌不消耗点数
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO 消耗骰子点数
|
||||||
|
// 设置角色卡牌
|
||||||
|
controller.selectedCharCard = cardInfo
|
||||||
|
// 设置操控者禁止操作
|
||||||
|
controller.allow = 0
|
||||||
|
// 广播选择的角色卡牌消息包
|
||||||
|
g.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, g.GCGMsgUpdateController())
|
||||||
|
g.AddMsgPack(controller.controllerId, proto.GCGActionType_GCG_ACTION_TYPE_SELECT_ONSTAGE, g.GCGMsgSelectOnStage(controller.controllerId, cardInfo.guid, proto.GCGReason_GCG_REASON_DEFAULT))
|
||||||
|
}
|
||||||
|
|
||||||
|
// onTick 游戏的Tick
|
||||||
|
func (g *GCGGame) onTick() {
|
||||||
|
// 判断游戏是否运行中
|
||||||
|
if g.gameState != GCGGameState_Running {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 每10s触发
|
||||||
|
if g.gameTick%10 == 0 {
|
||||||
|
// GCG游戏心跳包
|
||||||
|
for _, controller := range g.controllerMap {
|
||||||
|
// 跳过AI
|
||||||
|
if controller.player == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
gcgHeartBeatNotify := &proto.GCGHeartBeatNotify{
|
||||||
|
ServerSeq: g.serverSeqCounter,
|
||||||
|
}
|
||||||
|
GAME_MANAGER.SendMsg(cmd.GCGHeartBeatNotify, controller.player.PlayerID, controller.player.ClientSeq, gcgHeartBeatNotify)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 仅在游戏处于运行状态时执行阶段处理
|
||||||
|
if g.gameState == GCGGameState_Running {
|
||||||
|
phaseFunc, ok := phaseFuncMap[g.roundInfo.phaseType]
|
||||||
|
// 确保该阶段有进行处理的函数
|
||||||
|
if ok {
|
||||||
|
phaseFunc(g) // 进行该阶段的处理
|
||||||
|
// 发送阶段处理后的消息包
|
||||||
|
g.SendAllMsgPack(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.gameTick++
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitGame 初始化GCG游戏
|
||||||
|
func (g *GCGGame) InitGame(playerList []*model.Player) {
|
||||||
|
// 初始化玩家
|
||||||
|
for _, player := range playerList {
|
||||||
|
g.AddPlayer(player)
|
||||||
|
}
|
||||||
|
// 添加AI
|
||||||
|
g.AddAI()
|
||||||
|
|
||||||
|
// // 先手允许操作
|
||||||
|
// controller, ok := g.controllerMap[g.roundInfo.firstController]
|
||||||
|
// if !ok {
|
||||||
|
// logger.Error("controller is nil, controllerId: %v", g.roundInfo.firstController)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// controller.allow = 1
|
||||||
|
|
||||||
|
// TODO 验证玩家人数是否符合
|
||||||
|
// 预开始游戏
|
||||||
|
g.GameChangePhase(proto.GCGPhaseType_GCG_PHASE_TYPE_START)
|
||||||
|
g.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, g.GCGMsgUpdateController())
|
||||||
|
g.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_SEND_MESSAGE, g.GCGMsgPhaseContinue())
|
||||||
|
g.SendAllMsgPack(true)
|
||||||
|
|
||||||
|
// 游戏状态更改为等待玩家加载
|
||||||
|
g.gameState = GCGGameState_Waiting
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartGame 开始GCG游戏
|
||||||
|
func (g *GCGGame) StartGame() {
|
||||||
|
// 游戏开始设置所有玩家不允许操作
|
||||||
|
// for _, c := range g.controllerMap {
|
||||||
|
// c.allow = 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 游戏状态更改为游戏运行中
|
||||||
|
g.gameState = GCGGameState_Running
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckAllInitFinish 检查所有玩家是否加载完成
|
||||||
|
func (g *GCGGame) CheckAllInitFinish() {
|
||||||
|
// 判断游戏是否已开始
|
||||||
|
if g.gameState == GCGGameState_Running {
|
||||||
|
logger.Error("gcg game is running")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 检查所有玩家是否加载完成
|
||||||
|
for _, controller := range g.controllerMap {
|
||||||
|
if controller.loadState != ControllerLoadState_InitFinish {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO 可能会玩家中途退了 超时结束游戏
|
||||||
|
// 正式开始游戏
|
||||||
|
g.StartGame()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMsgPack 添加GCG消息包至待发送区
|
||||||
|
func (g *GCGGame) AddMsgPack(controllerId uint32, actionType proto.GCGActionType, msgList ...*proto.GCGMessage) {
|
||||||
|
pack := &proto.GCGMessagePack{
|
||||||
|
ActionType: actionType,
|
||||||
|
MsgList: make([]*proto.GCGMessage, 0, len(msgList)),
|
||||||
|
ControllerId: controllerId,
|
||||||
|
}
|
||||||
|
// 将每个GCG消息添加进消息包中
|
||||||
|
for _, message := range msgList {
|
||||||
|
pack.MsgList = append(pack.MsgList, message)
|
||||||
|
}
|
||||||
|
// 将消息包添加进待发送区
|
||||||
|
g.msgPackList = append(g.msgPackList, pack)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendAllMsgPack 发送所有待发送区的消息包
|
||||||
|
func (g *GCGGame) SendAllMsgPack(recordOnly bool) {
|
||||||
|
// 不发送空的消息包
|
||||||
|
if len(g.msgPackList) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 是否仅记录历史消息包
|
||||||
|
if !recordOnly {
|
||||||
|
g.serverSeqCounter++
|
||||||
|
for _, controller := range g.controllerMap {
|
||||||
|
GAME_MANAGER.SendGCGMessagePackNotify(controller, g.serverSeqCounter, g.msgPackList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 记录发送的历史消息包
|
||||||
|
for _, pack := range g.msgPackList {
|
||||||
|
g.historyMsgPackList = append(g.historyMsgPackList, pack)
|
||||||
|
}
|
||||||
|
// 清空待发送区消息包
|
||||||
|
g.msgPackList = make([]*proto.GCGMessagePack, 0, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCGMsgPhaseChange GCG消息阶段改变
|
||||||
|
func (g *GCGGame) GCGMsgPhaseChange(beforePhase proto.GCGPhaseType, afterPhase proto.GCGPhaseType) *proto.GCGMessage {
|
||||||
|
gcgMsgPhaseChange := &proto.GCGMsgPhaseChange{
|
||||||
|
BeforePhase: beforePhase,
|
||||||
|
AfterPhase: afterPhase,
|
||||||
|
AllowControllerMap: make([]*proto.Uint32Pair, 0, len(g.controllerMap)),
|
||||||
|
}
|
||||||
|
if gcgMsgPhaseChange.AfterPhase != proto.GCGPhaseType_GCG_PHASE_TYPE_DRAW && gcgMsgPhaseChange.AfterPhase != proto.GCGPhaseType_GCG_PHASE_TYPE_PRE_MAIN {
|
||||||
|
// 操控者的是否允许操作
|
||||||
|
for _, controller := range g.controllerMap {
|
||||||
|
pair := &proto.Uint32Pair{
|
||||||
|
Key: controller.controllerId,
|
||||||
|
Value: controller.allow,
|
||||||
|
}
|
||||||
|
gcgMsgPhaseChange.AllowControllerMap = append(gcgMsgPhaseChange.AllowControllerMap, pair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gcgMessage := &proto.GCGMessage{
|
gcgMessage := &proto.GCGMessage{
|
||||||
@@ -100,13 +449,11 @@ func (g *GCGManager) GCGMsgPhaseChange(game *GCGGame, afterPhase proto.GCGPhaseT
|
|||||||
PhaseChange: gcgMsgPhaseChange,
|
PhaseChange: gcgMsgPhaseChange,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// 修改游戏的阶段状态
|
|
||||||
game.roundInfo.phaseType = afterPhase
|
|
||||||
return gcgMessage
|
return gcgMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCGMsgPhaseContinue GCG消息阶段跳过
|
// GCGMsgPhaseContinue GCG消息阶段跳过
|
||||||
func (g *GCGManager) GCGMsgPhaseContinue() *proto.GCGMessage {
|
func (g *GCGGame) GCGMsgPhaseContinue() *proto.GCGMessage {
|
||||||
gcgMsgPhaseContinue := &proto.GCGMsgPhaseContinue{}
|
gcgMsgPhaseContinue := &proto.GCGMsgPhaseContinue{}
|
||||||
gcgMessage := &proto.GCGMessage{
|
gcgMessage := &proto.GCGMessage{
|
||||||
Message: &proto.GCGMessage_PhaseContinue{
|
Message: &proto.GCGMessage_PhaseContinue{
|
||||||
@@ -117,16 +464,17 @@ func (g *GCGManager) GCGMsgPhaseContinue() *proto.GCGMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GCGMsgUpdateController GCG消息更新操控者
|
// GCGMsgUpdateController GCG消息更新操控者
|
||||||
func (g *GCGManager) GCGMsgUpdateController(game *GCGGame) *proto.GCGMessage {
|
func (g *GCGGame) GCGMsgUpdateController() *proto.GCGMessage {
|
||||||
gcgMsgUpdateController := &proto.GCGMsgUpdateController{
|
gcgMsgUpdateController := &proto.GCGMsgUpdateController{
|
||||||
AllowControllerMap: make([]*proto.Uint32Pair, 0, len(game.controllerMap)),
|
AllowControllerMap: make([]*proto.Uint32Pair, 0, len(g.controllerMap)),
|
||||||
}
|
}
|
||||||
// 操控者的允许次数
|
// 操控者的是否允许操作
|
||||||
for controllerId, _ := range game.roundInfo.allowControllerMap {
|
for _, controller := range g.controllerMap {
|
||||||
gcgMsgUpdateController.AllowControllerMap = append(gcgMsgUpdateController.AllowControllerMap, &proto.Uint32Pair{
|
pair := &proto.Uint32Pair{
|
||||||
Key: controllerId,
|
Key: controller.controllerId,
|
||||||
Value: 0,
|
Value: controller.allow,
|
||||||
})
|
}
|
||||||
|
gcgMsgUpdateController.AllowControllerMap = append(gcgMsgUpdateController.AllowControllerMap, pair)
|
||||||
}
|
}
|
||||||
gcgMessage := &proto.GCGMessage{
|
gcgMessage := &proto.GCGMessage{
|
||||||
Message: &proto.GCGMessage_UpdateController{
|
Message: &proto.GCGMessage_UpdateController{
|
||||||
@@ -137,7 +485,7 @@ func (g *GCGManager) GCGMsgUpdateController(game *GCGGame) *proto.GCGMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GCGMsgClientPerform GCG消息客户端执行
|
// GCGMsgClientPerform GCG消息客户端执行
|
||||||
func (g *GCGManager) GCGMsgClientPerform(performType proto.GCGClientPerformType, paramList []uint32) *proto.GCGMessage {
|
func (g *GCGGame) GCGMsgClientPerform(performType proto.GCGClientPerformType, paramList []uint32) *proto.GCGMessage {
|
||||||
gcgMsgClientPerform := &proto.GCGMsgClientPerform{
|
gcgMsgClientPerform := &proto.GCGMsgClientPerform{
|
||||||
ParamList: paramList,
|
ParamList: paramList,
|
||||||
PerformType: performType,
|
PerformType: performType,
|
||||||
@@ -150,278 +498,92 @@ func (g *GCGManager) GCGMsgClientPerform(performType proto.GCGClientPerformType,
|
|||||||
return gcgMessage
|
return gcgMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCGRoundInfo 游戏对局回合信息
|
// GCGMsgSelectOnStage GCG消息切换角色卡牌
|
||||||
type GCGRoundInfo struct {
|
func (g *GCGGame) GCGMsgSelectOnStage(controllerId uint32, cardGuid uint32, reason proto.GCGReason) *proto.GCGMessage {
|
||||||
roundNum uint32 // 游戏当前回合数
|
gcgMsgClientPerform := &proto.GCGMsgSelectOnStage{
|
||||||
phaseType proto.GCGPhaseType // 现在所处的阶段类型
|
Reason: reason,
|
||||||
allowControllerMap map[uint32]uint32 // 回合内操控者允许的次数
|
|
||||||
firstController uint32 // 当前回合先手的操控者
|
|
||||||
}
|
|
||||||
|
|
||||||
// GCGGame 游戏对局
|
|
||||||
type GCGGame struct {
|
|
||||||
guid uint32 // 唯一Id
|
|
||||||
gameId uint32 // 游戏Id
|
|
||||||
serverSeqCounter uint32 // 请求序列生成计数器
|
|
||||||
controllerIdCounter uint32 // 操控者Id生成器
|
|
||||||
cardGuidCounter uint32 // 卡牌guid生成计数器
|
|
||||||
roundInfo *GCGRoundInfo // 游戏回合信息
|
|
||||||
controllerMap map[uint32]*GCGController // 操控者列表 uint32 -> controllerId
|
|
||||||
controllerMsgPackMap map[uint32][]*proto.GCGMessagePack // 操控者消息包待发送区 0代表全局
|
|
||||||
// TODO 游戏重连
|
|
||||||
historyCardList []*proto.GCGCard // 历史发送的卡牌
|
|
||||||
historyMsgPackList []*proto.GCGMessagePack // 历史发送的消息包
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPlayer GCG游戏添加玩家
|
|
||||||
func (g *GCGGame) AddPlayer(player *model.Player) {
|
|
||||||
// 创建操控者
|
|
||||||
g.controllerIdCounter++
|
|
||||||
controller := &GCGController{
|
|
||||||
controllerId: g.controllerIdCounter,
|
|
||||||
cardMap: make(map[uint32]*GCGCardInfo, 0),
|
|
||||||
loadState: ControllerLoadState_None,
|
|
||||||
controllerType: ControllerType_Player,
|
|
||||||
player: player,
|
|
||||||
}
|
|
||||||
// 生成卡牌信息
|
|
||||||
g.cardGuidCounter++
|
|
||||||
controller.cardMap[1301] = &GCGCardInfo{
|
|
||||||
cardId: 1301,
|
|
||||||
guid: g.cardGuidCounter,
|
|
||||||
faceType: 0,
|
|
||||||
tagList: []uint32{203, 303, 401},
|
|
||||||
tokenMap: map[uint32]uint32{
|
|
||||||
1: 10,
|
|
||||||
2: 10,
|
|
||||||
4: 0,
|
|
||||||
5: 3,
|
|
||||||
},
|
|
||||||
skillIdList: []uint32{
|
|
||||||
13011,
|
|
||||||
13012,
|
|
||||||
13013,
|
|
||||||
},
|
|
||||||
skillLimitList: []uint32{},
|
|
||||||
isShow: true,
|
|
||||||
}
|
|
||||||
g.cardGuidCounter++
|
|
||||||
controller.cardMap[1103] = &GCGCardInfo{
|
|
||||||
cardId: 1103,
|
|
||||||
guid: g.cardGuidCounter,
|
|
||||||
faceType: 0,
|
|
||||||
tagList: []uint32{201, 301, 401},
|
|
||||||
tokenMap: map[uint32]uint32{
|
|
||||||
1: 10, // 血量
|
|
||||||
2: 10, // 最大血量(不确定)
|
|
||||||
4: 0, // 充能
|
|
||||||
5: 2, // 充能条
|
|
||||||
},
|
|
||||||
skillIdList: []uint32{
|
|
||||||
11031,
|
|
||||||
11032,
|
|
||||||
11033,
|
|
||||||
},
|
|
||||||
skillLimitList: []uint32{},
|
|
||||||
isShow: true,
|
|
||||||
}
|
|
||||||
g.cardGuidCounter++
|
|
||||||
controller.cardMap[3001] = &GCGCardInfo{
|
|
||||||
cardId: 3001,
|
|
||||||
guid: g.cardGuidCounter,
|
|
||||||
faceType: 0,
|
|
||||||
tagList: []uint32{200, 300, 502, 503},
|
|
||||||
tokenMap: map[uint32]uint32{
|
|
||||||
1: 4,
|
|
||||||
2: 4,
|
|
||||||
4: 0,
|
|
||||||
5: 2,
|
|
||||||
},
|
|
||||||
skillIdList: []uint32{
|
|
||||||
30011,
|
|
||||||
30012,
|
|
||||||
30013,
|
|
||||||
},
|
|
||||||
skillLimitList: []uint32{},
|
|
||||||
isShow: true,
|
|
||||||
}
|
|
||||||
// g.cardGuidCounter++
|
|
||||||
// controller.cardMap[1301011] = &GCGCardInfo{
|
|
||||||
// cardId: 1301011,
|
|
||||||
// guid: g.cardGuidCounter,
|
|
||||||
// faceType: 0,
|
|
||||||
// skillIdList: []uint32{
|
|
||||||
// 13010111,
|
|
||||||
// },
|
|
||||||
// skillLimitList: []uint32{},
|
|
||||||
// isShow: true,
|
|
||||||
// }
|
|
||||||
// 记录操控者
|
|
||||||
g.controllerMap[g.controllerIdCounter] = controller
|
|
||||||
player.GCGCurGameGuid = g.guid
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAI GCG游戏添加AI
|
|
||||||
func (g *GCGGame) AddAI() {
|
|
||||||
// 创建操控者
|
|
||||||
g.controllerIdCounter++
|
|
||||||
controller := &GCGController{
|
|
||||||
controllerId: g.controllerIdCounter,
|
|
||||||
cardMap: make(map[uint32]*GCGCardInfo, 0),
|
|
||||||
loadState: ControllerLoadState_InitFinish,
|
|
||||||
controllerType: ControllerType_AI,
|
|
||||||
ai: 233,
|
|
||||||
}
|
|
||||||
// 生成卡牌信息
|
|
||||||
g.cardGuidCounter++
|
|
||||||
controller.cardMap[3001] = &GCGCardInfo{
|
|
||||||
cardId: 3001,
|
|
||||||
guid: g.cardGuidCounter,
|
|
||||||
faceType: 0,
|
|
||||||
tagList: []uint32{200, 300, 502, 503},
|
|
||||||
tokenMap: map[uint32]uint32{
|
|
||||||
1: 4,
|
|
||||||
2: 4,
|
|
||||||
4: 0,
|
|
||||||
5: 2,
|
|
||||||
},
|
|
||||||
skillIdList: []uint32{
|
|
||||||
30011,
|
|
||||||
30012,
|
|
||||||
30013,
|
|
||||||
},
|
|
||||||
skillLimitList: []uint32{},
|
|
||||||
isShow: true,
|
|
||||||
}
|
|
||||||
g.cardGuidCounter++
|
|
||||||
controller.cardMap[3302] = &GCGCardInfo{
|
|
||||||
cardId: 3302,
|
|
||||||
guid: g.cardGuidCounter,
|
|
||||||
faceType: 0,
|
|
||||||
tagList: []uint32{200, 303, 502, 503},
|
|
||||||
tokenMap: map[uint32]uint32{
|
|
||||||
1: 8,
|
|
||||||
2: 8,
|
|
||||||
4: 0,
|
|
||||||
5: 2,
|
|
||||||
},
|
|
||||||
skillIdList: []uint32{
|
|
||||||
33021,
|
|
||||||
33022,
|
|
||||||
33023,
|
|
||||||
33024,
|
|
||||||
},
|
|
||||||
skillLimitList: []uint32{},
|
|
||||||
isShow: true,
|
|
||||||
}
|
|
||||||
// 记录操控者
|
|
||||||
g.controllerMap[g.controllerIdCounter] = controller
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitGame 初始化GCG游戏
|
|
||||||
func (g *GCGGame) InitGame(playerList []*model.Player) {
|
|
||||||
// 初始化玩家
|
|
||||||
for _, player := range playerList {
|
|
||||||
g.AddPlayer(player)
|
|
||||||
}
|
|
||||||
// 添加AI
|
|
||||||
g.AddAI()
|
|
||||||
|
|
||||||
// 初始化每个操控者的次数
|
|
||||||
for controllerId := range g.controllerMap {
|
|
||||||
g.roundInfo.allowControllerMap[controllerId] = 0
|
|
||||||
}
|
|
||||||
// 先手者操控数为1
|
|
||||||
g.roundInfo.allowControllerMap[g.roundInfo.firstController] = 1
|
|
||||||
|
|
||||||
// TODO 验证玩家人数是否符合
|
|
||||||
// 预开始游戏
|
|
||||||
g.AddMessagePack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, GCG_MANAGER.GCGMsgPhaseChange(g, proto.GCGPhaseType_GCG_PHASE_TYPE_START), GCG_MANAGER.GCGMsgUpdateController(g))
|
|
||||||
g.AddMessagePack(0, proto.GCGActionType_GCG_ACTION_TYPE_SEND_MESSAGE, GCG_MANAGER.GCGMsgPhaseContinue())
|
|
||||||
g.SendMessagePack(0)
|
|
||||||
// 预开始游戏后 ServerSeq 会跟官服不同 这里重置一下
|
|
||||||
g.serverSeqCounter = 0
|
|
||||||
logger.Error("gcg init")
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartGame 开始GCG游戏
|
|
||||||
func (g *GCGGame) StartGame() {
|
|
||||||
// 开始游戏消息包
|
|
||||||
g.AddMessagePack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, GCG_MANAGER.GCGMsgUpdateController(g))
|
|
||||||
g.AddMessagePack(0, proto.GCGActionType_GCG_ACTION_TYPE_PHASE_EXIT, GCG_MANAGER.GCGMsgClientPerform(proto.GCGClientPerformType_GCG_CLIENT_PERFORM_TYPE_FIRST_HAND, []uint32{g.roundInfo.firstController}))
|
|
||||||
g.AddMessagePack(0, proto.GCGActionType_GCG_ACTION_TYPE_NEXT_PHASE, GCG_MANAGER.GCGMsgPhaseChange(g, proto.GCGPhaseType_GCG_PHASE_TYPE_DRAW))
|
|
||||||
g.AddMessagePack(0, proto.GCGActionType_GCG_ACTION_TYPE_NEXT_PHASE, GCG_MANAGER.GCGMsgPhaseChange(g, proto.GCGPhaseType_GCG_PHASE_TYPE_ON_STAGE))
|
|
||||||
g.SendMessagePack(0)
|
|
||||||
logger.Error("gcg start")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckAllInitFinish 检查所有玩家是否加载完成
|
|
||||||
func (g *GCGGame) CheckAllInitFinish() {
|
|
||||||
// 检查所有玩家是否加载完成
|
|
||||||
for _, controller := range g.controllerMap {
|
|
||||||
if controller.loadState != ControllerLoadState_InitFinish {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO 可能会玩家中途退了 超时结束游戏
|
|
||||||
// 正式开始游戏
|
|
||||||
g.StartGame()
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddMessagePack 添加操控者的待发送区GCG消息
|
|
||||||
func (g *GCGGame) AddMessagePack(controllerId uint32, actionType proto.GCGActionType, msgList ...*proto.GCGMessage) {
|
|
||||||
_, ok := g.controllerMsgPackMap[controllerId]
|
|
||||||
if !ok {
|
|
||||||
g.controllerMsgPackMap[controllerId] = make([]*proto.GCGMessagePack, 0, len(msgList)*5)
|
|
||||||
}
|
|
||||||
pack := &proto.GCGMessagePack{
|
|
||||||
ActionType: actionType,
|
|
||||||
MsgList: make([]*proto.GCGMessage, 0, len(msgList)),
|
|
||||||
ControllerId: controllerId,
|
ControllerId: controllerId,
|
||||||
|
CardGuid: cardGuid,
|
||||||
}
|
}
|
||||||
// 将每个GCG消息添加进消息包中
|
gcgMessage := &proto.GCGMessage{
|
||||||
for _, message := range msgList {
|
Message: &proto.GCGMessage_SelectOnStage{
|
||||||
pack.MsgList = append(pack.MsgList, message)
|
SelectOnStage: gcgMsgClientPerform,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// 将消息包添加进待发送区
|
return gcgMessage
|
||||||
g.controllerMsgPackMap[controllerId] = append(g.controllerMsgPackMap[controllerId], pack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMessagePack 发送操控者的待发送区GCG消息
|
// GCGMsgPVEIntention GCG消息PVE意向
|
||||||
func (g *GCGGame) SendMessagePack(controllerId uint32) {
|
func (g *GCGGame) GCGMsgPVEIntention(pveIntentionList ...*proto.GCGMsgPVEIntention) *proto.GCGMessage {
|
||||||
msgPackList, ok := g.controllerMsgPackMap[controllerId]
|
gcgMsgPVEIntention := &proto.GCGMsgPVEIntentionInfo{
|
||||||
if !ok {
|
IntentionMap: make(map[uint32]*proto.GCGMsgPVEIntention),
|
||||||
logger.Error("msg pack list error, controllerId: %v", controllerId)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// 0代表广播给全体玩家
|
for _, intention := range pveIntentionList {
|
||||||
if controllerId == 0 {
|
gcgMsgPVEIntention.IntentionMap[intention.CardGuid] = intention
|
||||||
g.serverSeqCounter++
|
|
||||||
for _, controller := range g.controllerMap {
|
|
||||||
GAME_MANAGER.SendGCGMessagePackNotify(controller, g.serverSeqCounter, msgPackList)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 获取指定的操控者
|
|
||||||
controller, ok := g.controllerMap[controllerId]
|
|
||||||
if !ok {
|
|
||||||
logger.Error("controller is nil, controllerId: %v", controllerId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
g.serverSeqCounter++
|
|
||||||
GAME_MANAGER.SendGCGMessagePackNotify(controller, g.serverSeqCounter, msgPackList)
|
|
||||||
}
|
}
|
||||||
// 记录发送的历史消息包
|
gcgMessage := &proto.GCGMessage{
|
||||||
for _, pack := range msgPackList {
|
Message: &proto.GCGMessage_PveIntentionInfo{
|
||||||
g.historyMsgPackList = append(g.historyMsgPackList, pack)
|
PveIntentionInfo: gcgMsgPVEIntention,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// 清空待发送区的数据
|
return gcgMessage
|
||||||
g.controllerMsgPackMap[controllerId] = make([]*proto.GCGMessagePack, 0, len(msgPackList))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // CreateGameCardInfo 生成操控者卡牌信息
|
// GCGMsgDuelDataChange GCG消息切换回合
|
||||||
// func (g *GCGManager) CreateGameCardInfo(controller *GCGController, gcgDeck *model.GCGDeck) *GCGCardInfo {
|
func (g *GCGGame) GCGMsgDuelDataChange() *proto.GCGMessage {
|
||||||
//
|
gcgMsgDuelDataChange := &proto.GCGMsgDuelDataChange{
|
||||||
// }
|
Round: g.roundInfo.roundNum,
|
||||||
|
}
|
||||||
|
gcgMessage := &proto.GCGMessage{
|
||||||
|
Message: &proto.GCGMessage_DuelDataChange{
|
||||||
|
DuelDataChange: gcgMsgDuelDataChange,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return gcgMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCGMsgDiceRoll GCG消息摇骰子
|
||||||
|
func (g *GCGGame) GCGMsgDiceRoll(controllerId uint32, diceNum uint32, diceSideList []proto.GCGDiceSideType) *proto.GCGMessage {
|
||||||
|
gcgMsgDiceRoll := &proto.GCGMsgDiceRoll{
|
||||||
|
ControllerId: controllerId,
|
||||||
|
DiceNum: diceNum,
|
||||||
|
DiceSideList: diceSideList,
|
||||||
|
}
|
||||||
|
gcgMessage := &proto.GCGMessage{
|
||||||
|
Message: &proto.GCGMessage_DiceRoll{
|
||||||
|
DiceRoll: gcgMsgDiceRoll,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return gcgMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCGMsgUseSkill GCG消息使用技能
|
||||||
|
func (g *GCGGame) GCGMsgUseSkill(cardGuid uint32, skillId uint32) *proto.GCGMessage {
|
||||||
|
gcgMsgMsgUseSkill := &proto.GCGMsgUseSkill{
|
||||||
|
SkillId: skillId,
|
||||||
|
CardGuid: cardGuid,
|
||||||
|
}
|
||||||
|
gcgMessage := &proto.GCGMessage{
|
||||||
|
Message: &proto.GCGMessage_UseSkill{
|
||||||
|
UseSkill: gcgMsgMsgUseSkill,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return gcgMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCGMsgUseSkillEnd GCG消息使用技能结束
|
||||||
|
func (g *GCGGame) GCGMsgUseSkillEnd(cardGuid uint32, skillId uint32) *proto.GCGMessage {
|
||||||
|
gcgMsgMsgUseSkillEnd := &proto.GCGMsgUseSkillEnd{
|
||||||
|
SkillId: skillId,
|
||||||
|
CardGuid: cardGuid,
|
||||||
|
}
|
||||||
|
gcgMessage := &proto.GCGMessage{
|
||||||
|
Message: &proto.GCGMessage_UseSkillEnd{
|
||||||
|
UseSkillEnd: gcgMsgMsgUseSkillEnd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return gcgMessage
|
||||||
|
}
|
||||||
|
|
||||||
// GetControllerByUserId 通过玩家Id获取GCGController对象
|
// GetControllerByUserId 通过玩家Id获取GCGController对象
|
||||||
func (g *GCGGame) GetControllerByUserId(userId uint32) *GCGController {
|
func (g *GCGGame) GetControllerByUserId(userId uint32) *GCGController {
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ func (r *RouteManager) initRoute() {
|
|||||||
r.registerRouter(cmd.GetOnlinePlayerInfoReq, GAME_MANAGER.GetOnlinePlayerInfoReq)
|
r.registerRouter(cmd.GetOnlinePlayerInfoReq, GAME_MANAGER.GetOnlinePlayerInfoReq)
|
||||||
r.registerRouter(cmd.GCGAskDuelReq, GAME_MANAGER.GCGAskDuelReq)
|
r.registerRouter(cmd.GCGAskDuelReq, GAME_MANAGER.GCGAskDuelReq)
|
||||||
r.registerRouter(cmd.GCGInitFinishReq, GAME_MANAGER.GCGInitFinishReq)
|
r.registerRouter(cmd.GCGInitFinishReq, GAME_MANAGER.GCGInitFinishReq)
|
||||||
|
r.registerRouter(cmd.GCGOperationReq, GAME_MANAGER.GCGOperationReq)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||||
|
|||||||
@@ -363,6 +363,10 @@ func (t *TickManager) onTickSecond(now int64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// GCG游戏Tick
|
||||||
|
for _, game := range GCG_MANAGER.gameMap {
|
||||||
|
game.onTick()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onTick200MilliSecond(now int64) {
|
func (t *TickManager) onTick200MilliSecond(now int64) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package game
|
|||||||
import (
|
import (
|
||||||
"hk4e/common/constant"
|
"hk4e/common/constant"
|
||||||
"hk4e/gs/model"
|
"hk4e/gs/model"
|
||||||
|
"hk4e/pkg/logger"
|
||||||
"hk4e/protocol/cmd"
|
"hk4e/protocol/cmd"
|
||||||
"hk4e/protocol/proto"
|
"hk4e/protocol/proto"
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message)
|
|||||||
// 阶段数据
|
// 阶段数据
|
||||||
Phase: &proto.GCGPhase{
|
Phase: &proto.GCGPhase{
|
||||||
PhaseType: game.roundInfo.phaseType,
|
PhaseType: game.roundInfo.phaseType,
|
||||||
AllowControllerMap: game.roundInfo.allowControllerMap,
|
AllowControllerMap: make(map[uint32]uint32),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,7 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message)
|
|||||||
playerField := &proto.GCGPlayerField{
|
playerField := &proto.GCGPlayerField{
|
||||||
Unk3300_IKJMGAHCFPM: 0,
|
Unk3300_IKJMGAHCFPM: 0,
|
||||||
// 卡牌图片
|
// 卡牌图片
|
||||||
ModifyZoneMap: make(map[uint32]*proto.GCGZone, len(controller.cardMap)),
|
ModifyZoneMap: make(map[uint32]*proto.GCGZone, len(controller.cardList)),
|
||||||
Unk3300_GGHKFFADEAL: 0,
|
Unk3300_GGHKFFADEAL: 0,
|
||||||
Unk3300_AOPJIOHMPOF: &proto.GCGZone{
|
Unk3300_AOPJIOHMPOF: &proto.GCGZone{
|
||||||
CardList: []uint32{},
|
CardList: []uint32{},
|
||||||
@@ -196,7 +197,7 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message)
|
|||||||
ControllerId: controller.controllerId,
|
ControllerId: controller.controllerId,
|
||||||
// 卡牌位置
|
// 卡牌位置
|
||||||
Unk3300_INDJNJJJNKL: &proto.GCGZone{
|
Unk3300_INDJNJJJNKL: &proto.GCGZone{
|
||||||
CardList: make([]uint32, 0, len(controller.cardMap)),
|
CardList: make([]uint32, 0, len(controller.cardList)),
|
||||||
},
|
},
|
||||||
Unk3300_EFNAEFBECHD: &proto.GCGZone{
|
Unk3300_EFNAEFBECHD: &proto.GCGZone{
|
||||||
CardList: []uint32{},
|
CardList: []uint32{},
|
||||||
@@ -208,7 +209,7 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message)
|
|||||||
Unk3300_GLNIFLOKBPM: 0,
|
Unk3300_GLNIFLOKBPM: 0,
|
||||||
}
|
}
|
||||||
// 卡牌信息
|
// 卡牌信息
|
||||||
for _, info := range controller.cardMap {
|
for _, info := range controller.cardList {
|
||||||
gcgCard := &proto.GCGCard{
|
gcgCard := &proto.GCGCard{
|
||||||
TagList: info.tagList,
|
TagList: info.tagList,
|
||||||
Guid: info.guid,
|
Guid: info.guid,
|
||||||
@@ -239,6 +240,8 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message)
|
|||||||
// Field
|
// Field
|
||||||
playerField.ModifyZoneMap[info.guid] = &proto.GCGZone{CardList: []uint32{}}
|
playerField.ModifyZoneMap[info.guid] = &proto.GCGZone{CardList: []uint32{}}
|
||||||
playerField.Unk3300_INDJNJJJNKL.CardList = append(playerField.Unk3300_INDJNJJJNKL.CardList, info.guid)
|
playerField.Unk3300_INDJNJJJNKL.CardList = append(playerField.Unk3300_INDJNJJJNKL.CardList, info.guid)
|
||||||
|
// Phase
|
||||||
|
gcgAskDuelRsp.Duel.Phase.AllowControllerMap[controller.controllerId] = controller.allow
|
||||||
}
|
}
|
||||||
// 添加完所有卡牌的位置之类的信息 添加这个牌盒
|
// 添加完所有卡牌的位置之类的信息 添加这个牌盒
|
||||||
gcgAskDuelRsp.Duel.FieldList = append(gcgAskDuelRsp.Duel.FieldList, playerField)
|
gcgAskDuelRsp.Duel.FieldList = append(gcgAskDuelRsp.Duel.FieldList, playerField)
|
||||||
@@ -276,12 +279,68 @@ func (g *GameManager) GCGInitFinishReq(player *model.Player, payloadMsg pb.Messa
|
|||||||
game.CheckAllInitFinish()
|
game.CheckAllInitFinish()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendGCGMessagePackNotify 发送GCG消息包通知
|
// GCGOperationReq GCG游戏客户端操作请求
|
||||||
func (g *GameManager) SendGCGMessagePackNotify(controller *GCGController, serverSeq uint32, msgPackList []*proto.GCGMessagePack) {
|
func (g *GameManager) GCGOperationReq(player *model.Player, payloadMsg pb.Message) {
|
||||||
// 确保为玩家
|
req := payloadMsg.(*proto.GCGOperationReq)
|
||||||
if controller.player == nil {
|
|
||||||
|
// 获取玩家所在的游戏
|
||||||
|
game, ok := GCG_MANAGER.gameMap[player.GCGCurGameGuid]
|
||||||
|
if !ok {
|
||||||
|
g.CommonRetError(cmd.GCGOperationRsp, player, &proto.GCGOperationRsp{}, proto.Retcode_RET_GCG_GAME_NOT_RUNNING)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 获取玩家的操控者对象
|
||||||
|
gameController := game.GetControllerByUserId(player.PlayerID)
|
||||||
|
if gameController == nil {
|
||||||
|
g.CommonRetError(cmd.GCGOperationRsp, player, &proto.GCGOperationRsp{}, proto.Retcode_RET_GCG_NOT_IN_GCG_DUNGEON)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch req.Op.Op.(type) {
|
||||||
|
case *proto.GCGOperation_OpSelectOnStage:
|
||||||
|
// 选择角色卡牌
|
||||||
|
op := req.Op.GetOpSelectOnStage()
|
||||||
|
// 操作者是否拥有该卡牌
|
||||||
|
cardInfo := gameController.GetCardByGuid(op.CardGuid)
|
||||||
|
if cardInfo == nil {
|
||||||
|
GAME_MANAGER.CommonRetError(cmd.GCGOperationRsp, player, &proto.GCGOperationRsp{}, proto.Retcode_RET_GCG_SELECT_HAND_CARD_GUID_ERROR)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 操控者选择角色牌
|
||||||
|
game.ControllerSelectChar(gameController, cardInfo, op.CostDiceIndexList)
|
||||||
|
case *proto.GCGOperation_OpReroll:
|
||||||
|
// 确认骰子不重投
|
||||||
|
op := req.Op.GetOpReroll()
|
||||||
|
diceSideList, ok := game.roundInfo.diceSideMap[gameController.controllerId]
|
||||||
|
if !ok {
|
||||||
|
g.CommonRetError(cmd.GCGOperationRsp, player, &proto.GCGOperationRsp{}, proto.Retcode_RET_GCG_DICE_INDEX_INVALID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 判断骰子索引是否有效
|
||||||
|
for _, diceIndex := range op.DiceIndexList {
|
||||||
|
if diceIndex > uint32(len(diceSideList)) {
|
||||||
|
g.CommonRetError(cmd.GCGOperationRsp, player, &proto.GCGOperationRsp{}, proto.Retcode_RET_GCG_DICE_INDEX_INVALID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 客户端更新操控者
|
||||||
|
game.AddMsgPack(0, proto.GCGActionType_GCG_ACTION_TYPE_NONE, game.GCGMsgUpdateController())
|
||||||
|
// 游戏行动阶段
|
||||||
|
game.GameChangePhase(proto.GCGPhaseType_GCG_PHASE_TYPE_PRE_MAIN)
|
||||||
|
default:
|
||||||
|
logger.Error("gcg op is not handle, op: %T", req.Op.Op)
|
||||||
|
g.CommonRetError(cmd.GCGOperationRsp, player, &proto.GCGOperationRsp{}, proto.Retcode_RET_GCG_OPERATION_PARAM_ERROR)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// PacketGCGOperationRsp
|
||||||
|
gcgOperationRsp := &proto.GCGOperationRsp{
|
||||||
|
OpSeq: req.OpSeq,
|
||||||
|
}
|
||||||
|
GAME_MANAGER.SendMsg(cmd.GCGOperationRsp, player.PlayerID, player.ClientSeq, gcgOperationRsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) SendGCGMessagePackNotify(controller *GCGController, serverSeq uint32, msgPackList []*proto.GCGMessagePack) {
|
||||||
// 确保加载完成
|
// 确保加载完成
|
||||||
if controller.loadState != ControllerLoadState_InitFinish {
|
if controller.loadState != ControllerLoadState_InitFinish {
|
||||||
return
|
return
|
||||||
@@ -291,7 +350,16 @@ func (g *GameManager) SendGCGMessagePackNotify(controller *GCGController, server
|
|||||||
ServerSeq: serverSeq,
|
ServerSeq: serverSeq,
|
||||||
MsgPackList: msgPackList,
|
MsgPackList: msgPackList,
|
||||||
}
|
}
|
||||||
GAME_MANAGER.SendMsg(cmd.GCGMessagePackNotify, controller.player.PlayerID, controller.player.ClientSeq, gcgMessagePackNotify)
|
// 根据操控者的类型发送消息包
|
||||||
|
switch controller.controllerType {
|
||||||
|
case ControllerType_Player:
|
||||||
|
GAME_MANAGER.SendMsg(cmd.GCGMessagePackNotify, controller.player.PlayerID, controller.player.ClientSeq, gcgMessagePackNotify)
|
||||||
|
case ControllerType_AI:
|
||||||
|
controller.ai.ReceiveGCGMessagePackNotify(gcgMessagePackNotify)
|
||||||
|
default:
|
||||||
|
logger.Error("controller type error, %v", controller.controllerType)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PacketGCGGameBriefDataNotify GCG游戏简要数据通知
|
// PacketGCGGameBriefDataNotify GCG游戏简要数据通知
|
||||||
@@ -309,7 +377,7 @@ func (g *GameManager) PacketGCGGameBriefDataNotify(player *model.Player, busines
|
|||||||
gcgPlayerBriefData := &proto.GCGPlayerBriefData{
|
gcgPlayerBriefData := &proto.GCGPlayerBriefData{
|
||||||
ControllerId: controller.controllerId,
|
ControllerId: controller.controllerId,
|
||||||
ProfilePicture: new(proto.ProfilePicture),
|
ProfilePicture: new(proto.ProfilePicture),
|
||||||
CardIdList: make([]uint32, 0, len(controller.cardMap)),
|
CardIdList: make([]uint32, 0, len(controller.cardList)),
|
||||||
}
|
}
|
||||||
// 玩家信息
|
// 玩家信息
|
||||||
if controller.player != nil {
|
if controller.player != nil {
|
||||||
|
|||||||
@@ -260,11 +260,14 @@ func (c *CmdProtoMap) registerAllMessage() {
|
|||||||
c.registerMessage(GCGTCTavernInfoNotify, &proto.GCGTCTavernInfoNotify{}) // GCG酒馆信息通知
|
c.registerMessage(GCGTCTavernInfoNotify, &proto.GCGTCTavernInfoNotify{}) // GCG酒馆信息通知
|
||||||
c.registerMessage(GCGTavernNpcInfoNotify, &proto.GCGTavernNpcInfoNotify{}) // GCG酒馆NPC信息通知
|
c.registerMessage(GCGTavernNpcInfoNotify, &proto.GCGTavernNpcInfoNotify{}) // GCG酒馆NPC信息通知
|
||||||
c.registerMessage(GCGGameBriefDataNotify, &proto.GCGGameBriefDataNotify{}) // GCG游戏简要数据通知
|
c.registerMessage(GCGGameBriefDataNotify, &proto.GCGGameBriefDataNotify{}) // GCG游戏简要数据通知
|
||||||
c.registerMessage(GCGAskDuelReq, &proto.GCGAskDuelReq{}) // GCG决斗请求
|
c.registerMessage(GCGAskDuelReq, &proto.GCGAskDuelReq{}) // GCG游戏对局信息请求
|
||||||
c.registerMessage(GCGAskDuelRsp, &proto.GCGAskDuelRsp{}) // GCG决斗响应
|
c.registerMessage(GCGAskDuelRsp, &proto.GCGAskDuelRsp{}) // GCG游戏对局信息响应
|
||||||
c.registerMessage(GCGInitFinishReq, &proto.GCGInitFinishReq{}) // GCG初始化完成请求
|
c.registerMessage(GCGInitFinishReq, &proto.GCGInitFinishReq{}) // GCG游戏初始化完成请求
|
||||||
c.registerMessage(GCGInitFinishRsp, &proto.GCGInitFinishRsp{}) // GCG初始化完成响应
|
c.registerMessage(GCGInitFinishRsp, &proto.GCGInitFinishRsp{}) // GCG游戏初始化完成响应
|
||||||
c.registerMessage(GCGMessagePackNotify, &proto.GCGMessagePackNotify{}) // GCG消息包通知
|
c.registerMessage(GCGMessagePackNotify, &proto.GCGMessagePackNotify{}) // GCG游戏消息包通知
|
||||||
|
c.registerMessage(GCGHeartBeatNotify, &proto.GCGHeartBeatNotify{}) // GCG游戏心跳包通知
|
||||||
|
c.registerMessage(GCGOperationReq, &proto.GCGOperationReq{}) // GCG游戏客户端操作请求
|
||||||
|
c.registerMessage(GCGOperationRsp, &proto.GCGOperationRsp{}) // GCG游戏客户端操作响应
|
||||||
|
|
||||||
// // TODO 客户端开始GCG游戏
|
// // TODO 客户端开始GCG游戏
|
||||||
// c.registerMessage(GCGStartChallengeByCheckRewardReq, &proto.GCGStartChallengeByCheckRewardReq{}) // GCG开始挑战来自检测奖励请求
|
// c.registerMessage(GCGStartChallengeByCheckRewardReq, &proto.GCGStartChallengeByCheckRewardReq{}) // GCG开始挑战来自检测奖励请求
|
||||||
|
|||||||
Reference in New Issue
Block a user