import { STATUS } from './../../../consts/statusCode'; import { HANG_UP_CONSTS, GOLD_COST_RATIO, TOWER_TASK_CONST, REDIS_KEY, CURRENCY_BY_TYPE, CURRENCY_TYPE } from './../../../consts'; import { TowerTaskRecModel } from './../../../db/TowerTaskRec'; import { HangUpSpdUpRecModel } from './../../../db/HangUpSpdUpRec'; import { HangUpRecordModel } from './../../../db/HangUpRecord'; import { RoleModel } from './../../../db/Role'; import { TowerRecordModel } from './../../../db/TowerRecord'; import { Application, BackendSession } from 'pinus'; 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 { checkBattleHeroes } from '../../../services/normalBattleService'; import { getRank, setRank, initRank, existsRank } from '../../../services/redisService'; export default function(app: Application) { return new TowerBattleHandler(app); } export class TowerBattleHandler { constructor(private app: Application) { } /** * 获取天梯当前挑战状态 * @param session */ async getStatus(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let serverId = session.get('serverId'); let { towerLv } = await RoleModel.findByRoleId(roleId); if (!towerLv) { towerLv = 1; let role = await RoleModel.towerLvUp(roleId); // 更新redis let { roleName, towerUpTime, lv, vLv } = role; await setRank(REDIS_KEY.TOWER_RANK, serverId, roleId, towerLv, towerUpTime.getTime(), {roleName, lv, vLv, guildName:"", head: "zhaoyun"}); } let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv); if (!towerRec) { const towerInfo = getTowerDataByLv(towerLv); const { warArray } = towerInfo; const sts = decodeArrayStr(warArray, '&').map(id => { return {warId: parseInt(id), status: false}; }); towerRec = await TowerRecordModel.createRecord({roleId, lv: towerLv, warStatus: sts}); // return { code: 201, data: '天梯记录异常' }; } const data = { canHungUp: towerLv >= HANG_UP_CONSTS.ENABLE_LV, hungUpEnableLv: HANG_UP_CONSTS.ENABLE_LV, canSendTask: true, curLv: towerLv, usedHeroes: towerRec.heroes, progress: towerRec.warStatus }; return resResult(STATUS.SUCCESS, data); } /** * 重置天梯当前层的挑战记录 * @param towerLv 要重置的天梯层数 * @param session */ async resetLv(msg: {towerLv: number}, session: BackendSession) { let roleId = session.get('roleId'); let { towerLv } = await RoleModel.findByRoleId(roleId); if (msg.towerLv !== towerLv) { return resResult(STATUS.TOWER_RESET_ERR); } const record = await TowerRecordModel.resetRecordByLv(roleId, towerLv); if (!record) { return resResult(STATUS.TOWER_NOT_FOUND); } return resResult(STATUS.SUCCESS, record); } async checkHangUpRewards(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); const result = await calcuHangUpReward(roleId); if(result.status == -1) { return result.resResult } let {timeReward, startTime, deltaTime} = result.data; let {hangUpSpdUpCnt, lastSpdUpTime} = await RoleModel.findByRoleId(roleId); let curTime = new Date(); if (!lastSpdUpTime || (shouldRefresh(lastSpdUpTime, curTime, HANG_UP_CONSTS.REFRESH_TIME, 1) && hangUpSpdUpCnt <= HANG_UP_CONSTS.MAX_SPD_UP_CNT)) { hangUpSpdUpCnt = HANG_UP_CONSTS.MAX_SPD_UP_CNT; } let num = HANG_UP_CONSTS.MAX_SPD_UP_CNT - hangUpSpdUpCnt + 1; let nextCostGold = calculateNum(GOLD_COST_RATIO.TOWER_HANG_SPDUP, {num}, 50); return resResult(STATUS.SUCCESS, {startTime, hangUpPassTime: Math.floor(deltaTime/1000), hangUpSpdUpCnt, nextCostGold, rewards: timeReward}); } async recHangUpRewards(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); const result = await calcuHangUpReward(roleId); if(result.status == -1) { return result.resResult } let { timeReward, endLv, endTime, deltaTime, needReceiveGoods } = result.data; const goods = await addItems(roleId, roleName, sid, timeReward); await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods); return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.UNIT_TIME)/1000), goods }); } async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); if (msg.speedUpCnt <= 0) { return resResult(STATUS.WRONG_PARMS); } const curTime = new Date(); const calResult = await calcuHangUpReward(roleId, true, msg.speedUpCnt, curTime); if(calResult.status == -1) { return calResult.resResult; } let { timeReward, endLv, deltaTime, needReceiveGoods } = calResult.data; let result = await checkHangUpSpdUpCnt(roleId, msg.speedUpCnt, curTime); if(result.status == -1) return result.resResult; let {data: {hangUpSpdUpCnt, gold}} = result; const costGold = this.getHangUpCost(hangUpSpdUpCnt, msg.speedUpCnt); if(costGold > gold) { return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); } await handleCost(roleId, sid, [{id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: costGold}]) const spdUpResult = await RoleModel.hangUpSpdUp(roleId, msg.speedUpCnt, curTime); if (!spdUpResult) { return resResult(STATUS.TOWER_HANG_UP_FAILED); } const spdUpRec = await HangUpSpdUpRecModel.updateRec(roleId, roleName, msg.speedUpCnt, endLv, needReceiveGoods); const goods = await addItems(roleId, roleName, sid, timeReward); hangUpSpdUpCnt -= msg.speedUpCnt; let num = HANG_UP_CONSTS.MAX_SPD_UP_CNT - hangUpSpdUpCnt + 1; let nextCostGold = calculateNum(GOLD_COST_RATIO.TOWER_HANG_SPDUP, {num}, 50); return resResult(STATUS.SUCCESS, { goods, hangUpSpdUpCnt, nextCostGold, hangUpPassTime: Math.floor(deltaTime/1000), rewardLv: endLv, costGold }); } getHangUpCost(originCnt: number, count: number) { let gold = 0; for(let i = 1; i <= count; i++) { let num = HANG_UP_CONSTS.MAX_SPD_UP_CNT - originCnt + i; if(num < 0) num = i; gold += calculateNum(GOLD_COST_RATIO.TOWER_HANG_SPDUP, {num}, 50); } return gold } async getTasks(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let curTime = new Date(); let { towerLv, towerTaskRefTime, towerTaskReCnt = 0 } = await RoleModel.findByRoleId(roleId); let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 const needRefresh = shouldRefresh(towerTaskRefTime, curTime, TOWER_TASK_CONST.REFRESH_TIME); if(needRefresh) { const batchCode = genCode(8); let {waitingTaskCode, doingTaskCode, doingIds} = getDoingOrWaitingTasks(curTasks, curTime); await TowerTaskRecModel.hideTask(roleId, waitingTaskCode); // 隐藏没有在做的任务 await TowerTaskRecModel.updateBatchCode(roleId, doingTaskCode, batchCode); // 更新留下来的旧任务的batchCode await createCurTasks(towerLv, batchCode, roleId, roleName, doingTaskCode.length, TOWER_TASK_CONST.RAND_CNT-doingTaskCode.length, doingIds); // 新建任务 curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 重置派遣次数 const role = await RoleModel.resetTowerCnt(roleId, curTime); towerTaskReCnt = role.towerTaskReCnt; } let refRemainTime = getRemainTime(curTime); let nextCostGold = calculateNum(GOLD_COST_RATIO.TOWER_TASK_REF, {num: towerTaskReCnt + 1}, 50); return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold }); } async refreshTasks(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let curTime = new Date(); let { towerLv, towerTaskCnt = 0, towerTaskReCnt=0 } = await RoleModel.findByRoleId(roleId); if(TOWER_TASK_CONST.MAX_TASK_REF_CNT <= towerTaskCnt) { // 每派遣一个任务加一,最多8个完成任务 return resResult(STATUS.TOWER_REF_CNT_NOT_ENOUGH); } let costGold = calculateNum(GOLD_COST_RATIO.TOWER_TASK_REF, {num: towerTaskReCnt}, 50); let {gold} = await RoleModel.findByRoleId(roleId); if(costGold > gold) { return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); } // 只刷掉当前面板上没有做派遣的任务 const batchCode = genCode(8); let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 let {waitingTaskCode, doingTaskCode, doingIds} = getDoingOrWaitingTasks(curTasks, curTime); await TowerTaskRecModel.hideTask(roleId, waitingTaskCode); // 隐藏没有在做的任务 await TowerTaskRecModel.updateBatchCode(roleId, doingTaskCode, batchCode); // 更新留下来的旧任务的batchCode await createCurTasks(towerLv, batchCode, roleId, roleName, 0, waitingTaskCode.length, doingIds); curTasks = await TowerTaskRecModel.getCurTasks(roleId); await RoleModel.increaseTowerRefCnt(roleId, 1); let refRemainTime = getRemainTime(curTime); let nextCostGold = calculateNum(GOLD_COST_RATIO.TOWER_TASK_REF, {num: towerTaskReCnt + 1}, 50); return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), costGold, nextCostGold, refRemainTime}); } async sendTaskHero(msg: {batchCode: string, tasks: Array<{taskCode: string, heroes: Array}>}, session: BackendSession) { let roleId = session.get('roleId'); const curTime = new Date(); let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前一批的任务 if (!curTasks || curTasks.length == 0) { return resResult(STATUS.TOWER_TASK_NOT_FOUND); } let usedHeroes = [], tasks = []; const tasksCode = []; const taskMap = new Map() curTasks.forEach(task => { usedHeroes = usedHeroes.concat(task.heroes); tasksCode.push(task.taskCode); taskMap.set(task.taskCode, task); }); for (let task of msg.tasks) { let curTask = taskMap.get(task.taskCode); // 数据库中,这个任务的数据 if(!curTask) { return resResult(STATUS.TOWER_TASK_MISSING) } let taskInfo = getTaskById(curTask.taskId); if (task.heroes.length !== taskInfo.actorNeeded) { // 武将数,从策划表中读取 return resResult(STATUS.TOWER_TASK_MAX_HERO); } let hasHero = await checkBattleHeroes(roleId, task.heroes); if(!hasHero) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); if (tasksCode.indexOf(task.taskCode) === -1) { return resResult(STATUS.TOWER_TASK_CODE_NOT_FOUND); } if (usedHeroes.length > 0) { // 是否在其他任务重使用了武将 let used = !!task.heroes.find(seqId => usedHeroes.indexOf(seqId) !== -1); if (used) { return resResult(STATUS.TOWER_TASK_HERO_HAS_USED); } } tasks.push({...task, completeTime: taskInfo.completeTime}) } const recs = await TowerTaskRecModel.sendHeroes(roleId, msg.batchCode, tasks, curTime,); if (!recs || recs.length === 0) { return resResult(STATUS.TOWER_TASK_SEND_ERR); } await RoleModel.increaseTowerCnt(roleId, tasks.length) let refRemainTime = getRemainTime(curTime); curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 let costGold = TOWER_TASK_CONST.COST_GOLD; return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold: costGold }); } async settleTask(msg: {batchCode: string, taskCode: string}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); let allFlag = !msg.taskCode; const curTime = new Date(); let curTasks = await TowerTaskRecModel.getCurTasks(roleId); if (!curTasks || curTasks.length == 0) { return resResult(STATUS.TOWER_TASK_NOT_FOUND); } const compTasks = []; let goods = []; for (let task of curTasks) { if (task.batchCode !== msg.batchCode) { return resResult(STATUS.TOWER_TASK_BATCH_NOT_FOUND); } if ((allFlag || task.taskCode === msg.taskCode) && task.status === 1) { let {completeTime, reward, termsForAdd, additionalReward} = getTaskById(task.taskId); if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) { compTasks.push(task.taskCode); const rewardGoods = await handleFixedReward(roleId, roleName, sid, reward, 1); goods = goods.concat(rewardGoods); if(termsForAdd) { const result = await checkTaskConditions(roleId, task.heroes, termsForAdd); const bonusGoods = await handleFixedReward(roleId, roleName, sid, result?additionalReward:'', 1); goods = goods.concat(bonusGoods); } } } } await TowerTaskRecModel.finishTask(msg.batchCode, compTasks); await TowerTaskRecModel.showTask(roleId, msg.batchCode, compTasks.length); let refRemainTime = getRemainTime(curTime); curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 let costGold = TOWER_TASK_CONST.COST_GOLD; return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold }); } async getTowerRank(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let serverId = session.get('serverId') const hasTowerRank = await existsRank(REDIS_KEY.TOWER_RANK, serverId); if(!hasTowerRank) await initRank(serverId); let {ranks, myRank} = await getRank(REDIS_KEY.TOWER_RANK, serverId, roleId); if(!myRank) { let role = await RoleModel.findByRoleId(roleId); let {towerLv, lv, vLv} = role; myRank = { rank: 0, roleId, roleName, lv, vLv,guildName: "", head: "zhaoyun", num: towerLv, str: '' } } return resResult(STATUS.SUCCESS, { ranks, myRank }); } }