pvp刷新规则,区段没有人时刷前后一名

This commit is contained in:
luying
2021-01-08 20:02:23 +08:00
parent c743e2bd40
commit c3b4a59906
6 changed files with 227 additions and 127 deletions

View File

@@ -1,25 +1,24 @@
import {Application, BackendSession} from 'pinus';
const _ = require('underscore');
import { gameData, getPvpBoxs } from '../../../pubUtils/data';
import { refreshEnemies, getEnemies, getPlusScore, getLvByScore, defaultHeroes, comsumeChallengeCnt, refresh, findPvpDefByRoleId, checkRoleIsRobot, getRefOppCnt, findPvpDefAllByRoleId } from '../../../services/pvpService';
import { refreshEnemies, getEnemies, getLvByScore, defaultHeroes, comsumeChallengeCnt, refresh, findPvpDefByRoleId, checkRoleIsRobot, getRefOppCnt, findPvpDefAllByRoleId, generPVPOppRecInfo, generMyRecInfo, getRobotLineup, getPlayerLineup } from '../../../services/pvpService';
import { RoleModel, RoleType } from '../../../db/Role';
import { STATUS } from '../../../consts/statusCode';
import { resResult, reduceCe, genCode } from '../../../pubUtils/util';
import { resResult, genCode } from '../../../pubUtils/util';
import { SystemConfigModel } from '../../../db/SystemConfig'
import { PvpDefenseModel, PvpDefenseType, OppPlayers } from '../../../db/PvpDefense';
import { PvpDefenseModel, OppPlayers } from '../../../db/PvpDefense';
import { oppHeroesDefenseInter, pvpEndParamInter, RankParam, PlayerDetail, PlayerDetailHero } from '../../../pubUtils/interface';
import { PVP_HERO_POS, REDIS_KEY } from '../../../consts';
import { addItems } from '../../../services/rewardService';
import { HeroType, HeroModel } from '../../../db/Hero';
import { CeAttrNumber } from '../../../db/generalField';
import { HeroModel } from '../../../db/Hero';
import { checkBattleHeroesByHid } from '../../../services/normalBattleService';
import { BattleRecordModel } from '../../../db/BattleRecord';
import { PvpRecordModel, HeroesRecord } from '../../../db/PvpRecord';
import { setPvpDefResult } from '../../../services/timeTaskService';
import { existsRank, initRank, getRank, setRank, getMyRank } from '../../../services/redisService';
import { handleCost } from '../../../services/rewardService';
import { matchPlayerByRank } from '../../../services/pvpService';
export default function(app: Application) {
return new PvpHandler(app);
@@ -90,52 +89,9 @@ export class PvpHandler {
let heroes = new Array<oppHeroesDefenseInter>();
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
});
}
}
heroes = await getRobotLineup(mapWarJson, curOpp, role.topFiveCe, role.lv);
} else { // 真人
let oppDef = <PvpDefenseType>curOpp.oppDef;
let role = <RoleType>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 = <HeroType>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
});
}
heroes = await getPlayerLineup(mapWarJson, curOpp);
}
return resResult(STATUS.SUCCESS, { roleId: oppoRoleId, pos: curOpp.pos, heroes });
@@ -212,80 +168,22 @@ export class PvpHandler {
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<HeroesRecord>();
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<HeroesRecord>();
for(let { hid, damage, heal, underDamage } of oppHeroes) {
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
});
}
}
const role = await RoleModel.findByRoleId(roleId);
const myRecInfo = await generMyRecInfo(heroScores, winStreakNum, role, isSuccess, pos, myHeroes);
let { attackInfo, showHeroScores, addSumScore } = myRecInfo
score += addSumScore;
if(score > hisScore) hisScore = score;
let pLv = getLvByScore(heroScores);
const defenseInfo = await generPVPOppRecInfo(isSuccess, curOpp, oppRoleId, oppHeroes);
// 战报记录
await PvpRecordModel.createRec({roleId1: roleId, roleId2: oppRoleId, warId: BattleRecord.battleId, attackInfo, defenseInfo});
// 刷新对手
const role = await RoleModel.findByRoleId(roleId);
let newOppPlayers: Array<OppPlayers> = await refreshEnemies(role, score, pLv);
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
}})
// 更新battleRecord
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: { status: isSuccess?1:2 }

