import {Application, BackendSession} from 'pinus'; const _ = require('underscore'); import { gameData } from '../../../pubUtils/data'; import { checkPvp, initPvpInfo, refreshEnemies, getEnemies, getPlusScore, getLvByScore, defaultHeroes} from '../../../services/pvpService'; import { RoleModel, RoleType } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; import { resResult, reduceCe, genCode } from '../../../pubUtils/util'; import { SystemConfigModel } from '../../../db/SystemConfig' import { PvpDefenseModel, PvpDefenseType, OppPlayers } from '../../../db/PvpDefense'; import { oppHeroesDefenseInter, pvpEndParamInter } from '../../../pubUtils/interface'; import { PVP_HERO_POS, ROBOT_NAME } from '../../../consts'; import { HeroType, HeroModel } from '../../../db/Hero'; import { CeAttrNumber } from '../../../db/generalField'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { BattleRecordModel } from '../../../db/BattleRecord'; import { PvpRecordModel, HeroesRecord } from '../../../db/PvpRecord'; export default function(app: Application) { return new PvpHandler(app); } export class PvpHandler { constructor(private app: Application) { } async test(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let role = await RoleModel.findByRoleId(roleId); const result = await initPvpInfo(role); return resResult(STATUS.SUCCESS, {result}); } async getData (msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let {heroes, score, pLv, winStreakNum, oppPlayers: oppPlayerInfos, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, seasonNum: playerSeaSonNum} = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); let oppPlayers = getEnemies(oppPlayerInfos, winStreakNum); let {warId, seasonNum, seasonEndTime} = await SystemConfigModel.findSystemConfig(); if (playerSeaSonNum !== seasonNum) { //TODO去结算 } let myRank = 999;//TODO去redis中获取 let data = {warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes, score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores} return resResult(STATUS.SUCCESS, { data: data }); } // TODO 刷新 async refreshOppPlayer (msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); let role = pvpDefense.role; let oppPlayers = await refreshEnemies(role, pvpDefense.score, pvpDefense.pLv); pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers }); let result = getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum); return resResult(STATUS.SUCCESS, { oppPlayers: result, refOppCnt: 0 }); } // 获取对手阵容具体信息 async getOppoPlayer (msg: { roleId: string }, session: BackendSession) { let roleId = session.get('roleId'); let oppoRoleId = msg.roleId; let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); let { oppPlayers } = pvpDefense; let role = pvpDefense.role; let curOpp = oppPlayers.find(cur => cur.roleId == oppoRoleId); if(!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); let system = await SystemConfigModel.findSystemConfig(); let mapWarJson = gameData.warJson.get(system.warId); let heroes = new Array(); if(curOpp.isRobot) { // 机器人 let { pos, robot } = curOpp; let { warId } = robot; let dicWarJson = gameData.warJson.get(warId); let dicOpp = gameData.pvpOpponent.get(pos); for(let json of dicWarJson) { let curDicMapJson = mapWarJson.find(cur => cur.dataId == json.dataId); const { actorId, actorName, attribute, skill, seid, star, spine, relation } = json; if(relation == 2 && actorId > 0) { // 默认格子 let newAttribute = new CeAttrNumber(); for(let attrName in newAttribute) { newAttribute[attrName] = Math.floor(attribute[attrName] * role.topFiveCe / 10000 * dicOpp.ratio); } newAttribute['speed'] = 0; newAttribute['ap'] = 0; let heroInfo = { actorId, actorName, skill, seid, star, spine, attribute: newAttribute, lv: role.lv }; heroes.push({ ...curDicMapJson, ...heroInfo }); } } } else { // 真人 let oppDef = curOpp.oppDef; let role = oppDef.role; let { globalCeAttr } = role; for(let { actorId, hero, dataId, order } of oppDef.heroes) { let curDicMapJson = mapWarJson.find(cur => cur.dataId == dataId); let dicHero = gameData.hero.get(actorId); let h = hero; let { ceAttr } = h; let newAttribute = new CeAttrNumber(); for(let attrName in newAttribute) { let { base, ratioUp, fixUp, equipUp } = ceAttr[attrName]; let { ratioUp: ratioUp2, fixUp: fixUp2 } = globalCeAttr[attrName]; let result = base * ( 1 + ratioUp + ratioUp2) + fixUp + fixUp2 + equipUp; newAttribute[attrName] += reduceCe(result); } newAttribute['speed'] = 0; newAttribute['ap'] = 0; let heroInfo = { outIndex: order, actorId, actorName: dicHero.name, skill:0, seid:'&', star: h.star, spine: 0, attribute: newAttribute, lv: h.lv }; heroes.push({ ...curDicMapJson, ...heroInfo }); } } return resResult(STATUS.SUCCESS, { roleId: oppoRoleId, pos: curOpp.pos, heroes }); } // 开战 async pvpStart (msg: { warId: number, heroes: number[], roleId: string }, session: BackendSession) { const { warId, heroes, roleId: oppRoleId } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let warInfo = gameData.war.get(warId); if(!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } let checkHeroes = await checkBattleHeroesByHid(roleId, heroes); if(!checkHeroes) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); const pvpDefense = await PvpDefenseModel.findByRoleId(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); let { oppPlayers } = pvpDefense; let curOpp = oppPlayers.find(cur => cur.roleId == oppRoleId); if(!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND) const battleCode = genCode(8); // 关卡唯一值 await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { roleId, roleName, warId, status: 0, warName: warInfo.gk_name, warType: warInfo.warType, record: { heroes, pos: curOpp.pos, oppRoleId } } }, true); return resResult(STATUS.SUCCESS, { battleCode }); } // 结算 async pvpEnd (msg: { battleCode: string, isSuccess: boolean, myHeroes: pvpEndParamInter[], oppHeroes: pvpEndParamInter[] }, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); const { battleCode, isSuccess, myHeroes, oppHeroes } = 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 } } = 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.findByRoleId(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); let { oppPlayers, winStreakNum, heroScores, score } = pvpDefense; let curOpp = oppPlayers.find(cur => cur.roleId == oppRoleId && cur.pos == pos); if(!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); const dicOpp = gameData.pvpOpponent.get(pos); let plusScore = getPlusScore(winStreakNum); let myHeroRecords = new Array(); let showHeroScores = new Array<{hid: number, addScore: number, plusScore: number, score: number}>(); let addSumScore = 0; for(let { hid, damage, heal, underDamage } of myHeroes) { 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 }); winStreakNum ++; } else { showHeroScores.push({ hid, addScore: 0, plusScore: 0, score: curHeroScore.score }); winStreakNum = 0; } const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv'); let { quality, star, colorStar, lv} = myHero; myHeroRecords.push({ hid, quality, star, colorStar, lv, damage, heal, underDamage }); } let oppHeroRecords = new Array(); for(let { hid, damage, heal, underDamage } of myHeroes) { if(curOpp.isRobot) { let dicHero = gameData.hero.get(hid); let { quality, initialStars: star } = dicHero; oppHeroRecords.push({ hid, quality, star, colorStar: 0, lv: 0, damage, heal, underDamage }); } else { const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv'); let { quality, star, colorStar, lv} = myHero; oppHeroRecords.push({ hid, quality, star, colorStar, lv, damage, heal, underDamage }); } } score += addSumScore; let pLv = getLvByScore(heroScores); // 刷新对手 const role = await RoleModel.findByRoleId(roleId); let newOppPlayers: Array = await refreshEnemies(role, score, pLv); pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers: newOppPlayers, heroScores, score, pLv, winStreakNum }); let result = getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum); // 更新battleRecord await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess?1:2 } }, true); let oppRole; if(curOpp.isRobot) { oppRole = { ...curOpp.robot, title: 1, topFiveCe: curOpp.robot.defCe}; } else { oppRole = await RoleModel.findByRoleId(oppRoleId); } // TODO 战报记录方法抽象 await PvpRecordModel.createRec({roleId1: roleId, roleId2: oppRoleId, warId: BattleRecord.battleId, attackInfo: { roleId, roleName, lv: role.lv, sHid: role.sHid, headHid: role.headHid, title: role.title, ce: role.topFiveCe, heroes: myHeroRecords, isSuccess, score: isSuccess?addSumScore:0 }, defenseInfo: { roleId: oppRole.roleId, roleName: oppRole.roleName, lv: oppRole.lv, sHid: oppRole.sHid, headHid: oppRole.headHid, title: oppRole.title, ce: oppRole.topFiveCe, heroes: myHeroRecords, isSuccess: !isSuccess, score: 0 }}) return resResult(STATUS.SUCCESS, { battleCode, isSuccess, score, pLv, myRank: 0, heroScores: showHeroScores, oppPlayers: result }); } async saveDefense(msg: { heroes: Array<{actorId: number, dataId: number, order: number}>, isDefaultHero:boolean }, session: BackendSession) { let {heroes, isDefaultHero} = msg; let roleId = session.get('roleId'); if (heroes.length > 5) { return resResult(STATUS.WRONG_PARMS); } heroes = _.uniq(heroes, function(item) { return item.order; }); let { heroes: defHeros } = await PvpDefenseModel.findByRoleId(roleId); let defCe = 0; if (!!isDefaultHero) { let role = await RoleModel.findByRoleId(roleId); let { resHeroes } = await defaultHeroes(role); return resResult(STATUS.SUCCESS, { data: { heroes: resHeroes } }); } else { for (let dataId = PVP_HERO_POS.START; dataId <= PVP_HERO_POS.END; dataId++) { let index = _.findIndex(heroes, {dataId}); let defIndex = _.findIndex(defHeros, {dataId}); if (defIndex == -1) { defIndex = defHeros.length; defHeros.push({actorId:0, order:0,ce:0, hero:null,dataId}); } if (index == -1) { defHeros[defIndex].actorId = 0; defHeros[defIndex].order = 0; defHeros[defIndex].ce = 0; defHeros[defIndex].hero = null; defHeros[defIndex].dataId = dataId; continue; } let hero = await HeroModel.findByHidAndRole(heroes[index].actorId, roleId); if (!hero) { continue; } defHeros[defIndex].actorId = heroes[index].actorId; defHeros[defIndex].order = heroes[index].order; defHeros[defIndex].ce = hero.ce; defHeros[defIndex].hero = hero._id; defCe += hero.ce; } let { heroes: resHeroes } = await PvpDefenseModel.updateInfo(roleId, {defCe, heroes: defHeros}); return resResult(STATUS.SUCCESS, { data: { heroes: resHeroes } }); } } }