pvp随机地图

This commit is contained in:
mamengke01
2021-01-07 12:25:19 +08:00
parent a339b8adcc
commit 94fc48a59a
17 changed files with 327 additions and 84 deletions

View File

@@ -14,7 +14,7 @@ import * as routeUtil from './app/util/routeUtil';
import { preload } from './preload';
var checkEventFilter = require('./app/servers/battle/filter/checkEventFilter');
import { connectRedis } from './config/redis';
import * as timeTaskService from './app/services/timeTaskService';
// TODO 需要整理。
import _pinus = require('pinus');
@@ -102,6 +102,15 @@ app.configure('production|development|alpha|dev', 'gate', function () {
});
});
app.configure('production|development|alpha|dev', 'systimer', function () {
app.set('connectorConfig',
{
connector: pinus.connectors.hybridconnector,
useProtobuf: true
});
timeTaskService.init();
});
function errorHandler(err: Error, msg: any, resp: any,
session: FrontendOrBackendSession, cb: HandlerCallback) {

View File

@@ -1,7 +1,7 @@
import {Application, BackendSession} from 'pinus';
const _ = require('underscore');
import { gameData } from '../../../pubUtils/data';
import { checkPvp, initPvpInfo, refreshEnemies, getEnemies } from '../../../pubUtils/pvpUtil';
import { checkPvp, initPvpInfo, refreshEnemies, getEnemies, } from '../../../services/pvpService';
import { RoleModel, RoleType } from '../../../db/Role';
import { STATUS } from '../../../consts/statusCode';
import { resResult } from '../../../pubUtils/util';
@@ -25,13 +25,15 @@ export class PvpHandler {
async getData (msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let serverId = session.get('serverId');
let result = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
let system = await SystemConfigModel.findSystemConfig();
return resResult(STATUS.SUCCESS, { data: result });
let {heroes, score, pLv, winStreakNum, oppPlayers: oppPlayerInfos, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, seasonNum: playerSeaSonNum} = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
let oppPlayers = getEnemies(oppPlayerInfos, winStreakNum);
let {warId, seasonNum, seasonEndTime} = await SystemConfigModel.findSystemConfig();
if (playerSeaSonNum !== seasonNum) {
//TODO去结算
}
let myRank = 999;//TODO去redis中获取
let data = {warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes, score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores}
return resResult(STATUS.SUCCESS, { data: data });
}

View File

@@ -2,7 +2,7 @@
* 体力系统
*/
import { fromCallback } from 'bluebird';
import { checkPvp } from '../pubUtils/pvpUtil'
import { checkPvp } from '../services/pvpService'
import { getFuncsSwitch } from '../pubUtils/data';
import { FUNCS_ID, FUNC_OPT_TYPE } from '../consts/constModules/sysConst';
import { RoleModel } from '../db/Role'

View File

@@ -1,14 +1,14 @@
/**
*
*/
import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType } from '../db/pvpDefense';
import { RoleType } from '../db/Role';
import { PVP_PLAYER_POS, PVP_HERO_POS, ROBOT_NAME } from '../consts';
import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType } from '../../../shared/db/pvpDefense';
import { RoleType } from '../../../shared/db/Role';
import { PVP_HERO_POS, ROBOT_NAME } from '../../../shared/consts';
import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent";
import { getRandomIndexByLen, genCode, getRandomByLen } from '../pubUtils/util';
import { oppPlayersInter } from '../pubUtils/interface';
import { gameData } from "../pubUtils/data";
import { dicPvpOpponent, DicPvpOpponent } from "../../../shared/pubUtils/dictionary/DicPvpOpponent";
import { getRandomIndexByLen, genCode, getRandomByLen } from '../../../shared/pubUtils/util';
import { oppPlayersInter } from '../../../shared/pubUtils/interface';
import { gameData } from "../../../shared/pubUtils/data";
export async function initPvpInfo(role: RoleType) {
@@ -26,9 +26,8 @@ export async function initPvpInfo(role: RoleType) {
});
}
}
//初始化对手人阵容TODO
//初始化对手人阵容
let oppPlayers: Array<OppPlayers> = await refreshEnemies(role, 0, 1);
let result = await PvpDefenseModel.createPvpDefense({ roleId: role.roleId, roleName: role.roleName, role: role._id, heroes, oppPlayers, defCe: role.topFiveCe });
//加入排行榜 TODO
return result;

