package worldtask import ( "errors" "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/lego/sys/log" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" cfg "go_dreamfactory/sys/configure/structs" "go_dreamfactory/utils" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/x/bsonx" ) type ModelWorldtask struct { modules.MCompModel moduleWorldtask *Worldtask service core.IService } func (this *ModelWorldtask) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { err = this.MCompModel.Init(service, module, comp, options) this.TableName = comm.TableWorldtask this.moduleWorldtask = module.(*Worldtask) this.service = service this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "uid", Value: bsonx.Int32(1)}}, }) return } // 获取玩家世界任务 func (this *ModelWorldtask) getWorldtask(uid string) (*pb.DBWorldtask, error) { d := &pb.DBWorldtask{} if err := this.Get(uid, d); err != nil { if err != mongo.ErrNoDocuments { log.Error("getWorldtask", log.Field{Key: "uid", Value: uid}) return d, err } } return d, nil } // 判断前置任务是否完成 // true 已完成 false未完成 func (this *ModelWorldtask) IsPreFinished(userTask *pb.DBWorldtask, curTaskConf *cfg.GameWorldTaskData) bool { var ( lastTaskId int32 preTaskFinished bool ) if curTaskConf.Ontxe == 0 { preTaskFinished = true } else { lastTaskId = curTaskConf.Ontxe } for _, v := range userTask.TaskList { if lastTaskId == v { preTaskFinished = true } } return preTaskFinished } // 判断任务是否已完成 func (this *ModelWorldtask) isFinished(taskId int32, list []*pb.Worldtask) bool { for _, v := range list { if v.TaskId == taskId { return true } } return false } // 完成任务 func (this *ModelWorldtask) finishTask(taskId int32, task *pb.DBWorldtask) error { if task == nil { return errors.New("worldtask is nil") } worldtaskConf, err := this.moduleWorldtask.configure.getWorldtaskCfg() if err != nil { this.moduleWorldtask.Errorln(err.Error()) return comm.NewCustomError(pb.ErrorCode_ConfigNoFound) } update := map[string]interface{}{} taskConf := worldtaskConf.GetDataMap()[taskId] if taskConf == nil { return comm.NewCustomError(pb.ErrorCode_ConfigNoFound) } update["uid"] = task.Uid // wt := &pb.Worldtask{ // TaskId: taskId, // TaskType: taskConf.Des, // } for _, tId := range task.TaskList { if tId == taskId { return comm.NewCustomError(pb.ErrorCode_WorldtaskFinihed) } } task.TaskList = append(task.TaskList, taskId) if task.CurrentTasks == nil { task.CurrentTasks = make(map[int32]*pb.Worldtasks) } //有下个任务 // if taskConf.IdAfter != 0 { // wt.NpcStatus = 0 // wt.DeliverNpc = 0 // task.CurrentTasks[groupId] = wt // update[""] = task.CurrentTasks // } update["taskList"] = task.TaskList if err := this.Change(task.Uid, update); err != nil { return err } return nil } // 查找后续任务 func (this *ModelWorldtask) findNextTasks(parentTaskId int32) (taskIds []int32) { gwt, err := this.moduleWorldtask.configure.getWorldtaskCfg() if err != nil || gwt == nil { return } for _, v := range gwt.GetDataList() { if v.Ontxe == parentTaskId { taskIds = append(taskIds, v.Key) } } return } // 更新当前任务的完成条件 func (this *ModelWorldtask) updateCurrentTaskCond(uid string, userLv int32, userTask *pb.DBWorldtask, currentTaskId, nextTaskId int32) *pb.DBWorldtask { nextTaskConf, err := this.moduleWorldtask.configure.getWorldtaskById(nextTaskId) if err != nil { return nil } if nextTaskConf == nil { return nil } if userLv < nextTaskConf.Lock { return nil } if nextTaskConf.Des == 1 || nextTaskConf.Des == 4 { return nil } if userTask.CurrentTasks == nil { userTask.CurrentTasks = make(map[int32]*pb.Worldtasks) } update := make(map[string]interface{}) nwt, ok := userTask.CurrentTasks[nextTaskConf.Group] if ok { // 删除 delete(nwt.TaskMap, currentTaskId) } if nwt == nil { nwt = &pb.Worldtasks{ TaskMap: make(map[int32]*pb.Worldtask), } userTask.CurrentTasks[nextTaskConf.Group] = nwt } nwt.TaskMap[nextTaskId] = &pb.Worldtask{ TaskId: nextTaskId, TaskType: nextTaskConf.Des, } update["currentTasks"] = userTask.CurrentTasks if len(update) > 0 { if err := this.Change(uid, update); err != nil { return nil } } return userTask } // 任务完成推送 func (this *ModelWorldtask) taskFinishPush(session comm.IUserSession, userTask *pb.DBWorldtask, curTaskConf *cfg.GameWorldTaskData) { // this.updateRandomTask(session.GetUserId(), userTask) u := this.moduleWorldtask.ModuleUser.GetUser(session.GetUserId()) if u == nil { return } nextTaskIds := this.findNextTasks(curTaskConf.Key) this.moduleWorldtask.Debug("nextTaskIds", log.Field{Key: "nextTaskIds", Value: nextTaskIds}) nextTask := make(map[int32]*pb.Worldtasks) if len(nextTaskIds) > 0 { for _, next := range nextTaskIds { ut := this.updateCurrentTaskCond(session.GetUserId(), u.Lv, userTask, curTaskConf.Key, next) if ut != nil { for k, v := range ut.CurrentTasks { nextTask[k] = v } } } } else { if curTaskConf.Des == 5 { nwt, ok := userTask.CurrentTasks[curTaskConf.Group] if ok { // 删除 delete(nwt.TaskMap, curTaskConf.Key) } } } if nextTaskIds == nil { nextTask[curTaskConf.Group] = &pb.Worldtasks{} //表示没有下一个任务 } if curTaskConf.IdAfter == 0 { // 章节完成 if _, ok := userTask.Chapters[curTaskConf.Group]; !ok { delete(userTask.CurrentTasks, curTaskConf.Group) delete(nextTask, curTaskConf.Group) if userTask.Chapters == nil { userTask.Chapters = make(map[int32]int32) } userTask.Chapters[curTaskConf.Group] = 1 //已解锁待领取 } } update := map[string]interface{}{ "chapters": userTask.Chapters, "currentTasks": userTask.CurrentTasks, } this.Change(session.GetUserId(), update) // 任务完成推送 session.SendMsg(string(this.moduleWorldtask.GetType()), WorldtaskNexttaskPush, &pb.WorldtaskNexttaskPush{ NextTask: nextTask, FinishedTaskIds: []int32{curTaskConf.Key}, }) } // 任务完成 func (this *ModelWorldtask) taskFinish(session comm.IUserSession, taskId int32, userTask *pb.DBWorldtask, curTaskConf *cfg.GameWorldTaskData) { if err := this.finishTask(taskId, userTask); err != nil { this.moduleWorldtask.Error("完成任务失败", log.Field{Key: "uid", Value: session.GetUserId()}, log.Field{Key: "taskId", Value: taskId}, log.Field{Key: "err", Value: err.Error()}, ) return } this.moduleWorldtask.DispenseRes(session, curTaskConf.Reword, true) //判断是否配置了通知module for _, m := range curTaskConf.Module { i, err := this.service.GetModule(core.M_Modules(m)) if err != nil { this.moduleWorldtask.Errorln(err) continue } if ic, ok := i.(comm.ITaskComplete); ok { ic.TaskComplete(session, taskId) } } } func (this *ModelWorldtask) filterTask(userLv, des int32, wt *pb.DBWorldtask) (taskIds []int32) { if des != 1 && des != 4 { return } gwt, err := this.moduleWorldtask.configure.getWorldtaskCfg() if err != nil { return } for _, v := range gwt.GetDataList() { // 主角等级 if v.Des == des && userLv >= v.Lock && userLv <= v.Lockend { if v.Ontxe != 0 { //寻找前置 if _, ok := utils.Findx(wt.TaskList, v.Ontxe); ok { taskIds = append(taskIds, v.Key) } } } } return } // 随机日常、周常任务 func (this *ModelWorldtask) randomTask(userLv, des int32, wt *pb.DBWorldtask) (taskIds []int32) { var num int32 if des == 1 { num = this.moduleWorldtask.ModuleTools.GetGlobalConf().DailyNum } else if des == 4 { num = this.moduleWorldtask.ModuleTools.GetGlobalConf().WeekNum } tIds := this.filterTask(userLv, des, wt) if len(tIds) < int(num) { num = int32(len(tIds)) } idx := utils.RandomNumbers(0, len(tIds), int(num)) for i := 0; i < len(idx); i++ { taskIds = append(taskIds, tIds[i]) } return } func (this *ModelWorldtask) updateRandomTask(uid string, myWorldtask *pb.DBWorldtask) { user := this.moduleWorldtask.ModuleUser.GetUser(uid) if user == nil { return } now := configure.Now().Unix() update := make(map[string]interface{}) // 日常 if now-myWorldtask.DaliyRefreshTime >= 3600*24 { dailyIds := this.randomTask(user.Lv, dailyDes, myWorldtask) if len(dailyIds) > 0 { for _, v := range dailyIds { gwtd, err := this.moduleWorldtask.configure.getWorldtaskById(v) if err != nil || gwtd == nil { continue } if task, ok := myWorldtask.CurrentTasks[gwtd.Group]; ok { task.TaskMap[v] = &pb.Worldtask{ TaskId: v, TaskType: gwtd.Des, } } else { taskMap := make(map[int32]*pb.Worldtask) taskMap[v] = &pb.Worldtask{ TaskId: v, TaskType: gwtd.Des, } myWorldtask.CurrentTasks[gwtd.Group] = &pb.Worldtasks{ TaskMap: taskMap, } } } update["daliyRefreshTime"] = configure.Now().Unix() } } //周常 if now-myWorldtask.WeekRefreshTime >= 3600*24*7 { weekIds := this.randomTask(user.Lv, weekDes, myWorldtask) if len(weekIds) > 0 { for _, v := range weekIds { gwtd, err := this.moduleWorldtask.configure.getWorldtaskById(v) if err != nil || gwtd == nil { continue } if task, ok := myWorldtask.CurrentTasks[gwtd.Group]; ok { task.TaskMap[v] = &pb.Worldtask{ TaskId: v, TaskType: gwtd.Des, } } else { taskMap := make(map[int32]*pb.Worldtask) taskMap[v] = &pb.Worldtask{ TaskId: v, TaskType: gwtd.Des, } myWorldtask.CurrentTasks[gwtd.Group] = &pb.Worldtasks{ TaskMap: taskMap, } } } update["weekRefreshTime"] = configure.Now().Unix() } } update["currentTasks"] = myWorldtask.CurrentTasks if err := this.Change(uid, update); err != nil { return } }