From 418655dea98e5131a65582395785e889dfcad186 Mon Sep 17 00:00:00 2001 From: flswld Date: Sun, 19 Feb 2023 19:40:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdconf/game_data_config.go | 2 + gdconf/quest_data.go | 88 ++++++++++ gdconf/table_struct_mapping.json | 245 +++++++++++++++++++++++++++ gs/game/player_fight_sync.go | 52 +++--- gs/game/player_login.go | 41 ++++- protocol/cmd/cmd_id_proto_obj_map.go | 11 ++ 6 files changed, 419 insertions(+), 20 deletions(-) create mode 100644 gdconf/quest_data.go diff --git a/gdconf/game_data_config.go b/gdconf/game_data_config.go index 14eb1f7b..9b9a2934 100644 --- a/gdconf/game_data_config.go +++ b/gdconf/game_data_config.go @@ -50,6 +50,7 @@ type GameDataConfig struct { AvatarFlycloakDataMap map[int32]*AvatarFlycloakData // 角色风之翼 ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性 ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性 + QuestDataMap map[int32]*QuestData // 任务 } func InitGameDataConfig() { @@ -135,6 +136,7 @@ func (g *GameDataConfig) load() { g.loadAvatarFlycloakData() // 角色风之翼 g.loadReliquaryMainData() // 圣遗物主属性 g.loadReliquaryAffixData() // 圣遗物追加属性 + g.loadQuestData() // 任务 } func (g *GameDataConfig) readCsvFileData(fileName string) []byte { diff --git a/gdconf/quest_data.go b/gdconf/quest_data.go new file mode 100644 index 00000000..bd23d78d --- /dev/null +++ b/gdconf/quest_data.go @@ -0,0 +1,88 @@ +package gdconf + +import ( + "fmt" + + "hk4e/pkg/logger" + + "github.com/jszwec/csvutil" +) + +// QuestData 任务配置表 +type QuestData struct { + QuestId int32 `csv:"QuestId"` // ID + ParentQuestId int32 `csv:"ParentQuestId,omitempty"` // 父任务ID + Sequence int32 `csv:"Sequence,omitempty"` // 序列 + // 领取条件 + AcceptCondCompose int32 `csv:"AcceptCondCompose,omitempty"` // [领取条件]组合 + AcceptCondType1 int32 `csv:"AcceptCondType1,omitempty"` // [领取条件]1类型 + AcceptCondType1Param1 int32 `csv:"AcceptCondType1Param1,omitempty"` // [领取条件]1参数1 + AcceptCondType1Param2 int32 `csv:"AcceptCondType1Param2,omitempty"` // [领取条件]1参数2 + AcceptCondType1Param3 int32 `csv:"AcceptCondType1Param3,omitempty"` // [领取条件]1参数3 + AcceptCondType2 int32 `csv:"AcceptCondType2,omitempty"` // [领取条件]2类型 + AcceptCondType2Param1 int32 `csv:"AcceptCondType2Param1,omitempty"` // [领取条件]2参数1 + AcceptCondType2Param2 int32 `csv:"AcceptCondType2Param2,omitempty"` // [领取条件]2参数2 + AcceptCondType2Param3 int32 `csv:"AcceptCondType2Param3,omitempty"` // [领取条件]2参数3 + AcceptCondType3 int32 `csv:"AcceptCondType3,omitempty"` // [领取条件]3类型 + AcceptCondType3Param1 int32 `csv:"AcceptCondType3Param1,omitempty"` // [领取条件]3参数1 + AcceptCondType3Param2 int32 `csv:"AcceptCondType3Param2,omitempty"` // [领取条件]3参数2 + AcceptCondType3Param3 int32 `csv:"AcceptCondType3Param3,omitempty"` // [领取条件]3参数3 + // 完成条件 + FinishCondCompose int32 `csv:"FinishCondCompose,omitempty"` // [完成条件]组合 + FinishCondType1 int32 `csv:"FinishCondType1,omitempty"` // [完成条件]1类型 + FinishCondType1Param1 int32 `csv:"FinishCondType1Param1,omitempty"` // [完成条件]1参数1 + FinishCondType1Param2 int32 `csv:"FinishCondType1Param2,omitempty"` // [完成条件]1参数2 + FinishCondType1ComplexParam string `csv:"FinishCondType1ComplexParam,omitempty"` // [完成条件]1复杂参数 + FinishCondType1Count int32 `csv:"FinishCondType1Count,omitempty"` // [完成条件]1次数 + FinishCondType2 int32 `csv:"FinishCondType2,omitempty"` // [完成条件]2类型 + FinishCondType2Param1 int32 `csv:"FinishCondType2Param1,omitempty"` // [完成条件]2参数1 + FinishCondType2Param2 int32 `csv:"FinishCondType2Param2,omitempty"` // [完成条件]2参数2 + FinishCondType2ComplexParam string `csv:"FinishCondType2ComplexParam,omitempty"` // [完成条件]2复杂参数 + FinishCondType2Count int32 `csv:"FinishCondType2Count,omitempty"` // [完成条件]2次数 + FinishCondType3 int32 `csv:"FinishCondType3,omitempty"` // [完成条件]3类型 + FinishCondType3Param1 int32 `csv:"FinishCondType3Param1,omitempty"` // [完成条件]3参数1 + FinishCondType3Param2 int32 `csv:"FinishCondType3Param2,omitempty"` // [完成条件]3参数2 + FinishCondType3ComplexParam string `csv:"FinishCondType3ComplexParam,omitempty"` // [完成条件]3复杂参数 + FinishCondType3Count int32 `csv:"FinishCondType3Count,omitempty"` // [完成条件]3次数 + // 失败条件 + FailCondCompose int32 `csv:"FailCondCompose,omitempty"` // [失败条件]组合 + FailCondType1 int32 `csv:"FailCondType1,omitempty"` // [失败条件]1类型 + FailCondType1Param1 int32 `csv:"FailCondType1Param1,omitempty"` // [失败条件]1参数1 + FailCondType1Param2 int32 `csv:"FailCondType1Param2,omitempty"` // [失败条件]1参数2 + FailCondType1ComplexParam string `csv:"FailCondType1ComplexParam,omitempty"` // [失败条件]1复杂参数 + FailCondType1Count int32 `csv:"FailCondType1Count,omitempty"` // [失败条件]1次数 + FailCondType2 int32 `csv:"FailCondType2,omitempty"` // [失败条件]2类型 + FailCondType2Param1 int32 `csv:"FailCondType2Param1,omitempty"` // [失败条件]2参数1 + FailCondType2Param2 int32 `csv:"FailCondType2Param2,omitempty"` // [失败条件]2参数2 + FailCondType2ComplexParam string `csv:"FailCondType2ComplexParam,omitempty"` // [失败条件]2复杂参数 + FailCondType2Count int32 `csv:"FailCondType2Count,omitempty"` // [失败条件]2次数 + FailCondType3 int32 `csv:"FailCondType3,omitempty"` // [失败条件]3类型 + FailCondType3Param1 int32 `csv:"FailCondType3Param1,omitempty"` // [失败条件]3参数1 + FailCondType3Param2 int32 `csv:"FailCondType3Param2,omitempty"` // [失败条件]3参数2 + FailCondType3ComplexParam string `csv:"FailCondType3ComplexParam,omitempty"` // [失败条件]3复杂参数 + FailCondType3Count int32 `csv:"FailCondType3Count,omitempty"` // [失败条件]3次数 +} + +func (g *GameDataConfig) loadQuestData() { + g.QuestDataMap = make(map[int32]*QuestData) + data := g.readCsvFileData("QuestData.csv") + var questDataList []*QuestData + err := csvutil.Unmarshal(data, &questDataList) + if err != nil { + info := fmt.Sprintf("parse file error: %v", err) + panic(info) + } + for _, questData := range questDataList { + // list -> map + g.QuestDataMap[questData.QuestId] = questData + } + logger.Info("QuestData count: %v", len(g.QuestDataMap)) +} + +func GetQuestDataById(sceneId int32) *QuestData { + return CONF.QuestDataMap[sceneId] +} + +func GetQuestDataMap() map[int32]*QuestData { + return CONF.QuestDataMap +} diff --git a/gdconf/table_struct_mapping.json b/gdconf/table_struct_mapping.json index e5a4fddb..3c041e4c 100644 --- a/gdconf/table_struct_mapping.json +++ b/gdconf/table_struct_mapping.json @@ -1018,5 +1018,250 @@ "origin_name": "随机权重" } ] + }, + { + "table_name": "QuestData", + "field_list": [ + { + "field_name": "QuestId", + "field_type": "int32", + "origin_name": "子任务ID" + }, + { + "field_name": "ParentQuestId", + "field_type": "int32", + "origin_name": "父任务ID" + }, + { + "field_name": "Sequence", + "field_type": "int32", + "origin_name": "序列" + }, + { + "field_name": "AcceptCondCompose", + "field_type": "int32", + "origin_name": "[领取条件]组合" + }, + { + "field_name": "AcceptCondType1", + "field_type": "int32", + "origin_name": "[领取条件]1类型" + }, + { + "field_name": "AcceptCondType1Param1", + "field_type": "int32", + "origin_name": "[领取条件]1参数1" + }, + { + "field_name": "AcceptCondType1Param2", + "field_type": "int32", + "origin_name": "[领取条件]1参数2" + }, + { + "field_name": "AcceptCondType1Param3", + "field_type": "int32", + "origin_name": "[领取条件]1参数3" + }, + { + "field_name": "AcceptCondType2", + "field_type": "int32", + "origin_name": "[领取条件]2类型" + }, + { + "field_name": "AcceptCondType2Param1", + "field_type": "int32", + "origin_name": "[领取条件]2参数1" + }, + { + "field_name": "AcceptCondType2Param2", + "field_type": "int32", + "origin_name": "[领取条件]2参数2" + }, + { + "field_name": "AcceptCondType2Param3", + "field_type": "int32", + "origin_name": "[领取条件]2参数3" + }, + { + "field_name": "AcceptCondType3", + "field_type": "int32", + "origin_name": "[领取条件]3类型" + }, + { + "field_name": "AcceptCondType3Param1", + "field_type": "int32", + "origin_name": "[领取条件]3参数1" + }, + { + "field_name": "AcceptCondType3Param2", + "field_type": "int32", + "origin_name": "[领取条件]3参数2" + }, + { + "field_name": "AcceptCondType3Param3", + "field_type": "int32", + "origin_name": "[领取条件]3参数3" + }, + { + "field_name": "FinishCondCompose", + "field_type": "int32", + "origin_name": "[完成条件]组合" + }, + { + "field_name": "FinishCondType1", + "field_type": "int32", + "origin_name": "[完成条件]1类型" + }, + { + "field_name": "FinishCondType1Param1", + "field_type": "int32", + "origin_name": "[完成条件]1参数1" + }, + { + "field_name": "FinishCondType1Param2", + "field_type": "int32", + "origin_name": "[完成条件]1参数2" + }, + { + "field_name": "FinishCondType1ComplexParam", + "field_type": "string", + "origin_name": "[完成条件]1复杂参数" + }, + { + "field_name": "FinishCondType1Count", + "field_type": "int32", + "origin_name": "[完成条件]1次数" + }, + { + "field_name": "FinishCondType2", + "field_type": "int32", + "origin_name": "[完成条件]2类型" + }, + { + "field_name": "FinishCondType2Param1", + "field_type": "int32", + "origin_name": "[完成条件]2参数1" + }, + { + "field_name": "FinishCondType2Param2", + "field_type": "int32", + "origin_name": "[完成条件]2参数2" + }, + { + "field_name": "FinishCondType2ComplexParam", + "field_type": "string", + "origin_name": "[完成条件]2复杂参数" + }, + { + "field_name": "FinishCondType2Count", + "field_type": "int32", + "origin_name": "[完成条件]2次数" + }, + { + "field_name": "FinishCondType3", + "field_type": "int32", + "origin_name": "[完成条件]3类型" + }, + { + "field_name": "FinishCondType3Param1", + "field_type": "int32", + "origin_name": "[完成条件]3参数1" + }, + { + "field_name": "FinishCondType3Param2", + "field_type": "int32", + "origin_name": "[完成条件]3参数2" + }, + { + "field_name": "FinishCondType3ComplexParam", + "field_type": "string", + "origin_name": "[完成条件]3复杂参数" + }, + { + "field_name": "FinishCondType3Count", + "field_type": "int32", + "origin_name": "[完成条件]3次数" + }, + { + "field_name": "FailCondCompose", + "field_type": "int32", + "origin_name": "[失败条件]组合" + }, + { + "field_name": "FailCondType1", + "field_type": "int32", + "origin_name": "[失败条件]1类型" + }, + { + "field_name": "FailCondType1Param1", + "field_type": "int32", + "origin_name": "[失败条件]1参数1" + }, + { + "field_name": "FailCondType1Param2", + "field_type": "int32", + "origin_name": "[失败条件]1参数2" + }, + { + "field_name": "FailCondType1ComplexParam", + "field_type": "string", + "origin_name": "[失败条件]1复杂参数" + }, + { + "field_name": "FailCondType1Count", + "field_type": "int32", + "origin_name": "[失败条件]1次数" + }, + { + "field_name": "FailCondType2", + "field_type": "int32", + "origin_name": "[失败条件]2类型" + }, + { + "field_name": "FailCondType2Param1", + "field_type": "int32", + "origin_name": "[失败条件]2参数1" + }, + { + "field_name": "FailCondType2Param2", + "field_type": "int32", + "origin_name": "[失败条件]2参数2" + }, + { + "field_name": "FailCondType2ComplexParam", + "field_type": "string", + "origin_name": "[失败条件]2复杂参数" + }, + { + "field_name": "FailCondType2Count", + "field_type": "int32", + "origin_name": "[失败条件]2次数" + }, + { + "field_name": "FailCondType3", + "field_type": "int32", + "origin_name": "[失败条件]3类型" + }, + { + "field_name": "FailCondType3Param1", + "field_type": "int32", + "origin_name": "[失败条件]3参数1" + }, + { + "field_name": "FailCondType3Param2", + "field_type": "int32", + "origin_name": "[失败条件]3参数2" + }, + { + "field_name": "FailCondType3ComplexParam", + "field_type": "string", + "origin_name": "[失败条件]3复杂参数" + }, + { + "field_name": "FailCondType3Count", + "field_type": "int32", + "origin_name": "[失败条件]3次数" + } + ] } ] diff --git a/gs/game/player_fight_sync.go b/gs/game/player_fight_sync.go index ed907abb..646c9a65 100644 --- a/gs/game/player_fight_sync.go +++ b/gs/game/player_fight_sync.go @@ -236,27 +236,41 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p sceneEntity.SetLastMoveSceneTimeMs(entityMoveInfo.SceneTime) sceneEntity.SetLastMoveReliableSeq(entityMoveInfo.ReliableSeq) + if motionInfo.State == proto.MotionState_MOTION_NOTIFY { + continue + } + + player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) + case proto.CombatTypeArgument_COMBAT_ANIMATOR_PARAMETER_CHANGED: + evtAnimatorParameterInfo := new(proto.EvtAnimatorParameterInfo) + err := pb.Unmarshal(entry.CombatData, evtAnimatorParameterInfo) + if err != nil { + logger.Error("parse EvtAnimatorParameterInfo error: %v", err) + continue + } + logger.Debug("EvtAnimatorParameterInfo: %v, ForwardType: %v", evtAnimatorParameterInfo, entry.ForwardType) + + // 这是否? + if evtAnimatorParameterInfo.IsServerCache { + evtAnimatorParameterInfo.IsServerCache = false + // TODO 暂时只做3.2协议的兼容了 在GS这边处理不同版本的协议太烦人了 有机会全部改到GATE那边处理 GS所有接收和发送的都应该是3.2版本的协议 + newCombatData, err := pb.Marshal(evtAnimatorParameterInfo) + if err != nil { + logger.Error("build EvtAnimatorParameterInfo error: %v", err) + continue + } + entry.CombatData = newCombatData + } + player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) case proto.CombatTypeArgument_COMBAT_ANIMATOR_STATE_CHANGED: evtAnimatorStateChangedInfo := new(proto.EvtAnimatorStateChangedInfo) - if config.GetConfig().Hk4e.ClientProtoProxyEnable { - clientProtoObj := g.GetClientProtoObjByName("EvtAnimatorStateChangedInfo") - if clientProtoObj == nil { - logger.Error("get client proto obj is nil") - continue - } - ok := utils.UnmarshalProtoObj(evtAnimatorStateChangedInfo, clientProtoObj, entry.CombatData) - if !ok { - continue - } - } else { - err := pb.Unmarshal(entry.CombatData, evtAnimatorStateChangedInfo) - if err != nil { - logger.Error("parse EvtAnimatorStateChangedInfo error: %v", err) - continue - } + err := pb.Unmarshal(entry.CombatData, evtAnimatorStateChangedInfo) + if err != nil { + logger.Error("parse EvtAnimatorStateChangedInfo error: %v", err) + continue } - logger.Debug("EvtAnimatorStateChangedInfo: %v", entry, player.PlayerID) + logger.Debug("EvtAnimatorStateChangedInfo: %v, ForwardType: %v", evtAnimatorStateChangedInfo, entry.ForwardType) player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) default: player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) @@ -375,7 +389,7 @@ func (g *GameManager) ClientAbilityInitFinishNotify(player *model.Player, payloa } invokeHandler := model.NewInvokeHandler[proto.AbilityInvokeEntry]() for _, entry := range req.Invokes { - // logger.Debug("ClientAbilityInitFinishNotify: %v", entry, player.PlayerID) + // logger.Debug("ClientAbilityInitFinishNotify: %v", entry) invokeHandler.AddEntry(entry.ForwardType, entry) } DoForward[proto.AbilityInvokeEntry](player, &proto.ClientAbilityInitFinishNotify{}, []string{"EntityId"}, "Invokes", invokeHandler) @@ -389,7 +403,7 @@ func (g *GameManager) ClientAbilityChangeNotify(player *model.Player, payloadMsg } invokeHandler := model.NewInvokeHandler[proto.AbilityInvokeEntry]() for _, entry := range req.Invokes { - // logger.Debug("ClientAbilityChangeNotify: %v", entry, player.PlayerID) + // logger.Debug("ClientAbilityChangeNotify: %v", entry) invokeHandler.AddEntry(entry.ForwardType, entry) } diff --git a/gs/game/player_login.go b/gs/game/player_login.go index 76dda55c..0e9225c7 100644 --- a/gs/game/player_login.go +++ b/gs/game/player_login.go @@ -148,7 +148,7 @@ func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq g.SendMsg(cmd.PlayerStoreNotify, userId, clientSeq, g.PacketPlayerStoreNotify(player)) g.SendMsg(cmd.AvatarDataNotify, userId, clientSeq, g.PacketAvatarDataNotify(player)) g.SendMsg(cmd.OpenStateUpdateNotify, userId, clientSeq, g.PacketOpenStateUpdateNotify()) - g.GCGLogin(player) // 发送GCG登录相关的通知包 + // g.GCGLogin(player) // 发送GCG登录相关的通知包 playerLoginRsp := &proto.PlayerLoginRsp{ IsUseAbilityHash: true, AbilityHashCode: 0, @@ -160,6 +160,45 @@ func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq TotalTickTime: 0.0, } g.SendMsg(cmd.PlayerLoginRsp, userId, clientSeq, playerLoginRsp) + + questListNotify := &proto.QuestListNotify{ + QuestList: make([]*proto.Quest, 0), + } + + for _, questDataConfig := range gdconf.GetQuestDataMap() { + if questDataConfig.QuestId == 35104 { + questListNotify.QuestList = append(questListNotify.QuestList, &proto.Quest{ + QuestId: 35104, + State: 2, + StartTime: uint32(time.Now().Unix()), + ParentQuestId: 351, + StartGameTime: 438, + AcceptTime: uint32(time.Now().Unix()), + FinishProgressList: []uint32{0}, + }) + continue + } + finishProgressList := make([]uint32, 0) + if questDataConfig.FinishCondType1 != 0 { + finishProgressList = append(finishProgressList, 0) + } + if questDataConfig.FinishCondType2 != 0 { + finishProgressList = append(finishProgressList, 0) + } + if questDataConfig.FinishCondType3 != 0 { + finishProgressList = append(finishProgressList, 0) + } + questListNotify.QuestList = append(questListNotify.QuestList, &proto.Quest{ + QuestId: uint32(questDataConfig.QuestId), + State: 1, + StartTime: uint32(time.Now().Unix()), + ParentQuestId: uint32(questDataConfig.ParentQuestId), + StartGameTime: 0, + AcceptTime: uint32(time.Now().Unix()), + FinishProgressList: finishProgressList, + }) + } + g.SendMsg(cmd.QuestListNotify, userId, clientSeq, questListNotify) } func (g *GameManager) PacketPlayerDataNotify(player *model.Player) *proto.PlayerDataNotify { diff --git a/protocol/cmd/cmd_id_proto_obj_map.go b/protocol/cmd/cmd_id_proto_obj_map.go index 52689a33..d3e9554d 100644 --- a/protocol/cmd/cmd_id_proto_obj_map.go +++ b/protocol/cmd/cmd_id_proto_obj_map.go @@ -301,6 +301,17 @@ func (c *CmdProtoMap) registerAllMessage() { // c.registerMessage(GCGStartChallengeReq, &proto.GCGStartChallengeReq{}) // GCG开始挑战请求 // c.registerMessage(GCGStartChallengeRsp, &proto.GCGStartChallengeRsp{}) // GCG开始挑战响应 + // 任务 + c.registerMessage(AddQuestContentProgressReq, &proto.AddQuestContentProgressReq{}) // 添加任务内容进度请求 + c.registerMessage(AddQuestContentProgressRsp, &proto.AddQuestContentProgressRsp{}) // 添加任务内容进度响应 + c.registerMessage(QuestListNotify, &proto.QuestListNotify{}) // 任务列表通知 + c.registerMessage(QuestListUpdateNotify, &proto.QuestListUpdateNotify{}) // 任务列表更新通知 + c.registerMessage(FinishedParentQuestNotify, &proto.FinishedParentQuestNotify{}) // 已完成父任务列表通知 + c.registerMessage(FinishedParentQuestUpdateNotify, &proto.FinishedParentQuestUpdateNotify{}) // 已完成父任务列表更新通知 + c.registerMessage(ServerCondMeetQuestListUpdateNotify, &proto.ServerCondMeetQuestListUpdateNotify{}) // 服务器动态任务列表更新通知 + c.registerMessage(QuestProgressUpdateNotify, &proto.QuestProgressUpdateNotify{}) // 任务进度更新通知 + c.registerMessage(QuestGlobalVarNotify, &proto.QuestGlobalVarNotify{}) // 任务全局变量通知 + // 乱七八糟 c.registerMessage(MarkMapReq, &proto.MarkMapReq{}) // 标记地图请求 c.registerMessage(TowerAllDataReq, &proto.TowerAllDataReq{}) // 深渊数据请求