import { PvpDefenseModel, PvpDefenseType, pvpUpdateInter } from '../db/PvpDefense'; import { Defense, Attack, LineupCe, OppPlayer, HeroScore, HeroReward, OppPlayerReturn, AttackHero, DefenseHero } from '../domain/battleField/pvp'; import { RoleType, CeAttrDataRole } from '../db/Role'; import { PVP_HERO_POS, REDIS_KEY, PVP_CONST, COUNTER, TASK_TYPE, MAIL_TYPE, TA_EVENT } from '../consts'; import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; import { getRandSingleIndex, genCode, shouldRefresh, getChineseName, makeRobotId, robotIdComBack, getRandSingleEelm } from '../pubUtils/util'; import { pvpEndParamInter, RewardInter } from '../pubUtils/interface'; import { gameData, getPLvByScore, getPvpHeroRewardsByScore, getPvpRankRewardsByRank, getPvpDifficultByScore } from "../pubUtils/data"; import { PVP } from '../pubUtils/dicParam'; import { PVPConfigModel, PVPConfigType } from '../db/SystemConfig' import { nowSeconds, getTimeFun } from '../pubUtils/timeUtil'; import { HeroesRecord, PvpRecordPlayerInfo } from '../db/PvpRecord'; import { HeroModel, CeAttrData, HeroType } from '../db/Hero'; import { AttributeCal } from '../domain/roleField/attribute'; import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '../domain/dbGeneral'; import { DicWarJson } from '../pubUtils/dictionary/DicWarJson'; import { findWhere, findIndex } from 'underscore'; import { pinus } from 'pinus'; import { PvpHistoryOppModel, PvpHistoryOppType } from '../db/PvpHistoryOpp'; import { Rank } from './rankService'; import { CounterModel } from '../db/Counter'; import { DicRankRewads } from '../pubUtils/dictionary/DicPvpRankReward'; import { PvpSeasonResultModel, PvpSeasonResultType } from '../db/PvpSeasonResult'; import { checkTask } from '../services/taskService'; import { sendMailByContent } from './mailService'; import { RoleRankInfo } from '../domain/rank'; import { reportTAEvent } from './sdkService'; /** * 返回对手三人信息 * * @param oppPlayers pvpDefense表中的oppPlayers字段,需要populate过的 * @param pLv 玩家本人的队伍等级 */ export async function getEnemies(oppPlayers: OppPlayer[], winStreakNum: number) { let result = new Array(); for (let oppPlayer of oppPlayers) { let dicOpponent = dicPvpOpponent.get(oppPlayer.pos); let oppDef = oppPlayer.oppDef; // select 'oppRoleId pos roleName head frame spine rankLv pLv defCe' if (oppDef) delete oppDef.heroes; result.push({ ...oppDef, roleId: oppDef.oppRoleId, defCe: oppDef.defCe, addScore: dicOpponent.score, rankLv: oppDef.rankLv, plusScore: getPlusScore(winStreakNum) }); } return result } /** * @description 刷新对手三个人 * @param role 数据库里我的role * @param score 我的军功 * @param pLv 我的排名 */ export async function refreshEnemies(role: RoleType, seasonNum: number, sumScore: number, score: number, pLv: number) { let { roleId } = role; let oppPlayers: OppPlayer[] = []; let opp = dicPvpOpponent.values() for (let dicOpp of opp) { let flag = false; // 是否筛选成功 if (sumScore >= PVP_CONST.SCORE_LINE) { // 将这个放到const flag = await matchPlayer(seasonNum, oppPlayers, roleId, pLv, dicOpp); // 按照等级匹配对手 if (!flag) flag = await matchPlayerByRank(seasonNum, oppPlayers, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家 if (!flag) flag = await matchRobot(oppPlayers, role, score, dicOpp); } else { flag = await matchRobot(oppPlayers, role, score, dicOpp); } if (!flag) continue; } return oppPlayers; } export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayer[], roleId: string, pos: number) { // console.log('matchPlayerByRank', JSON.stringify(oppPlayers)) let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum }); let ridRanks = new Array(); // 已经被使用了的排名 for (let { roleId: curRoleId } of oppPlayers) { let rankLv = await r.getMyRank({ roleId: robotIdComBack(curRoleId) }); ridRanks.push(rankLv); } let myRank = await r.getMyRank({ roleId }); ridRanks.push(myRank); let oppRoleId = ''; let oppRank = 0; if (myRank == 0) { return false } else if (myRank == 1) { // 第一名 if (pos == 1) { oppRank = 2; while (ridRanks.includes(oppRank)) { oppRank--; } } else if (pos == 2) { oppRank = 3; while (ridRanks.includes(oppRank)) { oppRank--; } } else { oppRank = 4; while (ridRanks.includes(oppRank)) { oppRank++; } } } else if (myRank == 0) { return false } else { if (pos == 1 || pos == 2) { // 刷新我前一名 oppRank = myRank - 1; while (ridRanks.includes(oppRank)) { oppRank--; } } else { // 刷新我后一名 oppRank = myRank + 1; while (ridRanks.includes(oppRank)) { oppRank++; } } } let result = await r.getUserByRank(oppRank); if (result.length <= 0) return false; oppRoleId = result[0]; let pvpdefense = await PvpDefenseModel.findByRoleIdIncludeAll(oppRoleId); if (!pvpdefense || pvpdefense.seasonNum != seasonNum) return false; let pvpHistoryOpp = await generPlayerOppHis(pvpdefense, roleId, pos); if (!pvpHistoryOpp) return false; oppPlayers.push({ roleId: pvpHistoryOpp.oppRoleId, oppDef: pvpHistoryOpp._id, pos, isRobot: false, }); return true } async function matchPlayer(seasonNum: number, oppPlayers: OppPlayer[], roleId: string, pLv: number, dicOpp: DicPvpOpponent) { // console.log('matchPlayer', JSON.stringify(oppPlayers)) let { id: pos, minLv, maxLv } = dicOpp let range = await PvpDefenseModel.findByTeamLv(seasonNum, pLv + minLv, pLv + maxLv); range = range.filter(cur => { return oppPlayers.findIndex(ccur => ccur.roleId == makeRobotId(cur.roleId)) == -1; }); if (range.length <= 0) return false; let index = getRandSingleIndex(range.length); let result = range[index]; // 本次匹配结果 pvpdefense if (!result) return false; if (result.roleId == roleId) { range.splice(index, 1); if (range.length <= 0) return false; index = getRandSingleIndex(range.length); result = range[index]; } let pvpHistoryOpp = await generPlayerOppHis(result, roleId, pos); if (!pvpHistoryOpp) return false; oppPlayers.push({ roleId: pvpHistoryOpp.oppRoleId, oppDef: pvpHistoryOpp._id, pos, isRobot: false, }); return true; } /** * @description 对手是玩家时,生成并返回pvpHistoryOpp * @param result 随机出的对手pvpDefense * @param roleId 自己的玩家id * @param pos 刷新这个对手的位置 */ async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos: number) { let { heroScores, defense } = pvpdefense; if(!defense) return false; let { warId, heroes: defenseHeroes } = defense; let role = pvpdefense.role; let seasonNum: number = pinus.app.get('pvpSeasonNum'); let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum }); let rankLv = await r.getMyRank({ roleId: role.roleId }); let dbHeroes = await HeroModel.findByRole(role.roleId, [{ field: 'ce', sortBy: -1 }]); let heroes = new Array(); let otherHeroes = new Array(); // 阵容外的所有武将信息 let defCe = 0; for (let dbHero of dbHeroes) { let h = defenseHeroes.find(cur => cur.actorId == dbHero.hid); // 阵容里是否有这个武将 let hs = heroScores.find(cur => cur.hid == dbHero.hid); // 这个武将是否有这个得分 if (!!h) { let mapWarJson = gameData.warJson.get(warId); let warJson = mapWarJson.find(cur => cur.dataId == h.dataId); if (warJson && warJson.relation == 2) { let heroInfo = new PvpHeroInfo(); heroInfo.setHeroInfo(dbHero); // heroInfo.setOutIndex(h.order); let { attribute, ce } = getPlayerAttribute(dbHero.lv, dbHero.attr, role.attr); heroInfo.setAttribute(attribute); let enemy = new PvpEnemies(warJson, heroInfo, hs ? hs.score : 0, ce); enemy.setOutIndex(h.order); heroes.push(enemy); defCe += ce; } } else { let heroInfo = new PvpOtherHeroes(hs ? hs.score : 0); heroInfo.setHeroInfo(dbHero); otherHeroes.push(heroInfo); } } heroes.sort((a, b) => b.score - a.score); otherHeroes.sort((a, b) => b.score - a.score); let pvpHistoryOpp = await PvpHistoryOppModel.createPvpOpp({ ...defense, defCe, ...role, pos, rankLv, heroes, otherHeroes, roleId, oppRoleId: makeRobotId(pvpdefense.roleId) }); return pvpHistoryOpp; } async function matchRobot(oppPlayers: OppPlayer[], role: RoleType, score: number, dicOpp: DicPvpOpponent) { // console.log('matchRobot', JSON.stringify(oppPlayers)) let { lv: myLv, roleId } = role; let { id: pos, minLv, maxLv, ratio } = dicOpp; let result = getRandSingleEelm(gameData.pvpWar); if (!result) return false; let robotWarjson = gameData.warJson.get(result.war_id); if (!robotWarjson) return false let heroes: PvpEnemies[] = []; let defCe = 0; for (let h of robotWarjson) { if (h.relation == 1) continue; let actorId = h.randomEnemy.length > 0? getRandSingleEelm(h.randomEnemy): 0; let dicHero = gameData.hero.get(actorId); if (!dicHero) continue; let heroInfo = new PvpHeroInfo(); let { attribute, ce, lv } = getRobotAttribute(actorId, ratio, score); heroInfo.setRobotInfo(dicHero, lv); defCe += ce; heroInfo.setAttribute(attribute); let enemy = new PvpEnemies(h, heroInfo, 0, ce); enemy.setOutIndex(h.outIndex); heroes.push(enemy); } let oppRoleId = generateRobotRoleId(); let roleName = getChineseName(); let pLv = getPLvByScore(score); let hisPLv = Math.floor(pLv + (minLv + maxLv) / 2); if (hisPLv < 1) hisPLv = 1 let pvpHistoryOpp = await PvpHistoryOppModel.createPvpOpp({ roleId, oppRoleId, roleName, pos, defCe, pLv: hisPLv, lv: myLv, heroes, rankLv: 0, warId: result.war_id, buff: getRandSingleEelm(result.mapseid)||0, }); oppPlayers.push({ roleId: oppRoleId, oppDef: pvpHistoryOpp._id, pos, isRobot: true }); return true } // 生成机器人roleId function generateRobotRoleId() { return `${genCode(10)}_r`; } // 根据连胜次数,获得加成的积分 export function getPlusScore(win: number) { let result = win - 1; if (result < 0) result = 0; if (result > PVP.PVP_WINREWARD_UPLIMIT) result = PVP.PVP_WINREWARD_UPLIMIT; return result; } export function getLvByScore(heroScores: HeroScore[]) { heroScores.sort((a, b) => b.score - a.score); let score = 0; for (let i = 0; i < 5; i++) { if (!heroScores[i]) break; score += heroScores[i].score; } return getPLvByScore(score); } export function refChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number) { let hasChanged = false; if (challengeCnt >= PVP.PVP_CHALLENGE_COUNTS) { return { hasChanged, challengeCnt, challengeRefTime }; } let period = PVP.PVP_CHALLENGE_NORMALTIMES * 60; if (getTimeFun(seasonEndTime).checkDay()) { period = PVP.PVP_CHALLENGE_FINALTIMES * 60; } let time = nowSeconds(); let num = Math.floor((time - challengeRefTime) / period); if (num > 0) { challengeCnt += num; challengeRefTime = challengeRefTime + period * num; hasChanged = true; } challengeCnt = challengeCnt > PVP.PVP_CHALLENGE_COUNTS ? PVP.PVP_CHALLENGE_COUNTS : challengeCnt; return { hasChanged, challengeCnt, challengeRefTime }; } export function comsumeChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number) { challengeCnt--; if (challengeCnt >= PVP.PVP_CHALLENGE_COUNTS) { return { challengeCnt, challengeRefTime }; } if (challengeCnt == PVP.PVP_CHALLENGE_COUNTS - 1) { challengeRefTime = nowSeconds(); return { challengeCnt, challengeRefTime }; } return refChallengeCnt(challengeCnt, challengeRefTime, seasonEndTime); } export async function sendLastSeasonRewardIfNotSent(pvpDefense: PvpDefenseType) { let seasonNum: number = pinus.app.get('pvpSeasonNum'); if(pvpDefense.seasonNum < seasonNum) { let oldPvpCongig = await PVPConfigModel.findPVPConfig(pvpDefense.seasonNum); let result = await sendPVPRewardToUser(pvpDefense, pvpDefense.seasonNum, oldPvpCongig.seasonEndTime); pvpDefense = result.pvpDefense; } return pvpDefense; } // 获取刷新对手次数及消耗 export function refreshRefOppCnt(pvpDefense: PvpDefenseType) { let { refOppCnt = 0, setAttackCnt = 0, buyAttackCnt = 0, refDaily } = pvpDefense; let curTime = new Date(); let shouldRefOpp = shouldRefresh(refDaily, curTime); if (shouldRefOpp) { refOppCnt = 0; setAttackCnt = 0; buyAttackCnt =0; refDaily = curTime; } return { shouldRefOpp, refOppCnt, refDaily, setAttackCnt, buyAttackCnt, consume: gameData.pvpRefreshConsume.get(refOppCnt + 1) } } /** * 根据比例计算机器人属性 * @param attribute 出兵表中的属性字段 * @param ce 我的战力 * @param enemyCe 出兵表对手战力 * @param ratio 系数 */ export function getRobotAttribute(hid: number, posRatio: number, score: number) { let difficultRatio = getPvpDifficultByScore(score); let dicHero = gameData.hero.get(hid); let newAttribute = new AttributeCal(); newAttribute.setLv(difficultRatio.enemyLv); newAttribute.setByMap(dicHero.baseAbilityArr, difficultRatio.value / 10000 * posRatio); let attrArr = newAttribute.getReduceAttributesToString(); let newCe = newAttribute.calCelAndReduce(); return { attribute: attrArr, ce: newCe, lv: difficultRatio.enemyLv }; } /** * @description 根据玩家数据获取到他的属性 * @param ceAttr hero表的ceAttr * @param globalCeAttr role表中的globalCeAttr */ export function getPlayerAttribute(lv: number, heroAttrs: CeAttrData[] = [], roleAttrs: CeAttrDataRole[] = []) { let newAttribute = new AttributeCal(); newAttribute.setLv(lv); newAttribute.setByDbData(roleAttrs, heroAttrs); let attribute = newAttribute.getReduceAttributesToString(); let ce = newAttribute.calCelAndReduce(); return { attribute, ce }; } /** * @description 根据玩家数据获取到他的主属性 * @param ceAttr * @param globalCeAttr */ export function getPlayerMainAttribute(heroAttrs: CeAttrData[], roleAttrs: CeAttrDataRole[]) { let newAttribute = new AttributeCal(); newAttribute.setByDbData(roleAttrs, heroAttrs); let mainAttributes = newAttribute.getReduceAttributes(); return mainAttributes; } // 获取我方战报记录 export async function generMyRecInfo(pvpDefense: PvpDefenseType, role: RoleType, isSuccess: boolean, pos: number, myHeroes: pvpEndParamInter[]) { let { attack, defense, heroScores, winStreakNum, hisWinStreakNum = 0, score, hisScore } = pvpDefense; let { roleId } = role; if (isSuccess) { winStreakNum ++; } else { winStreakNum = 0; } if(winStreakNum > hisWinStreakNum) { hisWinStreakNum = winStreakNum; } const dicOpp = gameData.pvpOpponent.get(pos); const plusScore = getPlusScore(winStreakNum); let pLv = getLvByScore(heroScores); let myHeroRecords: HeroesRecord[] = []; // 存入rec里面的数据 let showHeroScores = new Array<{ hid: number, addScore: number, plusScore: number, score: number }>(); let addSumScore = 0; for (let { actorId: hid } of attack.heroes) { if(hid == 0) continue; let params = myHeroes.find(cur => cur.hid == hid); let curHeroScore = heroScores.find(cur => cur.hid == hid); if (isSuccess) { if (!curHeroScore) { curHeroScore = { hid, score: dicOpp.score + plusScore }; heroScores.push(curHeroScore); } else { curHeroScore.score += dicOpp.score + plusScore; } addSumScore += dicOpp.score + plusScore; showHeroScores.push({ hid, addScore: dicOpp.score, plusScore, score: curHeroScore.score }); } else { showHeroScores.push({ hid, addScore: 0, plusScore: 0, score: curHeroScore ? curHeroScore.score : 0 }); } const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv skinId'); let record = new HeroesRecord(); record.setByHero(myHero, params); myHeroRecords.push(record); } let attackInfo = new PvpRecordPlayerInfo(); attackInfo.setByRole(role, myHeroRecords, isSuccess, isSuccess ? addSumScore : 0, pLv) let newAttack = calLineupScore(attack, heroScores); let newDefense = calLineupScore(defense, heroScores); let updateParam = { winStreakNum, hisWinStreakNum, attack: newAttack, defense: newDefense, heroScores, score: score + addSumScore, hisScore: hisScore > score + addSumScore? hisScore: score + addSumScore } return { attackInfo, showHeroScores, updateParam } } function calLineupScore(lineup: Attack|Defense, heroScores: HeroScore[]) { if(!lineup) return lineup; let score = 0; for(let { actorId } of lineup.heroes) { let hs = heroScores.find(cur => cur.hid == actorId); if(hs) { score += hs.score; } } let pLv = getPLvByScore(score); return {...lineup, score, pLv} } // 获取对手战报记录 export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayer, oppHeroes: pvpEndParamInter[], myLv: number) { let oppHeroRecords = new Array(); let oppRole = curOpp.oppDef; if (!oppRole) { console.error('opp role not found') } for (let params of oppHeroes) { let historyHero = oppRole.heroes.find(cur => cur.actorId == params.hid); if (historyHero) { let hs = new HeroesRecord(); hs.setByPvpHeroInfo(historyHero, params); oppHeroRecords.push(hs); } } let addSumScore = 0; if(!curOpp.isRobot && !isSuccess) { let pvpDefense = await PvpDefenseModel.findByRoleId(oppRole.roleId); if(pvpDefense && pvpDefense.defense) { let { attack, defense, heroScores, score } = pvpDefense; for(let { actorId } of defense.heroes) { let hs = heroScores.find(cur => cur.hid == actorId); if(hs) { hs.score += PVP.PVP_DEFENSE_SUCCESS_REWARD; } else { heroScores.push({ hid: actorId, score: PVP.PVP_DEFENSE_SUCCESS_REWARD }) } addSumScore += PVP.PVP_DEFENSE_SUCCESS_REWARD; } let newAttack = calLineupScore(attack, heroScores); let newDefense = calLineupScore(defense, heroScores); await PvpDefenseModel.updateInfo(oppRole.roleId, { attack: newAttack, defense: newDefense, heroScores, score: score + addSumScore }); } } let defenseInfo = new PvpRecordPlayerInfo(); defenseInfo.setByHistoryOpp(oppRole, oppHeroRecords, !isSuccess, isSuccess ? 0 : addSumScore) return defenseInfo } /** * pvp定时任务赛季结算 * @param obj */ export async function pvpSeasonEnd(seasonNum: number) { let pvpConfig = await PVPConfigModel.findPVPConfig(seasonNum); if(pvpConfig.hasSettleReward) return; console.log('exce pvpSeasonEnd' + pvpConfig.seasonNum); let resultMaxRank = gameData.pvpRankMax.max;//根据排行榜的奖励表,获得最大排名挡位的最小值,其余不在结算中结算的玩家按照最大排名挡位在登录或进入pvp时结算 let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: pvpConfig.seasonNum }, false, resultMaxRank.min - 1); let allRank = (await r.getRankByRange()); console.log('******** allRank', 0, resultMaxRank.min - 2, allRank) for(let { rank, roleId } of allRank) { console.log('******** pvpSeasonEnd: ', rank, roleId); let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); let { pvpSeasonResult } = await sendPVPRewardToUser(pvpDefense, pvpConfig.seasonNum, pvpConfig.seasonEndTime); reportTAEvent(roleId, TA_EVENT.PVP_SEASON_END, { top_rank: rank, hero_score: pvpSeasonResult.heroScores }) } await PVPConfigModel.setReward(pvpConfig.seasonNum); } /** * pvp定时任务结算获得添加邮件信息 * @param pvpDefense * @param seasonNum * @param oldSeasonEndTime */ export async function sendPVPRewardToUser(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number, notPush?: boolean) { //检查并返回排名结算以及武将功勋结算 let pvpSeasonResult = await savePvpSeasonResult(pvpDefense, seasonNum, seasonEndTime); let { rankGoods, heroGoods, rankLv } = pvpSeasonResult; //下发邮件 if (!!rankGoods.length) //排名奖励 await sendMailByContent(MAIL_TYPE.PVP_RANK_REWARD, pvpDefense.roleId, { params: [JSON.stringify(seasonNum), (rankLv > 1000 ? '999+' : JSON.stringify(rankLv))], goods: rankGoods, notPush }); if (!!heroGoods.length) //武将功勋奖励 await sendMailByContent(MAIL_TYPE.PVP_RESULT, pvpDefense.roleId, { params: [JSON.stringify(seasonNum)], goods: heroGoods, notPush }); return { pvpSeasonResult, pvpDefense: await resetPvpScores(pvpDefense, seasonNum + 1, pvpSeasonResult) } } async function resetPvpScores(pvpDefense: PvpDefenseType, seasonNum: number, pvpSeasonResult: PvpSeasonResultType) { let { roleId, attack, defense } = pvpDefense; let { newHeroScores, newScore } = pvpSeasonResult; let newAttack = calLineupScore(attack, newHeroScores); let newDefense = calLineupScore(defense, newHeroScores); pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { heroScores: newHeroScores, score: newScore, attack: newAttack, defense: newDefense, seasonNum, challengeCnt: PVP.PVP_CHALLENGE_COUNTS, challengeRefTime: 0, winStreakNum: 0, isFirstEntry: true }); return pvpDefense; } /** * 检查并返回排名结算以及武将功勋结算 * @param pvpDefense * @param seasonNum * @param oldSeasonEndTime * @param rankLv */ export async function savePvpSeasonResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number, rankLv?: number) { if (!rankLv) { let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum }); rankLv = await r.getMyRank({ roleId: pvpDefense.roleId });// 获得排行榜排名 } let pvpRankReward: DicRankRewads = getPvpRankRewardsByRank(rankLv); let rankGoods: RewardInter[] = []; if (pvpRankReward) { rankGoods = pvpRankReward.reward;//排名奖励 } let heroGoods: HeroReward[] = []; let newHeroScores: HeroScore[] = [], newScore = 0; for (let heroScore of pvpDefense.heroScores) { let pvpHeroReward = getPvpHeroRewardsByScore(heroScore.score); //获得武将功勋奖励 if (pvpHeroReward) { newHeroScores.push({...heroScore, score: pvpHeroReward.heroscore }); for(let { id, count } of pvpHeroReward.reward) { heroGoods.push({ hid: heroScore.hid, id, count }); } newScore += pvpHeroReward.heroscore; } else { newHeroScores.push(heroScore); newScore += heroScore.score; } } //pvp锁定的信息存入赛季结算表中 let pvpSeasonResult = await PvpSeasonResultModel.updatePvpSeasonResult(pvpDefense.roleId, seasonNum, { ...pvpDefense, rankLv, heroGoods, rankGoods, show: true, newScore, newHeroScores, seasonEndTime });//结算修改玩家pvp信息 if(newScore > 0) { let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: seasonNum + 1 }); await r.setRankWithRoleInfo(pvpDefense.roleId, newScore, Date.now()); } // 更新任务 await checkTask(pvpDefense.roleId, null, TASK_TYPE.PVP_HERO_SCORE, 0, false, { heroScores: pvpDefense.heroScores }); await checkTask(pvpDefense.roleId, null, TASK_TYPE.PVP_RANK, 1, false, { rankLv }); return pvpSeasonResult; } export async function generPvpLineupCe(roleId: string, lineupCe: LineupCe[], newHeroes: AttackHero[]|DefenseHero[], dbHeroes: HeroType[]) { let newHids: number[] = []; // 本次新增武将 let newLineupCe: { hid: number, ce: number }[] = []; // 新生成的lineupCe字段 for(let { actorId } of newHeroes) { let n = newLineupCe.find(cur => cur.hid == actorId); if(!n) { let lineup = lineupCe.find(cur => cur.hid == actorId); if(lineup) { newLineupCe.push(lineup); } else { let dbHero = dbHeroes.find(cur => cur.hid == actorId); if(dbHero) { newLineupCe.push({ hid: actorId, ce: dbHero.ce }); } else { newHids.push(actorId); } } } } let heroes = await HeroModel.findByHidRange(newHids, roleId, 'hid ce', true); for(let { hid, ce } of heroes) { newLineupCe.push({ hid, ce }); } return newLineupCe; }