View File

@@ -2,17 +2,21 @@
* 体力系统
*/
import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType, HeroScores } from '../db/PvpDefense';
import { RoleType } from '../db/Role';
import { RoleType, RoleModel } 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 { getRandomIndexByLen, genCode, getRandomByLen, shouldRefresh, reduceCe } from '../pubUtils/util';
import { oppPlayersInter, RankParam, pvpEndParamInter, oppHeroesDefenseInter } 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 { setRank, getMyRank, getFieldByRank } from './redisService';
import { nowSeconds, checkTodayTime } from '../pubUtils/timeUtil';
import { HeroesRecord } from '../db/PvpRecord';
import { HeroModel, HeroType } from '../db/Hero';
import { CeAttrNumber } from '../db/generalField';
import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
const _ = require('underscore');
@@ -65,7 +69,7 @@ export async function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number)
if(isRobot) {
let { roleId, roleName, headHid, sHid, pLv, defCe } = robot;
result.push({
pos, roleId, roleName, headHid, sHid, pLv, defCe,
pos, roleId, roleName, headHid, sHid, pLv, defCe: reduceCe(defCe),
addScore: dicOpponent.score,
rankLv: 0,
plusScore: getPlusScore(winStreakNum)
@@ -77,7 +81,7 @@ export async function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number)
let { pLv, defCe } = opp;
let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);
result.push({
pos, roleId, roleName, headHid, sHid, pLv, defCe,
pos, roleId, roleName, headHid, sHid, pLv, defCe: reduceCe(defCe),
addScore: dicOpponent.score,
rankLv, // 读取排名
plusScore: getPlusScore(winStreakNum)
@@ -87,7 +91,7 @@ export async function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number)
return result
}
// TODO 刷新对手
// 刷新对手
export async function refreshEnemies(role: RoleType, score: number, pLv: number) {
let { roleId, topFiveCe } = role;
let oppPlayers = new Array<OppPlayers>();
@@ -97,6 +101,7 @@ export async function refreshEnemies(role: RoleType, score: number, pLv: number)
if(score > 3000) { // TODO 将这个放到const
flag = await matchPlayer(oppPlayers, roleId, pLv, dicOpp);
// TODO 当前后分数段没有时,返回前一名的玩家
if(!flag) flag = await matchPlayerByRank(oppPlayers, roleId, dicOpp.id);
if(!flag) flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp);
} else {
flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp);
@@ -107,18 +112,53 @@ export async function refreshEnemies(role: RoleType, score: number, pLv: number)
return oppPlayers;
}
export async function matchPlayerByRank(oppPlayers: OppPlayers[], roleId: string, pos: number) {
let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);
let oppRoleId = '';
let oppRank = 0;
if(myRank == 1) { // 第一名
if(pos == 1) {
oppRank = 2;
} else if(pos == 2) {
oppRank = 3;
} else {
oppRank = 4;
}
} else {
if(pos == 1 || pos == 2) { // 刷新我前一名
oppRank = myRank - 1;
} else { // 刷新我后一名
oppRank = myRank + 1;
}
}
let result = await getFieldByRank(REDIS_KEY.PVP_RANK, 0, oppRank);
if(result.length <= 0) return false;
oppRoleId = result[0];
let pvpdefense = await PvpDefenseModel.findByRoleId(oppRoleId);
oppPlayers.push({
roleId: pvpdefense.roleId,
oppDef: pvpdefense._id,
pos,
isRobot: false,
robot: null
});
return true
}
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);
range = range.filter(cur => {
return oppPlayers.findIndex(ccur => ccur.roleId == cur.roleId) != -1;
});
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];
@@ -308,3 +348,154 @@ export async function findPvpDefAllByRoleId(roleId: string) {
return {pvpDefense, warId};
}
// 获取机器人阵容
export async function getRobotLineup(mapWarJson: DicWarJson[], curOpp: OppPlayers, topFiveCe: number, lv: number) {
let heroes = new Array<oppHeroesDefenseInter>();
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;
console.log(JSON.stringify(json))
if(relation == 2 && actorId > 0) { // 默认格子
let newAttribute = new CeAttrNumber();
for(let attrName in newAttribute) {
newAttribute[attrName] = Math.floor(attribute[attrName] * topFiveCe / 10000 * dicOpp.ratio);
}
newAttribute['speed'] = 0;
newAttribute['ap'] = 0;
let heroInfo = { actorId, actorName, skill, seid, star, spine, attribute: newAttribute, lv };
heroes.push({
...curDicMapJson, ...heroInfo
});
}
}
return heroes
}
// 获取阵容阵容
export async function getPlayerLineup(mapWarJson: DicWarJson[], curOpp: OppPlayers, ) {
let heroes = new Array<oppHeroesDefenseInter>();
let oppDef = <PvpDefenseType>curOpp.oppDef;
let role = <RoleType>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 = <HeroType>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 heroes
}
// 获取我方战报记录
export async function generMyRecInfo(heroScores: HeroScores[], winStreakNum: number, role: RoleType, isSuccess: boolean, pos: number, myHeroes: pvpEndParamInter[]) {
let { roleId, roleName } = role;
const dicOpp = gameData.pvpOpponent.get(pos);
const plusScore = getPlusScore(winStreakNum);
let myHeroRecords = new Array<HeroesRecord>();
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 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
}
return { attackInfo, showHeroScores, winStreakNum, addSumScore }
}
// 获取对手战报记录
export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayers, oppRoleId: string, oppHeroes: pvpEndParamInter[]) {
let oppHeroRecords = new Array<HeroesRecord>();
for (let { hid, damage, heal, underDamage } of oppHeroes) {
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, oppRoleId, 'quality star colorStar lv');
let { quality, star, colorStar, lv } = myHero;
oppHeroRecords.push({
hid, quality, star, colorStar, lv, damage, heal, underDamage
});
}
}
let oppRole;
if (curOpp.isRobot) {
oppRole = { ...curOpp.robot, title: 1, topFiveCe: curOpp.robot.defCe };
} else {
oppRole = await RoleModel.findByRoleId(oppRoleId);
}
return {
roleId: oppRole.roleId,
roleName: oppRole.roleName,
lv: oppRole.lv,
sHid: oppRole.sHid,
headHid: oppRole.headHid,
title: oppRole.title,
ce: oppRole.topFiveCe,
heroes: oppHeroRecords,
isSuccess: !isSuccess,
score: 0
}
}

