using System; using System.Collections.Generic; using Sog; using ProtoCSStruct; using Ubiety.Dns.Core.Common; namespace Game { public static class TaskEXSvc { /// todo 加的测试模式,此模式中所有任何接受、完成、交付都不作校验,全部通过 /// todo 应该前端需求,为方便前端测表现而增加 /// todo 上前线或完成测试后在这些代码全部去掉最安全 private static bool bGMTestModel = false; public static Dictionary> TaskUpdateDict = new Dictionary>(); public static List NoPreviewTaskId = new List(); public static bool GMTestModel { get { return bGMTestModel; } set { bGMTestModel = value; } } public static CSErrCode CommonProcesser(PlayerOnGame player, int taskID, bool bFromClient, Func process, out int index) { CSErrCode ret = CSErrCode.Fail; index = -1; if (IsVaildTaskID(player, taskID) == false) { // 以防万一,指不定就配错了呢 ret = CSErrCode.TaskInvaildTaskID; TraceLog.Error("TaskEXSvc.CommonProcesser userid {0} taskID {1} invaild taskid. ret {2}", player.UserID, taskID, ret); return ret; } QuestEXDesc taskDesc = QuestEXDescMgr.Instance.GetConfig(taskID); if (taskDesc != null) { index = GetTaskIndex(player, taskID); ret = process(taskDesc, index); } else { TraceLog.Error("TaskEXSvc.CommonProcesser userid {0} taskID {1} bFromClient {2}, QuestEXDesc == null ret {3}", player.UserID, taskID, bFromClient, ret); } TraceLog.TraceDetail("TaskEXSvc.CommonProcesser userid {0} taskID {1} ret {2}", player.UserID, taskID, ret); return ret; } internal static CSErrCode ProcessGetTitle(PlayerOnGame player, int titleId) { throw new NotImplementedException(); } public static CSErrCode ProcessAcceptTask(PlayerOnGame player, int taskID, bool bFromClient, out int index) { CSErrCode ret = CommonProcesser(player, taskID, bFromClient, (taskDesc, taskIndex) => { CSErrCode innerRet = CheckCanAcceptTask(player, taskDesc, bFromClient); if (innerRet == CSErrCode.None) { DBTaskEXOne newTask = new DBTaskEXOne() { TaskId = taskID, PickupTime = (int)GameServerUtils.GetTimeSecond(), }; AddTask(player, ref newTask); int innerIndex = player.RoleData.TaskEXData.TaskList.GetCount() - 1; UpdateTaskEXCondition(ref newTask, player, innerIndex); GameBDCLogUtils.ReceiveQuest(player, (int)taskDesc.questType, taskDesc.questId); } return innerRet; }, out index); index = GetTaskIndex(player, taskID); TraceLog.TraceDetail("TaskEXSvc.ProcessAcceptTask userid {0} taskID {1} ret {2}", player.UserID, taskID, ret); return ret; } public static CSErrCode CheckCanAcceptTask(PlayerOnGame player, QuestEXDesc desc, bool bFromClient) { CSErrCode ret = CSErrCode.None; // check task already exist ret = CheckCanAcceptTask_AlreadExist(player, desc); if (GMTestModel == true || ret != CSErrCode.None) { return ret; } // check level ret = CheckCanAcceptTask_Level(player, desc); if (ret != CSErrCode.None) { return ret; } // check system ret = CheckCanAcceptTask_System(player, desc); if (ret != CSErrCode.None) { return ret; } ret = CheckMainTask(player, desc); if (ret != CSErrCode.None) { return ret; } return ret; } // 客户端完成入口 以前的 先留着 public static CSErrCode ProcessCompleteTask(PlayerOnGame player, int taskID, bool bFromClient, out int index) { CSErrCode ret = CommonProcesser(player, taskID, bFromClient, (taskDesc, taskIndex) => { CSErrCode innerRet = CSErrCode.Fail; if (taskIndex == -1) { return CSErrCode.TaskNotExist; } ref DBTaskEXOne taskData = ref GetTaskByIndex(player, taskIndex); if (IsCompleteTask(ref taskData, taskDesc)) { innerRet = CSErrCode.None; } return innerRet; }, out index); TraceLog.Trace("TaskEXSvc.ProcessCompleteTask userid {0} taskID {1}, ret {2}", player.UserID, taskID, ret); return ret; } public static CSErrCode ProcessGiveupTask(PlayerOnGame player, int taskID, out int index) { CSErrCode ret = CommonProcesser(player, taskID, false, (taskDesc, taskIndex) => { CSErrCode innerRet = CSErrCode.Fail; if (taskIndex == -1) { return CSErrCode.TaskNotExist; } if (taskDesc != null && !CheckCanGiveupTaskType(taskDesc)) { innerRet = CSErrCode.ThisTaskTypeCannotGiveUp; } else { // 任务是可放弃的类型或者任务配置干脆不存在了(有可能是后面调整优化了),均需要允许将已接取到的任务放弃掉 innerRet = CSErrCode.None; } if (GMTestModel == true) { innerRet = CSErrCode.None; } if (innerRet == CSErrCode.None) { RemoveTask(player, taskIndex); } return innerRet; }, out index); TraceLog.Trace("TaskEXSvc.ProcessGiveupTask userid {0} taskID {1}, ret {2}", player.UserID, taskID, ret); return ret; } //强行删除 public static CSErrCode ProcessGiveupTask2(PlayerOnGame player, int taskID, out int index) { CSErrCode ret = CSErrCode.None; index = GetTaskIndex(player, taskID); if (index == -1) { ret = CSErrCode.TaskNotExist; } else { RemoveTask(player, index); } //已完成清理下状态 if (IsFinishTask(player, taskID)) { TraceLog.Trace("TaskEXSvc.DeleteTask uid {0} task {1} clear finish status", player.UserID, taskID); ClearTaskFinishStatus(player, taskID); return 0; } TraceLog.Trace("TaskEXSvc.ProcessGiveupTask userid {0} taskID {1}", player.UserID, taskID); return ret; } public static CSErrCode ProcessBatchHandoverTask(PlayerOnGame player, ref CSBatchTaskEXHandoverTaskReq req, bool bFromClient, out int index) { index = 0; var collect = new List(); for (var i = 0; i < req.TaskIds.Count; i++) { var taskId = req.TaskIds[i]; CommonProcesser(player, taskId, bFromClient, (desc, taskIndex) => { CSErrCode innerRet = CSErrCode.Fail; if (taskIndex == -1) { innerRet = IsFinishTask(player, taskId) ? CSErrCode.TaskAlreadyHandover : CSErrCode.TaskNotExist; TraceLog.Error( "TaskEXSvc.ProcessHandoverTask userid {0} taskID {1} bFromClient {2} GetTaskExIndex == -1, ret {3}", player.UserID, taskId, bFromClient, innerRet); } else { ref var taskData = ref GetTaskByIndex(player, taskIndex); if (taskData.Status == (int)TaskEXCfg.TaskStatusDone) { innerRet = CSErrCode.TaskAlreadyHandover; return innerRet; } if (desc != null) { if (IsCompleteTask(ref taskData, desc)) { // 发奖、处理任务完成后事件 innerRet = ProcessAfterHandover(player, ref taskData, desc, 0, taskIndex, true,collect); } } else { TraceLog.Error( "TaskEXSvc.ProcessHandoverTask userid {0} taskID {1} bFromClient {2} QuestEXDesc == null, ret {3}", player.UserID, taskId, bFromClient, innerRet); } } TraceLog.Trace("TaskEXSvc.ProcessHandoverTask userid {0} taskID {1} bFromClient {2} ret {3}", player.UserID, taskId, bFromClient, innerRet); return innerRet; }, out index); } UnifyOp unifyOp = new UnifyOp(player, BillChangeItemReason.BatchTaskEXReward,string.Join(",",collect)); foreach (var item in collect) { unifyOp.AddGoods(item.Type, item.Id.GetString(), item.Value); } CSErrCode opRet = unifyOp.DoOp(sendGetItemMsg: true); return opRet; } public static CSErrCode ProcessHandoverTask(PlayerOnGame player, int taskID, bool bFromClient, out int index) { CSErrCode ret = CommonProcesser(player, taskID, bFromClient, (desc, taskIndex) => { CSErrCode innerRet = CSErrCode.Fail; if (taskIndex == -1) { innerRet = IsFinishTask(player, taskID) ? CSErrCode.TaskAlreadyHandover : CSErrCode.TaskNotExist; TraceLog.Error("TaskEXSvc.ProcessHandoverTask userid {0} taskID {1} bFromClient {2} GetTaskExIndex == -1, ret {3}", player.UserID, taskID, bFromClient, innerRet); } else { ref DBTaskEXOne taskData = ref GetTaskByIndex(player, taskIndex); if (taskData.Status == (int)TaskEXCfg.TaskStatusDone) { innerRet = CSErrCode.TaskAlreadyHandover; return innerRet; } if (desc != null) { if (IsCompleteTask(ref taskData, desc)) { // 发奖、处理任务完成后事件 innerRet = ProcessAfterHandover(player, ref taskData, desc, 0, taskIndex, true); } } else { TraceLog.Error("TaskEXSvc.ProcessHandoverTask userid {0} taskID {1} bFromClient {2} QuestEXDesc == null, ret {3}", player.UserID, taskID, bFromClient, innerRet); } } TraceLog.Trace("TaskEXSvc.ProcessHandoverTask userid {0} taskID {1} bFromClient {2} ret {3}", player.UserID, taskID, bFromClient, innerRet); return innerRet; }, out index); return ret; } /// /// 处理任务交付后的(任务设置、发奖、触发等等)的处理 /// 单独拧出来方便之后做类似秒杀、扫荡的处理 /// /// /// /// /// /// /// /// /// public static CSErrCode ProcessAfterHandover(PlayerOnGame player, ref DBTaskEXOne taskData, QuestEXDesc desc, uint defParam, int index, bool bTellClient = false, List collect = null) { CSErrCode ret = CSErrCode.None; TraceLog.Trace("TaskEXSvc.ProcessAfterHandover userid {0} taskID {1} defParam {2}, ret {3}, index {4}", player.UserID, taskData.TaskId, defParam, ret, index); CSTaskEXDeleteNotify delNotify = new CSTaskEXDeleteNotify(); taskData.Status = (int)TaskEXCfg.TaskStatusDone; delNotify.DelTaskIDList.Add(taskData.TaskId); player.SendToClient((int)CSGameMsgID.TaskexDeleteNotify, ref delNotify); // remove/finish task RemoveTask(player, index); AddFinishTask(player, desc.questId); // 发奖励 begin var rets=TaskEXGetReward(player, desc, collect == null); if (collect != null) { collect.AddRange(rets); } // 发奖励 end if (bTellClient) { //领取任务奖励后前BP前端要求同步玩家数据 //领取任务奖励后前BP前端要求同步玩家数据 CSTaskEXHandoverTaskRes res = new CSTaskEXHandoverTaskRes(); res.TaskId = desc.questId; res.NextTaskId = desc.nextQuestId; res.Ret = CSErrCode.None; player.SendToClient((int)CSGameMsgID.TaskexHandoverTaskRes, ref res); } TraceLog.Trace("TaskEXSvc.ProcessAfterHandover userid {0} taskID {1} defParam {2}, ret {3}", player.UserID, desc.questId, defParam, ret); GameServerUtils.GetEventHandlerMgr().TriggerTaskexHandoverComplete(player, desc); GameTALogUtils.LogFinishTask(player,(int)desc.questType,desc.questId); // auto accept union task if (desc.nextQuestId != 0) { CSTaskEXAcceptTaskRes res = new CSTaskEXAcceptTaskRes { TaskId = desc.nextQuestId, Ret = ProcessAcceptTask(player, desc.nextQuestId, false, out int nAcceptIndex) }; if (res.Ret == CSErrCode.None) { res.Taskdata.CopyFrom(ref GetTaskByIndex(player, nAcceptIndex)); player.SendToClient((int)CSGameMsgID.TaskexAcceptTaskRes, ref res); CSTaskEXChangeNotify chgNotify = new CSTaskEXChangeNotify(); chgNotify.ChgTaskList.Add(ref GetTaskByIndex(player, nAcceptIndex)); player.SendToClient((int)CSGameMsgID.TaskexChangeNotify, ref chgNotify); } } return ret; } /// /// 封装一下地牢奖励的发放,方便后续查bug /// /// /// public static List TaskEXGetReward(PlayerOnGame player, QuestEXDesc desc, bool send = true) { int addRate = 100; List list = new List(); for (int i = 0; i < desc.rewardType.Length; i++) { if (desc.rewardType[i] == 0 || desc.rewardCount[i] == 0) { continue; } list.Add(new TypeIDValueString() { Type = (int)desc.rewardType[i], Id = new FixedStructString64(desc.rewardId[i]), Value = desc.rewardCount[i] * addRate / 100, }); } if (send && list.Count > 0) { UnifyOp unifyOp = new UnifyOp(player, BillChangeItemReason.TaskEXReward, desc.questId.ToString(), desc.questId); foreach (var item in list) { unifyOp.AddGoods(item.Type, item.Id.GetString(), item.Value); } CSErrCode opRet = unifyOp.DoOp(sendGetItemMsg: true); if (opRet != CSErrCode.None) { TraceLog.Error("TaskEXSvc.TaskEXGetReward userid {0} taskID {1} reward bag DoOp fail opRet {2}", player.UserID, desc.questId, opRet); } else { TraceLog.Trace("TaskEXSvc.TaskEXGetReward userid {0} taskID {1} reward bag DoOp success opRet {2}", player.UserID, desc.questId, opRet); } } string reward = "{reward:["; for (int j = 0; j < list.Count; j++) { reward += "{"; reward += "\"type\":\"" + list[j].Type + "\",\"id\":\"" + list[j].Id.GetString() + "\",\"value\":\"" + list[j].Value + "\""; reward += "}"; if (j != list.Count - 1) { reward += ","; } } reward += "]}"; //变更任务states GameBDCLogUtils.FinishQuest(player, (int)desc.questType, desc.questId, reward); GameTALogUtils.LogFinishTask(player, (int)desc.questType, desc.questId); return list; } public static bool AddFinishTask(PlayerOnGame player, int taskID) { if (IsVaildTaskID(player, taskID) == false) { TraceLog.Error("TaskEXSvc.AddFinishTask error,The taskid {0} is invalid", taskID); return false; } if (IsFinishTask(player, taskID)) { //任务已经完成了 TraceLog.Error("TaskEXSvc.AddFinishTask error,The taskid {0} Had been Complete", taskID); return false; } GetTaskIDByteIndex(taskID, out int index, out int ByteIndex); player.RoleData.TaskEXData.FinishTaskList[index] |= 1 << ByteIndex; TraceLog.TraceDetail("TaskEXSvc.AddFinishTask player{0} finished taskId:{1} FinishTaskList:{2}",player.UserID, taskID, player.RoleData.TaskEXData.FinishTaskList); player.MakeDirty(); return true; } public static bool RemoveTask(PlayerOnGame player, int index) { player.RoleData.TaskEXData.TaskList.RemoveAt(index); player.MakeDirty(); return true; } //任务已经接受过 public static bool IsAcceptEdTask(PlayerOnGame player, int taskID) { if (IsVaildTaskID(player, taskID) == false) { return true; } if (GetTaskIndex(player, taskID) > -1) { return true; } return IsFinishTask(player, taskID); } public static bool CheckCanGiveupTaskType(QuestEXDesc desc) { return !(IsMainTask(desc)); } public static CSErrCode CheckCanAcceptTask_AlreadExist(PlayerOnGame player, QuestEXDesc desc) { if (IsGoingOnTask(player, desc.questId) == true) { return CSErrCode.TaskAlreadyExist; } if (IsFinishTask(player, desc.questId) == true) { return CSErrCode.TaskAlreadyHandover; } return CSErrCode.None; } public static CSErrCode CheckCanAcceptTask_Level(PlayerOnGame player, QuestEXDesc desc) { //if (player.GetLevel() < desc.levelRequirement || (desc.levelLimit > 0 && player.GetLevel() > desc.levelLimit)) //{ // return CSErrCode.LevelNotEnough; //} return CSErrCode.None; } public static CSErrCode CheckCanAcceptTask_System(PlayerOnGame player, QuestEXDesc desc) { //if(desc.systemLimit.Length == 0 || ( desc.systemLimit.Length > 0 && desc.systemLimit[0] == 0)) //{ // return CSErrCode.None; //} //for(int i = 0; i < desc.systemLimit.Length; i++) //{ // if(desc.systemLimit[i] == 0) // { // continue; // } // if(!PlayerUtils.IsUnlockSys(player, (SystemUnlockId)desc.systemLimit[i])) // { // return CSErrCode.SysNotUnlock; // } //} return CSErrCode.None; } public static CSErrCode CheckCanAcceptTask_PreviousQuest(PlayerOnGame player, QuestEXDesc desc) { int main = GetCurrentMainTask(player); if (main == -1) { return CSErrCode.None; } else if (desc.questId == main + 1) { return CSErrCode.TaskPreviousQuestNotFinish; } return CSErrCode.None; } private static CSErrCode CheckMainTask(PlayerOnGame player, QuestEXDesc desc) { if (IsMainTask(desc)) { // 有主线任务就不能接了 int main = GetCurrentMainTask(player); if (main == -1) { return CSErrCode.None; } return CSErrCode.Fail; } return CSErrCode.None; } public static CSErrCode UpdateTaskEXCondition(ref DBTaskEXOne taskEXOne, PlayerOnGame player, int index, bool needChangeV = true) { QuestEXDesc questEXDesc = QuestEXDescMgr.Instance.GetConfig(taskEXOne.TaskId); if (questEXDesc == null) { return CSErrCode.Fail; } for(int i = 0; i < questEXDesc.fulfill.Length; i++) { if(questEXDesc.fulfill[i].Method == (int)QuestMethod.None) { continue; } TaskEXEvent.InitSingleCondition((int)questEXDesc.fulfill[i].Method, player, index); } return CSErrCode.None; } private static bool AddTask(PlayerOnGame player, ref DBTaskEXOne newtask) { for (int i = 0; i < newtask.Condition.GetMaxCount(); i++) { DBTaskEXOneNode newNode = new DBTaskEXOneNode(); newtask.Condition.Add(ref newNode); } player.RoleData.TaskEXData.TaskList.Add(ref newtask); player.MakeDirty(); return true; } public static void RefreshTaskStatus(PlayerOnGame player, int assignTaskID = 0) { TryAcceptNewNoPreTask(player); long nowSec = GameServerUtils.GetTimeSecond(); CSTaskEXChangeNotify chgNotify = new CSTaskEXChangeNotify(); player.RoleData.TaskEXData.NextDailyRefreshTime = AppTime.GetNextTime(nowSec, 0, 5); player.RoleData.TaskEXData.NextWeeklyRefreshTime = AppTime.GetNextTime(nowSec, 1, 5); //int outI; ref var playerTask = ref player.RoleData.TaskEXData.TaskList; for (int i = playerTask.Count - 1; i >= 0; i--) { if (assignTaskID != 0 && assignTaskID != playerTask[i].TaskId) continue; var taskDesc = QuestEXDescMgr.Instance.GetConfig(playerTask[i].TaskId); if (taskDesc == null) { chgNotify.ChgTaskList.Add(playerTask[i]); continue; } } if (chgNotify.ChgTaskList.GetCount() > 0) { player.SendToClient((int)CSGameMsgID.TaskexChangeNotify, ref chgNotify); } } public static void TryAcceptNewNoPreTask(PlayerOnGame player) { } //删除任务 public static int DeleteTask(PlayerOnGame player, int taskId) { TraceLog.Trace("TaskEXSvc.DeleteTask uid {0} task {1}", player.UserID, taskId); //已完成清理下状态 if (IsFinishTask(player, taskId)) { TraceLog.Trace("TaskEXSvc.DeleteTask uid {0} task {1} clear finish status", player.UserID, taskId); ClearTaskFinishStatus(player, taskId); return 0; } //未完成放弃 return (int)ProcessGiveupTask(player, taskId, out int index); } public static void ClearTaskFinishStatus(PlayerOnGame player, int questId) { //重置完成状态 GetTaskIDByteIndex(questId, out int indexTask, out int ByteIndex); player.RoleData.TaskEXData.FinishTaskList[indexTask] &= ~(1 << ByteIndex); } public static bool IsVaildTaskID(PlayerOnGame player, int taskID) { // 最大任务ID为 已完成任务列表支持的最大数量 * 32 (int bit) // 不允许等于,别的放调用会越界 if (taskID <= 0 || taskID >= player.RoleData.TaskEXData.FinishTaskList.GetMaxCount() * 32) { return false; } return true; } public static bool IsFinishTask(PlayerOnGame player, int taskID) { if (IsVaildTaskID(player, taskID) == false) { TraceLog.Error("TaskEXSvc.IsFinish error,player:{0} The taskid {1} is invalid",player.UserID, taskID); return false; } GetTaskIDByteIndex(taskID, out int index, out int ByteIndex); ref DBTaskEXData task = ref player.RoleData.TaskEXData; if ((task.FinishTaskList[index] & 1 << ByteIndex) != 0) { return true; } return false; } public static int GetTaskStatuse(PlayerOnGame player, int taskID) { for(int i = 0;i < player.RoleData.TaskEXData.TaskList.Count;i++) { if (taskID == player.RoleData.TaskEXData.TaskList[i].TaskId) return player.RoleData.TaskEXData.TaskList[i].Status; } return -1; } public static bool IsCompleteTask(PlayerOnGame player,int questId) { var questEXDesc = QuestEXDescMgr.Instance.GetConfig(questId); if (questEXDesc == null) { return false; } var index = -1; for (int i = 0; i < player.RoleData.TaskEXData.TaskList.Count; i++) { if(player.RoleData.TaskEXData.TaskList[i].TaskId == questEXDesc.questId) { index = i; break; } } if (index < 0) { return false; } var taskData = player.RoleData.TaskEXData.TaskList[index]; bool res = true; if (questEXDesc.fulfill.Length == taskData.Condition.GetMaxCount()) { for (int i = 0; i < questEXDesc.fulfill.Length; i++) { if (questEXDesc.fulfill[i].Method != (int)QuestMethod.None && !taskData.Condition[i].Done) return false; } } else { // 处理配置加长的特殊情况 for (int i = 0; i < taskData.Condition.GetMaxCount(); i++) { if (i < questEXDesc.fulfill.Length) { if (questEXDesc.fulfill[i].Method != (int)QuestMethod.None && !taskData.Condition[i].Done) return false; } } } return res; } public static bool IsCompleteTask(ref DBTaskEXOne taskData, QuestEXDesc questEXDesc) { bool res = true; if (questEXDesc.fulfill.Length == taskData.Condition.GetMaxCount()) { for (int i = 0; i < questEXDesc.fulfill.Length; i++) { if (questEXDesc.fulfill[i].Method != (int)QuestMethod.None && !taskData.Condition[i].Done) return false; } } else { // 处理配置加长的特殊情况 for (int i = 0; i < taskData.Condition.GetMaxCount(); i++) { if (i < questEXDesc.fulfill.Length) { if (questEXDesc.fulfill[i].Method != (int)QuestMethod.None && !taskData.Condition[i].Done) return false; } } } return res; } public static int GetCurrentMainTask(PlayerOnGame player) { ref var playerTasks = ref player.RoleData.TaskEXData.TaskList; for (int i = 0; i < playerTasks.Count; i++) { var desc = QuestEXDescMgr.Instance.GetConfig(playerTasks[i].TaskId); if (desc == null) continue; // if (desc.questType == (int)QuestMethod.MainTask) // { // return playerTasks[i].TaskId; // } } return -1; } public static ref DBTaskEXOne GetTaskByIndex(PlayerOnGame player, int index) { return ref player.RoleData.TaskEXData.TaskList.Get(index); } public static int GetTaskIndex(PlayerOnGame player, int taskID) { ref var playerTask = ref player.RoleData.TaskEXData.TaskList; for (int i = 0; i < playerTask.Count; i++) { if (playerTask[i].TaskId == taskID) { return i; } } return -1; } public static bool IsGoingOnTask(PlayerOnGame player, int taskID) { return GetTaskIndex(player, taskID) != -1; } public static bool IsMainTask(QuestEXDesc desc) { return false; // return desc.questType == (int)QuestType.MainTask; } public static void GetTaskIDByteIndex(int taskID, out int index, out int byteIndex) { index = (taskID - 1) / 32; byteIndex = (taskID - 1) % 32; } public static void OnNewDay(PlayerOnGame player, bool notifyclient) { var statChgOp = new RoleStatChgOp(player); statChgOp.AddIDDaily((int)CSRoleStatisticsID.LoginDay, 1); } } }