import { Application, BackendSession, HandlerService, } from 'pinus'; import { BattleRecordModel } from '../../../db/BattleRecord'; import { ExpeditionRecordModel } from '../../../db/ExpeditionRecord'; import { ExpeditionWarRecordModel } from '../../../db/ExpeditionWarRecord'; import { ExpeditionPointModel } from '../../../db/ExpeditionPoint'; import Role from '../../../db/Role'; import { genCode, getWarTypeName } from '../../../pubUtils/util'; import { getPointRewardStatus, getResetRemainCnt, findOrCreateEnemies, getExpeditionStatus } from '../../../services/expeditionService'; import { DEBUG_MAGIC_WORD, EXPEDITION_WAR_RECORD_STATUS, ITEM_CHANGE_REASON, KING_EXP_RATIO_TYPE, TASK_TYPE, TA_EVENT } from '../../../consts'; import { WarReward } from '../../../services/warRewardService'; import { addItems } from '../../../services/role/rewardService'; import { getAp, setAp } from '../../../services/actionPointService'; import { STATUS } from '../../../consts/statusCode'; import { resResult } from '../../../pubUtils/util'; import { calculateWarStar, checkBattleHeroes, roleLevelup } from '../../../services/normalBattleService'; import { checkTask, checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInSkipExpedition } from '../../../services/task/taskService'; import { gameData } from '../../../pubUtils/data'; import * as dicParam from '../../../pubUtils/dicParam'; import { getSeconds, nowSeconds } from '../../../pubUtils/timeUtil'; import { reportTAEvent } from '../../../services/sdkService'; import { getSumCe } from '../../../services/playerCeService'; import { vipCanSkipExpedition } from '../../../services/activity/monthlyTicketService'; import { isHeroHidden } from '../../../services/dataService'; export default function (app: Application) { new HandlerService(app, {}); return new ExpeditionBattleHandler(app); } export class ExpeditionBattleHandler { constructor(private app: Application) { } /** * 获取初始数据 * 获取当前远征挑战情况,远征点数,点数宝箱领取情况 */ async getStatus(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let res = await getExpeditionStatus(roleId, roleName); if (!res) return resResult(STATUS.ROLE_IS_NOT_INIT); return resResult(STATUS.SUCCESS, res); } /** * 重置远征本 * 每天5点可以重置远征本 */ async resetStatus(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let curTime = new Date(); let { needRefresh, resetCnt } = await getResetRemainCnt(curTime, roleId); if (resetCnt <= 0) { return resResult(STATUS.EXPEDITION_RESET_NUM_NOT_ENOUGH) } await ExpeditionRecordModel.hideRecord(roleId); // 刷掉旧关卡 // 我方战力 let myCe = await getSumCe(roleId); // 每一关的挑战状态 let { expeditionCode, heroes } = await ExpeditionRecordModel.createRecord({ roleId, roleName, heroes: [], myCe }); await findOrCreateEnemies(roleId, myCe, expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); await Role.increaseExpeditionResetCnt(roleId, needRefresh, curTime); let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode); let curLv = 0; if (expeditionWarRecord.length > 0) { curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId; } return resResult(STATUS.SUCCESS, { expeditionCode, curLv, expeditionWarRecord, heroes, resetCnt: resetCnt - 1 }); } /** * 获取敌军数据 * 匹配其他玩家,或机器人数据 */ async getEnemies(msg: { expeditionCode: string, expeditionId: number }, session: BackendSession) { const roleId = session.get('roleId'); // const roleName = session.get('roleName'); const { expeditionCode, expeditionId } = msg; let { myCe } = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); let curExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING); if (!curExpeditionWarRecord) { return resResult(STATUS.EXPEDITION_MATCH_NO_PLAYER); } let { battleId, mapseid, enemyFrom, enemies, battleStatus, ce: curCe } = curExpeditionWarRecord; let nextCe = 0; // 下一关战力 if (gameData.expedition.has(expeditionId + 1)) { let nextExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.HIDE); if (nextExpeditionWarRecord) nextCe = nextExpeditionWarRecord.ce; } return resResult(STATUS.SUCCESS, { expeditionCode, expeditionId, battleId, mapseid, battleStatus, enemyFrom, enemies, curCe, nextCe }); } /** * 进入战斗 * 记录我军数据,生成战斗唯一表示,记录状态 */ async checkBattle(msg: { expeditionCode: string, expeditionId: number, battleId: number, heroes: number[] }, session: BackendSession) { const { expeditionCode, expeditionId, battleId, heroes: seqIds = [] } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let ip = session.get('ip'); let serverId = session.get('serverId'); let sid = session.get('sid'); let warInfo = gameData.war.get(battleId); if (!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } let role = await Role.findByRoleId(roleId, 'lv warStar'); let apJson = await getAp(roleId, ip, role.lv); let { ap } = apJson; if (ap < warInfo.cost) { return resResult(STATUS.BATTLE_ACTION_POINT_LACK); } // 前置关卡是否挑战过 let previousGk = warInfo.previousGk; if (previousGk) { let preBattle = role.warStar.findIndex(cur => cur.id == previousGk); if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); } let { isOK, hids } = await checkBattleHeroes(roleId, seqIds); if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); if (!expeditionWarRecord) { return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); } if (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) { return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); } const battleCode = genCode(8); await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { roleId, roleName, battleId, status: 0, warName: warInfo.gk_name, warType: warInfo.warType, record: { heroes: hids, seqIds } } }, true); let result = await ExpeditionWarRecordModel.updateBattleCode(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING, battleCode); await checkTaskInBattleStart(serverId, roleId, sid, battleId); return resResult(STATUS.SUCCESS, { expeditionCode, expeditionId, battleId, battleCode, battleStatus: result.battleStatus }); } /** * 跳过 */ async skipExpedition(msg: { expeditionCode: string, expeditionId: number, battleId: number }, session: BackendSession) { const { expeditionCode, expeditionId, battleId } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let serverId = session.get('serverId'); let sid = session.get('sid'); let dicExpedition = gameData.expedition.get(expeditionId); if(dicExpedition.warId != battleId) return resResult(STATUS.WRONG_PARMS); let dicWar = gameData.war.get(battleId); if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); // 前置关卡是否挑战过 let role = await Role.findByRoleId(roleId, 'warStar topLineupCe vipStartTime') let { warStar, topLineupCe, vipStartTime } = role; let previousGk = dicWar.previousGk; if (previousGk) { let preBattle = warStar.findIndex(cur => cur.id == previousGk); if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); } // 检查record let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); if (!expeditionRecord || !expeditionWarRecord) { return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); } if(expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) { return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); } // 检查战力是否足够 if(!vipCanSkipExpedition(expeditionWarRecord.ce, topLineupCe, vipStartTime)) { return resResult(STATUS.EXPEDITION_SKIP_POWER_NOT_ENOUGH) } // 更新敌人剩余状态及战斗状态 expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.SUCCESS, []); // 更新点数 role = await Role.increaseExpeditionPoint(roleId, dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS); // 关卡奖励 let warReward = new WarReward(roleId, roleName, sid, battleId, true); let reward = await warReward.saveReward(1); let curWarStar = warStar.find(cur => cur.id == battleId); let { newWarStars, newStar } = calculateWarStar(warStar, battleId, []); if (!curWarStar || newStar > curWarStar.star) { role = await Role.updateRoleInfo(roleId, { warStar: newWarStars }); } // 更新下一关状态 if (gameData.expedition.has(expeditionId + 1)) { await findOrCreateEnemies(roleId, expeditionRecord.myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); } await checkTaskInSkipExpedition(serverId, roleId, sid, battleId); return resResult(STATUS.SUCCESS, { expeditionCode, expeditionId, battleId, goods: reward, expeditionPoint: role.expeditionPoint }); } /** * 战斗结算 * 结算战斗奖励,更新远征状态 */ async battleEnd(msg: { expeditionCode: string, expeditionId: number, battleCode: string, battleId: number, isSuccess: boolean, heroes: Array<{ dataId: number, hp: number, ap: number, shield: number }>, enemies: Array<{ dataId: number, hp: number, ap: number }>, star: number, stars: number[] }, session: BackendSession) { const { expeditionCode, battleCode, battleId, expeditionId, isSuccess, heroes = [], star, stars = [], enemies } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); const serverId = session.get('serverId'); let sid = session.get('sid'); let ip = session.get('ip'); let warInfo = gameData.war.get(battleId); if (!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); if (!BattleRecord || BattleRecord.status != 0) { return resResult(STATUS.BATTLE_STATUS_WRONG); } let flag = 1; // 对比hero信息 let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord; for (let { dataId } of heroes) { if (dbSeqIds.indexOf(dataId) == -1) flag = 0; } if (!flag) { return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); } let role = await Role.findByRoleId(roleId, 'lv'); let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess?-1 * warInfo.cost: 0, sid, ITEM_CHANGE_REASON.EXPEDITION_BATTLE_END); // 扣除体力 if (!apJson) { return resResult(STATUS.BATTLE_ACTION_POINT_LACK); } // 检查record let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); if (!expeditionRecord || !expeditionWarRecord) { return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); } // 更新我方剩余血量 await ExpeditionRecordModel.updateHeroStatus(expeditionCode, expeditionRecord.heroes, heroes); // 更新敌人剩余状态及战斗状态 let battleStatus = isSuccess ? EXPEDITION_WAR_RECORD_STATUS.SUCCESS : EXPEDITION_WAR_RECORD_STATUS.FAIL; expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, battleStatus, enemies); // 更新battleRecord状态 await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess ? 1 : 2, star } }, true); // 更新点数 role = await Role.increaseExpeditionPoint(roleId, isSuccess ? dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS : 0); let { expeditionPoint = 0, warStar = [] } = role; // 关卡奖励 let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess); let reward = await warReward.saveReward(1); let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验 let curWarStar = warStar.find(cur => cur.id == battleId); let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars); if (isSuccess) { // 更新下一关状态 await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); if(!curWarStar) { // 首通 reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes }); } if (!curWarStar || newStar > curWarStar.star) { await Role.updateRoleInfo(roleId, { warStar: newWarStars }); } } await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, star, isSuccess); return resResult(STATUS.SUCCESS, { expeditionCode, expeditionId, battleCode, battleId, battleStatus: expeditionWarRecord.battleStatus, battleGoods: reward, expeditionPoint, createdAt: getSeconds(createdAt), ...actordata }); } /** * 领取点数宝箱 * 领取点数宝箱,不扣除点数,那么就需要记录领取状态并且有返回 */ async pointReward(msg: { point: number }, session: BackendSession) { const { point } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); const serverId = session.get('serverId'); let role = await Role.findByRoleId(roleId); let { expeditionPoint } = role; let dicExpeditionPoint = gameData.expeditionPoint; let curDicExpeditionPoint = dicExpeditionPoint.get(point); if (!curDicExpeditionPoint) { return resResult(STATUS.EXPEDITION_MISS_POINT_INFO); } if (point > expeditionPoint) { return resResult(STATUS.EXPEDITION_POINT_NOT_ENOUGH); } let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId); if (pointStatusInDatabase) { let { rewards } = pointStatusInDatabase; let curReward = rewards.find(cur => cur.point == point); if (curReward && curReward.received) { return resResult(STATUS.EXPEDITION_WRONG_RECEIVE_STATUS); } } // 标记状态 let { rewards: resultRewards } = await ExpeditionPointModel.updatePointStatus(roleId, point, curDicExpeditionPoint.reward); let hasReceivedAll = true, maxPoint = 0; for (let [point] of dicExpeditionPoint) { let curReward = resultRewards.find(cur => cur.point == point); if (!curReward || !curReward.received) { hasReceivedAll = false; } if (point > maxPoint) maxPoint = point; } if (hasReceivedAll) { // 全部领取了,刷新 await ExpeditionPointModel.completeStatus(roleId); await Role.increaseExpeditionPoint(roleId, maxPoint * -1); } let pointRewards = await getPointRewardStatus(roleId); // 任务 await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EXPEDITION_BOX, { point }); let goods = await addItems(roleId, roleName, sid, curDicExpeditionPoint.reward, ITEM_CHANGE_REASON.EXPEDITION_POINT_REWARD); return resResult(STATUS.SUCCESS, { costPoint: hasReceivedAll ? maxPoint : 0, pointRewards, goods }) } async debugResetResetNum(msg: { magicWord: string }, session: BackendSession) { const { magicWord } = msg; if (magicWord !== DEBUG_MAGIC_WORD) { return resResult(STATUS.TOKEN_ERR); } let roleId = session.get('roleId'); await Role.updateRoleInfo(roleId, { expeditionResetCnt: 0 }); return resResult(STATUS.SUCCESS); } }