View File

@@ -2,12 +2,70 @@
* 体力系统
*/
import { scheduleJob, cancelJob } from 'pinus-scheduler';
import { scheduleJob } from 'pinus-scheduler';
import { SystemConfigModel } from '../db/SystemConfig';
import PvpDefenseType,{ PvpDefenseModel } from '../db/pvpDefense';
import { PVP } from '../pubUtils/dicParam';
import { nowSeconds, getTodayZeroPoint } from '../pubUtils/timeUtil';
import { getPvpGkWarIds } from '../pubUtils/data';
import { getRandomArr } from '../pubUtils/util';
const _ = require('underscore');
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
const SETTLE_DIFF = 29 * 60;
const LIMIT_NUM = 1000;
export async function init() {
scheduleJob("0 31 23 * * *", setPvpSeasonResult, {name:'setPvpSeasonResult'})
let seasonEndTime = 0;
let systemConfig = await SystemConfigModel.findSystemConfig();
if (!systemConfig) {
let warIds = getPvpGkWarIds();
let warId = warIds[0];//TODO随机地图
seasonEndTime = PVP.PVP_SEASON_DAYS * PER_DAY + getTodayZeroPoint();
await SystemConfigModel.createSystemConfig( seasonEndTime, warId );
} else {
seasonEndTime = systemConfig.seasonEndTime;
if (systemConfig.seasonEndTime - SETTLE_DIFF <= nowSeconds()) {
await setPvpSeasonResult();
seasonEndTime = PVP.PVP_SEASON_DAYS * PER_DAY + getTodayZeroPoint();
systemConfig.seasonNum++;
await SystemConfigModel.updateSystemConfig({ seasonEndTime, seasonNum: systemConfig.seasonNum});
}
}
let settleTime = seasonEndTime - SETTLE_DIFF - nowSeconds();
// setTimeout(setPvpSeasonResult, settleTime * PER_SECOND);
scheduleJob("0 0 0 * * 1", resetPvpWarId)
}
export async function setPvpSeasonResult() {
console.log('setPvpSeasonResult');
let pvpDefenses = await PvpDefenseModel.getPvpDef(LIMIT_NUM);
for (let pvpDefense of pvpDefenses) {
await setPvpDefResult(pvpDefense);
}
await setNextPvpTime();
}
async function setPvpDefResult(pvpDefense: PvpDefenseType) {
await PvpDefenseModel.updateInfo(pvpDefense.roleId, {score:100, pLv: 1});
}
export async function resetPvpWarId() {
console.log('resetPvpWarId');
let systemConfig = await SystemConfigModel.findSystemConfig();
let warIds = getPvpGkWarIds();
let index = _.indexOf(warIds, systemConfig.warId);
if (index != -1) {
warIds.splice(index, 1);
}
let res = getRandomArr(warIds, 1);
let warId = res[0];//TODO随机地图
await SystemConfigModel.updateSystemConfig({ warId });
}
async function setNextPvpTime() {
let seasonEndTime = PVP.PVP_SEASON_DAYS * PER_DAY + getTodayZeroPoint();
await SystemConfigModel.updateSeason(seasonEndTime);
let settleTime = seasonEndTime - SETTLE_DIFF - nowSeconds();
setTimeout(setPvpSeasonResult, settleTime * PER_SECOND);
}

View File

@@ -19,5 +19,4 @@ module.exports = [{
}, {
'type': 'systimer',
'token': 'agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn'
}
];
}];

View File

