diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index 295cc746b..2d45e3735 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -1,8 +1,8 @@ import {Application, BackendSession} from 'pinus'; const _ = require('underscore'); import { gameData } from '../../../pubUtils/data'; -import { checkPvp, initPvpInfo } from '../../../pubUtils/pvpUtil'; -import { RoleModel } from '../../../db/Role'; +import { checkPvp, initPvpInfo, refreshEnemies, getEnemies } from '../../../pubUtils/pvpUtil'; +import { RoleModel, RoleType } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; import { resResult } from '../../../pubUtils/util'; import { SystemConfigModel } from '../../../db/SystemConfig' @@ -33,4 +33,20 @@ export class PvpHandler { return resResult(STATUS.SUCCESS, { data: result }); } + + + // 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, { data: result }); + } } diff --git a/shared/db/PvpDefense.ts b/shared/db/PvpDefense.ts index ed15b60d1..c27951cee 100644 --- a/shared/db/PvpDefense.ts +++ b/shared/db/PvpDefense.ts @@ -5,6 +5,11 @@ import Role, { } from './Role'; import PvpDef, { } from './PvpDefense'; import { PVP_PLAYER_POS, PVP_HERO_POS } from '../consts'; +interface pvpUpdateInter { + _id?: string; + oppPlayers: OppPlayers[] +} + export class Heroes { @prop({ required: true }) actorId: number; // 武将id @@ -53,12 +58,15 @@ export class Robot { @prop({ required: true }) defCe: number; @prop({ required: true }) + pLv: number; + @prop({ required: true }) warId: number; // 模板的warId - constructor(roleId: string, roleName: string, defCe: number, warId: number) { + constructor(roleId: string, roleName: string, defCe: number, pLv: number, warId: number) { this.roleId = roleId; this.roleName = roleName; this.defCe = defCe; + this.pLv = pLv; this.warId = warId; } } @@ -93,7 +101,7 @@ export default class PvpDefense extends BaseModel { heroes: Array; @prop({ required: true, default: 0 }) score: number; - @prop({ required: true, default: 0 }) + @prop({ required: true, default: 1 }) pLv: number; @prop({ required: true, default: 0 }) hisScore: number; //历史最高积分 @@ -126,7 +134,7 @@ export default class PvpDefense extends BaseModel { return result; } - public static async createPvpDefense(params: { roleId: string, roleName: string, heroes: Array, oppPlayers: Array, defCe: number }, lean = true) { + public static async createPvpDefense(params: { roleId: string, roleName: string, role: string, heroes: Array, oppPlayers: Array, defCe: number }, lean = true) { const doc = new PvpDefenseModel(); const update = Object.assign(doc.toJSON(), params); const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: params.roleId }, update, { upsert: true, new: true }).lean(lean); @@ -163,12 +171,34 @@ export default class PvpDefense extends BaseModel { } public static async findByRoleIdIncludeAll(roleId: string, lean = true) { - const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).populate('role', 'Heroes.hero', 'OppPlayers.oppDef').lean(lean); + const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }) + .populate('role', 'headHid sHid topFiveCe roleId roleName') + .populate('heroes.hero') + .populate({ + path: 'oppPlayers.oppDef', + populate: { + path: 'role', + select: 'headHid sHid topFiveCe roleId roleName' + } + }).lean(); return result; } public static async findByTeamLv(min: number, max: number) { - const result: PvpDefenseType[] = await PvpDefenseModel.find({ $gte: { pLv: min }, $lte: { pLv: max } }).lean(); + const result: PvpDefenseType[] = await PvpDefenseModel.find({ pLv: { $gte: min, $lte: max } }).lean(); + return result; + } + + public static async updateInfoAndInclude(roleId: string, update: pvpUpdateInter) { + delete update._id; + let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true}) + .populate({ + path: 'oppPlayers.oppDef', + populate: { + path: 'role', + select: 'headHid sHid topFiveCe roleId roleName' + } + }).lean(); return result; } } diff --git a/shared/pubUtils/interface.ts b/shared/pubUtils/interface.ts index f4d976e04..18c70de01 100644 --- a/shared/pubUtils/interface.ts +++ b/shared/pubUtils/interface.ts @@ -55,3 +55,15 @@ export interface SclResultInter { position: SclPosInter[] } +// pvp对手返回 +export interface oppPlayersInter { + pos: number; // 对手位置 + roleId: string; // 对手玩家id + roleName: string; // 对手玩家名 + headHid: number; // 头像 + sHid: number; // 形象 + pLv: number; // 对手队伍等级 + defCe: number; // 防守阵容战力 + addScore: number; // 战胜后可获军功 + plusScore: number; // 连胜加成军功 +} \ No newline at end of file diff --git a/shared/pubUtils/pvpUtil.ts b/shared/pubUtils/pvpUtil.ts index 4ebee6963..a7ea29540 100644 --- a/shared/pubUtils/pvpUtil.ts +++ b/shared/pubUtils/pvpUtil.ts @@ -1,12 +1,13 @@ /** * 体力系统 */ -import { PvpDefenseModel, Heroes, OppPlayers, Robot } from '../db/pvpDefense'; +import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType } from '../db/pvpDefense'; import { RoleType } from '../db/Role'; import { PVP_PLAYER_POS, PVP_HERO_POS, ROBOT_NAME } from '../consts'; -import { dicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; +import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; import { getRandomIndexByLen, genCode, getRandomByLen } from '../pubUtils/util'; +import { oppPlayersInter } from '../pubUtils/interface'; import { gameData } from "../pubUtils/data"; @@ -28,7 +29,7 @@ export async function initPvpInfo(role: RoleType) { //初始化对手人阵容TODO let oppPlayers: Array = await refreshEnemies(role, 0, 1); - let result = await PvpDefenseModel.createPvpDefense({ roleId: role.roleId, roleName: role.roleName, heroes, oppPlayers, defCe: role.topFiveCe }); + let result = await PvpDefenseModel.createPvpDefense({ roleId: role.roleId, roleName: role.roleName, role: role._id, heroes, oppPlayers, defCe: role.topFiveCe }); //加入排行榜 TODO return result; } @@ -41,21 +42,51 @@ export async function checkPvp(role: RoleType) { return result; } +/** + * 返回对手三人信息 + * + * @param oppPlayers pvpDefense表中的oppPlayers字段,需要populate过的 + * @param pLv 玩家本人的队伍等级 + */ +export function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number) { + let result = new Array(); + for(let {pos, isRobot, oppDef, robot} of oppPlayers) { + let dicOpponent = dicPvpOpponent.get(pos); + if(isRobot) { + let { roleId, roleName, headHid, sHid, pLv, defCe } = robot; + result.push({ + pos, roleId, roleName, headHid, sHid, pLv, defCe, + addScore: dicOpponent.score, + plusScore: getPlusScore(winStreakNum) + }); + } else { + let opp = oppDef; + let role = opp.role; + let { roleId, roleName, headHid, sHid } = role; + let { pLv, defCe } = opp; + result.push({ + pos, roleId, roleName, headHid, sHid, pLv, defCe, + addScore: dicOpponent.score, + plusScore: getPlusScore(winStreakNum) + }); + } + } + return result +} - -// 刷新对手 +// TODO 刷新对手 export async function refreshEnemies(role: RoleType, score: number, pLv: number) { let { roleId, topFiveCe } = role; let oppPlayers = new Array(); let opp = dicPvpOpponent.values() - for(let { id, maxLv, minLv, ratio } of opp) { + for(let dicOpp of opp) { let flag = false; // 是否筛选成功 if(score > 3000) { // TODO 将这个放到const - flag = await matchPlayer(oppPlayers, id, roleId, pLv + minLv, pLv + maxLv); + flag = await matchPlayer(oppPlayers, roleId, pLv, dicOpp); // TODO 当前后分数段没有时,返回前一名的玩家 - if(!flag) flag = matchRobot(oppPlayers, id, topFiveCe, ratio); + if(!flag) flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp); } else { - flag = matchRobot(oppPlayers, id, topFiveCe, ratio); + flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp); } if(!flag) continue; } @@ -63,8 +94,9 @@ export async function refreshEnemies(role: RoleType, score: number, pLv: number) return oppPlayers; } -async function matchPlayer(oppPlayers: OppPlayers[], pos: number, roleId: string, minLv: number, maxLv: number ) { - let range = await PvpDefenseModel.findByTeamLv(minLv, maxLv); +async function matchPlayer(oppPlayers: OppPlayers[], roleId: string, pLv: number, dicOpp: DicPvpOpponent ) { + let { id: pos, minLv, maxLv } = dicOpp + let range = await PvpDefenseModel.findByTeamLv(pLv + minLv, pLv + maxLv); if(range.length <= 0) return false; let index = getRandomIndexByLen(range.length); @@ -86,7 +118,8 @@ async function matchPlayer(oppPlayers: OppPlayers[], pos: number, roleId: string return true; } -function matchRobot(oppPlayers: OppPlayers[], pos: number, myCe: number, ratio: number) { +function matchRobot(oppPlayers: OppPlayers[], myCe: number, pLv: number, dicOpp: DicPvpOpponent) { + let { id: pos, minLv, maxLv, ratio } = dicOpp; let range = gameData.pvpWar; if(range.length <= 0) return false; @@ -96,7 +129,7 @@ function matchRobot(oppPlayers: OppPlayers[], pos: number, myCe: number, ratio: let roleId = generateRobotRoleId(); let roleName = getRandomByLen(ROBOT_NAME); - let robot = new Robot(roleId, roleName, Math.floor(myCe * ratio), result.war_id) + let robot = new Robot(roleId, roleName, Math.floor(myCe * ratio), Math.floor(pLv + (minLv + maxLv)/2), result.war_id) oppPlayers.push({ oppDef: null, pos, @@ -106,10 +139,19 @@ function matchRobot(oppPlayers: OppPlayers[], pos: number, myCe: number, ratio: return true } +// 生成机器人roleId function generateRobotRoleId() { return `${genCode(10)}_r`; } +// 根据roleId判断是不是机器人 export function checkRoleIsRobot(roleId: string) { return !!roleId.match(/_r/); +} + +// 根据连胜次数,获得加成的积分 +export function getPlusScore(win: number) { + let result = win - 1; + if(result > 10) result = 10; + return result; } \ No newline at end of file