diff --git a/game-server/app/servers/battle/handler/towerBattleHandler.ts b/game-server/app/servers/battle/handler/towerBattleHandler.ts index c0e4c31ba..1c84ac806 100644 --- a/game-server/app/servers/battle/handler/towerBattleHandler.ts +++ b/game-server/app/servers/battle/handler/towerBattleHandler.ts @@ -10,7 +10,7 @@ import { getTaskById, getTowerDataByLv } from '../../../pubUtils/gamedata'; import { decodeArrayStr, resResult, shouldRefresh, calculateNum, getRefTime, genCode } from '../../../pubUtils/util'; import { calcuHangUpReward, checkTaskConditions, checkHangUpSpdUpCnt, createCurTasks, treatTask, getRemainTime, getTasksReward, getTaskStatus, getDoingOrWaitingTasks } from '../../../services/battleService'; import { handleFixedReward, addItems, handleCost } from '../../../services/rewardService'; -import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; +import { checkBattleHeroes } from '../../../services/normalBattleService'; import { getGoldObject } from '../../../pubUtils/itemUtils'; import { Rank } from '../../../services/rankService'; @@ -241,8 +241,8 @@ export class TowerBattleHandler { if (task.heroes.length !== taskInfo.actorNeeded) { // 武将数,从策划表中读取 return resResult(STATUS.TOWER_TASK_MAX_HERO); } - let hasHero = await checkBattleHeroesByHid(roleId, task.heroes); - if(!hasHero) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + let { isOK } = await checkBattleHeroes(roleId, task.heroes); + if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); if (tasksCode.indexOf(task.taskCode) === -1) { return resResult(STATUS.TOWER_TASK_CODE_NOT_FOUND); } diff --git a/game-server/app/servers/connector/handler/entryHandler.ts b/game-server/app/servers/connector/handler/entryHandler.ts index 55abdd2d1..43673275f 100644 --- a/game-server/app/servers/connector/handler/entryHandler.ts +++ b/game-server/app/servers/connector/handler/entryHandler.ts @@ -22,7 +22,7 @@ import { getMails } from '../../../services/mailService'; import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGuildChannel, leaveSysChannel, leaveWorldChannel, recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from '../../../services/chatService'; import { reportOneOnline } from '../../../services/timeTaskService'; import { Rank } from '../../../services/rankService'; -import { checkTaskWithRole } from '../../../services/taskService'; +import { checkTaskWithRole, getCurTask } from '../../../services/taskService'; export default function (app: Application) { return new EntryHandler(app); } @@ -152,6 +152,11 @@ export class EntryHandler { } } } + // 任务 + let { mainTask, dailyTask, achievement } = await getCurTask(role.roleId); + role['mainTask'] = mainTask; + role['dailyTask'] = dailyTask; + role['achievement'] = achievement; return resResult(STATUS.SUCCESS, { role }); } diff --git a/game-server/app/servers/role/handler/taskHandler.ts b/game-server/app/servers/role/handler/taskHandler.ts new file mode 100644 index 000000000..b8c0cbde5 --- /dev/null +++ b/game-server/app/servers/role/handler/taskHandler.ts @@ -0,0 +1,182 @@ +import { Application, BackendSession } from "pinus"; +import { resResult, parseGoodStr } from "../../../pubUtils/util"; +import { STATUS, TASK_FUN_TYPE } from "../../../consts"; +import { gameData } from "../../../pubUtils/data"; +import { UserTaskRecModel } from "../../../db/UserTaskRec"; +import { addItems } from "../../../services/rewardService"; +import { UserTaskModel } from "../../../db/UserTask"; +import { getCurWeekDate } from "../../../pubUtils/timeUtil"; +import { DicDailyTask, DicAchievement } from "../../../pubUtils/dictionary/DicTask"; +import { getMainTask } from "../../../services/taskService"; +import { TASK } from "../../../pubUtils/dicParam"; +import { RewardInter } from "../../../pubUtils/interface"; + +export default function(app: Application) { + return new ShopHandler(app); +} + +export class ShopHandler { + constructor(private app: Application) { + } + + // 领取主线任务、每日任务、成就单条任务 + async receiveTask(msg: { type: number, id: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { type, id } = msg; + + let dicTask = gameData.tasks.get(type).get(id); + let { group, taskType, taskReward, condition } = dicTask; + // 检查 + let rec = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); + if(!rec) return resResult(STATUS.TASK_NOT_REACH_CONDITION); + if(rec.count < condition) return resResult(STATUS.TASK_NOT_REACH_CONDITION); + if(rec.received.includes(id)) return resResult(STATUS.TASK_HAS_RECEIVED); + + // 领取记录 + rec = await UserTaskRecModel.receiveTask(roleId, type, taskType, group, id); + + // 每日、成就增加积分 + let point = 0, weeklyPoint = 0; + if(type == TASK_FUN_TYPE.DAILY) { // 增加积分 + let userTask = await UserTaskModel.findByRole(roleId); + let dic = dicTask; + let curWeek = getCurWeekDate(1, 5); + if(curWeek > userTask.dailyTaskRefWeekly) { + userTask = await UserTaskModel.resetDailyScore(roleId, dic.point, curWeek); + } else { + userTask = await UserTaskModel.incInfo(roleId, { dailyTaskPoint: dic.point, dailyTaskPointWeekly: dic.point }); + } + point = userTask.dailyTaskPoint; + weeklyPoint = userTask.dailyTaskPointWeekly; + } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { + let dic = dicTask; + let userTask = await UserTaskModel.incInfo(roleId, { achievementPoint: dic.point }); + point = userTask.achievementPoint; + } + + let goods = await addItems(roleId, roleName, sid, taskReward); + + return resResult(STATUS.SUCCESS, { + type, id, count: rec.count, received: rec.received.includes(id), + point, weeklyPoint, + goods + }); + } + + // 领取主线阶段奖励 + async receiveMainStage(msg: { stage: number }, session: BackendSession) { + + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { stage } = msg; + + let dicMainStage = gameData.mainTaskStage.get(stage); + if(!dicMainStage) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 检查 + let userTask = await UserTaskModel.findByRole(roleId); + if(userTask.mainTaskStage != stage) { + return resResult(STATUS.WRONG_PARMS); + } + let recs = await UserTaskRecModel.getReceiveRec(roleId, TASK_FUN_TYPE.MAIN); + for(let id of dicMainStage.mainTaskId) { + let curRecs = recs.find(cur => cur.received.includes(id)); + if(!curRecs) return resResult(STATUS.TASK_NOT_ALL_RECEIVED); + } + // 更新数据 + userTask = await UserTaskModel.incInfo(roleId, { mainTaskStage: 1 }); + + let goods = await addItems(roleId, roleName, sid, dicMainStage.reward); + let mainTask = await getMainTask(roleId, userTask); + + return resResult(STATUS.SUCCESS, { + type: TASK_FUN_TYPE.MAIN, + ...mainTask, + goods + }); + } + + // 领取每日活跃奖励 + async receiveActiveReward(msg: { }, session: BackendSession) { + + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + + // 检查 + let userTask = await UserTaskModel.findByRole(roleId); + let { dailyTaskPoint } = userTask; + if(dailyTaskPoint < TASK.DAILYTASK_POINT) { + return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + } + // 更新数据 + userTask = await UserTaskModel.decreaseDailyPoint(roleId, TASK.DAILYTASK_POINT); + if(!userTask) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + + let reward = parseGoodStr(TASK.DAILYTASK_POINT_REWARD); + let goods = await addItems(roleId, roleName, sid, reward); + + return resResult(STATUS.SUCCESS, { + type: TASK_FUN_TYPE.DAILY, + point: userTask.dailyTaskPoint, + goods + }); + } + + // 领取每日周宝箱 + async receiveBox(msg: { type: number, id: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { type, id } = msg; + + let userTask = await UserTaskModel.findByRole(roleId); + let dicTaskBox = gameData.taskBox.get(type)?.get(id); + if(!dicTaskBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let point = 0, weeklyPoint = 0, box: number[] = []; + // 每日、成就增加积分 + if(type == TASK_FUN_TYPE.DAILY) { // 增加积分 + let curWeek = getCurWeekDate(1, 5); + let shouldRefresh = false; + let { dailyTaskPointWeekly, dailyTaskBox, dailyTaskRefWeekly } = userTask; + + if(curWeek > dailyTaskRefWeekly) { + shouldRefresh = true; + dailyTaskPointWeekly = 0; + dailyTaskBox = []; + } + if(dailyTaskPointWeekly > dicTaskBox.point) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + if(dailyTaskBox.includes(id)) return resResult(STATUS.TASK_BOX_HAS_RECEIVED); + + userTask = await UserTaskModel.pushDailyBox(roleId, id, curWeek, shouldRefresh); + + point = userTask.dailyTaskPoint; + box = userTask.dailyTaskBox; + weeklyPoint = userTask.dailyTaskPointWeekly; + + } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { + let { achievementPoint, achievementBox } = userTask; + if(achievementPoint > dicTaskBox.point) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + if(achievementBox.includes(id)) return resResult(STATUS.TASK_BOX_HAS_RECEIVED); + + userTask = await UserTaskModel.pushAchievementBox(roleId, id); + + point = userTask.achievementPoint; + box = userTask.achievementBox; + } else { + return resResult(STATUS.WRONG_PARMS); + } + + let goods = await addItems(roleId, roleName, sid, dicTaskBox.reward); + + return resResult(STATUS.SUCCESS, { + type, + point, weeklyPoint, box, + goods + }); + } +} \ No newline at end of file diff --git a/game-server/app/services/normalBattleService.ts b/game-server/app/services/normalBattleService.ts index be39836be..3b6a1e210 100644 --- a/game-server/app/services/normalBattleService.ts +++ b/game-server/app/services/normalBattleService.ts @@ -65,7 +65,9 @@ export async function checkBattleHeroes(roleId: string, seqIds: Array) { if(findHeroes.length != seqIds.length) flag = false; for(let seqId of seqIds) { let hero = findHeroes.find(cur => cur.seqId == seqId); - if(!hero) flag = false; + if(!hero) { + flag = false; break; + } heroes.push(hero.hid); } return { isOK: flag, heroes }; diff --git a/game-server/app/services/taskService.ts b/game-server/app/services/taskService.ts index 7f670c37c..b43f2195f 100644 --- a/game-server/app/services/taskService.ts +++ b/game-server/app/services/taskService.ts @@ -2,13 +2,17 @@ import * as taskUtil from '../pubUtils/taskUtil'; import { RoleType } from '../db/Role'; import { pinus } from 'pinus'; import { resResult } from '../pubUtils/util'; -import { STATUS, TASK_TYPE } from '../consts'; -import { TaskParam } from '../domain/roleField/task'; +import { STATUS, TASK_TYPE, TASK_FUN_TYPE } from '../consts'; +import { TaskParam, TaskListReturn } from '../domain/roleField/task'; import { HeroType } from '../db/Hero'; import { EquipType } from '../db/Equip'; import { getRoleOnlineInfo } from './redisService'; import { HeroScores } from '../db/PvpHistoryOpp'; import { ItemInter } from '../pubUtils/interface'; +import { UserTaskModel, UserTaskType } from '../db/UserTask'; +import { UserTaskRecModel } from '../db/UserTaskRec'; +import { gameData } from '../pubUtils/data'; +import { getCurWeekDate } from '../pubUtils/timeUtil'; export async function checkTaskWithRoles(roleId: string, sid: string, funcs: number[], taskType: number, roles: RoleType[]) { for(let role of roles) { @@ -53,15 +57,17 @@ export async function checkTask(roleId: string, sid: string, funcs: number[], ta pushTaskUpdate(roleId, sid, funcs, pushMessage); } -export async function pushTaskUpdate(roleId: string, sid: string, funcs: number[], pushMessage: {type: number, id: number, count: number, received: boolean}[]) { - if(!sid || !funcs) { - let onlineUser = await getRoleOnlineInfo(roleId); - sid = onlineUser.sid; - funcs = onlineUser.funcs||[]; - } - if(!!sid) { - let uids = [{uid: roleId, sid}]; - pinus.app.get('channelService').pushMessageByUids('onTaskUpdate', resResult(STATUS.SUCCESS, pushMessage), uids); +export async function pushTaskUpdate(roleId: string, sid: string, funcs: number[], pushMessage: TaskListReturn[]) { + if(pushMessage.length > 0) { + if(!sid || !funcs) { + let onlineUser = await getRoleOnlineInfo(roleId); + sid = onlineUser.sid; + funcs = onlineUser.funcs||[]; + } + if(!!sid) { + let uids = [{uid: roleId, sid}]; + pinus.app.get('channelService').pushMessageByUids('onTaskUpdate', resResult(STATUS.SUCCESS, pushMessage), uids); + } } } @@ -104,4 +110,72 @@ export async function checkTaskInPvpEnd(roleId: string, sid: string, funcs: numb } await checkTask(roleId, sid, funcs, TASK_TYPE.PVP, 0, false, { heroScores }); +} + + +// 获取task状态 +export async function getCurTask(roleId: string) { + let userTask = await UserTaskModel.findByRole(roleId); + let mainTask = await getMainTask(roleId, userTask); + let dailyTask = await getDailyTask(roleId, userTask); + let achievement = await getAchievement(roleId, userTask); + return { mainTask, dailyTask, achievement }; +} + +export async function getMainTask(roleId: string, userTask: UserTaskType) { + let type = TASK_FUN_TYPE.MAIN; + let { mainTaskStage: stage } = userTask; + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for(let [id, dic] of gameData.mainTask) { + if(dic.taskStage == stage) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if(dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + } + return { stage, taskList } +} + +export async function getDailyTask(roleId: string, userTask: UserTaskType) { + let type = TASK_FUN_TYPE.DAILY; + let { dailyTaskPoint: point, dailyTaskRefWeekly, dailyTaskPointWeekly: weeklyPoint, dailyTaskBox: box } = userTask; + let curWeekStart = getCurWeekDate(1, 5); + if(dailyTaskRefWeekly < curWeekStart) { // 刷新 + weeklyPoint = 0; + box = []; + } + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for(let [id, dic] of gameData.dailyTask) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if(dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + return { point, weeklyPoint, taskList, box } +} + +export async function getAchievement(roleId: string, userTask: UserTaskType) { + let type = TASK_FUN_TYPE.ACHIEVEMENT; + let { achievementBox: box, achievementPoint: point } = userTask; + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for(let [id, dic] of gameData.dailyTask) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if(dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + return { point, taskList, box } } \ No newline at end of file diff --git a/shared/consts/constModules/itemConst.ts b/shared/consts/constModules/itemConst.ts index c4044573e..cb6a15399 100644 --- a/shared/consts/constModules/itemConst.ts +++ b/shared/consts/constModules/itemConst.ts @@ -125,6 +125,7 @@ const itid_array = [ { id: 32, name: '典籍', table: 'equip', type: EQUIP_TYPE.BOOK }, { id: 33, name: '神兵', table: 'equip', type: EQUIP_TYPE.WEAPON }, { id: 34, name: '代币', table: 'item', type: CONSUME_TYPE.POINT }, + { id: 53, name: '武将招募券', table: 'item', type: CONSUME_TYPE.POINT }, { id: 39, name: '时装', table: 'hero', type: CONSUME_TYPE.SKIN }, { id: 40, name: '装备碎片', table: 'item', type: CONSUME_TYPE.PIECE }, { id: 41, name: '图纸', table: 'item', type: CONSUME_TYPE.CONSUME }, diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index ea087c5e7..e16b1378e 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -469,7 +469,10 @@ export const FILENAME = { DIC_RANK_REWARD: 'dic_zyz_rankingReward', DIC_MAIN_TASK: 'dic_zyz_mainTask', DIC_DAILY_TASK: 'dic_zyz_dailyTask', - DIC_ACHIEVEMENT: 'dic_zyz_achievement' + DIC_ACHIEVEMENT: 'dic_zyz_achievement', + DIC_MAIN_TASK_STAGE: 'dic_zyz_mainTaskStage', + DIC_TASK_BOX: 'dic_zyz_taskBox', + DIC_ACHIEVEMENT_BOX: 'dic_zyz_dic_zyz_achievementBox', } export const WAR_RELATE_TABLES = [ diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index a53e3786b..4704d239b 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -313,6 +313,14 @@ export const STATUS = { SKIN_HAS_NOT_HERO: { code: 30903, simStr: '未拥有该武将不可获得皮肤' }, HERO_NOT_MAX: { code: 30904, simStr: '该武将未升满星' }, + // 任务相关 31001-31100 + TASK_NOT_REACH_CONDITION: { code: 30900, simStr: '任务不满足条件' }, + TASK_HAS_RECEIVED: { code: 30901, simStr: '奖励已领取' }, + TASK_NOT_ALL_RECEIVED: { code: 30902, simStr: '任务未领取完' }, + TASK_ACTIVE_NOT_ENOUGH: { code: 30903, simStr: '活跃不足' }, + TASK_POINT_NOT_ENOUGH: { code: 30904, simStr: '积分不足' }, + TASK_BOX_HAS_RECEIVED: { code: 30905, simStr: '奖励已领取' }, + // 社交相关状态 40000 - 49999 SYS_CHANNEL_AUTH_NOT_ENOUGH: {code: 40000, simStr: '无法在系统频道发送消息'}, UPDATE_PRIVATE_MSG_READ_TIME_ERR: {code: 40001, simStr: '更新私聊阅读时间失败'}, diff --git a/shared/db/UserTask.ts b/shared/db/UserTask.ts new file mode 100644 index 000000000..d924c3d8e --- /dev/null +++ b/shared/db/UserTask.ts @@ -0,0 +1,88 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; +import { getCurWeekDate } from '../pubUtils/timeUtil'; + +/** + * 玩家购买商店记录表,每个商品一条,每次刷新新建一条 +**/ +@modelOptions({ schemaOptions: { id: false } }) +@index({ roleId: 1, itemId: 1 }) + +export default class UserTask extends BaseModel { + + @prop({ required: true }) + roleId: string; // 玩家id + + @prop({ required: true, default: 1 }) + mainTaskStage: number; // 主线所处在的阶段 + + @prop({ required: true, default: 0 }) + dailyTaskPoint: number; // 每日任务的累计积分 + + @prop({ required: true }) + dailyTaskRefWeekly: Date; // 每日任务的每周刷新时间 + + @prop({ required: true, default: 0 }) + dailyTaskPointWeekly: number; // 每日任务的每周活跃积分 + + @prop({ required: true, type: Number, default: [] }) + dailyTaskBox: number[]; // 每日任务每周已领取箱子 + + @prop({ required: true, default: 0 }) + achievementPoint: number; // 成就积分 + + @prop({ required: true, type: Number, default: [] }) + achievementBox: number[]; // 成就已领取了的箱子 + + + public static async findByRole(roleId: string) { + let curWeek = getCurWeekDate(1, 5); + let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, { $setOnInsert: { + mainTaskStage: 1, dailyTaskPoint: 0, dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: 0, dailyTaskBox: [], achievementPoint: 0, achievementBox: [] + } }, { new: true, upsert: true }).lean(); + return rec; + } + + public static async resetDailyScore(roleId: string, point: number, curWeek: Date) { + let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, { + $set: { dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: point, dailyTaskBox: [] }, + $inc: { dailyTaskPoint: point } + }, { new: true }).lean(); + return rec; + } + + public static async incInfo(roleId: string, inc: UserTaskIncParam) { + let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, { + $inc: inc + }, { new: true }).lean(); + return rec; + } + + public static async decreaseDailyPoint(roleId: string, point: number) { + let rec: UserTaskType = await UserTaskModel.findOneAndUpdate( { roleId, dailyTaskPoint: { $gte: point }}, { $inc: { dailyTaskPoint: -point } }, { new: true }).lean(); + return rec; + } + + public static async pushDailyBox(roleId: string, id: number, curWeek: Date, shouldRefresh: boolean) { + let rec: UserTaskType; + if(shouldRefresh) { + rec = await UserTaskModel.findOneAndUpdate({ roleId }, { + $set: { dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: 0, dailyTaskBox: [ id ] } + }, { new: true }).lean() + } else { + rec = await UserTaskModel.findOneAndUpdate({ roleId }, { $push: { dailyTaskBox: id } }, { new: true }).lean(); + } + return rec; + } + + public static async pushAchievementBox(roleId: string, id: number) { + let rec = await UserTaskModel.findOneAndUpdate({ roleId }, { $push: { achievementBox: id } }, { new: true }).lean(); + return rec; + } +} + +export const UserTaskModel = getModelForClass(UserTask); + +export interface UserTaskType extends Pick, keyof UserTask> { } +export type UserTaskParam = Partial; +export type UserTaskIncParam = Pick; diff --git a/shared/db/UserTaskRec.ts b/shared/db/UserTaskRec.ts index 5d0da1858..b16cf95b6 100644 --- a/shared/db/UserTaskRec.ts +++ b/shared/db/UserTaskRec.ts @@ -32,34 +32,33 @@ export default class UserTaskRec extends BaseModel { @prop({ required: true }) count: number; // 达成次数 - @prop({ required: true, default: false }) - received: boolean; // 是否已领取 + @prop({ required: true, type: Number, default: [] }) + received: number[]; // 是否已领取 private static getRefreshCondition(type: number) { let today = getTodayZeroDate(5); if(type == TASK_FUN_TYPE.DAILY) { - return { createdAt: { $gte: today } }; + return { type, createdAt: { $gte: today } }; } else { - return {}; + return { type }; } } public static async setTaskRec(roleId: string, type: number, taskType: number, group: number, count: number) { let condition = this.getRefreshCondition(type); - let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, type, group, ...condition }, { $setOnInsert: { code: genCode(8), taskType, received: false }, $set: { count } }, { new: true, upsert: true }).lean(); + let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, group, taskType, ...condition }, { $setOnInsert: { code: genCode(8), received: [] }, $set: { count } }, { new: true, upsert: true }).lean(); return rec; } public static async incTaskRec(roleId: string, type: number, taskType: number, group: number, count: number) { let condition = this.getRefreshCondition(type); - let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, type, group, ...condition }, { $setOnInsert: { code: genCode(8), taskType, received: false }, $inc: { count } }, { new: true, upsert: true }).lean(); + let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, group, taskType, ...condition }, { $setOnInsert: { code: genCode(8), received: [] }, $inc: { count } }, { new: true, upsert: true }).lean(); return rec; } public static async checkHistoryAndSetTaskRec(roleId: string, type: number, taskType: number, group: number, count: number) { - let condition = this.getRefreshCondition(type); - let rec: UserTaskRecType = await UserTaskRecModel.findOne({ roleId, type, group, ...condition }).lean(); + let rec: UserTaskRecType = await UserTaskRecModel.findByRoleAndGroup(roleId, type, group, taskType); if(rec) { if(rec.count < count) { rec = await UserTaskRecModel.setTaskRec(roleId, type, taskType, group, count); @@ -70,7 +69,38 @@ export default class UserTaskRec extends BaseModel { return rec; } + public static async findByRoleAndType(roleId: string, type: number) { + let condition = this.getRefreshCondition(type); + let rec: UserTaskRecType[] = await UserTaskRecModel.find({ roleId, ...condition }).lean(); + let map = new Map>(); // taskType => group => userTask + for(let userTaskRec of rec) { + let { taskType, group } = userTaskRec; + if(!map.has(taskType)) { + map.set(taskType, new Map()); + } + map.get(taskType).set(group, userTaskRec); + } + return map; + } + + public static async findByRoleAndGroup(roleId: string, type: number, taskType: number, group: number) { + let condition = this.getRefreshCondition(type); + let rec: UserTaskRecType = await UserTaskRecModel.findOne({ roleId, taskType, group, ...condition }).lean(); + return rec; + } + public static async receiveTask(roleId: string, type: number, taskType: number, group: number, id: number) { + let condition = this.getRefreshCondition(type); + let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, taskType, group, ...condition }, { $push: { received: id } }, { new: true }).lean(); + return rec; + } + + public static async getReceiveRec(roleId: string, type: number) { + let condition = this.getRefreshCondition(type); + let rec = await UserTaskRecModel.find({ roleId, ...condition }).lean(); + console.log(JSON.stringify(rec)) + return rec + } } export const UserTaskRecModel = getModelForClass(UserTaskRec); diff --git a/shared/domain/roleField/task.ts b/shared/domain/roleField/task.ts index 5c4cfd6e3..ad6b5ee0b 100644 --- a/shared/domain/roleField/task.ts +++ b/shared/domain/roleField/task.ts @@ -22,4 +22,11 @@ export class TaskParam { title?: number; job?: number; aid?: number; +} + +export class TaskListReturn { + type: number; // 类型 + id: number; // 任务id + count: number; // 达成次数 + received: boolean; // 是否领取 } \ No newline at end of file diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index 4da39b1db..a133c6059 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -73,7 +73,9 @@ import { dicShop, dicShopItem } from "./dictionary/DicShop"; import { dicShopList } from "./dictionary/DicShopList"; import { dicRank } from "./dictionary/DicRank"; import { dicRankReward } from "./dictionary/DicRankReward"; -import { dicTaskType, dicMainTask, dicDailyTask, dicAchievement } from "./dictionary/DicTask"; +import { dicTaskType, taskMap, dicMainTask, dicDailyTask, dicAchievement } from "./dictionary/DicTask"; +import { dicMainTaskStage } from "./dictionary/DicMainTaskStage"; +import { dicTaskBox } from './dictionary/DicTaskBox'; export const gameData = { blurprtCompose: dicBlueprtCompose, @@ -174,9 +176,12 @@ export const gameData = { rank: dicRank, generalRankReward: dicRankReward, taskType: dicTaskType, + tasks: taskMap, mainTask: dicMainTask, dailyTask: dicDailyTask, - achievement: dicAchievement + achievement: dicAchievement, + mainTaskStage: dicMainTaskStage, + taskBox: dicTaskBox }; // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 diff --git a/shared/pubUtils/dictionary/DicMainTaskStage.ts b/shared/pubUtils/dictionary/DicMainTaskStage.ts new file mode 100644 index 000000000..079e5e4df --- /dev/null +++ b/shared/pubUtils/dictionary/DicMainTaskStage.ts @@ -0,0 +1,27 @@ +// 主线任务阶段内容 +import {readJsonFile, parseNumberList, parseGoodStr} from '../util' +import { FILENAME } from '../../consts' +import { RewardInter } from '../interface'; + +export interface DicMainTaskStage { + // id + readonly id: number; + // 阶段 + readonly stageId: number; + // 包括哪些id + readonly mainTaskId: number[]; + // 奖励 + readonly reward: RewardInter[]; +} + +const str = readJsonFile(FILENAME.DIC_MAIN_TASK_STAGE); +let arr = JSON.parse(str); + +export const dicMainTaskStage = new Map(); + +arr.forEach(o => { + o.mainTaskId = parseNumberList(o.mainTaskId); + o.reward = parseGoodStr(o.reward); + dicMainTaskStage.set(o.id, o); +}); +arr = undefined; \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicTask.ts b/shared/pubUtils/dictionary/DicTask.ts index db3f37aee..0d0621078 100644 --- a/shared/pubUtils/dictionary/DicTask.ts +++ b/shared/pubUtils/dictionary/DicTask.ts @@ -89,6 +89,10 @@ export type DicTask = DicTaskBase & { type: number }; export const dicMainTask = new Map(); // 主线任务 export const dicDailyTask = new Map(); // 每日任务 export const dicAchievement = new Map(); // 成就 +export const taskMap = new Map>(); +taskMap.set(TASK_FUN_TYPE.MAIN, dicMainTask); +taskMap.set(TASK_FUN_TYPE.DAILY, dicDailyTask); +taskMap.set(TASK_FUN_TYPE.ACHIEVEMENT, dicAchievement); export const dicTaskType = new Map(); diff --git a/shared/pubUtils/dictionary/DicTaskBox.ts b/shared/pubUtils/dictionary/DicTaskBox.ts new file mode 100644 index 000000000..67c2d11eb --- /dev/null +++ b/shared/pubUtils/dictionary/DicTaskBox.ts @@ -0,0 +1,37 @@ +// 主线任务阶段内容 +import {readJsonFile, parseGoodStr} from '../util' +import { FILENAME, TASK_FUN_TYPE } from '../../consts' +import { RewardInter } from '../interface'; + +export interface DicTaskBox { + // id + readonly id: number; + // 积分 + readonly point: number; + // 奖励 + readonly reward: RewardInter[]; +} + +export const dicTaskBox = new Map>(); + +const str1 = readJsonFile(FILENAME.DIC_TASK_BOX); +let arr1 = JSON.parse(str1); +arr1.forEach(o => { + if(!dicTaskBox.has(TASK_FUN_TYPE.DAILY)) { + dicTaskBox.set(TASK_FUN_TYPE.DAILY, new Map()); + } + o.reward = parseGoodStr(o.reward); + dicTaskBox.get(TASK_FUN_TYPE.DAILY).set(o.id, o); +}); +arr1 = undefined; + +const str2 = readJsonFile(FILENAME.DIC_ACHIEVEMENT_BOX); +let arr2 = JSON.parse(str2); +arr2.forEach(o => { + if(!dicTaskBox.has(TASK_FUN_TYPE.ACHIEVEMENT)) { + dicTaskBox.set(TASK_FUN_TYPE.ACHIEVEMENT, new Map()); + } + o.reward = parseGoodStr(o.reward); + dicTaskBox.get(TASK_FUN_TYPE.ACHIEVEMENT).set(o.id, o); +}); +arr2 = undefined; \ No newline at end of file diff --git a/shared/pubUtils/taskUtil.ts b/shared/pubUtils/taskUtil.ts index 0b765fac0..8b1be655e 100644 --- a/shared/pubUtils/taskUtil.ts +++ b/shared/pubUtils/taskUtil.ts @@ -3,14 +3,14 @@ import { DicTask } from './dictionary/DicTask'; import { TASK_TYPE, ABI_STAGE, WAR_TYPE, GUILD_JOB, TASK_FUN_TYPE, FUNCS_ID } from '../consts'; import { UserTaskRecModel, UserTaskRecType } from '../db/UserTaskRec' import { RoleType, RoleModel } from '../db/Role'; -import { TaskParam } from '../domain/roleField/task'; +import { TaskParam, TaskListReturn } from '../domain/roleField/task'; import { getTodayZeroPoint } from './timeUtil'; import { HeroType } from '../db/Hero'; import { EquipType, EquipModel } from '../db/Equip'; import { ItemInter } from './interface'; export async function checkTaskWithRoles(taskType: number, roles: RoleType[], funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); for(let role of roles) { if(role) { let singlePush = await checkTaskWithRole(role.roleId, taskType, role, funcs); @@ -21,7 +21,7 @@ export async function checkTaskWithRoles(taskType: number, roles: RoleType[], fu } export async function checkTaskWithRole(roleId: string, taskType: number, role: RoleType, funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); if(taskType == TASK_TYPE.LOGIN_SUM) { @@ -52,7 +52,7 @@ export async function checkTaskWithRole(roleId: string, taskType: number, role: export async function checkTaskWithHeroes(roleId: string, taskType: number, heroes: HeroType[], funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); for(let hero of heroes) { let singlePush = await checkTaskWithHero(roleId, taskType, hero, [], funcs); pushMessage.concat(singlePush); @@ -61,7 +61,7 @@ export async function checkTaskWithHeroes(roleId: string, taskType: number, hero } export async function checkTaskWithHero(roleId: string, taskType: number, hero: HeroType, args: number[] = [], funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); if(taskType == TASK_TYPE.HERO_STAR_UP) { let dicHero = gameData.hero.get(hero.hid); @@ -133,7 +133,7 @@ export async function checkTaskWithHero(roleId: string, taskType: number, hero: export async function checkTaskWithEquip(roleId: string, taskType: number, equip: EquipType, args: number[] = [], funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); if(taskType == TASK_TYPE.EQUIP_QUALITY) { // args[0] 1:装上 -1:脱下 @@ -194,7 +194,7 @@ export async function checkTaskWithEquip(roleId: string, taskType: number, equip } export async function checkTaskWithArgs(roleId: string, taskType: number, args: number[], funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); if(taskType == TASK_TYPE.ROLE_SCHOOL_PUT_HERO) { @@ -231,7 +231,7 @@ export async function checkTaskWithArgs(roleId: string, taskType: number, args: export async function checkTaskWithWar(roleId: string, taskType: number, warId: number, heroes: number[], count: number, star: number, funcs?: number[]) { let dicWar = gameData.war.get(warId); - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); if(taskType == TASK_TYPE.BATTLE_WITH_HERO) { pushMessage = await checkTask(roleId, taskType, count, true, { warId, heroes }, funcs); @@ -295,7 +295,7 @@ export async function checkTaskWithWar(roleId: string, taskType: number, warId: export async function checkTaskWithGoods(roleId: string, taskType: number, goods: ItemInter[], funcs?: number[]) { - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); if(taskType == TASK_TYPE.COM_BATTLE_DROP) { for(let { id, count } of goods) { @@ -309,7 +309,7 @@ export async function checkTaskWithGoods(roleId: string, taskType: number, goods // 根据taskType判断有哪些任务需要check的 export async function checkTask(roleId: string, taskType: number, count: number, isInc: boolean, param: TaskParam, funcs?: number[]) { let tasks = gameData.taskType.get(taskType)||[]; - let pushMessage = new Array<{type: number, id: number, count: number, received: boolean}>(); + let pushMessage = new Array(); let groups = new Map(); for(let dicTask of tasks) { if(!groups.has(dicTask.group)) { @@ -326,8 +326,9 @@ export async function checkTask(roleId: string, taskType: number, count: number, let rec = await checkTaskRec(roleId, group, task0, count, isInc, param, funcs); if(rec) { for(let dicTask of tasks) { - if(checkRecResult(rec, dicTask.condition)) { - pushMessage.push({ type: dicTask.type, id: dicTask.id, count: rec.count, received: rec.received }); + if(checkRecResult(rec, dicTask.id, dicTask.condition)) { + let received = rec.received||[]; + pushMessage.push({ type: dicTask.type, id: dicTask.id, count: rec.count, received: received.includes(dicTask.id) }); } } } @@ -473,9 +474,9 @@ function checkHero(taskParam: number[], index: number, heroes: number[]) { return heroes.indexOf(hid) != -1; } -function checkRecResult(rec: UserTaskRecType, condition: number) { +function checkRecResult(rec: UserTaskRecType, id: number, condition: number) { if(!rec) return false; - if(rec.received) return false; + if(rec.received && rec.received.includes(id)) return false; // 已领取,不再推送 if(rec.count >= condition) { return rec