From 1ce535669bf4a0673dc3335ee512d65ca4cdb329 Mon Sep 17 00:00:00 2001 From: liangtongchuan Date: Sun, 29 Nov 2020 00:52:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BB=E5=AE=9D=E6=88=98=E6=96=97=E7=BB=93?= =?UTF-8?q?=E6=9D=9F=E5=88=A4=E6=96=AD=EF=BC=9B=E5=AF=BB=E5=AE=9D=E6=88=98?= =?UTF-8?q?=E6=96=97=E7=BB=93=E6=9D=9F=E4=BF=9D=E5=AD=98=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../battle/handler/comBattleHandler.ts | 141 ++++++++++++++++-- shared/consts/statusCode.ts | 1 + shared/db/ComBattleTeam.ts | 10 ++ 3 files changed, 141 insertions(+), 11 deletions(-) diff --git a/game-server/app/servers/battle/handler/comBattleHandler.ts b/game-server/app/servers/battle/handler/comBattleHandler.ts index 7961e657c..21d792078 100644 --- a/game-server/app/servers/battle/handler/comBattleHandler.ts +++ b/game-server/app/servers/battle/handler/comBattleHandler.ts @@ -1,7 +1,7 @@ -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 } from './../../../consts/consts'; +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 { getGoodById, getBossHpByBlueprtId, getComBtlSetByQuality, getBlueprtComposeByQuality, getBluePrtByQuality } from '../../../pubUtils/gamedata'; -import { COM_TEAM_STATUS, COM_TEAM_ENABLE_LV } from '../../../consts/consts'; +import { COM_TEAM_ENABLE_LV } from '../../../consts/consts'; import { ComBattleTeamModel } from '../../../db/ComBattleTeam'; import Role, { RoleModel } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; @@ -65,12 +65,17 @@ export class ComBattleHandler { } private teamMap: Map = new Map(); - async createTeam(msg: {blueprtId: number, heroes: [ number ], pub: boolean, ceLimit: number}, session: BackendSession) { + /** + * 队长创建队伍 + * @param msg 藏宝图Id,是否公开,战力限制 + * @param session + */ + async createTeam(msg: {blueprtId: number, pub: boolean, ceLimit: number}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); let teamCode = session.get('teamCode'); - const { blueprtId, heroes, pub, ceLimit } = msg; + const { blueprtId, pub, ceLimit } = msg; console.log('createTeam msg: ', msg); // 检查藏宝图Id是否合法 @@ -92,14 +97,16 @@ export class ComBattleHandler { roleIds.push(roleId); let capStatus = new RoleStatus(roleId, roleName, true, false, headHid, sHid, topFiveCe, lv); roleStatus.push(capStatus); + + // 检查是否有正在匹配的符合要求的玩家 let teammates = await getTeamSearchByQuality(goodData.quality); console.log('teammates: ', teammates); if (teammates) { for (let teammate of teammates) { - // TODO: 要判断战力 let roleInfo = await RoleModel.findByRoleId(teammate.roleId); if (!roleInfo || roleIds.indexOf(teammate.roleId) !== -1) continue; let {roleId, roleName, headHid = 19, sHid = 19, topFiveCe, lv} = roleInfo; + if (topFiveCe < ceLimit) continue; // TODO: 没处理情谊助战 const st = new RoleStatus(roleId, roleName, false, false, headHid, sHid, topFiveCe, lv); roleStatus.push(st); @@ -140,6 +147,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS, { teamCode, roleStatus }); } + /** + * 匹配队伍 + * @param msg 要匹配的品质数组列表 + * @param session + */ async searchTeam(msg: {qualityArr: [number]}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); @@ -148,17 +160,18 @@ export class ComBattleHandler { let { lv, headHid = 19, topFiveCe = 1000, sHid = 19 } = await RoleModel.findByRoleId(roleId); const team = await ComBattleTeamModel.getOneTeamByQualityAndSt(qualityArr, COM_TEAM_STATUS.DEFAULT, topFiveCe); - // TODO: 有匹配的队伍还需要重新触发加入 + // TODO: 有匹配的队伍还需要重新 joinTeam 加入,有失败可能,体验不好,需优化 if (team) { return resResult(STATUS.SUCCESS, {teamCode: team.teamCode}); } let teamCode = session.get('teamCode'); await setTeamSearchReq(roleId, sid, qualityArr); let thiz = this; + // 倒计时匹配两个机器人 setTimeout(async () => { let roleStatus = []; let roleIds = [] - let robotHeroes = getRandRobot(2); + let robotHeroes = getRandRobot(2); // 随机两个阵容 let roleInfo = new RoleStatus(roleId, roleName, false, false, headHid, sHid, topFiveCe, lv); roleStatus.push(roleInfo); roleIds.push(roleId); @@ -166,6 +179,7 @@ export class ComBattleHandler { 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)); + // 创建并添加机器人 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); @@ -181,6 +195,7 @@ export class ComBattleHandler { const team = await ComBattleTeamModel.createTeam(comTeam); // if (!team) channelService.pushMessageByUids('onTeamJoin', {teamInfo: null}, [{uid: roleId, sid}]); thiz.teamMap.set(teamCode, comTeam); + // 推送组队消息 channelService.pushMessageByUids('onTeamJoin', {teamInfo: comTeam}, [{uid: roleId, sid}]); let channel = channelService.getChannel(teamCode, true); let users = channel.getMembers(); @@ -191,6 +206,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS); } + /** + * 当匹配 searchTeam 匹配到其它队伍时,需要调用此接口加入 + * @param msg 要加入的队伍编号,是否情谊助战 + * @param session + */ async joinTeam(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); @@ -214,12 +234,14 @@ export class ComBattleHandler { 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) { return resResult(STATUS.COM_BATTLE_JOIN_ERR); } + // 推送加入信息给其他玩家 let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); teamStatus.roleIds.push(roleId); @@ -233,6 +255,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS, { teamInfo: teamStatus}); } + /** + * 获取队伍列表-deprecated + * @param msg + * @param session + */ async getTeams(msg: { blueprtIds: Array }, session: BackendSession) { let roleId = session.get('roleId'); let { lv } = await Role.findByRoleId(roleId); @@ -242,6 +269,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS, { teamInfos: teams}); } + /** + * 获取今日已助战次数 + * @param msg + * @param session + */ async getAssistCnt(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, null, new Date(new Date().setHours(0, 0, 0, 0)), true); @@ -254,6 +286,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS, {cnt}); } + /** + * 队伍准备-deprecated + * @param msg + * @param session + */ async teammateReady(msg: {teamCode: string, heroes: Array}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, heroes } = msg; @@ -275,6 +312,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS); } + /** + * 出兵时记录玩家阵容 + * @param msg 队伍编号;阵容 + * @param session + */ async setupHeroes(msg: {teamCode: string, heroes: Array}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, heroes } = msg; @@ -296,14 +338,21 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS); } + /** + * 从队伍中移除玩家 + * @param msg 队伍编号;要移除的玩家 Id + * @param session + */ async rmTeammate(msg: {teamCode: string, roleIdToRm: string}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, roleIdToRm } = msg; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (roleId === teamStatus.capId && roleId === roleIdToRm) return resResult(STATUS.COM_BATTLE_RM_SELF); - if (roleId !== teamStatus.capId && roleId !== roleIdToRm) return resResult(STATUS.COM_BATTLE_CAN_NOT_RM); + if (roleId === teamStatus.capId && roleId === roleIdToRm) return resResult(STATUS.COM_BATTLE_RM_SELF); // 队长移除自己视为解散,提示确认 + // if (roleId !== teamStatus.capId && roleId !== roleIdToRm) return resResult(STATUS.COM_BATTLE_CAN_NOT_RM); + if (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); // 只有队长可以移除玩家 + // 移除操作 let team = await ComBattleTeamModel.removeRole(teamCode, roleIdToRm); if (!team) return resResult(STATUS.COM_BATTLE_RM_TEAMMATE_ERR); @@ -316,6 +365,7 @@ export class ComBattleHandler { } }); + // 推送移除消息 let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); let users = channel.getMembers(); @@ -326,6 +376,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS); } + /** + * 队长解散队伍 + * @param msg 要解散的队伍编号 + * @param session + */ async dismiss(msg: {teamCode: string}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode } = msg; @@ -347,22 +402,35 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS); } + /** + * 开始战斗,队长操作或机器人队伍操作 + * @param msg 队伍编号 + * @param session + */ async startBattle(msg: {teamCode: string}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode } = msg; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (teamStatus.capId !== roleId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); + if (teamStatus.capId !== roleId && teamStatus.capId !== 'robot') return resResult(STATUS.COM_BATTLE_CAP_ONLY); if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_ALREADY_START); teamStatus.status = COM_TEAM_STATUS.FIGHTING; + let team = await ComBattleTeamModel.updateStatus(teamCode, COM_TEAM_STATUS.FIGHTING); + if (!team) return resResult(STATUS.COM_BATTLE_START_ERR); + let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); channel.pushMessage('onComBtlStart', {teamCode, roleStatus: teamStatus.roleStatus}); return resResult(STATUS.SUCCESS); } + /** + * 战场中的状态同步,推送信息包括玩家总伤害、玩家武将阵亡情况、boss 血量 + * @param msg 队伍编号;武将伤害;boss 承伤;武将阵亡;当前回合 + * @param session + */ async action(msg: {teamCode: string, heroes: Array<{hid: number, hurtHp: number}>, bossHurts: Array<{dataId: number, hurtHp: number}>, killed: Array, curRnd: number}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, heroes, killed, bossHurts, curRnd } = msg; @@ -370,6 +438,7 @@ export class ComBattleHandler { if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); if (teamStatus.status !== COM_TEAM_STATUS.FIGHTING) return resResult(STATUS.COM_BATTLE_NOT_START); + // 仅做武将伤害和 boss 承伤的校验,不处理溢出 let totalHurtHp = 0; let totalBossHurt = 0; if (heroes && heroes.length) { @@ -386,7 +455,7 @@ export class ComBattleHandler { } }); } - if (totalHurtHp !== totalBossHurt) return resResult(STATUS.COM_BATTLE_HURT_NUM_ERR); // 仅做校验,不处理溢出 + if (totalHurtHp !== totalBossHurt) return resResult(STATUS.COM_BATTLE_HURT_NUM_ERR); // 重置总血量,计算真实伤害 totalHurtHp = 0, totalBossHurt = 0; @@ -403,6 +472,7 @@ export class ComBattleHandler { } }) }); + // 更新玩家武将阵亡情况,计算玩家总伤害,计算机器人造成的伤害 teamStatus.roleStatus.forEach(roleSt => { if (roleSt.roleId === roleId) { if (killed && killed.length) { @@ -436,13 +506,57 @@ export class ComBattleHandler { }); teamStatus.curRnd = curRnd; teamStatus.bossCurHp -= totalHurtHp; + if (teamStatus.bossCurHp < 0) teamStatus.bossCurHp = 0; + // 推送本次行动情况 let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); 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}); + 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}); + } + } + } return resResult(STATUS.SUCCESS); } + /** + * 客户端给服务器的战斗结束通知-deprecated + * @param msg + * @param session + */ async battleEnd(msg: {teamCode: string, isSuccess: boolean}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, isSuccess } = msg; @@ -469,6 +583,11 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS, { bossCurHp: teamStatus.bossCurHp }); } + /** + * 获取自己一段时间内的寻宝记录 + * @param msg + * @param session + */ async getTeamRec(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, null, new Date(new Date().setHours(0, 0, 0, 0) - 2 * 24 * 60 * 60 * 1000)); diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index b0b1c5ffe..1e7ee97b6 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -97,6 +97,7 @@ export const STATUS = { COM_BATTLE_DISSMISS_ERR: { code: 20623, simStr: '解散队伍异常' }, COM_BATTLE_NO_RECENT_REC: { code: 20624, simStr: '没有最近的寻宝记录' }, COM_BATTLE_HURT_NUM_ERR: { code: 20625, simStr: '血量计算错误' }, + COM_BATTLE_START_ERR: { code: 20626, simStr: '开始战斗失败' }, // 共斗藏宝图合成 COM_BLUEPRT_QUALITY_CANNOT_COMPOSE: { code: 20630, simStr: '该品质藏宝图不可合成' }, diff --git a/shared/db/ComBattleTeam.ts b/shared/db/ComBattleTeam.ts index 7dfa2a81a..a9f65e7bc 100644 --- a/shared/db/ComBattleTeam.ts +++ b/shared/db/ComBattleTeam.ts @@ -121,6 +121,16 @@ export default class ComBattleTeam extends BaseModel { return team; } + public static async syncTeamData(teamData: {teamCode: string, status: number, roleStatus: Array}, lean = true) { + const team = await ComBattleTeamModel.findOneAndUpdate({ teamCode: teamData.teamCode }, {$set :{...teamData}}, {new: true}).lean(lean); + return team; + } + + public static async updateStatus(teamCode: string, status: number, lean = true) { + const team = await ComBattleTeamModel.findOneAndUpdate({ teamCode: teamCode }, {status}, {new: true}).lean(lean); + return team; + } + public static async updateResult(teamCode: string, roleId: string, isSuccess: boolean, _lean = true) { let team = await ComBattleTeamModel.findOne({teamCode}).select('status roleStatus'); if(!team) return;