363 lines
16 KiB
TypeScript
363 lines
16 KiB
TypeScript
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, RankParam } from '../../../pubUtils/interface';
|
|
import { PVP_HERO_POS, REDIS_KEY } 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';
|
|
import { setPvpDefResult } from '../../../services/timeTaskService';
|
|
import { existsRank, initRank, getRank, setRank, getMyRank } from '../../../services/redisService';
|
|
|
|
export default function(app: Application) {
|
|
return new PvpHandler(app);
|
|
}
|
|
|
|
export class PvpHandler {
|
|
constructor(private app: Application) {
|
|
}
|
|
|
|
async getData (msg: {}, session: BackendSession) {
|
|
let roleId = session.get('roleId');
|
|
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
|
|
let oppPlayers = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum);
|
|
let {warId, seasonNum, seasonEndTime} = await SystemConfigModel.findSystemConfig();
|
|
let {heroes, score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry} = pvpDefense;
|
|
if (pvpDefense.seasonNum !== seasonNum) {
|
|
let { score, pLv, winStreakNum, heroScores, refOppCnt, challengeCnt, challengeRefTime } = await setPvpDefResult(pvpDefense, seasonNum);
|
|
}
|
|
if (isFirstEntry) {
|
|
await PvpDefenseModel.updateInfo(roleId, {isFirstEntry:false});
|
|
}
|
|
let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);//去redis中获取排名
|
|
let data = {warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes, score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry}
|
|
return resResult(STATUS.SUCCESS, data);
|
|
}
|
|
|
|
// TODO 刷新
|
|
async refreshOppPlayer (msg: {}, session: BackendSession) {
|
|
let roleId = session.get('roleId');
|
|
|
|
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
|
|
|
|
let role = <RoleType>pvpDefense.role;
|
|
let oppPlayers = await refreshEnemies(role, pvpDefense.score, pvpDefense.pLv);
|
|
|
|
pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers });
|
|
let result = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum);
|
|
|
|
// TODO 刷新次数及消耗
|
|
|
|
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 = <RoleType>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<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
|
|
});
|
|
}
|
|
}
|
|
} 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
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
// TODO 检查挑战次数
|
|
|
|
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<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 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<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 }
|
|
}, true);
|
|
|
|
// TODO 增加挑战次数
|
|
|
|
pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers: newOppPlayers, heroScores, score, pLv, winStreakNum });
|
|
let result = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum);
|
|
|
|
// 加入排行榜
|
|
let params = new RankParam(roleName, role.lv, role.vLv, role.headHid, role.sHid, role.title);
|
|
await setRank(REDIS_KEY.PVP_RANK, 0, roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params);
|
|
let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);
|
|
return resResult(STATUS.SUCCESS, {
|
|
battleCode, isSuccess,
|
|
score, pLv, myRank,
|
|
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 } });
|
|
}
|
|
}
|
|
|
|
async getRank(msg: {}, session: BackendSession) {
|
|
|
|
let roleId = session.get('roleId');
|
|
let roleName = session.get('roleName');
|
|
let serverId = session.get('serverId')
|
|
|
|
const hasRank = await existsRank(REDIS_KEY.PVP_RANK, serverId);
|
|
if(!hasRank) await initRank(serverId);
|
|
|
|
let {ranks, myRank} = await getRank(REDIS_KEY.PVP_RANK, 0, roleId);
|
|
if(!myRank) {
|
|
let pvpDefense = await PvpDefenseModel.findByRoleId(roleId);
|
|
let role = await RoleModel.findByRoleId(roleId);
|
|
let { lv, vLv, headHid, sHid, title} = role;
|
|
let rankRank = new RankParam(roleName, lv, vLv, headHid, sHid, title);
|
|
myRank = {
|
|
rank: 0, roleId, ...rankRank, num: pvpDefense.score, str: ''
|
|
}
|
|
}
|
|
|
|
return resResult(STATUS.SUCCESS, { ranks: ranks.slice(0, 100), myRank });
|
|
}
|
|
}
|