Files
ZYZ/game-server/app/services/pvpService.ts
T
2021-01-08 16:41:24 +08:00

281 lines
10 KiB
TypeScript

/**
* 体力系统
*/
import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType, HeroScores } from '../db/PvpDefense';
import { RoleType } from '../db/Role';
import { PVP_HERO_POS, ROBOT_NAME, REDIS_KEY, PVP_CONST } from '../consts';
import { setPvpDefResult } from '../services/timeTaskService';
import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent";
import { getRandomIndexByLen, genCode, getRandomByLen, shouldRefresh } 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';
import { nowSeconds, checkTodayTime } from '../pubUtils/timeUtil';
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, seasonEndTime} = 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, seasonEndTime, 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, challengeCnt?:number, challengeRefTime?:number,) {
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;
}
if (!!challengeCnt && !!challengeRefTime) {
let { heroes: resHeroes} = await PvpDefenseModel.updateInfo(role.roleId, {defCe, heroes, challengeCnt, challengeRefTime});
return { resHeroes};
} else {
let { heroes: resHeroes} = await PvpDefenseModel.updateInfo(role.roleId, {defCe, heroes});
return { resHeroes};
}
}
export function refresh(challengeCnt: number, challengeRefTime: number, seasonEndTime: number) {
if (challengeCnt >= PVP.PVP_CHALLENGE_COUNTS) {
return {challengeCnt, challengeRefTime};
}
let period = PVP.PVP_CHALLENGE_NORMALTIMES;
if (checkTodayTime(seasonEndTime)) {
period = PVP.PVP_CHALLENGE_FINALTIMES;
}
let time = nowSeconds();
let num = Math.floor(( time - challengeRefTime)/period);
if (num > 0) {
challengeCnt += num;
challengeRefTime = challengeRefTime + period * num;
}
return {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 refresh(challengeCnt, challengeRefTime, seasonEndTime);
}
export async function findPvpDefByRoleId(roleId: string) {
let pvpDefense = await PvpDefenseModel.findByRoleId(roleId);
let {warId, seasonNum, seasonEndTime} = await SystemConfigModel.findSystemConfig();
if (pvpDefense.seasonNum !== seasonNum) {
let newPvpDefense = await setPvpDefResult(pvpDefense, seasonNum, seasonEndTime);
return {pvpDefense: newPvpDefense, warId};
} else {
let {challengeCnt, challengeRefTime} = refresh(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, pvpDefense.seasonEndTime)
if (challengeCnt != pvpDefense.challengeCnt) {
pvpDefense = await PvpDefenseModel.updateInfo( roleId, { challengeCnt, challengeRefTime});
}
return {pvpDefense, warId};
}
}
// 获取刷新对手次数及消耗
export function getRefOppCnt(refOppCnt: number, refOppTime: Date) {
let curTime = new Date();
if(shouldRefresh(refOppTime, curTime, PVP_CONST.REFRESH_TIME)) {
refOppCnt = 0; refOppTime = curTime;
}
return {
refOppCnt, refOppTime,
consume: gameData.pvpRefreshConsume.get(refOppCnt + 1)
}
}