diff --git a/game-server/app/servers/battle/handler/comBattleHandler.ts b/game-server/app/servers/battle/handler/comBattleHandler.ts index b02dae73a..7b7f34061 100644 --- a/game-server/app/servers/battle/handler/comBattleHandler.ts +++ b/game-server/app/servers/battle/handler/comBattleHandler.ts @@ -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); diff --git a/game-server/app/services/comBattleService.ts b/game-server/app/services/comBattleService.ts index a20213a1a..37dbed758 100644 --- a/game-server/app/services/comBattleService.ts +++ b/game-server/app/services/comBattleService.ts @@ -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, cnt = 1) { +export function getRandBlueprtId(qualityArr: Array, 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, 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; +} \ No newline at end of file diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index c1590b00c..62953a920 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -11,6 +11,7 @@ declare module 'redis' { hdelAsync(...args: any[]): Promise; spopAsync(...args: any[]): Promise; sremAsync(...args: any[]): Promise; + sismemberAsync(...args: any[]): Promise; srandmemberAsync(...args: any[]): Promise; } export interface Multi extends Commands { @@ -177,6 +178,16 @@ export async function getTeamSearchByQuality(quality: number) { return res; } +export async function checkRoleInQueue(roleId: string, sid: string, qualityArr: Array) { + 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方法 diff --git a/shared/consts/consts.ts b/shared/consts/consts.ts index 81f112b58..acb4ba508 100644 --- a/shared/consts/consts.ts +++ b/shared/consts/consts.ts @@ -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 血量百分比 diff --git a/shared/db/ComBattleTeam.ts b/shared/db/ComBattleTeam.ts index a9f65e7bc..71f5a4a61 100644 --- a/shared/db/ComBattleTeam.ts +++ b/shared/db/ComBattleTeam.ts @@ -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, 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}});