Files
ZYZ/game-server/app/services/pvpService.ts
2021-01-08 14:00:25 +08:00

219 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 体力系统
*/
import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType, HeroScores } from '../db/PvpDefense';
import { RoleType } from '../db/Role';
import { PVP_HERO_POS, ROBOT_NAME, REDIS_KEY } from '../consts';
import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent";
import { getRandomIndexByLen, genCode, getRandomByLen } from '../pubUtils/util';
import { oppPlayersInter, RankParam } from '../pubUtils/interface';
import { gameData, getPLvByScore } from "../pubUtils/data";
import { PVP } from '../pubUtils/dicParam';
import { SystemConfigModel } from '../db/SystemConfig'
import { setRank, getMyRank } from './redisService';
const _ = require('underscore');
export async function initPvpInfo(role: RoleType) {
let heroes: Array<Heroes> = [];
//初始化最强5人阵容
for (let i = PVP_HERO_POS.START; i <= PVP_HERO_POS.END; i++) {
let index = i - PVP_HERO_POS.START;
let item = role.topFive[index];
heroes.push({
actorId: item?.hid||0,
hero: item?.hero||null,
ce: item?.ce||0,
dataId: i,
order: index + 1,
});
}
//初始化对手人阵容
let oppPlayers: Array<OppPlayers> = await refreshEnemies(role, 0, 1);
let {warId, seasonNum } = await SystemConfigModel.findSystemConfig();
let challengeCnt = PVP.PVP_CHALLENGE_COUNTS;
let result = await PvpDefenseModel.createPvpDefense({ roleId: role.roleId, roleName: role.roleName, role: role._id, heroes, oppPlayers, defCe: role.topFiveCe, seasonNum, warId, challengeCnt });
//加入排行榜
let { roleId, roleName, lv, vLv, headHid, sHid, title } = role;
let params = new RankParam(roleName, lv, vLv, headHid, sHid, title);
await setRank(REDIS_KEY.PVP_RANK, 0, roleId, result.score, result.updatedAt.getTime(), params);
return result;
}
export async function checkPvp(role: RoleType) {
let result = await PvpDefenseModel.findByRoleId(role.roleId);
if (!!result)
return result;
result = await initPvpInfo(role);
return result;
}
/**
* 返回对手三人信息
*
* @param oppPlayers pvpDefense表中的oppPlayers字段需要populate过的
* @param pLv 玩家本人的队伍等级
*/
export async function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number) {
let result = new Array<oppPlayersInter>();
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,
rankLv: 0,
plusScore: getPlusScore(winStreakNum)
});
} else {
let opp = <PvpDefenseType>oppDef;
let role = <RoleType>opp.role;
let { roleId, roleName, headHid, sHid } = role;
let { pLv, defCe } = opp;
let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);
result.push({
pos, roleId, roleName, headHid, sHid, pLv, defCe,
addScore: dicOpponent.score,
rankLv, // 读取排名
plusScore: getPlusScore(winStreakNum)
});
}
}
return result
}
// TODO 刷新对手
export async function refreshEnemies(role: RoleType, score: number, pLv: number) {
let { roleId, topFiveCe } = role;
let oppPlayers = new Array<OppPlayers>();
let opp = dicPvpOpponent.values()
for(let dicOpp of opp) {
let flag = false; // 是否筛选成功
if(score > 3000) { // TODO 将这个放到const
flag = await matchPlayer(oppPlayers, roleId, pLv, dicOpp);
// TODO 当前后分数段没有时,返回前一名的玩家
if(!flag) flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp);
} else {
flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp);
}
if(!flag) continue;
}
return oppPlayers;
}
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);
let result = range[index];
if(!result) return false;
if(result.roleId == roleId) {
console.log(range.length)
range.splice(index, 1);
console.log(JSON.stringify(range))
if(range.length <= 0) return false;
index = getRandomIndexByLen(range.length);
result = range[index];
}
oppPlayers.push({
roleId: result.roleId,
oppDef: result._id,
pos,
isRobot: false,
robot: null
});
return true;
}
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;
let index = getRandomIndexByLen(range.length);
let result = range[index];
if(!result) return false;
let roleId = generateRobotRoleId();
let roleName = getRandomByLen(ROBOT_NAME);
let hisPLv = Math.floor(pLv + (minLv + maxLv)/2);
if(hisPLv < 1) hisPLv = 1
let robot = new Robot(roleId, roleName, Math.floor(myCe * ratio), hisPLv, result.war_id)
oppPlayers.push({
roleId,
oppDef: null,
pos,
isRobot: true,
robot
});
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 < 0) result = 0;
if(result > PVP.PVP_WINREWARD_UPLIMIT) result = PVP.PVP_WINREWARD_UPLIMIT;
return result;
}
export function getLvByScore(heroScores: HeroScores[]) {
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 async function defaultHeroes ( role:RoleType) {
let { heroes } = await PvpDefenseModel.findByRoleId(role.roleId);
heroes.sort(function(a, b) {
return a.ce + a.dataId - b.ce + b.dataId;
});
role.topFive.sort(function(a, b) {
return a.ce - b.ce;
});
let defCe = 0;
for (let i = 1; i < role.topFive.length; i++) {
let item = role.topFive[i];
if (!_.findWhere(heroes, {actorId: item.hid})) {
for (let j = 0; j < heroes.length; j++) {
let hero = heroes[j];
if (heroes.length >= 5 && !hero.actorId) {
continue;
}
let index = _.findIndex(role.topFive,{hid: hero.actorId});
if (index == -1) {
hero.actorId = item.hid;
hero.hero = item.hero||'';
hero.ce = item.ce||0;
} else {
heroes[index].ce = item.ce||0;
}
}
}
defCe += item.ce;
}
let { heroes: resHeroes} = await PvpDefenseModel.updateInfo(role.roleId, {defCe, heroes});
return { resHeroes};
}