import { WAR_TYPE } from './../../../consts/constModules/battleConst'; import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; import { findIndex } from 'underscore'; import { gameData, getPvpBoxBySeasonNumAndIndex } from '../../../pubUtils/data'; import { refreshEnemies, getEnemies, refChallengeCnt, generPVPOppRecInfo, generMyRecInfo, sendLastSeasonRewardIfNotSent, refreshRefOppCnt, generPvpLineupCe, calLineupScore, checkPvpSeasonIsStart, checkPvpSeasonIsSummit, getPvpSeasonStatus, checkPvpSeasonIsWaiting } from '../../../services/pvpService'; import { RoleModel, RoleType } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; import { resResult, genCode, checkRoleIsRobot, robotIdComBack } from '../../../pubUtils/util'; import { PvpDefenseModel, pvpUpdateInter } from '../../../db/PvpDefense'; import { PvpSeasonResultModel } from '../../../db/PvpSeasonResult'; import { Rank } from '../../../services/rankService'; import { checkTask, checkTaskInPvpEnd } from '../../../services/task/taskService'; import { Attack, Combo, Defense, DefenseHero, PvpDataReturn, pvpSaveDataReturn } from '../../../domain/battleField/pvp'; import { DEBUG_MAGIC_WORD, FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, LINEUP_NUM, REDIS_KEY, TASK_TYPE } from '../../../consts'; import { PVP } from '../../../pubUtils/dicParam'; import { addItems, getGoldObject, handleCost, unlockFigure } from '../../../services/role/rewardService'; import { pick } from "underscore"; import { HeroModel } from '../../../db/Hero'; import PvpHistoryOpp, { PvpHistoryOppModel } from '../../../db/PvpHistoryOpp'; import { BattleRecordModel } from '../../../db/BattleRecord'; import { PvpRecordModel, PvpRecordParam, PvpRecordType } from '../../../db/PvpRecord'; import { pvpEndParamInter } from '../../../pubUtils/interface'; import { getSeconds, nowSeconds } from '../../../pubUtils/timeUtil'; import { getRemoteRplPrefix, getRemoteRplFilePath } from '../../../pubUtils/battleUtils'; import { PlayerDetail, PlayerDetailHero } from '../../../domain/battleField/guild'; import { PvpSaveDataModel } from '../../../db/PvpSaveData'; import { PVPConfigModel } from '../../../db/PvpConfig'; import { getAllServerName, getServerName } from '../../../services/redisService'; import { RoleRankInfo } from '../../../domain/rank'; import { isHeroHidden } from '../../../services/dataService'; import { getPVPGroupIdOfServer } from '../../../services/serverService'; import { getBattleRecordParam } from '../../../services/normalBattleService'; export default function (app: Application) { new HandlerService(app, {}); return new PvpHandler(app); } export class PvpHandler { constructor(private app: Application) { } //1获取主界面 async getData(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let serverId = session.get('serverId'); let seasonNum: number = this.app.get('pvpSeasonNum'); let seasonStartTime: number = this.app.get('pvpSeasonStartTime'); let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); let seasonRewardTime: number = this.app.get('pvpSeasonRewardTime'); let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); if(!pvpDefense) { let role = await RoleModel.findByRoleId(roleId); pvpDefense = await PvpDefenseModel.createPvpDefense(seasonNum, { serverId: role.serverId, roleId: role.roleId, roleName: role.roleName, role: role._id }); } else { // 如果没有发过,将上赛季的奖励发下 pvpDefense = await sendLastSeasonRewardIfNotSent(pvpDefense); } let update: pvpUpdateInter = { }; let result = new PvpDataReturn(); // 返回对象 // 刷新次数 let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); if(refChallengeObj.hasChanged) { update = { ...update, ...refChallengeObj } } let refOppObj = refreshRefOppCnt(pvpDefense); // 每天首次打开要刷掉对手 if(refOppObj.shouldRefOpp) { if(pvpDefense.attack) { let role = pvpDefense.role; let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); update.oppPlayers = oppPlayers; } update = { ...update, ...refOppObj } } if(Object.keys(update).length > 0) { pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); } result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); result.setPvpDefense(pvpDefense); result.calHasSaveDefense(); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); result.setOppPlayers(oppPlayersReturn); // 赛季结算 let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId); if (!!pvpSeasonResult && !!pvpSeasonResult.show) { result.setPvpSeasonResult(pvpSeasonResult); await PvpSeasonResultModel.setShow(roleId); } // 排行榜 let myRank = await r.getMyRank({ roleId });//去redis中获取排名 result.setMyRank(myRank); return resResult(STATUS.SUCCESS, result); } // 刷新对手 async refreshOppPlayer(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let sid = session.get('sid'); let serverId = session.get('serverId'); let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); if(!pvpDefense.attack) return resResult(STATUS.PVP_NOT_SET_ATTACK); // 刷新次数及消耗 let refOppObj = refreshRefOppCnt(pvpDefense); if (refOppObj.refOppCnt >= gameData.maxPvpRefreshCnt.max) { return resResult(STATUS.PVP_REFRESH_CNT_REACH_MAX); } let costResult = await handleCost(roleId, sid, refOppObj.consume, ITEM_CHANGE_REASON.PVP_REFRESH_OPP); if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); refOppObj.refOppCnt ++; // 刷新对手 let role = pvpDefense.role; let seasonNum: number = this.app.get('pvpSeasonNum'); let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers, ...refOppObj }); let result = new PvpDataReturn(); // 返回对象 result.setPvpDefense(pvpDefense); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); result.setOppPlayers(oppPlayersReturn); return resResult(STATUS.SUCCESS, pick(result, ['oppPlayers', 'refOppCnt', 'buyAttackCnt', 'setAttackCnt'])); } // 获取对手阵容具体信息 async getOppPlayer(msg: { roleId: string }, session: BackendSession) { let roleId = session.get('roleId'); if(!checkPvpSeasonIsStart()) { return resResult(STATUS.PVP_SEASON_NOT_OPEN); } let oppoRoleId = msg.roleId; let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); let { oppPlayers } = pvpDefense; let curOpp = oppPlayers.find(cur => cur.roleId == oppoRoleId); if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); let pvpHistoryOpp = curOpp.oppDef; return resResult(STATUS.SUCCESS, { roleId: pvpHistoryOpp.oppRoleId, ...pick(pvpHistoryOpp, ['pos', 'title', 'warId', 'buff', 'heroes', 'combo']) }); } // 开战 async pvpStart(msg: { warId: number, roleId: string }, session: BackendSession) { const { warId, roleId: oppRoleId } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let serverId = session.get('serverId'); let sid = session.get('sid'); let warInfo = gameData.war.get(warId); if (!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } const role = await RoleModel.findByRoleId(roleId, null, true); if(!role || role.lv < 50) return resResult(STATUS.PVP_NOT_OPEN); let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); // 检查挑战次数 let seasonNum: number = this.app.get('pvpSeasonNum'); let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); let { challengeCnt, challengeRefTime } = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); if (challengeCnt == 0) { return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH); } let curOpp = pvpDefense.oppPlayers.find(cur => cur.roleId == oppRoleId); if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND) const battleCode = genCode(8); // 关卡唯一值 let heroes = pvpDefense.attack.heroes.map(cur => cur.actorId); await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { roleId, roleName, battleId: warId, status: 0, warName: warInfo.gk_name, warType: warInfo.warType, record: { heroes, pos: curOpp.pos, oppRoleId, pvpSeasonNum: seasonNum } } }, true); await checkTask(serverId, roleId, sid, TASK_TYPE.PVP); // 战报记录 await PvpRecordModel.createRec(roleId, robotIdComBack(oppRoleId), battleCode); // 对手记录更新 await PvpHistoryOppModel.setStatus(curOpp.oppDef.toString(), 1); let update: pvpUpdateInter = { oppBeforePlayers: pvpDefense.oppPlayers }; // 刷新对手 let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score ,pvpDefense.attack.score, pvpDefense.attack.pLv||1); update.oppPlayers = oppPlayers; // 减少挑战次数 let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); refChallengeObj.challengeCnt--; update = {...update, ...refChallengeObj}; pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); let result = new PvpDataReturn(); // 返回对象 result.setPvpDefense(pvpDefense); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); result.setOppPlayers(oppPlayersReturn); return resResult(STATUS.SUCCESS, { battleCode, ...pick(result, ['oppPlayers', 'challengeCnt', 'challengeRefTime']) }); } // 结算 async pvpEnd(msg: { battleCode: string, isSuccess: boolean, myHeroes: pvpEndParamInter[], oppHeroes: pvpEndParamInter[], round: number }, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); const serverId = session.get('serverId'); const { battleCode, isSuccess, myHeroes, oppHeroes, round } = msg; const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); if (!BattleRecord || BattleRecord.status != 0) { return resResult(STATUS.BATTLE_STATUS_WRONG); } let { record: { heroes: dbHeroes, oppRoleId, pos, pvpSeasonNum }, createdAt } = BattleRecord; let flag = 1; // 对比hero信息 for (let { hid } of myHeroes) { if (dbHeroes.indexOf(hid) == -1) flag = 0; } if (!flag) return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); // 更新军功 let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); let { hisWinStreakNum = 0 } = pvpDefense; let update: pvpUpdateInter = {}; const role = await RoleModel.findByRoleId(roleId, null, true); const myRecInfo = await generMyRecInfo(pvpDefense, role, isSuccess, pos, myHeroes); let { attackInfo, showHeroScores, updateParam } = myRecInfo update = { ...update, ...updateParam }; let curOpp = pvpDefense.oppBeforePlayers.find(cur => cur.roleId == oppRoleId && cur.pos == pos); if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); const defenseInfo = await generPVPOppRecInfo(isSuccess, curOpp, oppHeroes, serverId); let seasonNum: number = this.app.get('pvpSeasonNum'); // 战报记录 await PvpRecordModel.updateByBattleCode(battleCode, { warId: BattleRecord.battleId, attackInfo, defenseInfo, createTime: nowSeconds(), timeout: seasonNum != pvpSeasonNum }); // 更新battleRecord await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess ? 1 : 2, ...getBattleRecordParam(myHeroes, round) } }, true); if(seasonNum == pvpSeasonNum) { pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); } let result = new PvpDataReturn(); // 返回对象 result.setPvpDefense(pvpDefense); if(seasonNum == pvpSeasonNum) { // 加入排行榜 let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: pvpSeasonNum, groupId }); await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); let myRank = await r.getMyRank({ roleId }); result.setMyRank(myRank); if(defenseInfo && defenseInfo.score > 0) await r.setRankWithRoleInfo(defenseInfo.roleId, defenseInfo.score, pvpDefense.updatedAt.getTime(), null, true); } let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); result.setOppPlayers(oppPlayersReturn); await checkTaskInPvpEnd(serverId, roleId, sid, isSuccess, pvpDefense.heroScores, pvpDefense.seasonWinNum); if(hisWinStreakNum < pvpDefense.hisWinStreakNum) { await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES, paramWinStreakNum: pvpDefense.hisWinStreakNum }]); } return resResult(STATUS.SUCCESS, { battleCode, isSuccess, heroScores: showHeroScores, createdAt: getSeconds(createdAt), ...pick(result, ['score', 'myRank', 'winStreakNum', 'attack', 'oppPlayers', 'challengeCnt', 'challengeRefTime', 'seasonWinNum']) }); } async buyAttackCnt(msg: { count: number }, session: BackendSession) { let { count } = msg; let roleId = session.get('roleId'); let sid = session.get('sid'); let serverId = session.get('serverId'); let seasonNum: number = this.app.get('pvpSeasonNum'); let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); // 次数 let refOppObj = refreshRefOppCnt(pvpDefense); if(refOppObj.buyAttackCnt + count > PVP.PVP_BUY_SET_ATTACK_CNT) { return resResult(STATUS.PVP_BUY_ATTACK_CNT_NOT_ENOUGH); } refOppObj.buyAttackCnt += count; let gold = getGoldObject(PVP.PVP_SET_ATTACK_CNT_GOLD * count); let costResult = await handleCost(roleId, sid, [gold], ITEM_CHANGE_REASON.PVP_BUY_ATTACK_CNT); if(!costResult) return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); let update: pvpUpdateInter = { ...refOppObj }; // 更新挑战阵容 if(refOppObj.shouldRefOpp) { if(pvpDefense.attack) { let role = await RoleModel.findByRoleId(roleId); let seasonNum: number = this.app.get('pvpSeasonNum'); let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); update.oppPlayers = oppPlayers; } } // 保存 pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); // 返回 let result = new PvpDataReturn(); result.setPvpDefense(pvpDefense); let pickParam = ['buyAttackCnt', 'setAttackCnt', 'refOppCnt']; if(refOppObj.shouldRefOpp) { let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); result.setOppPlayers(oppPlayersReturn); pickParam.push('oppPlayers'); } return resResult(STATUS.SUCCESS, pick(result, pickParam)); } async saveAttack(msg: { heroes: { actorId: number, order: number, subHid: number }[] }, session: BackendSession) { let { heroes } = msg; let roleId = session.get('roleId'); let serverId = session.get('serverId'); let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); // 次数 let refOppObj = refreshRefOppCnt(pvpDefense); if(refOppObj.setAttackCnt >= PVP.PVP_SET_ATTACK_FREE_CNT + refOppObj.buyAttackCnt) { return resResult(STATUS.PVP_SET_ATTACK_CNT_NOT_ENOUGH); } if(!!pvpDefense.attack) { refOppObj.setAttackCnt ++; } let seasonNum: number = this.app.get('pvpSeasonNum'); let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); // 更新挑战阵容 let scores: number[] = []; for(let { actorId, subHid } of heroes) { if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); if(heroScore) { scores.push(heroScore.score); } let dicHero = gameData.hero.get(actorId); if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); } let attack = new Attack(heroes, scores); let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, attack.heroes, pvpDefense.defense?.heroes??[], []); // 刷对手 let role = pvpDefense.role; let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, attack?.score||0, attack?.pLv||1); // 保存 pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { ...refOppObj, ...refChallengeObj, attack, oppPlayers, lineupCe }); // 返回 let result = new PvpDataReturn(); result.setPvpDefense(pvpDefense); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); result.setOppPlayers(oppPlayersReturn); return resResult(STATUS.SUCCESS, pick(result, ['attack', 'oppPlayers', 'buyAttackCnt', 'setAttackCnt', 'challengeCnt', 'challengeRefTime'])); } // 只保存副将 async saveAttackSub(msg: { heroes: { actorId: number, order: number, subHid: number }[] }, session: BackendSession) { let { heroes } = msg; let roleId = session.get('roleId'); let serverId = session.get('serverId'); let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); // 更新挑战阵容 let oldAttack = pvpDefense.attack?.heroes||[]; let scores: number[] = []; for(let { actorId, order, subHid } of heroes) { let oldData = oldAttack.find(cur => cur.actorId == actorId); if(!oldData || oldData.order != order) return resResult(STATUS.PVP_CAN_NOT_CHANGE_HERO); if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); if(heroScore) { scores.push(heroScore.score); } let dicHero = gameData.hero.get(actorId); if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); } let attack = new Attack(heroes, scores); let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, attack.heroes, pvpDefense.defense?.heroes??[], []); // 保存 pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { attack, lineupCe }); // 返回 let result = new PvpDataReturn(); result.setPvpDefense(pvpDefense); return resResult(STATUS.SUCCESS, pick(result, ['attack'])); } // 获取存档列表 async getSaveData(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); let pvpConfig = await PVPConfigModel.findCurPVPConfig(); if(!pvpConfig) return resResult(STATUS.PVP_SEASON_NOT_OPEN); let saveDatas = await PvpSaveDataModel.findByRoleId(roleId); let list: pvpSaveDataReturn[] = []; for(let warId of (pvpConfig.warIds||[])) { let dicWar = gameData.war.get(warId); if(dicWar && dicWar.selectView == 1) { let data = new pvpSaveDataReturn(warId); let curSaveData = saveDatas.find(cur => cur.warId == warId); data.setUserSaveData(curSaveData); if(pvpDefense.defense?.warId == warId) { data.setAsUsing(); } list.push(data); } } return resResult(STATUS.SUCCESS, { list }); } //3. 保存防守阵容 async saveDefense(msg: { heroes: { actorId: number, dataId: number, order: number, ai: number, subHid?: number }[], warId: number, buff: number, combo: Combo[] }, session: BackendSession) { let { heroes, warId, buff, combo } = msg; let roleId = session.get('roleId'); if (heroes.length > LINEUP_NUM || heroes.length <= 0) { return resResult(STATUS.WRONG_PARMS); } if(checkPvpSeasonIsSummit()) { return resResult(STATUS.PVP_CAN_NOT_SAVE_DEFENSE); } let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); // 刷新次数 let seasonNum: number = this.app.get('pvpSeasonNum'); let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); // 更新防守阵容 let scores: number[] = [], heroIdMap = new Map(), hids: number[] = []; for(let { actorId, subHid } of heroes) { if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); let dicHero = gameData.hero.get(actorId); if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); if(heroScore) { scores.push(heroScore.score); } // 记录hero的objectId,用于存defense.heroes.hero if(pvpDefense.defense && pvpDefense.defense.heroes) { let heroInDefense = pvpDefense.defense.heroes.find(cur => cur.actorId == actorId); if(heroInDefense) { heroIdMap.set(actorId, heroInDefense.hero); } else { hids.push(actorId); } } else { hids.push(actorId); } } let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true); for(let hero of dbHeroes) { heroIdMap.set(hero.hid, hero._id); } let defenseHeroes = heroes.map(cur => { return new DefenseHero(cur, heroIdMap.get(cur.actorId)); }); let defense = new Defense(defenseHeroes, scores, warId, buff, combo); let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, pvpDefense.attack?.heroes??[], defense.heroes, dbHeroes); await PvpSaveDataModel.createSaveData(roleId, warId, buff, defenseHeroes); pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { ...refChallengeObj, defense, lineupCe, hasDefense: true, seasonNum }); // 返回 let result = new PvpDataReturn(); result.setPvpDefense(pvpDefense); return resResult(STATUS.SUCCESS, {...pick(result, ['defense', 'challengeCnt', 'challengeRefTime']), hasSaveDefense: true}); } //8. 排行榜 async getRank(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let serverId = session.get('serverId'); let seasonNum: number = this.app.get('pvpSeasonNum'); if(checkPvpSeasonIsWaiting()) { // 休赛期 seasonNum ++; } let serverNames = await getAllServerName(); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); r.setGenerFieldsFun(function (param: RoleRankInfo) { let { serverId } = param; return { ...param, serverName: serverNames[serverId]||'无' }; }); let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); if (!myRank) { let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); myRank = await r.generMyRankWithRole(roleId, pvpDefense.score, getSeconds(pvpDefense.refDaily)); } return resResult(STATUS.SUCCESS, { ranks, myRank }); } //2.5. 获取对手详细信息(排行榜,战报,阵容查看) async getPlayerDetail(msg: { roleId: string }, session: BackendSession) { let roleId = session.get('roleId'); let serverId = session.get('serverId'); let { roleId: oppoRoleId } = msg; let isRobot = checkRoleIsRobot(oppoRoleId); let result: PlayerDetail; if (isRobot) { // 如果是机器人,从自己的pvpDefense中寻找 let pvpHistoryOpp = await PvpHistoryOppModel.findByRoleIdAndOppId(roleId, oppoRoleId); if (!pvpHistoryOpp) { return resResult(STATUS.PVP_ROLE_NOT_FOUND); } let heroes = new Array(); for (let hero of pvpHistoryOpp.heroes) { let newHero = new PlayerDetailHero(); newHero.setPvpHeroInfo(hero); newHero.setIsDefense(true); heroes.push(newHero); } for (let hero of pvpHistoryOpp.otherHeroes) { let newHero = new PlayerDetailHero(); newHero.setPvpHeroInfo(hero); newHero.setIsDefense(false); heroes.push(newHero); } result = new PlayerDetail(pvpHistoryOpp.oppRoleId, heroes, pvpHistoryOpp.rankLv); result.setRobot(pvpHistoryOpp); if(pvpHistoryOpp.isRobot) { result.setServerName(await getServerName(serverId)); } else { let role = await RoleModel.findByRoleId(robotIdComBack(oppoRoleId), 'serverId'); result.setServerName(await getServerName(role.serverId)); } } else { // 查询对方pvpDefense let pvpDefense = await PvpDefenseModel.findByRoleId(oppoRoleId); let dbHeroes = await HeroModel.findByRole(oppoRoleId); let role = await RoleModel.findByRoleId(oppoRoleId); let heroes = new Array(); for (let dbHero of dbHeroes) { let hero = new PlayerDetailHero(); hero.setByDbHero(dbHero); hero.setPvpDefense(pvpDefense); heroes.push(hero); } heroes.sort((a, b) => b.score - a.score); let seasonNum: number = this.app.get('pvpSeasonNum'); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); let rank = await r.getMyRank({ roleId: oppoRoleId });//去redis中获取排名 result = new PlayerDetail(oppoRoleId, heroes, rank); result.setPlayer(role); result.setPvpDefense(pvpDefense); result.setServerName(await getServerName(role.serverId)); } return resResult(STATUS.SUCCESS, result); } //7. 领取巅峰之路奖励 async receiveBox(msg: { id: number }, session: BackendSession) { let { id } = msg; let roleId = session.get('roleId'); let sid: string = session.get('sid'); let serverId = session.get('serverId'); let roleName = session.get('roleName'); let seasonNum: number = this.app.get('pvpSeasonNum'); let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); let { seasonWinNum, receivedBox, challengeCnt: lastChallengeCnt, challengeRefTime: lastChallengeRefTime } = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); let dicPvpBox = getPvpBoxBySeasonNumAndIndex(seasonNum, id); if(!dicPvpBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); if (seasonWinNum < dicPvpBox.winTimes) { return resResult(STATUS.PVP_NOT_REACH_BOX_SCORE); } if (receivedBox.indexOf(id) != -1) { return resResult(STATUS.PVP_BOX_IS_GOT); } receivedBox.push(id); let { challengeCnt, challengeRefTime } = await refChallengeCnt(lastChallengeCnt, lastChallengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); await PvpDefenseModel.updateInfo(roleId, { receivedBox, challengeCnt, challengeRefTime }); let result = await addItems(roleId, roleName, sid, dicPvpBox.reward, ITEM_CHANGE_REASON.PVP_BOX_REWARD); // 任务 await checkTask(serverId, roleId, sid, TASK_TYPE.PVP_RECEIVE_BOX); return resResult(STATUS.SUCCESS, { goods: result, receivedBox, challengeCnt, challengeRefTime, seasonWinNum }); } //9. 战报 async getRec(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let pvpRecords = await PvpRecordModel.getRecByRoleId(roleId); let serverNames = await getAllServerName(); for(let record of pvpRecords) { // console.log('#####', record.defenseInfo.serverId, serverNames, serverNames[record.defenseInfo.serverId]) if(record.defenseInfo) record.defenseInfo['serverName'] = serverNames[record.defenseInfo.serverId]; if(record.attackInfo) record.attackInfo['serverName'] = serverNames[record.attackInfo.serverId]; } return resResult(STATUS.SUCCESS, { list: pvpRecords.map(rec => { const { roleId1, battleCode, hasRpl, remoteUrl } = rec; const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; return { ...rec, rplFileUrl }; }), rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) }); } // debug接口 async addRoleScore(msg: { heroScores: Array<{ hid: number, score: number }> }, session: BackendSession) { let { heroScores: addHeroScores } = msg; let roleId = session.get('roleId'); let sid = session.get('sid'); let serverId = session.get('serverId'); let { heroScores, hisScore, attack, defense } = await PvpDefenseModel.findByRoleId(roleId); let score = 0; for (let { hid, score: heroScore } of addHeroScores) { if (heroScore < 0) continue; let index = findIndex(heroScores, { hid }); if (index != -1) { heroScores[index].score = heroScore; } else { heroScores.push({ hid, score: heroScore }); } } for (let heroScore of heroScores) { score += heroScore.score; } if (score < 0) { score = 0; } if (hisScore < score) { hisScore = score; } let newAttack = calLineupScore(attack, heroScores); let newDefense = calLineupScore(defense, heroScores); let pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { score, hisScore, heroScores, attack: newAttack, defense: newDefense }); const role = await RoleModel.findByRoleId(roleId); // 加入排行榜 let seasonNum: number = this.app.get('pvpSeasonNum'); let groupId = await getPVPGroupIdOfServer(serverId); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); // 任务 await checkTask(serverId, roleId, sid, TASK_TYPE.PVP_HERO_SCORE, { heroScores }); return resResult(STATUS.SUCCESS, { score, hisScore, heroScores }); } async debugPvpSeasonResetTime(msg: {}, session: BackendSession) { return resResult(STATUS.DEBUG_FUNCTION_ERR); } async debugAddChallengeCnt(msg: { challengeCnt: number }, session: BackendSession) { let { challengeCnt } = msg; let roleId = session.get('roleId'); if (challengeCnt > PVP.PVP_CHALLENGE_COUNTS) { challengeCnt = PVP.PVP_CHALLENGE_COUNTS; } let { challengeRefTime } = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, challengeRefTime: nowSeconds(), refOppCnt: 0 }); return resResult(STATUS.SUCCESS, { challengeCnt, challengeRefTime }); } async debugResetRefOppCnt(msg: { magicWord: string }, session: BackendSession) { const { magicWord } = msg; if (magicWord !== DEBUG_MAGIC_WORD) { return resResult(STATUS.TOKEN_ERR); } let roleId = session.get('roleId'); await PvpDefenseModel.updateInfo(roleId, { refOppCnt: 0 }); return resResult(STATUS.SUCCESS); } async debugResetAttackCnt(msg: { magicWord: string }, session: BackendSession) { const { magicWord } = msg; if (magicWord !== DEBUG_MAGIC_WORD) { return resResult(STATUS.TOKEN_ERR); } let roleId = session.get('roleId'); await PvpDefenseModel.updateInfo(roleId, { setAttackCnt: 0, buyAttackCnt: 0 }); return resResult(STATUS.SUCCESS); } async debugResetBox(msg: { magicWord: string }, session: BackendSession) { const { magicWord } = msg; if (magicWord !== DEBUG_MAGIC_WORD) { return resResult(STATUS.TOKEN_ERR); } let roleId = session.get('roleId'); await PvpDefenseModel.updateInfo(roleId, { hisScore: 5000, receivedBox: [] }); return resResult(STATUS.SUCCESS); } }