寻宝:创建队伍超时匹配机器人;战斗超时判负;优化代码并修复部分bug

This commit is contained in:
liangtongchuan
2020-11-30 23:49:07 +08:00
parent 20d638189e
commit dd29d0dd44
5 changed files with 127 additions and 68 deletions

View File

@@ -2,10 +2,10 @@
* @Author: 梁桐川
* @Date: 2020-11-30 15:05:48
* @Last Modified by: 梁桐川
* @Last Modified time: 2020-11-30 18:08:49
* @Last Modified time: 2020-11-30 23:45:32
*/
import { COM_BATTLE_ROBOT_CE_RATIO, COM_BATTLE_ROBOT_ID_NAME, COM_BATTLE_ASSIST_TIME, COM_BATTLE_ROBOT_ROUND_LMT, COM_BATTLE_ROBOT_HURT_RATIO, COM_BATTLE_ROBOT_HURT_CH_RATIO, COM_TEAM_STATUS } from './../../../consts/consts';
import { IT_TYPE, GOLD_COST_RATIO, CURRENCY_BY_TYPE, CURRENCY_TYPE } from '../../../consts/consts';
import { COM_BATTLE_ASSIST_TIME, COM_BATTLE_ROBOT_ROUND_LMT, COM_BATTLE_ROBOT_HURT_RATIO, COM_BATTLE_ROBOT_HURT_CH_RATIO, COM_TEAM_STATUS } from './../../../consts/consts';
import { IT_TYPE, GOLD_COST_RATIO, CURRENCY_BY_TYPE, CURRENCY_TYPE, COM_BATTLE_CAP_TIME, COM_BATTLE_TIME_LMT } from './../../../consts/consts';
import { getGoodById, getBossHpByBlueprtId, getComBtlSetByQuality, getBlueprtComposeByQuality, getBluePrtByQuality } from '../../../pubUtils/gamedata';
import { COM_TEAM_ENABLE_LV } from '../../../consts/consts';
import { ComBattleTeamModel } from '../../../db/ComBattleTeam';
@@ -16,9 +16,9 @@ import { resResult, getRandomByLen, calculateNum, getRandValue } from '../../../
import { RoleStatus } from '../../../db/ComBattleTeam';
import { ItemModel } from '../../../db/Item';
import { handleReward } from '../../../services/rewardService';
import { getTeamSearchByQuality, setTeamSearchReq } from '../../../services/redisService';
import { getRandRobot, transBossHpArr } from '../../../services/battleService';
import { getRandBlueprtId } from '../../../services/comBattleService';
import { checkRoleInQueue, getTeamSearchByQuality, setTeamSearchReq } from '../../../services/redisService';
import { transBossHpArr } from '../../../services/battleService';
import { getRandBlueprtId, getRandComBtlRobots, checkComBattleResult } from '../../../services/comBattleService';
export default function(app: Application) {
return new ComBattleHandler(app);
@@ -141,16 +141,28 @@ export class ComBattleHandler {
channel.add(roleId, sid);
}
}
let uids = [];
if (teammates) {
let uids = [];
for (let teammate of teammates) {
let { roleId, sid } = teammate;
uids.push({uid: roleId, sid});
}
// TODO: 处理助战 timer
channelService.pushMessageByUids('onTeamJoin', {teamInfo: comTeam}, uids);
}
let thiz = this;
// 倒计时一定时间给队长匹配机器人
setTimeout(async () => {
let team = thiz.teamMap.get(teamCode);
if (team.roleIds.length < 3) {
let { robotStArr, robotIdArr } = getRandComBtlRobots(topFiveCe, lv, 3 - team.roleIds.length);
team.roleIds = team.roleIds.concat(robotIdArr);
team.roleStatus = team.roleStatus.concat(robotStArr);
for (let st of robotStArr) {
await ComBattleTeamModel.addRole(teamCode, st);
}
}
channelService.pushMessageByUids('onTeamJoin', {teamInfo: team}, uids);
}, COM_BATTLE_CAP_TIME);
return resResult(STATUS.SUCCESS, { teamCode, roleStatus });
}
@@ -179,26 +191,25 @@ export class ComBattleHandler {
let thiz = this;
// 倒计时匹配两个机器人
setTimeout(async () => {
let inQueue = await checkRoleInQueue(roleId, sid, qualityArr);
if (!inQueue) return;
let roleStatus = [];
let roleIds = []
let robotHeroes = getRandRobot(2); // 随机两个阵容
let roleInfo = new RoleStatus(roleId, roleName, false, false, headHid, sHid, topFiveCe, lv);
roleStatus.push(roleInfo);
roleIds.push(roleId);
let blueprtId = (await getRandBlueprtId(qualityArr)).pop();
// 创建队伍
let blueprtId = getRandBlueprtId(qualityArr).pop();
let { quality } = getGoodById(blueprtId);
let { bossHpSum, bossHpArr } = getBossHpByBlueprtId(blueprtId);
let comTeam = new ComTeam(teamCode, false, blueprtId, COM_TEAM_STATUS.DEFAULT, 'robot', 0, bossHpSum || 10000, quality, transBossHpArr(bossHpArr));
// 将玩家加入队伍
let roleInfo = new RoleStatus(roleId, roleName, false, false, headHid, sHid, topFiveCe, lv);
roleStatus.push(roleInfo);
roleIds.push(roleId);
// 创建并添加机器人
for (let robot of robotHeroes) {
const robotCe = getRandValue(topFiveCe, COM_BATTLE_ROBOT_CE_RATIO, 0);
const robotLv = getRandValue(lv, COM_BATTLE_ROBOT_CE_RATIO, 0);
const imgHid = robot[Math.floor(Math.random() * robot.length)];
const { robotRoleId, robotRoleName } = COM_BATTLE_ROBOT_ID_NAME[Math.floor(Math.random() * COM_BATTLE_ROBOT_ID_NAME.length)];
let robotStatus = new RoleStatus(robotRoleId, robotRoleName, false, false, imgHid, imgHid, robotCe, robotLv, robot, true);
roleStatus.push(robotStatus);
roleIds.push(robotRoleId);
}
let { robotStArr, robotIdArr } = getRandComBtlRobots(topFiveCe, lv, 2);
roleStatus = roleStatus.concat(robotStArr);
roleIds = roleIds.concat(robotIdArr);
comTeam.roleStatus = roleStatus;
comTeam.roleIds = roleIds;
let channelService = thiz.app.get('channelService');
@@ -243,13 +254,13 @@ export class ComBattleHandler {
return resResult(STATUS.COM_BATTLE_CE_LIMIT);
}
let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, teamStatus.quality, new Date(new Date().setHours(0, 0, 0, 0)), true);
let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, [teamStatus.quality], new Date(new Date().setHours(0, 0, 0, 0)), true);
if (teams.length >= assistanceTime) resResult(STATUS.COM_BATTLE_ASSIST_NOT_ENOUGH);
// 加入队伍
let roleStatus = new RoleStatus(roleId, roleName, false, isFrd, headHid, sHid, topFiveCe, lv);
const team = await ComBattleTeamModel.addRole(teamCode, roleStatus);
if (!team || team.roleIds.length === 3) {
if (!team || team.roleIds.length > 3) {
return resResult(STATUS.COM_BATTLE_JOIN_ERR);
}
@@ -447,6 +458,18 @@ export class ComBattleHandler {
let channelService = this.app.get('channelService');
let channel = channelService.getChannel(teamCode, false);
channel.pushMessage('onComBtlStart', {teamCode, roleStatus: teamStatus.roleStatus});
// 每场倒计时结算
let thiz = this;
setTimeout(async () => {
let teamStatus = thiz.teamMap.get(teamCode);
if (teamStatus.status === COM_TEAM_STATUS.FIGHTING) {
let channelService = thiz.app.get('channelService');
let channel = channelService.getChannel(teamCode, false);
let team = await ComBattleTeamModel.syncTeamData({teamCode, status: COM_TEAM_STATUS.LOOSE, roleStatus: teamStatus.roleStatus});
if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR);
channel.pushMessage('onTeamComplete', {teamCode, result: false});
}
}, COM_BATTLE_TIME_LMT);
return resResult(STATUS.SUCCESS);
}
@@ -521,41 +544,12 @@ export class ComBattleHandler {
const roleStatus = teamStatus.roleStatus.map(st => {return {roleId: st.roleId, totalDmg: st.totalDmg, killed: st.killed}});
channel.pushMessage('onTeammateAct', {teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus});
// 判断战斗是否结束
if (teamStatus.bossCurHp === 0) {
let team = await ComBattleTeamModel.syncTeamData({teamCode, status: COM_TEAM_STATUS.WIN, roleStatus: teamStatus.roleStatus});
let battleSt = checkComBattleResult(teamStatus);
if (battleSt === COM_TEAM_STATUS.WIN || battleSt === COM_TEAM_STATUS.LOOSE) {
let result = battleSt === COM_TEAM_STATUS.WIN;
let team = await ComBattleTeamModel.syncTeamData({teamCode, status: battleSt, roleStatus: teamStatus.roleStatus});
if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR);
channel.pushMessage('onTeamComplete', {teamCode, result: true});
} else {
let allPlayerKilled = true;
let robotRestHurt = 0;
// 看看是否还有活人
teamStatus.roleStatus.forEach(st => {
if (!st.isRobot && st.killed.length < st.heroes.length) {
allPlayerKilled = false
}
});
// 没有活人的话看看还有没有机器人没打完伤害
if (allPlayerKilled && teamStatus.curRnd < COM_BATTLE_ROBOT_ROUND_LMT) {
teamStatus.roleStatus.forEach(st => {
if (st.isRobot) {
const deltaRnd = COM_BATTLE_ROBOT_ROUND_LMT - teamStatus.curRnd;
let hurtHp = getRandValue(teamStatus.bossHp / COM_BATTLE_ROBOT_ROUND_LMT * COM_BATTLE_ROBOT_HURT_RATIO, COM_BATTLE_ROBOT_HURT_CH_RATIO, 0) * deltaRnd; // 1 个机器人对 boss 造成的总伤害
robotRestHurt += hurtHp;
}
})
}
if (allPlayerKilled) {
// 没有活人且机器人剩余伤害打不死 boss战败
if (teamStatus.bossCurHp > robotRestHurt) {
let team = await ComBattleTeamModel.syncTeamData({teamCode, status: COM_TEAM_STATUS.LOOSE, roleStatus: teamStatus.roleStatus});
if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR);
channel.pushMessage('onTeamComplete', {teamCode, result: false});
} else {
let team = await ComBattleTeamModel.syncTeamData({teamCode, status: COM_TEAM_STATUS.WIN, roleStatus: teamStatus.roleStatus});
if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR);
channel.pushMessage('onTeamComplete', {teamCode, result: true});
}
}
channel.pushMessage('onTeamComplete', {teamCode, result});
}
return resResult(STATUS.SUCCESS);
}
@@ -577,7 +571,6 @@ export class ComBattleHandler {
let team = await ComBattleTeamModel.updateResult(teamCode, roleId, isSuccess);
if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR);
// TODO: 根据策划结论考虑是否在推送中添加掉落
// TODO: 用户总伤害等的持久化
channel.pushMessage('onTeamComplete', {teamCode, result: isSuccess});
} else if (!isSuccess) {
let team = await ComBattleTeamModel.updateResult(teamCode, roleId, isSuccess);

View File

@@ -1,12 +1,15 @@
import { COM_BATTLE_ROBOT_ID_NAME, COM_BATTLE_ROBOT_CE_RATIO, COM_BATTLE_ROBOT_ROUND_LMT, COM_BATTLE_ROBOT_HURT_RATIO, COM_BATTLE_ROBOT_HURT_CH_RATIO, COM_TEAM_STATUS } from './../consts/consts';
import { RoleStatus } from './../db/ComBattleTeam';
import { getBluePrtByQuality } from "../pubUtils/gamedata";
import { getRandEelm } from "../pubUtils/util";
import { getRandEelm, getRandValue } from "../pubUtils/util";
import { getRandRobot } from "./battleService";
/**
* 在给定的品质列表中随机返回一定数量的藏宝图Id
* @param qualityArr 品质数组在所有给定品质的藏宝图中筛选1
* @param cnt 返回藏宝图数量
*/
export async function getRandBlueprtId(qualityArr: Array<number>, cnt = 1) {
export function getRandBlueprtId(qualityArr: Array<number>, cnt = 1) {
if (!qualityArr || !qualityArr.length) return null;
let blueprtIdArr = [];
for (let q of qualityArr) {
@@ -16,3 +19,55 @@ export async function getRandBlueprtId(qualityArr: Array<number>, cnt = 1) {
const res = getRandEelm(blueprtIdArr, cnt);
return res;
}
export function getRandComBtlRobots(topFiveCe: number, lv: number, cnt: number) {
let robotHeroes = getRandRobot(cnt); // 随机两个阵容
// 创建并添加机器人
let robotStArr = [], robotIdArr = [];
for (let robot of robotHeroes) {
const robotCe = getRandValue(topFiveCe, COM_BATTLE_ROBOT_CE_RATIO, 0);
const robotLv = getRandValue(lv, COM_BATTLE_ROBOT_CE_RATIO, 0);
const imgHid = robot[Math.floor(Math.random() * robot.length)];
const { robotRoleId, robotRoleName } = COM_BATTLE_ROBOT_ID_NAME[Math.floor(Math.random() * COM_BATTLE_ROBOT_ID_NAME.length)];
let robotStatus = new RoleStatus(robotRoleId, robotRoleName, false, false, imgHid, imgHid, robotCe, robotLv, robot, true);
robotStArr.push(robotStatus);
robotIdArr.push(robotRoleId);
}
return {
robotStArr, robotIdArr
}
}
export function checkComBattleResult(teamStatus) {
if (teamStatus.bossCurHp === 0) {
return COM_TEAM_STATUS.WIN;
} else {
let allPlayerKilled = true;
let robotRestHurt = 0;
// 看看是否还有活人
teamStatus.roleStatus.forEach(st => {
if (!st.isRobot && st.killed.length < st.heroes.length) {
allPlayerKilled = false
}
});
// 没有活人的话看看还有没有机器人没打完伤害
if (allPlayerKilled && teamStatus.curRnd < COM_BATTLE_ROBOT_ROUND_LMT) {
teamStatus.roleStatus.forEach(st => {
if (st.isRobot) {
const deltaRnd = COM_BATTLE_ROBOT_ROUND_LMT - teamStatus.curRnd;
let hurtHp = getRandValue(teamStatus.bossHp / COM_BATTLE_ROBOT_ROUND_LMT * COM_BATTLE_ROBOT_HURT_RATIO, COM_BATTLE_ROBOT_HURT_CH_RATIO, 0) * deltaRnd; // 1 个机器人对 boss 造成的总伤害
robotRestHurt += hurtHp;
}
})
}
if (allPlayerKilled) {
// 没有活人且机器人剩余伤害打不死 boss战败
if (teamStatus.bossCurHp > robotRestHurt) {
return COM_TEAM_STATUS.LOOSE;
} else {
return COM_TEAM_STATUS.WIN;
}
}
}
return COM_TEAM_STATUS.FIGHTING;
}

View File

@@ -11,6 +11,7 @@ declare module 'redis' {
hdelAsync(...args: any[]): Promise<any>;
spopAsync(...args: any[]): Promise<any>;
sremAsync(...args: any[]): Promise<any>;
sismemberAsync(...args: any[]): Promise<any>;
srandmemberAsync(...args: any[]): Promise<any>;
}
export interface Multi extends Commands<Multi> {
@@ -177,6 +178,16 @@ export async function getTeamSearchByQuality(quality: number) {
return res;
}
export async function checkRoleInQueue(roleId: string, sid: string, qualityArr: Array<number>) {
for (let quality of qualityArr) {
let res = await client.sismemberAsync(`${REDIS_KEY.COM_TEAM_SEARCH_PRE}${quality}`, `${roleId}:${sid}`);
if (res) {
return true;
}
};
return false;
}
/**************** 寻宝相关 end */
////// redis方法

View File

@@ -277,8 +277,8 @@ export const COM_TEAM_ENABLE_LV = 1;
export const COM_ASSIST_DROP_RATE = 0.5;
// 藏宝图伪随机所需体力
export const COM_BLUEPRT_DROP_PER_AP = 10;
// 每局时长限制,秒
export const COM_BATTLE_TIME_LMT = 10 * 60;
// 每局时长限制
export const COM_BATTLE_TIME_LMT = 10 * 60 * 1000;
// 机器人生成时间,秒
// export const COM_BATTLE_ROBOT_TIME_LMT = 1;
// 每个机器人消耗 boss 血量百分比

View File

@@ -102,7 +102,7 @@ export default class ComBattleTeam extends BaseModel {
}
public static async addRole(teamCode: string, roleStatus: RoleStatus, lean = true) {
const team = await ComBattleTeamModel.findOneAndUpdate({ teamCode }, {$push: {roleIds: roleStatus.roleId, roleStatus}}, {upsert: true, new: true}).lean(lean);
const team = await ComBattleTeamModel.findOneAndUpdate({ teamCode }, {$push: {roleIds: roleStatus.roleId, roleStatus}}, {new: true}).lean(lean);
return team;
}
@@ -173,10 +173,10 @@ export default class ComBattleTeam extends BaseModel {
return team;
}
public static async getTeamByRoleAndTime(roleId: string, quality?: number, time?: Date, isAssist?: boolean, limitCnt = 50, lean = true) {
public static async getTeamByRoleAndTime(roleId: string, qualityArr?: Array<number>, time?: Date, isAssist?: boolean, limitCnt = 50, lean = true) {
let query = {roleIds: roleId};
if (quality) {
query = Object.assign(query, {quality});
if (qualityArr) {
query = Object.assign(query, {quality: {$in: qualityArr}});
}
if (time) {
query = Object.assign(query, {createdAt: {$gte: time}});