@@ -1,3 +1,98 @@
module.exports = {
'onChat': {
'required string msg': 1,
'required string from': 2,
'required string target': 3
},
'onItemUpdate': {
'message Data': {
"message Good": {
'required uInt32 id': 1,
'required uInt32 count': 2,
},
'repeated Good goods': 1,
},
'required string msg': 1,
'required uInt32 code': 2,
'required Data data': 3
},
'onPlayerCeUpdate': {
'message Data': {
"message Hero": {
'required uInt32 hid': 1,
'required uInt32 ce': 2,
},
'required uInt32 ce': 1,
'repeated Hero heros': 2,
'required uInt32 topFiveCe': 3
},
'required string msg': 1,
'required uInt32 code': 2,
'required Data data': 3
},
'onPlayerDataChange': {
'message Data': {
'optional uInt32 coin': 1,
'optional uInt32 giftGold': 2,
'optional uInt32 gold': 3,
'optional uInt32 ap': 4
},
'required string msg': 1,
'required uInt32 code': 2,
'required Data data': 3
},
'onHeroSkinChange': {
'message Data': {
"message SkinInfo": {
"message Skin": {
'required uInt32 id': 1,
'required boolean enable': 2
},
'repeated Skin skins': 1,
},
'repeated SkinInfo skinInfos': 1
},
'required string msg': 1,
'required uInt32 code': 2,
'required Data data': 3
},
'onEquipAdd': {
'message Data': {
"message EquipInfo": {
"message RandSe": {
'required uInt32 id': 1,
'required uInt32 seid': 2,
'required int32 rand': 3,
'required boolean locked': 4
},
"message Hole": {
'required uInt32 id': 1,
'required boolean isOpen': 2,
'required uInt32 jewel': 3
},
'repeated Hole holes': 1,
'repeated RandSe randSe': 2,
'required uInt32 seqId': 3,
'required uInt32 id': 4,
'required uInt32 hid': 6,
'required uInt32 count': 7,
'required uInt32 quality': 8,
'required uInt32 ePlaceId': 9,
'required uInt32 suitId': 11,
'required int32 randRange': 12
},
'repeated EquipInfo equipInfos': 1
},
'required string msg': 1,
'required uInt32 code': 2,
'required Data data': 3
},
'onEquipDel': {
'message Data': {
'repeated uInt32 equips': 1
},
'required string msg': 1,
'required uInt32 code': 2,
'required Data data': 3
}
};

View File

