diff --git a/game-server/app/servers/battle/handler/comBattleHandler.ts b/game-server/app/servers/battle/handler/comBattleHandler.ts index 783c084c6..ff12a43d8 100644 --- a/game-server/app/servers/battle/handler/comBattleHandler.ts +++ b/game-server/app/servers/battle/handler/comBattleHandler.ts @@ -7,16 +7,16 @@ import { difference } from 'underscore'; * @Last Modified time: 2020-12-03 21:36:00 */ import { IT_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, COM_TEAM_STATUS, COM_BTL_CONST, CONSUME_TYPE, COM_BTL_QUALITY } from './../../../consts'; -import { getGoodById, getBlueprtComposeByQuality, getBluePrtByQuality, getWarById, getWarIdByBlueprtId, comBtlRangeByLv } from '../../../pubUtils/gamedata'; +import { getGoodById, getBlueprtComposeByQuality, getBluePrtByQuality, getWarById, getWarIdByBlueprtId } from '../../../pubUtils/gamedata'; import Role, { RoleModel } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; import { Application, BackendSession } from 'pinus'; -import { resResult, getRandomByLen, reduceCe, getRandValueByMinMax } from '../../../pubUtils/util'; +import { resResult, getRandomByLen, reduceCe } from '../../../pubUtils/util'; import { RoleStatus, ComBattleTeamModel, ComBattleTeamType } from '../../../db/ComBattleTeam'; import { ItemModel } from '../../../db/Item'; import { handleFixedReward, addItems, handleCost } from '../../../services/rewardService'; -import { checkRoleInQueue, getTeamSearchByQuality, rmRoleFromQueue, setTeamSearchReq } from '../../../services/redisService'; -import { getRandBlueprtId, getRandComBtlRobots, clearComBtlTimer, getAssistTimesByQuality, getFrd, updateRobotHurtByTime, comBtlLvInvalid, clearRobotHurtTimer, setDismissTimer, dismissTeam, incEquipPrintDrop, randEquipPrintId, handleComBtlProgress, getComBattleFriendAdd, getValidTeammateRoleSt, teammateInBlackList, blueprtIdValid, createComTeamData, hasEnoughBlueprt, addRoleToTeam, addRoleStToTeam, addValidSearchingRoles } from '../../../services/comBattleService'; +import { checkRoleInQueue, rmRoleFromQueue, setTeamSearchReq } from '../../../services/redisService'; +import { getRandBlueprtId, clearComBtlTimer, getAssistTimesByQuality, getFrd, updateRobotHurtByTime, comBtlLvInvalid, clearRobotHurtTimer, setDismissTimer, dismissTeam, incEquipPrintDrop, randEquipPrintId, handleComBtlProgress, getComBattleFriendAdd, teammateInBlackList, blueprtIdValid, createComTeamData, hasEnoughBlueprt, addRoleToTeam, addRoleStToTeam, addValidSearchingRoles, validToJoin, addRobotsToTeam, addRobotsLater, teamIsFullToStart, oneTeamNotInBlack } from '../../../services/comBattleService'; import { setAp } from '../../../services/actionPointService'; import { roleLevelup } from '../../../services/normalBattleService'; import { addUserToChannel } from '../../../services/roleService'; @@ -53,7 +53,6 @@ export class ComBattleHandler { const roleInfo = await RoleModel.findByRoleId(roleId); const { lv } = roleInfo; - const topFiveCe = reduceCe(roleInfo.topFiveCe || 100); if (lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); let channelService = this.app.get('channelService'); @@ -74,30 +73,11 @@ export class ComBattleHandler { } this.teamMap.set(teamCode, comTeam); - let thiz = this; - // 倒计时一定时间给队长匹配机器人 - let teamStatus = thiz.teamMap.get(teamCode); - if (pub === true && teamStatus && teamStatus.roleIds && teamStatus.status === COM_TEAM_STATUS.DEFAULT && teamStatus.roleIds.length < 3) { - const robotCnt = 3 - teamStatus.roleIds.length; - for(let robotIdx = 0; robotIdx < robotCnt; robotIdx++) { - const joinTime = getRandValueByMinMax(COM_BTL_CONST.MIN_CAP_TIME, COM_BTL_CONST.MAX_CAP_TIME, 0); - setTimeout(async () => { - teamStatus = thiz.teamMap.get(teamCode); - if (teamStatus && teamStatus.status === COM_TEAM_STATUS.DEFAULT && teamStatus.roleIds.length < 3) { - let { robotStArr, robotIdArr } = getRandComBtlRobots(topFiveCe, teamStatus.ceLimit, lv, 1); - teamStatus.roleIds = teamStatus.roleIds.concat(robotIdArr); - teamStatus.roleStatus = teamStatus.roleStatus.concat(robotStArr); - for (let st of robotStArr) { - await ComBattleTeamModel.addRole(teamCode, st); - } - channel.pushMessage('onTeamJoin', resResult(STATUS.SUCCESS, {teamInfo: teamStatus})); - setDismissTimer(teamStatus, thiz.teamMap, roleId, thiz.teamDisTimer, thiz.app); - } - }, joinTime); - } + if (pub === true) { + await addRobotsLater(comTeam, roleInfo, this.teamMap, this.teamDisTimer, channel); } - setDismissTimer(teamStatus, thiz.teamMap, roleId, thiz.teamDisTimer, thiz.app); + setDismissTimer(comTeam, this.teamMap, roleId, this.teamDisTimer, channel); return resResult(STATUS.SUCCESS, { teamCode, roleStatus: comTeam.roleStatus }); } @@ -125,20 +105,11 @@ export class ComBattleHandler { } const teams = await ComBattleTeamModel.getOtherTeamByQualityAndSt(roleId, qualityArr, COM_TEAM_STATUS.DEFAULT, lvRange, topFiveCe); - let team: ComBattleTeamType; - for(let curTeam of teams) { - let { roleIds } = curTeam; - const inBlackList = await teammateInBlackList(roleId, roleIds); - if(!inBlackList) { - team = curTeam; - break; - } - } - - // TODO: 有匹配的队伍还需要重新 joinTeam 加入,有失败可能,体验不好,需优化 + const team: ComBattleTeamType = await oneTeamNotInBlack(teams, roleId); if (team && team.roleIds.length < 3 && team.status === COM_TEAM_STATUS.DEFAULT && team.roleIds.indexOf(roleId) === -1) { return resResult(STATUS.SUCCESS, {teamCode: team.teamCode}); } + let teamCode = session.get('teamCode'); await setTeamSearchReq(roleId, sid, qualityArr, lvRange); let thiz = this; @@ -147,9 +118,6 @@ export class ComBattleHandler { let inQueue = await checkRoleInQueue(roleId, sid, qualityArr, lvRange); if (!inQueue) return; await rmRoleFromQueue(roleId, sid, qualityArr, lvRange); - let roleStatus = []; - let roleIds = []; - // 创建队伍 let blueprtId = getRandBlueprtId(qualityArr).pop(); let comTeam: MemComBtlTeam = createComTeamData(teamCode, false, blueprtId, 'robot', 0) @@ -158,23 +126,15 @@ export class ComBattleHandler { let isFrd = await getFrd(roleId, quality); // 将玩家加入队伍 addRoleToTeam(comTeam, roleInfo, false, isFrd); - // 创建并添加机器人 - let { robotStArr, robotIdArr } = getRandComBtlRobots(topFiveCe, comTeam.ceLimit, lv, 2); - roleStatus = roleStatus.concat(robotStArr); - roleIds = roleIds.concat(robotIdArr); - comTeam.roleStatus = roleStatus; - comTeam.roleIds = roleIds; let channelService = thiz.app.get('channelService'); - const team = await ComBattleTeamModel.createTeam(comTeam); - // if (!team) channelService.pushMessageByUids('onTeamJoin', {teamInfo: null}, [{uid: roleId, sid}]); - thiz.teamMap.set(teamCode, comTeam); - // 推送组队消息 - channelService.pushMessageByUids('onTeamJoin', resResult(STATUS.SUCCESS, {teamInfo: comTeam}), [{uid: roleId, sid}]); let channel = channelService.getChannel(teamCode, true); - let users = channel.getMembers(); - if (users.indexOf(roleId) === -1) { - channel.add(roleId, sid); - } + addUserToChannel(channel, new ChannelUser(roleId, sid)); + + // 创建并添加机器人 + await addRobotsToTeam(comTeam, roleId, topFiveCe, lv, thiz.teamMap, thiz.teamDisTimer, channel, 2); + + await ComBattleTeamModel.createTeam(comTeam); + thiz.teamMap.set(teamCode, comTeam); // 机器人队伍 3 秒直接开战 setTimeout(async () => { thiz.startBattle({teamCode}, session); @@ -211,7 +171,7 @@ export class ComBattleHandler { let { teamCode, isFrd } = msg; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (teamStatus.roleIds.length === 3) return resResult(STATUS.COM_BATTLE_MEMBER_LIMIT); + if (teamIsFullToStart(teamStatus)) return resResult(STATUS.COM_BATTLE_MEMBER_LIMIT); if (teamStatus.roleIds.indexOf(roleId) !== -1) return resResult(STATUS.COM_BATTLE_DUP_ENTER); let { lv = 1, headHid = 19, topFiveCe = 0, sHid = 19 } = await Role.findByRoleId(roleId); @@ -230,25 +190,22 @@ export class ComBattleHandler { } // 加入队伍 + if (!validToJoin(teamStatus, roleId)) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); 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) { return resResult(STATUS.COM_BATTLE_JOIN_ERR); } + addRoleStToTeam(teamStatus, roleStatus); + // 推送队伍信息给所有玩家 let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); - teamStatus.roleIds.push(roleId); - teamStatus.roleStatus.push(roleStatus); - - let users = channel.getMembers(); - if (users.indexOf(roleId) === -1) { - channel.add(roleId, sid); - } + addUserToChannel(channel, new ChannelUser(roleId, sid)); channel.pushMessage('onTeamJoin', resResult(STATUS.SUCCESS, {teamInfo: teamStatus})); - setDismissTimer(teamStatus, this.teamMap, roleId, this.teamDisTimer, this.app); + setDismissTimer(teamStatus, this.teamMap, roleId, this.teamDisTimer, channel); return resResult(STATUS.SUCCESS, { teamInfo: teamStatus}); } @@ -393,25 +350,18 @@ export class ComBattleHandler { clearComBtlTimer(teamCode, this.teamDisTimer); // 移除队员停止解散计时 let thiz = this; setTimeout(async () => { - let team = thiz.teamMap.get(teamCode); - if (team && team.roleIds && team.status === COM_TEAM_STATUS.DEFAULT && team.roleIds.length < 3) { + let curTeamStatus = thiz.teamMap.get(teamCode); + if (validToJoin(curTeamStatus)) { let roleSt: RoleStatus; - for (let st of team.roleStatus) { + for (let st of curTeamStatus.roleStatus) { if (st.roleId === roleId) { roleSt = st; } } if (!roleSt) return; let { topFiveCe, lv } = roleSt; - let { robotStArr, robotIdArr } = getRandComBtlRobots(topFiveCe, team.ceLimit, 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); - } - channel.pushMessage('onTeamJoin', resResult(STATUS.SUCCESS, {teamInfo: team})); + await addRobotsToTeam(curTeamStatus, roleId, topFiveCe, lv, thiz.teamMap, thiz.teamDisTimer, channel, 3 - curTeamStatus.roleIds.length); } - await setDismissTimer(team, thiz.teamMap, roleId, thiz.teamDisTimer, thiz.app); }, COM_BTL_CONST.ASSIST_TIME); return resResult(STATUS.SUCCESS); } @@ -427,7 +377,9 @@ export class ComBattleHandler { let roleId = session.get('roleId'); let { teamCode } = msg; let teamStatus = this.teamMap.get(teamCode); - let result = await dismissTeam(teamStatus, this.teamMap, roleId, this.teamDisTimer, this.app); + let channelService = this.app.get('channelService'); + let channel = channelService.getChannel(teamCode, false); + let result = await dismissTeam(teamStatus, this.teamMap, roleId, this.teamDisTimer, channel); return result; } diff --git a/game-server/app/services/comBattleService.ts b/game-server/app/services/comBattleService.ts index f476b5b1d..713c95861 100644 --- a/game-server/app/services/comBattleService.ts +++ b/game-server/app/services/comBattleService.ts @@ -8,7 +8,7 @@ import { EquipPrintDropType, EquipPrintDropModel } from './../db/EquipPrintDrop' import { FriendPointModel } from './../db/FriendPoint'; import { STATUS } from './../consts/statusCode'; import { COM_TEAM_STATUS, CURRENCY_BY_TYPE, CURRENCY_TYPE, FRIEND_DROP_TYPE, COM_BTL_CONST, FRIEND_DROP_MAX } from './../consts'; -import { RoleStatus, ComBattleTeamModel } from './../db/ComBattleTeam'; +import { RoleStatus, ComBattleTeamModel, ComBattleTeamType } from './../db/ComBattleTeam'; import { getBluePrtByQuality, getComBtlSetByQuality, getRewardByBlueprtId, getWarById, getWarIdByBlueprtId, comBtlRangeInfo, getGoodById, comBtlRangeByLv, getBossHpByBlueprtId } from "../pubUtils/gamedata"; import { getRandEelm, getRandValue, resResult, ratioReward, getRandValueByMinMax, getRandomWithWeight, decodeStr, getRobotInfo, reduceCe } from "../pubUtils/util"; import { getRandRobot, transBossHpArr } from "./battleService"; @@ -346,7 +346,7 @@ export function comBtlLvInvalid(lv: number, lvRange: number) { return lv < minLv; } -export async function dismissTeam(teamStatus, teamMap: Map, roleId: string, teamDisTimer: Map, app) { +export async function dismissTeam(teamStatus, teamMap: Map, roleId: string, teamDisTimer: Map, channel) { const { teamCode } = teamStatus; if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); @@ -358,19 +358,17 @@ export async function dismissTeam(teamStatus, teamMap: Map, roleId: let rmSt = teamMap.delete(teamCode); if (!rmSt) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); - let channelService = app.get('channelService'); - let channel = channelService.getChannel(teamCode, false); channel.pushMessage('onTeamDismiss', resResult(STATUS.SUCCESS, {teamCode})); channel.destroy(); clearComBtlTimer(teamCode, teamDisTimer); // 队伍解散停止解散计时 return resResult(STATUS.SUCCESS); } -export function setDismissTimer(teamStatus, teamMap: Map, roleId: string, teamDisTimer: Map, app) { - if (teamStatus && teamStatus.roleIds && teamStatus.roleIds.length === 3 && teamStatus.status === COM_TEAM_STATUS.DEFAULT) { +export function setDismissTimer(teamStatus, teamMap: Map, roleId: string, teamDisTimer: Map, channel) { + if (teamIsFullToStart(teamStatus)) { clearComBtlTimer(teamStatus.teamCode, teamDisTimer); let timer = setTimeout(async () => { - await dismissTeam(teamStatus, teamMap, roleId, teamDisTimer, app); + await dismissTeam(teamStatus, teamMap, roleId, teamDisTimer, channel); }, COM_BTL_CONST.CAP_START_TIME); teamDisTimer.set(teamStatus.teamCode, timer); } @@ -575,7 +573,7 @@ export async function hasEnoughBlueprt(roleId: string, blueprtId: number) { * @param {boolean} isCap * @param {boolean} isFrd */ -export async function addRoleToTeam(comTeam: MemComBtlTeam, roleInfo: RoleType, isCap: boolean, isFrd: boolean) { +export function addRoleToTeam(comTeam: MemComBtlTeam, roleInfo: RoleType, isCap: boolean, isFrd: boolean) { const { roleId, roleName, headHid = 19, sHid = 19, lv } = roleInfo; let { topFiveCe = 1000 } = roleInfo; topFiveCe = reduceCe(topFiveCe); @@ -617,4 +615,94 @@ export async function addValidSearchingRoles(comTeam: MemComBtlTeam, channelServ } channelService.pushMessageByUids('onTeamJoin', resResult(STATUS.SUCCESS, {teamInfo: comTeam}), teammates.map(t => {return {uid: t.roleId, sid: t.sid}})); } -} \ No newline at end of file +} + +/** + * @description 判断队伍是否处于可加入状态 + * @export + * @param {MemComBtlTeam} comTeam + * @param {string} [roleId=''] 要加入的玩家 id + * @returns + */ +export function validToJoin(comTeam: MemComBtlTeam, roleId = '') { + return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length < 3 && comTeam.roleIds.indexOf(roleId) === -1; +} + +/** + * @description 判断队伍是否处于可满员状态 + * @export + * @param {MemComBtlTeam} comTeam + * @returns + */ +export function teamIsFullToStart(comTeam: MemComBtlTeam) { + return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length === 3; +} + +/** + * @description 添加指定数量的机器人到队伍 + * @export + * @param {MemComBtlTeam} comTeam + * @param {number} roleCe 真实玩家战力,用来做机器人战力基准 + * @param {number} roleLv 真实玩家等级,用来做机器人等级基准 + * @param {number} [count=1] + */ +export async function addRobotsToTeam(comTeam: MemComBtlTeam, roleId: string, roleCe: number, roleLv: number, teamMap: Map, teamDisTimer: Map, channel: Channel, count = 1) { + const { teamCode } = comTeam; + const { robotStArr, robotIdArr } = getRandComBtlRobots(roleCe, comTeam.ceLimit, roleLv, count); + comTeam.roleIds = comTeam.roleIds.concat(robotIdArr); + comTeam.roleStatus = comTeam.roleStatus.concat(robotStArr); + for (let st of robotStArr) { + addRoleStToTeam(comTeam, st); + await ComBattleTeamModel.addRole(teamCode, st); + } + channel.pushMessage('onTeamJoin', resResult(STATUS.SUCCESS, {teamInfo: comTeam})); + setDismissTimer(comTeam, teamMap, roleId, teamDisTimer, channel); +} + +/** + * @description 在不同的时间加入机器人 + * @export + * @param {MemComBtlTeam} comTeam + * @param {RoleType} roleInfo + * @param {Map} teamMap + * @param {Map} teamDisTimer + * @param {Channel} channel + */ +export async function addRobotsLater(comTeam: MemComBtlTeam, roleInfo: RoleType, teamMap: Map, teamDisTimer: Map, channel: Channel) { + const teamStatus = comTeam; + const { teamCode } = teamStatus; + const { roleId, lv } = roleInfo; + let { topFiveCe = 1000 } = roleInfo; + topFiveCe = reduceCe(topFiveCe); + + if (validToJoin(teamStatus)) { + const robotCnt = 3 - teamStatus.roleIds.length; + for(let robotIdx = 0; robotIdx < robotCnt; robotIdx++) { + const joinTime = getRandValueByMinMax(COM_BTL_CONST.MIN_CAP_TIME, COM_BTL_CONST.MAX_CAP_TIME, 0); + setTimeout(async () => { + const curTeamStatus = teamMap.get(teamCode); + if (validToJoin(curTeamStatus)) { + await addRobotsToTeam(curTeamStatus, roleId, topFiveCe, lv, teamMap, teamDisTimer, channel, 1); + } + }, joinTime); + } + } +} + +/** + * @description 从数组里找出第一个不在黑名单的队伍 + * @export + * @param {Array} teams 队伍数组 + * @param {string} roleId 要加入的玩家 id + * @returns + */ +export async function oneTeamNotInBlack(teams: Array, roleId: string) { + for(let team of teams) { + let { roleIds } = team; + const inBlackList = await teammateInBlackList(roleId, roleIds); + if(!inBlackList) { + return team; + } + } + return null; +} diff --git a/shared/db/ComBattleTeam.ts b/shared/db/ComBattleTeam.ts index 058614cb1..c1a2611b3 100644 --- a/shared/db/ComBattleTeam.ts +++ b/shared/db/ComBattleTeam.ts @@ -150,7 +150,7 @@ export default class ComBattleTeam extends BaseModel { } public static async addRole(teamCode: string, roleStatus: RoleStatus, lean = true) { - const team: ComBattleTeamType = await ComBattleTeamModel.findOneAndUpdate({ teamCode }, {$push: {roleIds: roleStatus.roleId, roleStatus}, $inc: {roleCnt: 1}}, {new: true}).lean(lean); + const team: ComBattleTeamType = await ComBattleTeamModel.findOneAndUpdate({ teamCode, roleCnt: { $lte: 2 } }, {$push: {roleIds: roleStatus.roleId, roleStatus}, $inc: {roleCnt: 1}}, {new: true}).lean(lean); return team; }