fix pvp刷新对手时保存数据

This commit is contained in:
luying
2021-01-14 15:57:05 +08:00
parent f3c76b8d6d
commit 5823a1b3eb
11 changed files with 372 additions and 221 deletions

View File

@@ -1,26 +1,27 @@
import {Application, BackendSession, pinus} from 'pinus';
import { uniq, findWhere, findIndex } from 'underscore';
import { gameData, getPvpBoxs } from '../../../pubUtils/data';
import { refreshEnemies, getEnemies, getLvByScore, defaultHeroes, comsumeChallengeCnt, refresh, findPvpDefByRoleId, checkRoleIsRobot, getRefOppCnt, findPvpDefAllByRoleId, generPVPOppRecInfo, generMyRecInfo, getRobotLineup, getPlayerLineup } from '../../../services/pvpService';
import { refreshEnemies, getEnemies, getLvByScore, defaultHeroes, comsumeChallengeCnt, refresh, findPvpDefByRoleId, checkRoleIsRobot, getRefOppCnt, findPvpDefAllByRoleId, generPVPOppRecInfo, generMyRecInfo } from '../../../services/pvpService';
import { RoleModel, RoleType } from '../../../db/Role';
import { STATUS } from '../../../consts/statusCode';
import { resResult, genCode } from '../../../pubUtils/util';
import { SystemConfigModel } from '../../../db/SystemConfig'
import { PvpDefenseModel, OppPlayers } from '../../../db/PvpDefense';
import { oppHeroesDefenseInter, pvpEndParamInter, RankParam, PlayerDetail, PlayerDetailHero } from '../../../pubUtils/interface';
import { pvpEndParamInter, RankParam, PlayerDetail, PlayerDetailHero } from '../../../pubUtils/interface';
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, HeroesRecord } from '../../../db/PvpRecord';
import { PvpRecordModel } from '../../../db/PvpRecord';
import { existsRank, initRank, getRank, setRank, getMyRank } 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';
export default function(app: Application) {
return new PvpHandler(app);
}
@@ -158,22 +159,13 @@ export class PvpHandler {
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 { oppRoleId, heroes } = <PvpHistoryOppType>curOpp.oppDef;
let heroes = new Array<oppHeroesDefenseInter>();
if(curOpp.isRobot) { // 机器人
heroes = await getRobotLineup(mapWarJson, curOpp, role.topFiveCe, role.lv);
} else { // 真人
heroes = await getPlayerLineup(mapWarJson, curOpp);
}
return resResult(STATUS.SUCCESS, { roleId: oppoRoleId, pos: curOpp.pos, heroes });
return resResult(STATUS.SUCCESS, { roleId: oppRoleId, pos: curOpp.pos, heroes });
}
// 开战
@@ -287,6 +279,9 @@ export class PvpHandler {
await setRank(REDIS_KEY.PVP_RANK, 0, roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params);
let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);
// 对手记录更新
await PvpHistoryOppModel.setStatus(roleId, oppRoleId, 1);
return resResult(STATUS.SUCCESS, {
battleCode, isSuccess,
score, pLv, myRank, hisScore,
@@ -386,34 +381,17 @@ export class PvpHandler {
let result: PlayerDetail;
if(isRobot) { // 如果是机器人从自己的pvpDefense中寻找
let role = await RoleModel.findByRoleId(roleId);
let pvpDefense = await PvpDefenseModel.findByRoleId(roleId);
let { oppPlayers } = pvpDefense;
let curOpp = oppPlayers.find(cur => cur.roleId == oppoRoleId);
if(!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND);
let heroes = new Array<PlayerDetailHero>();
let { robot } = curOpp;
let { warId } = robot;
let dicWarJson = gameData.warJson.get(warId);
for(let json of dicWarJson) {
const { actorId, relation } = json;
if(relation == 2 && actorId > 0) { // 默认格子
let dicHero = gameData.hero.get(actorId);
heroes.push({
actorId,
star: dicHero.initialStars,
colorStar: 0,
quality: dicHero.quality,
score: 0,
lv: role.lv
});
}
let pvpHistoryOpp = await PvpHistoryOppModel.findByRoleIdAndOppId(roleId, oppoRoleId);
if(!pvpHistoryOpp) {
return resResult(STATUS.PVP_ROLE_NOT_FOUND);
}
result = new PlayerDetail({...robot, lv: role.lv, heroes})
let heroes = pvpHistoryOpp.heroes.map(hero => {
let newHero = new PlayerDetailHero();
newHero.setPvpHeroInfo(hero);
return newHero;
})
result = new PlayerDetail({...pvpHistoryOpp, roleId: pvpHistoryOpp.oppRoleId, heroes});
} else { // 查询对方pvpDefense
let pvpDefense = await PvpDefenseModel.findByRoleId(oppoRoleId);
let dbHeroes = await HeroModel.findByRole(oppoRoleId);

View File

@@ -1,10 +1,8 @@
import { fromCallback } from 'bluebird';
import { checkPvp, findPvpDefByRoleId } from '../services/pvpService'
import { getFuncsSwitch } from '../pubUtils/data';
import { FUNCS_ID, FUNC_OPT_TYPE } from '../consts/constModules/sysConst';
import { RoleModel } from '../db/Role';
import { startEvent } from "./eventSercive";
export async function eventOnPlayerLvUp(roleId: string, lv: number, addFuncs: Array<number>, dataFuncs: Array<number>) {

View File

@@ -4,7 +4,7 @@ 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, reduceCe } from '../pubUtils/util';
import { getRandomIndexByLen, genCode, getRandomByLen, shouldRefresh, reduceCe, getChineseName } from '../pubUtils/util';
import { oppPlayersInter, RankParam, pvpEndParamInter, oppHeroesDefenseInter, Attributes } from '../pubUtils/interface';
import { gameData, getPLvByScore } from "../pubUtils/data";
import { PVP } from '../pubUtils/dicParam';
@@ -13,11 +13,11 @@ 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, CeAttr, CeAttrRole } from '../db/generalField';
import { CeAttrNumber, CeAttr, CeAttrRole, PvpEnemies, PvpHeroInfo } from '../db/generalField';
import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
import { findWhere, findIndex } from 'underscore';
import { pinus } from 'pinus';
import { PvpHistoryOppModel, PvpHistoryOppType } from '../db/PvpHistoryOpp';
export async function initPvpInfo(role: RoleType) {
let heroes: Array<Heroes> = [];
@@ -62,47 +62,39 @@ export async function checkPvp(role: RoleType) {
* @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: reduceCe(defCe),
addScore: dicOpponent.score,
rankLv: 0,
plusScore: getPlusScore(winStreakNum)
});
} else {
let opp = <PvpDefenseType>oppDef;
let role = <RoleType>opp.role;
let { roleId, roleName, headHid, sHid, lv } = role;
let { pLv, defCe } = opp;
let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);
result.push({
pos, roleId, roleName, headHid, sHid, pLv, defCe: reduceCe(defCe),
addScore: dicOpponent.score,
rankLv, // 读取排名
plusScore: getPlusScore(winStreakNum)
});
}
for(let oppPlayer of oppPlayers) {
let dicOpponent = dicPvpOpponent.get(oppPlayer.pos);
let oppDef = <PvpHistoryOppType>oppPlayer.oppDef; // select 'oppRoleId pos roleName headHid sHid rankLv pLv defCe'
result.push({
...oppDef,
roleId: oppDef.oppRoleId,
defCe: reduceCe(oppDef.defCe),
addScore: dicOpponent.score,
rankLv: 0,
plusScore: getPlusScore(winStreakNum)
});
}
return result
}
// 刷新对手
export async function refreshEnemies(role: RoleType, score: number, pLv: number) {
let { roleId, topFiveCe } = role;
let system = await SystemConfigModel.findSystemConfig();
let mapWarJson = gameData.warJson.get(system.warId);
let { roleId } = role;
let oppPlayers = new Array<OppPlayers>();
let opp = dicPvpOpponent.values()
for(let dicOpp of opp) {
let flag = false; // 是否筛选成功
if(score >= PVP_CONST.SCORE_LINE) { // TODO 将这个放到const
flag = await matchPlayer(oppPlayers, roleId, pLv, dicOpp);
if(!flag) flag = await matchPlayerByRank(oppPlayers, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家
if(!flag) flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp);
if(score >= PVP_CONST.SCORE_LINE) { // 将这个放到const
flag = await matchPlayer(oppPlayers, mapWarJson, roleId, pLv, dicOpp); // 按照等级匹配对手
if(!flag) flag = await matchPlayerByRank(oppPlayers, mapWarJson, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家
if(!flag) flag = await matchRobot(oppPlayers, mapWarJson, role, pLv, dicOpp);
} else {
flag = matchRobot(oppPlayers, topFiveCe, pLv, dicOpp);
flag = await matchRobot(oppPlayers, mapWarJson, role, pLv, dicOpp);
}
if(!flag) continue;
}
@@ -110,7 +102,7 @@ export async function refreshEnemies(role: RoleType, score: number, pLv: number)
return oppPlayers;
}
export async function matchPlayerByRank(oppPlayers: OppPlayers[], roleId: string, pos: number) {
export async function matchPlayerByRank(oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], roleId: string, pos: number) {
let ridRanks = new Array<number>(); // 已经被使用了的排名
for(let { roleId: curRoleId } of oppPlayers) {
let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, curRoleId);
@@ -146,17 +138,18 @@ export async function matchPlayerByRank(oppPlayers: OppPlayers[], roleId: string
oppRoleId = result[0];
let pvpdefense = await PvpDefenseModel.findByRoleId(oppRoleId);
let pvpHistoryOpp = await generPlayerOppHis(pvpdefense, mapWarJson, roleId, pos);
oppPlayers.push({
roleId: pvpdefense.roleId,
oppDef: pvpdefense._id,
oppDef: pvpHistoryOpp._id,
pos,
isRobot: false,
robot: null
});
return true
}
async function matchPlayer(oppPlayers: OppPlayers[], roleId: string, pLv: number, dicOpp: DicPvpOpponent ) {
async function matchPlayer(oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], 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 => {
@@ -165,7 +158,7 @@ async function matchPlayer(oppPlayers: OppPlayers[], roleId: string, pLv: number
if(range.length <= 0) return false;
let index = getRandomIndexByLen(range.length);
let result = range[index];
let result = range[index]; // 本次匹配结果 pvpdefense
if(!result) return false;
if(result.roleId == roleId) {
range.splice(index, 1);
@@ -173,18 +166,54 @@ async function matchPlayer(oppPlayers: OppPlayers[], roleId: string, pLv: number
index = getRandomIndexByLen(range.length);
result = range[index];
}
let pvpHistoryOpp = await generPlayerOppHis(result, mapWarJson, roleId, pos);
oppPlayers.push({
roleId: result.roleId,
oppDef: result._id,
oppDef: pvpHistoryOpp._id,
pos,
isRobot: false,
robot: null
});
return true;
}
function matchRobot(oppPlayers: OppPlayers[], myCe: number, pLv: number, dicOpp: DicPvpOpponent) {
/**
* @description 对手是玩家时生成并返回pvpHistoryOpp
* @param result 随机出的对手pvpDefense
* @param mapWarJson 本周地图出兵表
* @param roleId 自己的玩家id
* @param pos 刷新这个对手的位置
*/
async function generPlayerOppHis(result: PvpDefenseType, mapWarJson: DicWarJson[], roleId: string, pos: number) {
let heroScores = result.heroScores;
let role = <RoleType>result.role;
let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, role.roleId);
let heroes = new Array<PvpEnemies>();
for(let warJson of mapWarJson) {
if(warJson.relation == 1) continue;
let h = result.heroes.find(cur => cur.dataId == warJson.dataId);
if(h) {
let hs = heroScores.find(cur => cur.hid == warJson.actorId); // 这个武将的军功
let hero = <HeroType>h.hero;
let heroInfo = new PvpHeroInfo();
heroInfo.setHeroInfo(hero);
heroInfo.setOutIndex(h.order);
let attribute = getPlayerAttribute(hero.ceAttr, role.globalCeAttr);
heroInfo.setAttribute(attribute);
let enemy = new PvpEnemies(warJson, heroInfo, hs?hs.score: 0);
heroes.push(enemy);
} else {
let enemy = new PvpEnemies(warJson, new PvpHeroInfo(), 0);
heroes.push(enemy);
}
}
let pvpHistoryOpp = await PvpHistoryOppModel.createPvpOpp({
...result, ...role, pos, rankLv, heroes, roleId, oppRoleId: result.roleId
});
return pvpHistoryOpp;
}
async function matchRobot(oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], role: RoleType, pLv: number, dicOpp: DicPvpOpponent) {
let { lv: myLv, topFiveCe: myCe, roleId } = role;
let { id: pos, minLv, maxLv, ratio } = dicOpp;
let range = gameData.pvpWar;
if(range.length <= 0) return false;
@@ -193,17 +222,41 @@ function matchRobot(oppPlayers: OppPlayers[], myCe: number, pLv: number, dicOpp:
let result = range[index];
if(!result) return false;
let roleId = generateRobotRoleId();
let roleName = getRandomByLen(ROBOT_NAME);
let robotWarjson = gameData.warJson.get(result.war_id);
if(!robotWarjson) { /* TODO 判空处理 */ }
let heroes = new Array<PvpEnemies>();
for(let warJson of mapWarJson) {
if(warJson.relation == 1) continue;
let h = robotWarjson.find(cur => cur.dataId == warJson.dataId);
if(h) {
let dicHero = gameData.hero.get(h.actorId);
if(!dicHero) continue;
let heroInfo = new PvpHeroInfo();
heroInfo.setRobotInfo(h, myLv, dicHero.initialStars, dicHero.quality);
let attribute = getRobotAttribute(h.attribute, myCe, PVP_CONST.ENEMY_CE, ratio);
heroInfo.setAttribute(attribute);
let enemy = new PvpEnemies(warJson, heroInfo, 0);
heroes.push(enemy);
} else {
let enemy = new PvpEnemies(warJson, new PvpHeroInfo(), 0);
heroes.push(enemy);
}
}
let oppRoleId = generateRobotRoleId();
let roleName = getChineseName();
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)
let pvpHistoryOpp = await PvpHistoryOppModel.createPvpOpp({
roleId, oppRoleId, roleName, pos, defCe: Math.floor(myCe * ratio), pLv: hisPLv, lv: myLv, heroes
});
oppPlayers.push({
roleId,
oppDef: null,
roleId: oppRoleId,
oppDef: pvpHistoryOpp._id,
pos,
isRobot: true,
robot
isRobot: true
});
return true
}
@@ -386,10 +439,10 @@ export async function findPvpDefAllByRoleId(roleId: string) {
let role = <RoleType>pvpDefense.role;
let oppPlayers = await refreshEnemies(role, pvpDefense.score, pvpDefense.pLv);
update.oppPlayers = oppPlayers;
pvpDefense.oppPlayers = oppPlayers;
}
await PvpDefenseModel.updateInfo( roleId, update);
let updateResult = await PvpDefenseModel.updateInfoAndInclude( roleId, update);
pvpDefense.oppPlayers = updateResult.oppPlayers;
pvpDefense.challengeCnt = challengeCnt;
pvpDefense.challengeRefTime = challengeRefTime;
pvpDefense.refOppCnt = refOppCnt;
@@ -399,52 +452,13 @@ export async function findPvpDefAllByRoleId(roleId: string) {
return {pvpDefense, warId, shouldRefOpp};
}
// 获取机器人阵容
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;
if(relation == 2 && actorId > 0) { // 默认格子
let newAttribute = getRobotAttribute(attribute, topFiveCe, PVP_CONST.ENEMY_CE, dicOpp.ratio);
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) {
if(actorId > 0) {
let curDicMapJson = mapWarJson.find(cur => cur.dataId == dataId);
let dicHero = gameData.hero.get(actorId);
let h = <HeroType>hero;
let { ceAttr } = h;
let newAttribute = getPlayerAttribute(ceAttr, globalCeAttr);
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
}
// 按比例计算出兵表中的属性
/**
* 根据比例计算机器人属性
* @param attribute 出兵表中的属性字段
* @param ce 我的战力
* @param enemyCe 出兵表对手战力
* @param ratio 系数
*/
export function getRobotAttribute(attribute: Attributes, ce: number, enemyCe: number, ratio: number) {
let newAttribute = new CeAttrNumber();
@@ -457,7 +471,11 @@ export function getRobotAttribute(attribute: Attributes, ce: number, enemyCe: nu
return newAttribute;
}
// 计算玩家的属性
/**
* @description 根据玩家数据获取到他的属性
* @param ceAttr hero表的ceAttr
* @param globalCeAttr role表中的globalCeAttr
*/
export function getPlayerAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) {
let newAttribute = new CeAttrNumber();
for(let attrName in newAttribute) {
@@ -529,27 +547,15 @@ export async function generMyRecInfo(heroScores: HeroScores[], winStreakNum: num
// 获取对手战报记录
export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayers, oppRoleId: string, oppHeroes: pvpEndParamInter[], myLv: number) {
let oppHeroRecords = new Array<HeroesRecord>();
let oppRole = <PvpHistoryOppType>curOpp.oppDef;
if(!oppRole) { /* TODO 判空处理 */ }
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 historyHero = oppRole.heroes.find(cur => cur.actorId == hid);
if(historyHero) {
let hs = new HeroesRecord(historyHero, damage, heal, underDamage);
oppHeroRecords.push(hs);
}
}
let oppRole;
if (curOpp.isRobot) {
oppRole = { ...curOpp.robot, title: 1, topFiveCe: curOpp.robot.defCe, lv: myLv };
} else {
oppRole = await RoleModel.findByRoleId(oppRoleId);
}
return {
roleId: oppRole.roleId,
roleName: oppRole.roleName,
@@ -557,7 +563,7 @@ export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayers,
sHid: oppRole.sHid,
headHid: oppRole.headHid,
title: oppRole.title,
ce: oppRole.topFiveCe,
ce: oppRole.defCe,
heroes: oppHeroRecords,
isSuccess: !isSuccess,
score: 0

View File

@@ -7,6 +7,7 @@
"@typegoose/typegoose": "^7.3.5",
"@types/mongoose": "^5.7.36",
"bcrypt": "^5.0.0",
"chinese-random-name": "^1.0.0",
"lodash": "^4.17.20",
"moment": "^2.27.0",
"mongoose": "^5.10.4",

View File

@@ -1,44 +1,8 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { EXPEDITION_WAR_RECORD_STATUS } from '../consts';
import { Enemies } from './generalField'
class Enemies {
@prop({ required: true })
actorId: number; // 敌人id
@prop({ required: false })
actorName: string; // 敌人名
@prop({ required: false })
dataId: number; // 战场中唯一指向武将的代码
@prop({ required: false })
relation: number; // 角色属于我方还是地方
@prop({ required: false })
outIndex: number; // 程序将信息存入数组顺序
@prop({ required: false })
x: number; // 战场x坐标
@prop({ required: false })
y: number; // 战场y坐标
@prop({ required: false })
direction: number; // 朝向
@prop({ required: false })
var: number; // 变量
@prop({ required: false })
lv: number; // 角色等级
@prop({ required: false })
hide: number; // 是否隐藏
@prop({ required: false })
initial_ai: number; // AI类型
@prop({ required: true })
attribute: {hp: number, atk: number, matk: number, def: number, mdef: number, agi: number, luk: number, speed: number, hit: number, cri: number, flee: number, antCri: number, damageIncrease: number, damageDecrease: number, defIgnore: number, bloodSuck: number, ap: number}; // 属性
@prop({ required: false })
skill: string; // 技能
@prop({ required: false })
seid: string; // 技能
@prop({ required: false })
star: number; // 角色星级
@prop({ required: false })
spine: string; // S动画
}
class EnemiesCurHPAP {
@prop({ required: true })
@@ -72,7 +36,7 @@ export default class ExpeditionWarRecord extends BaseModel {
@prop({ required: true, default: '' })
enemyId: string; // 敌军队伍id或玩家id
@prop({ required: true, type: Enemies, default: [], _id: false })
enemies: Array<Enemies>; // 敌军数据
enemies: Array<Enemies>; // 敌军数据
@prop({ required: true, type: EnemiesCurHPAP, default: [], _id: false })
enemiesCurHpAp: Array<EnemiesCurHPAP>; // 敌军数据
@prop({ required: true, default: 0 })

View File

@@ -2,8 +2,8 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import Hero, { } from './Hero';
import Role, { } from './Role';
import PvpDef, { } from './PvpDefense';
import { PVP_PLAYER_POS, PVP_HERO_POS } from '../consts';
import PvpHistoryOpp from './PvpHistoryOpp';
export interface pvpUpdateInter {
_id?: string;
@@ -91,14 +91,12 @@ export class Robot {
export class OppPlayers {
@prop({ required: true })
roleId: string;
@prop({ ref: 'PvpDefense', type: mongoose.Schema.Types.ObjectId })
oppDef: Ref<PvpDef>;
@prop({ ref: 'PvpHistoryOpp', type: mongoose.Schema.Types.ObjectId })
oppDef: Ref<PvpHistoryOpp>;
@prop({ required: true })
pos: number;
@prop({ required: true })
isRobot: boolean;
@prop({ required: true, type: Robot, default: null, _id: false })
robot: Robot
}
export class HeroScores {
@@ -136,7 +134,7 @@ export default class PvpDefense extends BaseModel {
isDefaultHero: boolean;
@prop({ required: true, default: 0 })
refOppCnt: number; // 刷新对手总次数,消耗可根据消耗表算出
@prop({ required: true, default: 0 })
@prop({ required: true, default: new Date() })
refOppTime: Date; // 刷新对手时间
@prop({ required: true, default: 0 })
challengeCnt: number; // 可挑战次数
@@ -159,7 +157,7 @@ export default class PvpDefense extends BaseModel {
public static async findByScale(roleId: string, min: number, max: number, lean = true) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ roleId: { $ne: roleId }, defCe: { $lte: max, $gte: min } })
.populate('role', 'headHid sHid topFiveCe roleId roleName')
.populate('role', 'headHid sHid topFiveCe roleId roleName lv')
.populate('heroes.hero')
.sort({ updatedAt: -1 }).limit(100).lean(lean);
return result;
@@ -203,15 +201,9 @@ export default class PvpDefense extends BaseModel {
public static async findByRoleIdIncludeAll(roleId: string) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId })
.populate('role', 'headHid sHid topFiveCe roleId roleName')
.populate('role', 'headHid sHid topFiveCe roleId roleName lv')
.populate('heroes.hero')
.populate({
path: 'oppPlayers.oppDef',
populate: {
path: 'role heroes.hero',
select: 'headHid sHid topFiveCe roleId roleName hid ceAttr globalCeAttr'
}
}).lean();
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName headHid sHid rankLv pLv defCe heroes').lean();
return result;
}
@@ -223,13 +215,8 @@ export default class PvpDefense extends BaseModel {
public static async updateInfoAndInclude(roleId: string, update: pvpUpdateInter) {
delete update._id;
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true})
.populate({
path: 'oppPlayers.oppDef',
populate: {
path: 'role',
select: 'headHid sHid topFiveCe roleId roleName'
}
}).lean();
.populate('role', 'headHid sHid topFiveCe roleId roleName lv')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName headHid sHid rankLv pLv defCe').lean();
return result;
}
public static async updateInfo(roleId: string, update: pvpUpdateInter, lean = true) {

View File

@@ -0,0 +1,67 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { PvpEnemies } from './generalField';
export class HeroScores {
@prop({ required: true })
hid: number;
@prop({ required: true })
score: number;
}
@index({ roleId: 1 })
export default class PvpHistoryOpp extends BaseModel {
@prop({ required: true })
roleId: string; // 玩家id
@prop({ required: true })
pos: number; // 对手位置
@prop({ required: true })
oppRoleId: string; // 对手角色 id
@prop({ required: true })
roleName: string; // 角色名称
@prop({ required: true, default: 19 })
headHid: number; // 对手头像
@prop({ required: true, default: 19 })
sHid: number; // 对手形象
@prop({ required: true, default: 0 })
score: number; // 对手军功
@prop({ required: true, default: 1 })
pLv: number; // 对手等级
@prop({ required: true, default: 1 })
lv: number; // 对手角色等级
@prop({ required: true, default: 1 })
title: number; // 对手等级
@prop({ required: true, default: 0 })
defCe: number; // 防守战力
@prop({ required: true, default: 0 })
rankLv: number; // 对手排名
@prop({ required: true, type: PvpEnemies, default: [] })
heroes: PvpEnemies[]; // 对手阵容
@prop({ required: true, default: 0 })
status: number; // 状态 0-仅刷出 1-挑战过
public static async createPvpOpp(params: PvpOppCreateParam, lean = true) {
const doc = new PvpHistoryOppModel();
const update = Object.assign(doc.toJSON(), params);
delete update._id;
const defense: PvpHistoryOppType = await PvpHistoryOppModel.findOneAndUpdate({ roleId: params.roleId, pos: params.pos }, update, { upsert: true, new: true }).lean(lean);
return defense;
}
public static async findByRoleIdAndOppId(roleId: string, oppRoleId: string) {
const result: PvpHistoryOppType = await PvpHistoryOppModel.findOne({ roleId, oppRoleId, status: 0 }).lean();
return result;
}
public static async setStatus(roleId: string, oppRoleId: string, status: number) {
const result: PvpHistoryOppType = await PvpHistoryOppModel.findOneAndUpdate({ roleId, oppRoleId }, {status}, {new: true}).lean();
return result;
}
}
export const PvpHistoryOppModel = getModelForClass(PvpHistoryOpp);
export interface PvpHistoryOppType extends Pick<DocumentType<PvpHistoryOpp>, keyof PvpHistoryOpp> { };
export type PvpOppCreateParam = Partial<PvpHistoryOppType>; // 将所有字段变成可选项

View File

@@ -2,6 +2,7 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { getBeforeDayDate } from '../pubUtils/timeUtil';
import { genCode } from '../pubUtils/util';
import { PvpHeroInfo } from './generalField';
export class HeroesRecord {
@prop({ required: true, default: 0 })
@@ -20,6 +21,17 @@ export class HeroesRecord {
heal: number; // 治疗
@prop({ required: true, default: 0 })
underDamage: number; // 承伤
constructor(pvpHero: PvpHeroInfo, damage: number, heal: number, underDamage: number) {
this.hid = pvpHero.actorId;
this.quality = pvpHero.quality;
this.star = pvpHero.star;
this.colorStar = pvpHero.colorStar;
this.lv = pvpHero.lv;
this.damage = damage;
this.heal = heal;
this.underDamage = underDamage;
}
}
export class PlayerInfo {

View File

@@ -1,4 +1,6 @@
import { prop } from '@typegoose/typegoose';
import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
import { HeroType } from './Hero';
export class CeAttrData {
@prop({ required: true })
@@ -120,3 +122,125 @@ export class CeAttrNumber {
bloodSuck?: number = 0;
}
// 从玩家数据中覆盖warjson的部分字段
export class PvpHeroInfo {
@prop({ required: true })
actorId?: number = 0; // 敌人id
@prop({ required: false })
actorName?: string = ""; // 敌人名
@prop({ required: false })
outIndex?: number = 0; // 程序将信息存入数组顺序
@prop({ required: false })
star?: number = 0; // 角色星级
@prop({ required: false })
lv?: number = 0; // 角色等级
@prop({ required: false })
skill?: string = "0"; // 技能
@prop({ required: false })
seid?: string = "&"; // 技能
@prop({ required: false })
spine?: string = "0"; // S动画
@prop({ required: false })
colorStar?: number = 0; // 觉醒
@prop({ required: false })
quality?: number = 0; // 品质
@prop({ required: true, _id: false, default: new CeAttrNumber() })
attribute?: CeAttrNumber; // 属性
setHeroInfo(hero: HeroType) {
this.actorId = hero.hid;
this.actorName = hero.hName;
this.star = hero.star;
this.lv = hero.lv;
this.colorStar = hero.colorStar;
this.quality = hero.quality;
}
setRobotInfo(warjson: DicWarJson, lv: number, initialStar: number, quality: number) {
this.actorId = warjson.actorId;
this.actorName = warjson.actorName;
this.star = initialStar;
this.lv = lv;
this.quality = quality;
}
setAttribute(attribute: CeAttrNumber) {
this.attribute = attribute;
}
setOutIndex(order: number) {
this.outIndex = order;
}
}
// 远征敌军
export class Enemies extends PvpHeroInfo {
@prop({ required: true })
actorId: number; // 敌人id
@prop({ required: false })
actorName: string; // 敌人名
@prop({ required: false })
dataId: number; // 战场中唯一指向武将的代码
@prop({ required: false })
relation: number; // 角色属于我方还是地方
@prop({ required: false })
x: number; // 战场x坐标
@prop({ required: false })
y: number; // 战场y坐标
@prop({ required: false })
direction: number; // 朝向
@prop({ required: false })
var: number; // 变量
@prop({ required: false })
hide: number; // 是否隐藏
@prop({ required: false })
initial_ai: number; // AI类型
// warjson 出兵表
// heroInfo 覆盖掉出兵表的相应参数
constructor(warjson: DicWarJson, heroInfo: PvpHeroInfo) {
super();
this.actorId = heroInfo.actorId != undefined? heroInfo.actorId: warjson.actorId;
this.actorName = heroInfo.actorName != undefined? heroInfo.actorName: warjson.actorName;
this.dataId = warjson.dataId;
this.relation = warjson.relation;
this.outIndex = heroInfo.outIndex != undefined? heroInfo.outIndex: warjson.outIndex;
this.x = warjson.x;
this.y = warjson.y;
this.direction = warjson.direction;
this.var = warjson.var;
this.lv = heroInfo.lv != undefined? heroInfo.lv: warjson.lv;
this.hide = warjson.hide;
this.initial_ai = warjson.initial_ai;
this.attribute = heroInfo.attribute;
this.skill = heroInfo.skill != undefined? heroInfo.skill: warjson.skill;
this.seid = heroInfo.seid != undefined? heroInfo.seid: warjson.seid;
this.star = heroInfo.star != undefined? heroInfo.star: warjson.star;
this.spine = heroInfo.spine!= undefined? heroInfo.spine: warjson.spine;
}
}
export class PvpEnemies extends Enemies {
@prop({ required: true })
star: number;
@prop({ required: true })
colorStar: number;
@prop({ required: true })
quality: number;
@prop({ required: true })
lv: number;
@prop({ required: true })
score: number;
// score: 这个武将的军功
constructor(warjson: DicWarJson, heroInfo: PvpHeroInfo, score: number) {
super(warjson, heroInfo);
this.star = heroInfo.star;
this.colorStar = heroInfo.colorStar;
this.quality = heroInfo.quality;
this.lv = heroInfo.lv;
this.score = score;
}
}

View File

@@ -3,6 +3,7 @@
import { RoleType } from "../db/Role";
import { Robot } from "../db/PvpDefense";
import { reduceCe } from "./util";
import { PvpHeroInfo, PvpEnemies } from "../db/generalField";
export interface RewardInter {
id: number;
@@ -121,13 +122,22 @@ export class RankParam {
}
}
export interface PlayerDetailHero {
export class PlayerDetailHero {
actorId: number;
lv: number;
star: number;
colorStar: number;
quality: number;
score: number;
setPvpHeroInfo?(hero: PvpEnemies) {
this.actorId = hero.actorId;
this.lv = hero.lv;
this.star = hero.star;
this.colorStar = hero.colorStar;
this.quality = hero.quality;
this.score = hero.score;
}
}
export class PlayerDetail {

View File

@@ -8,7 +8,7 @@ import { DicRandomEffectPool } from './dictionary/DicRandomEffectPool';
import { HERO_CE_RATIO, ABI_STAGE } from '../consts';
import { findIndex } from 'underscore';
const randomName = require("chinese-random-name");
const moment = require('moment');
export function genCode(len) {
@@ -516,3 +516,7 @@ export function getAllAttrStage() {
};
return attrs;
}
export function getChineseName() {
return randomName.generate()
}