@@ -40,6 +40,9 @@ module.exports = {
'frontend': true,
"args": " --inspect=9236"
}
],
'systimer': [
{'id': 'systimer-server-1', 'host': '127.0.0.1', 'port': 6056, "args": " --inspect=9233"}
]
},
'production': {

View File

@@ -292,7 +292,7 @@ export const FILENAME = {
DIC_PVP_OPPONENT: 'dic_pvp_opponent',
DIC_PVP_TEAM_LEVEL: 'dic_pvp_teamLevel',
DIC_GK_PVP: 'dic_zyz_gk_pvp',
DIC_PVP_REFRESHCONSUME: 'dic_pvp_refreshConsume'
DIC_PVP_REFRESHCONSUME: 'dic_pvp_refreshConsume',
}
export const WAR_RELATE_TABLES = [

View File

@@ -1,7 +1,7 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
const _ = require('underscore');
const Transaction = require('mongoose-transactions');
@index({ roleId: 1, id: 1 })
@index({ seqId: 1 })
@modelOptions({ schemaOptions: { id: false } })
@@ -50,59 +50,59 @@ export default class Item extends BaseModel {
return items;
}
public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number }>, lean = true) {
let updateItems = new Array<{ id: number, count: number, ratio?: number }>(), hasError: boolean = false, result = new Array();
for (let { id, count, ratio } of items) {
let rec: ItemType;
if (!ratio) {
rec = await ItemModel.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: -1 * count } }, { new: true }).lean(lean);
} else {
rec = await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: ratio * count } }, { new: true, upsert: true }).lean(lean);
}
if (!!rec) {
let index = _.findIndex(result,{id})
if (!!result[index]) {
result[index] = { id: rec.id, count: rec.count }
} else {
result.push({ id: rec.id, count: rec.count });
}
updateItems.push({ id, count, ratio });
} else {
hasError = true; break;
}
}
if (hasError) { // 数量不足
for (let { id, count, ratio } of updateItems) {
if (!ratio) ratio = -1;
await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: -ratio * count } }, { new: true }).lean(lean);
}
return { hasError: true }
} else {
return { hasError: false, result }
}
}
// public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number}>, lean = true) {
// const transaction = new Transaction();
// let hasError: boolean = false, result = new Array();
// try {
// for (let { id, count, ratio } of items) {
// if (ratio) ratio = -1;
// await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true});
// //const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean);
// // if (!!rec) {
// // result.push({ id: rec.id, count: rec.count });
// // } else {
// // hasError = true; break;
// // }
// public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number }>, lean = true) {
// let updateItems = new Array<{ id: number, count: number, ratio?: number }>(), hasError: boolean = false, result = new Array();
// for (let { id, count, ratio } of items) {
// let rec: ItemType;
// if (!ratio) {
// rec = await ItemModel.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: -1 * count } }, { new: true }).lean(lean);
// } else {
// rec = await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: ratio * count } }, { new: true, upsert: true }).lean(lean);
// }
// await transaction.run();
// return {hasError, result};
// } catch (error) {
// await transaction.rollback().catch(console.error);
// transaction.clean();
// return {error};
// if (!!rec) {
// let index = _.findIndex(result,{id})
// if (!!result[index]) {
// result[index] = { id: rec.id, count: rec.count }
// } else {
// result.push({ id: rec.id, count: rec.count });
// }
// updateItems.push({ id, count, ratio });
// } else {
// hasError = true; break;
// }
// }
// if (hasError) { // 数量不足
// for (let { id, count, ratio } of updateItems) {
// if (!ratio) ratio = -1;
// await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: -ratio * count } }, { new: true }).lean(lean);
// }
// return { hasError: true }
// } else {
// return { hasError: false, result }
// }
// }
public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number}>, lean = true) {
const transaction = new Transaction();
let hasError: boolean = false, result = new Array();
try {
for (let { id, count, ratio } of items) {
if (ratio) ratio = -1;
await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true});
const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean);
if (!!rec) {
result.push({ id: rec.id, count: rec.count });
} else {
hasError = true; break;
}
}
await transaction.run();
return {hasError, result};
} catch (error) {
await transaction.rollback().catch(console.error);
transaction.clean();
return {error};
}
}
public static async deleteAccount(roleId: string) {
let result = await ItemModel.deleteMany({ roleId });

View File

@@ -7,7 +7,9 @@ import { PVP_PLAYER_POS, PVP_HERO_POS } from '../consts';
interface pvpUpdateInter {
_id?: string;
oppPlayers: OppPlayers[]
oppPlayers?: OppPlayers[];
score?: number;
pLv?:number;
}
export class Heroes {
@@ -123,7 +125,8 @@ export default class PvpDefense extends BaseModel {
challengeRefTime: number; // 上一次刷新的时间
@prop({ required: true, default: [] })
receivedBox: Array<number>;
@prop({ required: true, default: 0 })
seasonNum: number;
public static async findByRoleId(roleId: string, lean = true) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).lean(lean);
return result;
@@ -170,7 +173,7 @@ export default class PvpDefense extends BaseModel {
return result;
}
public static async findByRoleIdIncludeAll(roleId: string, lean = true) {
public static async findByRoleIdIncludeAll(roleId: string) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId })
.populate('role', 'headHid sHid topFiveCe roleId roleName')
.populate('heroes.hero')
@@ -201,6 +204,15 @@ export default class PvpDefense extends BaseModel {
}).lean();
return result;
}
public static async updateInfo(roleId: string, update: pvpUpdateInter, lean = true) {
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true}).lean(lean);
return result;
}
public static async getPvpDef(limitNum: number, lean = true) {
let result: Array<PvpDefenseType> = await PvpDefenseModel.find().sort({ score: -1 }).limit(limitNum).lean(lean);
return result;
}
}
export const PvpDefenseModel = getModelForClass(PvpDefense);

View File

