Files
ZYZ/game-server/app/servers/battle/handler/pvpHandler.ts
T
2021-02-01 17:10:14 +08:00

457 lines
21 KiB
TypeScript

import {Application, BackendSession, pinus} from 'pinus';
import { uniq, findWhere, findIndex } from 'underscore';
import { gameData, getPvpBoxs, getPLvByScore } from '../../../pubUtils/data';
import { refreshEnemies, getEnemies, getLvByScore, defaultHeroes, comsumeChallengeCnt, refresh, findPvpDefByRoleId, checkRoleIsRobot, getRefOppCnt, findPvpDefAllByRoleId, generPVPOppRecInfo, generMyRecInfo, robotIdComBack } from '../../../services/pvpService';
import { RoleModel, RoleType } from '../../../db/Role';
import { STATUS } from '../../../consts/statusCode';
import { resResult, genCode } from '../../../pubUtils/util';
import { PvpDefenseModel, OppPlayers } from '../../../db/PvpDefense';
import { pvpEndParamInter } from '../../../pubUtils/interface';
import { RankParam } from '../../../domain/rank';
import { PlayerDetail, PlayerDetailHero } from '../../../domain/battleField/guild';
import { PVP_HERO_POS, REDIS_KEY } from '../../../consts';
import { PVP } from '../../../pubUtils/dicParam';
import { addItems } from '../../../services/rewardService';
import { HeroModel } from '../../../db/Hero';
import { checkBattleHeroesByHid } from '../../../services/normalBattleService';
import { BattleRecordModel } from '../../../db/BattleRecord';
import { PvpRecordModel } from '../../../db/PvpRecord';
import { existsRank, getRank, setRank, getMyRank, initSingleRankWithServer } from '../../../services/redisService';
import { handleCost } from '../../../services/rewardService';
import { nowSeconds } from '../../../pubUtils/timeUtil';
import { setPvpSeasonResult, resetPvpWarId, resetPvpSeasonTime } from '../../../services/timeTaskService';
import { PvpSeasonResultModel } from '../../../db/PvpSeasonResult';
import { PvpHistoryOppModel, PvpHistoryOppType } from '../../../db/PvpHistoryOpp';
import { SystemConfigModel } from '../../../db/SystemConfig';
export default function(app: Application) {
return new PvpHandler(app);
}
export class PvpHandler {
constructor(private app: Application) {
}
async addRoleScore(msg: {heroScores: Array<{hid: number, score:number}>}, session: BackendSession) {
let { heroScores: addHeroScores } = msg;
let roleId = session.get('roleId');
let {heroScores, hisScore} = await PvpDefenseModel.findByRoleId(roleId);
let score = 0;
for (let {hid, score: heroScore} of addHeroScores) {
if (heroScore < 0) continue;
let index = findIndex(heroScores, {hid});
if (index != -1) {
heroScores[index].score = heroScore;
} else {
heroScores.push({hid, score :heroScore});
}
}
for (let heroScore of heroScores) {
score += heroScore.score;
}
if (score < 0) {
score = 0;
}
if (hisScore < score) {
hisScore = score;
}
let pLv = getPLvByScore(score);
let pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { score, hisScore, pLv, heroScores});
let roleName = session.get('roleName');
const role = await RoleModel.findByRoleId(roleId);
// 加入排行榜
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);
return resResult(STATUS.SUCCESS, {score, hisScore, heroScores});
}
async debugPvpSeasonReset(msg: {}, session: BackendSession) {
let { seasonNum, seasonEndTime } = await setPvpSeasonResult({name: 'exce setPvpSeasonResult debug'});
return resResult(STATUS.SUCCESS, { seasonNum, seasonEndTime })
}
async debugPvpWarReset(msg: {}, session: BackendSession) {
let systemConfig = await resetPvpWarId();
return resResult(STATUS.SUCCESS, {systemConfig});
}
async debugPvpSeasonResetTime(msg: {day: number}, session: BackendSession) {
let { day:hour } = msg;
let { seasonNum, seasonEndTime } = await pinus.app.rpc.systimer.systimerRemote.resetPvpSeasonTime.toServer('systimer-server-1', hour);
return resResult(STATUS.SUCCESS, { seasonNum, seasonEndTime });
}
async debugAddChallengeCnt(msg: {challengeCnt: number}, session: BackendSession) {
let { challengeCnt } = msg;
let roleId = session.get('roleId');
if (challengeCnt > PVP.PVP_CHALLENGE_COUNTS) {
challengeCnt = PVP.PVP_CHALLENGE_COUNTS;
}
let { challengeRefTime } = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, challengeRefTime: nowSeconds()});
return resResult(STATUS.SUCCESS, { challengeCnt, challengeRefTime });
}
async getData (msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let { pvpDefense, warId, seasonEndTime } = await findPvpDefAllByRoleId(roleId);
let oppPlayers = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum);
let { isDefaultHero, heroes, score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, seasonNum } = pvpDefense;
if (isFirstEntry) {
await PvpDefenseModel.updateInfo(roleId, {isFirstEntry:false});
}
let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId);
let flag = false;
if (!!pvpSeasonResult) {
var { oldSeasonData, show, heroGoods, rankGoods} = pvpSeasonResult;
if ( oldSeasonData.seasonEndTime > nowSeconds()) {//结算中锁定玩家信息
seasonEndTime = oldSeasonData.seasonEndTime;
heroScores = oldSeasonData.heroScores;
score = oldSeasonData.score;
refOppCnt = oldSeasonData.refOppCnt;
challengeCnt = oldSeasonData.challengeCnt;
challengeRefTime = oldSeasonData.challengeRefTime;
} else if (show) {
await PvpSeasonResultModel.updatePvpSeasonResult(roleId, {show: false});
flag = true;
}
}
let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);//去redis中获取排名
let data:any = {warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes: heroes.map(cur => {
let {actorId, dataId, order} = cur;
return { actorId, dataId, order }
}), score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, isDefaultHero }
if (flag) {//是否弹出结算奖励
data.resultRecord = { oldSeasonData, heroGoods, rankGoods }
}
return resResult(STATUS.SUCCESS, data);
}
// 刷新对手
async refreshOppPlayer (msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let sid = session.get('sid');
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
// 刷新次数及消耗
let { refOppCnt, refOppTime, consume } = getRefOppCnt(pvpDefense.refOppCnt, pvpDefense.refOppTime);
if(refOppCnt >= gameData.maxPvpRefreshCnt) {
return resResult(STATUS.PVP_REFRESH_CNT_REACH_MAX);
}
let costResult = await handleCost(roleId, sid, consume);
if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
// 刷新对手
let role = <RoleType>pvpDefense.role;
let oppPlayers = await refreshEnemies(role, pvpDefense.score, pvpDefense.pLv);
pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers, refOppCnt: refOppCnt + 1, refOppTime });
let result = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum);
return resResult(STATUS.SUCCESS, { oppPlayers: result, refOppCnt: pvpDefense.refOppCnt });
}
// 获取对手阵容具体信息
async getOppPlayer (msg: { roleId: string }, session: BackendSession) {
let roleId = session.get('roleId');
let oppoRoleId = msg.roleId;
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
let { oppPlayers } = pvpDefense;
let curOpp = oppPlayers.find(cur => cur.roleId == oppoRoleId);
if(!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND);
let { oppRoleId, heroes } = <PvpHistoryOppType>curOpp.oppDef;
return resResult(STATUS.SUCCESS, { roleId: oppRoleId, 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);
const pvpDefense = await PvpDefenseModel.findByRoleId(roleId);
if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN);
// 检查挑战次数
let { seasonEndTime } = await SystemConfigModel.findSystemConfig();
let { challengeCnt } = refresh(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
if (challengeCnt == 0) {
return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH);
}
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, battleId: 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, warId} = await findPvpDefByRoleId(roleId);
if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN);
let { oppPlayers, winStreakNum, heroScores, score, hisScore } = pvpDefense;
let curOpp = oppPlayers.find(cur => cur.roleId == oppRoleId && cur.pos == pos);
if(!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND);
const role = await RoleModel.findByRoleId(roleId);
if(isSuccess) {
winStreakNum ++;
} else {
winStreakNum = 0;
}
const myRecInfo = await generMyRecInfo(heroScores, winStreakNum, role, isSuccess, pos, myHeroes);
let { attackInfo, showHeroScores, addSumScore } = myRecInfo
score += addSumScore;
let pLv = getLvByScore(heroScores);
const defenseInfo = await generPVPOppRecInfo(isSuccess, curOpp, oppHeroes, role.lv);
// 战报记录
await PvpRecordModel.createRec({roleId1: roleId, roleId2: robotIdComBack(oppRoleId), warId: BattleRecord.battleId, attackInfo, defenseInfo, createTime: nowSeconds()});
// 对手记录更新
await PvpHistoryOppModel.setStatus(roleId, oppRoleId, 1);
// 刷新对手
let newOppPlayers: Array<OppPlayers> = await refreshEnemies(role, score, pLv);
// 更新battleRecord
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: { status: isSuccess?1:2 }
}, true);
let { seasonEndTime } = await SystemConfigModel.findSystemConfig();
// 减少挑战次数
let { challengeCnt, challengeRefTime } = comsumeChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
if ( hisScore < score) {
hisScore = score;
}
pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers: newOppPlayers, heroScores, score, pLv, winStreakNum, challengeCnt, challengeRefTime, hisScore });
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, hisScore,
heroScores: showHeroScores,
oppPlayers: result,
refOppCnt: pvpDefense.refOppCnt,
challengeCnt: pvpDefense.challengeCnt,
challengeRefTime: pvpDefense.challengeRefTime,
winStreakNum: pvpDefense.winStreakNum,
warId
});
}
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 || heroes.length <= 0) {
return resResult(STATUS.WRONG_PARMS);
}
heroes = uniq(heroes, function(item) {
return item.order;
});
let { seasonEndTime } = await SystemConfigModel.findSystemConfig();
let { heroes: defHeros, challengeCnt: lastChallengeCnt, challengeRefTime: lastChallengeRefTime } = await PvpDefenseModel.findByRoleId(roleId);
let defCe = 0;
let { challengeCnt, challengeRefTime } = refresh(lastChallengeCnt, lastChallengeRefTime, seasonEndTime);
if (!!isDefaultHero) {
let role = await RoleModel.findByRoleId(roleId);
let { resHeroes } = await defaultHeroes(role, challengeCnt, challengeRefTime, true);
return resResult(STATUS.SUCCESS, { heroes: resHeroes, challengeCnt, challengeRefTime, isDefaultHero} );
} 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;
}
if (heroes[index].order < 1 || heroes[index].order > 5) {
return resResult(STATUS.WRONG_PARMS);
}
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, challengeCnt, challengeRefTime, isDefaultHero });
return resResult(STATUS.SUCCESS, { heroes: resHeroes, challengeCnt, challengeRefTime, isDefaultHero });
}
}
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 initSingleRankWithServer(REDIS_KEY.PVP_RANK, 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 });
}
async getPlayerDetail(msg: { roleId: string }, session: BackendSession) {
let roleId = session.get('roleId');
let { roleId: oppoRoleId } = msg;
let isRobot = checkRoleIsRobot(oppoRoleId);
let result: PlayerDetail;
if(isRobot) { // 如果是机器人,从自己的pvpDefense中寻找
let pvpHistoryOpp = await PvpHistoryOppModel.findByRoleIdAndOppId(roleId, oppoRoleId);
if(!pvpHistoryOpp) {
return resResult(STATUS.PVP_ROLE_NOT_FOUND);
}
let heroes = new Array<PlayerDetailHero>();
for(let hero of pvpHistoryOpp.heroes) {
let newHero = new PlayerDetailHero();
newHero.setPvpHeroInfo(hero);
heroes.push(newHero);
}
for(let hero of pvpHistoryOpp.otherHeroes) {
let newHero = new PlayerDetailHero();
newHero.setPvpHeroInfo(hero);
heroes.push(newHero);
}
result = new PlayerDetail({...pvpHistoryOpp, roleId: pvpHistoryOpp.oppRoleId, heroes, rank: pvpHistoryOpp.rankLv});
} else { // 查询对方pvpDefense
let pvpDefense = await PvpDefenseModel.findByRoleId(oppoRoleId);
let dbHeroes = await HeroModel.findByRole(oppoRoleId);
let role = await RoleModel.findByRoleId(oppoRoleId);
let heroes = new Array<PlayerDetailHero>();
for(let {hid, lv, star, colorStar, quality } of dbHeroes) {
let heroScore = pvpDefense.heroScores.find(cur => cur.hid == hid);
heroes.push({
actorId: hid, lv, star, colorStar, quality,
score: heroScore?heroScore.score: 0
});
}
heroes.sort((a, b) => b.score - a.score);
let rank = await getMyRank(REDIS_KEY.PVP_RANK, 0, oppoRoleId);//去redis中获取排名
result = new PlayerDetail({...role, ...pvpDefense, heroes, rank});
}
return resResult(STATUS.SUCCESS, result);
}
async receiveBox(msg: {id: number}, session: BackendSession) {
let {id} = msg;
let roleId = session.get('roleId');
let sid: string = session.get('sid');
let roleName = session.get('roleName');
let { seasonEndTime } = await SystemConfigModel.findSystemConfig();
let { hisScore, receivedBox, challengeCnt: lastChallengeCnt, challengeRefTime: lastChallengeRefTime } = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
let pvpBoxs = getPvpBoxs();
let pvpBox = findWhere(pvpBoxs, {id});
if (hisScore < pvpBox.score) {
return resResult(STATUS.PVP_NOT_REACH_BOX_SCORE);
}
if (receivedBox.indexOf(id) != -1 ) {
return resResult(STATUS.PVP_BOX_IS_GOT);
}
receivedBox.push(id);
let { challengeCnt, challengeRefTime } = refresh(lastChallengeCnt, lastChallengeRefTime, seasonEndTime);
await PvpDefenseModel.updateInfo(roleId, {receivedBox, challengeCnt, challengeRefTime});
let result = await addItems(roleId, roleName, sid, pvpBox.reward );
return resResult(STATUS.SUCCESS,{goods: result, receivedBox, challengeCnt, challengeRefTime});
}
async getRec(msg: {}, session: BackendSession ) {
let roleId = session.get('roleId');
let pvpRecords = await PvpRecordModel.getRecByRoleId(roleId);
return resResult(STATUS.SUCCESS, {list: pvpRecords});
}
}