View File

@@ -127,6 +127,14 @@ export async function getMyRank(key: string, serverId: number, roleId: string) {
return myRank + 1;
}
// 获取排名第几名的信息
export async function getFieldByRank(key: string, serverId: number, rank: number) {
const client: Redis.RedisClient = pinus.app.get('redis');
let myRank = await client.zrevrangeAsync(getKeyName(key, serverId), rank - 1, rank - 1);
console.log('****', JSON.stringify(myRank))
return myRank;
}
// 有序排行综合时间和得分排序
function encodeScoreWithTime(score: number, timestamp: number): number {
// value = score * Math.power(10, 14) + max_time - timestamp

View File

@@ -41,6 +41,8 @@ declare module 'redis' {
zrankAsync(key: string, field: string): Promise<number>;
// 返回有序集中指定成员的排名,从大到小
zrevrankAsync(key: string, field: string): Promise<number>;
// 命令返回有序集中,指定区间内的成员,从大到小
zrevrangeAsync(key: string, start: number, end: number): Promise<any>;
}
export interface Multi extends Commands<Multi> {
execAsync(...args: any[]): Promise<any>;

View File

@@ -154,5 +154,5 @@ export const COM_BATTLE_ROBOT_ID_NAME = [
];
export const ROBOT_NAME = [
'徐埋农', '简普瞳', '邛瑛', '嵇晁伊', '颜校', '吉辉娇'
'徐埋农', '简普瞳', '邛瑛', '嵇晁伊', '颜校', '吉辉娇', '罗宾', 'A', 'B', 'C', 'D', 'E', 'F'
];

View File

@@ -113,4 +113,5 @@ function parseAttribute(str: string) {
break;
}
}
return attribute
}