@@ -15,6 +15,21 @@ export default class SystemConfig extends BaseModel {
const result: SystemConfigType = await SystemConfigModel.findOne({ id: 1 }).lean(lean);
return result;
}
public static async createSystemConfig(seasonEndTime: number, warId: number, lean = true) {
const result: SystemConfigType = await SystemConfigModel.findOneAndUpdate({ id: 1}, { seasonEndTime, warId }, { upsert: true, new: true }).lean(lean);
return result;
}
public static async updateSystemConfig(update: { seasonEndTime?: number, warId?: number, seasonNum?:number }, lean = true) {
const result: SystemConfigType = await SystemConfigModel.findOneAndUpdate({ id: 1}, update, { upsert: true, new: true }).lean(lean);
return result;
}
public static async updateSeason( seasonEndTime: number, lean = true) {
const result: SystemConfigType = await SystemConfigModel.findOneAndUpdate({ id: 1}, { $seasonEndTime: seasonEndTime, $inc: { seasonNum:1 } }, { upsert: true, new: true }).lean(lean);
return result;
}
}
export const SystemConfigModel = getModelForClass(SystemConfig);

View File

@@ -39,7 +39,7 @@ import { ABI_TYPE_TO_STAGE } from "../consts";
import { dicPvpOpponent } from './dictionary/DicPvpOpponent';
import { dicPvpTeamLevel } from './dictionary/DicPvpTeamLevel';
import { dicPvpRefreshConsume } from './dictionary/DicPvpRefreshConsume';
import { dicGkPvp, dicGkPvps } from './dictionary/DicGkPvp'
export const gameData = {
blurprtCompose: dicBlueprtCompose,
blueprtPossibility: dicBlueprtPossibility,
@@ -91,7 +91,9 @@ export const gameData = {
pvpOpponent: dicPvpOpponent,
pvpTeamLevel: dicPvpTeamLevel,
pvpWar: dicWarPvp,
pvpRefreshConsume: dicPvpRefreshConsume
pvpRefreshConsume: dicPvpRefreshConsume,
pvpGk: dicGkPvp,
pvpGks: dicGkPvps,
};
// 在此提供一些原先在gamedata中提供的方法以便更方便获取gameData数据
@@ -267,4 +269,13 @@ export function getPLvByScore(score: number) {
if(score < topFiveMax) break;
}
return lv;
}
export function getPvpGkByWarId (warId: number) {
return gameData.pvpGk.get(warId);
}
export function getPvpGkWarIds() {
let warIds = gameData.pvpGks;
return warIds;
}

View File

@@ -27,3 +27,10 @@ export const SCHOOL = {
export const SCROLL = {
SCROLL_ACTIVE_FAVOUR: 50, // 首次激活增加的好感度
};
export const PVP = {
PVP_CHALLENGE_COUNTS: 10, // pvp初始挑战次数
PVP_CHALLENGE_NORMALTIMES: 120, // pvp日常挑战次数刷新时间分钟
PVP_CHALLENGE_FINALTIMES: 60, // PVP赛季最后一天挑战次数刷新时间分钟
PVP_SEASON_DAYS: 30, // PVP一个赛季的时间
PVP_OPPONENT_FREEREFRESH: 3, // pvp挑战对手每日免费刷新次数
};

View File

@@ -0,0 +1,19 @@
import { readJsonFile } from '../util'
import { FILENAME } from '../../consts'
export interface DicGkPvp {
readonly war_id: number;
readonly dispatchJsonId: number;
readonly bg_img_id: number;
readonly warType: number;
}
const str = readJsonFile(FILENAME.DIC_GK_PVP);
let arr = JSON.parse(str);
export const dicGkPvp = new Map<number, DicGkPvp>();
export const dicGkPvps = new Array<number>();
arr.forEach(o => {
dicGkPvp.set(o.war_id, o);
dicGkPvps.push(o.war_id);
});

View File

@@ -0,0 +1,15 @@
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
export function nowSeconds() {
return Math.floor(Date.now() / PER_SECOND );
}
export function getTodayZeroPoint() {
var date = new Date();
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
var time = Math.floor(date.getTime() / PER_SECOND);
return time;
}

View File

@@ -6,7 +6,6 @@ import fs = require('fs');
import path = require('path');
import { DicRandomEffectPool } from './dictionary/DicRandomEffectPool';
import { HERO_CE_RATIO, ABI_STAGE } from '../consts';
import { PvpDefenseType } from '../db/PvpDefense';
const _ = require('underscore');