/* * @Author: 梁桐川 * @Date: 2020-11-30 15:05:48 * @Last Modified by: 梁桐川 * @Last Modified time: 2020-11-30 18:08:49 */ 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_ENABLE_LV } from '../../../consts/consts'; import { ComBattleTeamModel } from '../../../db/ComBattleTeam'; import Role, { RoleModel } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; import { Application, BackendSession } from 'pinus'; import { resResult, getRandomByLen, calculateNum, getRandValue } from '../../../pubUtils/util'; 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'; export default function(app: Application) { return new ComBattleHandler(app); } class ComTeam { // 队伍唯一编号 teamCode: string; // 玩家列表 roleIds: Array // 队伍是否开放加入 pub: boolean; // 对应藏宝图 Id blueprtId: number; // 战斗状态 0:未开始,1:已开始,2:胜利,3:失败 status: number; // 玩家状态 roleStatus: Array; // 队长 roleId capId: string; // 战力限制 ceLimit: number; // boss 总血量 bossHp: number; // boss 当前血量 bossCurHp: number; // 单个 boss 血量状态 bossHpArr: Array<{dataId: number, hp: number, curHp: number}>; // 品质 quality: number; // 当前回合 curRnd: number; constructor(teamCode: string, pub: boolean, blueprtId: number, status: number, capId: string, ceLimit: number, bossHp: number, quality: number, bossHpArr:Array<{dataId: number, hp: number, curHp: number}> ) { this.teamCode = teamCode; this.pub = pub; this.blueprtId = blueprtId; this.status = status; this.capId = capId; this.ceLimit = ceLimit; this.bossHp = bossHp; this.bossCurHp = bossHp; this.quality = quality; this.bossHpArr = bossHpArr; this.curRnd = 0; } } export class ComBattleHandler { constructor(private app: Application) { } private teamMap: Map = new Map(); /** * @description 队长创建队伍 * @param {{blueprtId: number, pub: boolean, ceLimit: number}} msg 藏宝图Id,是否公开,战力限制 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ 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, pub, ceLimit } = msg; console.log('createTeam msg: ', msg); // 检查藏宝图Id是否合法 let goodData = getGoodById(blueprtId); if (!goodData || goodData.itid !== IT_TYPE.BLUEPRT) return resResult(STATUS.COM_BATTLE_BLUEPRT_INVALID); // 检查藏宝图是否足够 let { lv, headHid = 19, topFiveCe, sHid = 19 } = await RoleModel.findByRoleId(roleId); if (lv < COM_TEAM_ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); let blueprt = await ItemModel.findbyRoleAndGidAndCount(roleId, blueprtId, 1); if (!blueprt) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_FOUND); // 检查是否有已创建未结束的寻宝,预先占用一张藏宝图 let teams = await ComBattleTeamModel.getTeamByCapAndStatus(roleId, COM_TEAM_STATUS.FIGHTING); if (teams && blueprt.count <= teams.length) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); let roleStatus = []; let roleIds = []; 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) { 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); roleIds.push(roleInfo.roleId); } } let { bossHpSum, bossHpArr } = getBossHpByBlueprtId(blueprtId); // 创建队伍数据结构 let comTeam = new ComTeam(teamCode, pub, blueprtId, COM_TEAM_STATUS.DEFAULT, roleId, ceLimit, bossHpSum || 10000, goodData.quality, transBossHpArr(bossHpArr)); comTeam.roleStatus = roleStatus; comTeam.roleIds = roleIds; this.teamMap.set(teamCode, comTeam); // TODO: 处理助战回滚 const team = await ComBattleTeamModel.createTeam(comTeam); if (!team) return resResult(STATUS.COM_BATTLE_CREATE_ERR); let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, true); let users = channel.getMembers(); for (let roleId of roleIds) { if (users.indexOf(roleId) === -1) { channel.add(roleId, sid); } } 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); } return resResult(STATUS.SUCCESS, { teamCode, roleStatus }); } /** * @description 匹配队伍 * @param {{qualityArr: [number]}} msg 要匹配的品质数组列表 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async searchTeam(msg: {qualityArr: [number]}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); const { qualityArr } = msg; let { lv, headHid = 19, topFiveCe = 1000, sHid = 19 } = await RoleModel.findByRoleId(roleId); const team = await ComBattleTeamModel.getOneTeamByQualityAndSt(qualityArr, COM_TEAM_STATUS.DEFAULT, topFiveCe); // 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 roleInfo = new RoleStatus(roleId, roleName, false, false, headHid, sHid, topFiveCe, lv); roleStatus.push(roleInfo); roleIds.push(roleId); let blueprtId = (await 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)); // 创建并添加机器人 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); } 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', {teamInfo: comTeam}, [{uid: roleId, sid}]); let channel = channelService.getChannel(teamCode, true); let users = channel.getMembers(); if (users.indexOf(roleId) === -1) { channel.add(roleId, sid); } }, COM_BATTLE_ASSIST_TIME); return resResult(STATUS.SUCCESS); } /** * @description 当匹配 searchTeam 匹配到其它队伍时,需要调用此接口加入 * @param {{teamCode: string, isFrd: boolean}} msg 要加入的队伍编号,是否情谊助战 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async joinTeam(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); console.log('teamMap:' + JSON.stringify(this.teamMap)); let { teamCode, isFrd } = msg; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || teamStatus.status !== 0 || teamStatus.roleIds.length === 3) 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); let { quality } = getGoodById(teamStatus.blueprtId); let { assistanceLevel, assistanceTime } = getComBtlSetByQuality(quality); if (lv < COM_TEAM_ENABLE_LV) { return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); } else if (lv < assistanceLevel) { return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); } else if (topFiveCe < teamStatus.ceLimit) { 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); 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); teamStatus.roleStatus.push(roleStatus); channel.pushMessage('onTeamJoin', {teamInfo: teamStatus}); let users = channel.getMembers(); if (users.indexOf(roleId) === -1) { channel.add(roleId, sid); } 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); if (lv < COM_TEAM_ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); const teams = await ComBattleTeamModel.getTeamByBlueprt(msg.blueprtIds, COM_TEAM_STATUS.DEFAULT, true); if (!teams) return resResult(STATUS.COM_BATTLE_NO_VALID_TEAM); return resResult(STATUS.SUCCESS, { teamInfos: teams}); } /** * @description 获取今日已助战次数 * @param {{}} msg * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ 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); let cnt = [0, 0, 0, 0, 0]; teams.forEach(team => { if (team && team.quality) { cnt[team.quality - 1] += 1; } }); return resResult(STATUS.SUCCESS, {cnt}); } /** * @description 队伍准备-deprecate * @param {{teamCode: string, heroes: Array}} msg * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async teammateReady(msg: {teamCode: string, heroes: Array}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, heroes } = msg; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); let team = await ComBattleTeamModel.updateHeroes(teamCode, roleId, heroes); if (!team) return resResult(STATUS.COM_BATTLE_UPDATE_HEROES_ERR); teamStatus.roleStatus.forEach(st => { if (st && st.roleId === roleId) { st.heroes = heroes; } }); let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); channel.pushMessage('onTeammateReady', {teamCode, roleId, heroes}); return resResult(STATUS.SUCCESS); } /** * @description 出兵时记录玩家阵容 * @param {{teamCode: string, heroes: Array}} msg 队伍编号;阵容 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async setupHeroes(msg: {teamCode: string, heroes: Array}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, heroes } = msg; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); let team = await ComBattleTeamModel.updateHeroes(teamCode, roleId, heroes); if (!team) return resResult(STATUS.COM_BATTLE_UPDATE_HEROES_ERR); teamStatus.roleStatus.forEach(st => { if (st && st.roleId === roleId) { st.heroes = heroes; } }); let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); channel.pushMessage('onTeammateReady', {teamCode, roleId, heroes}); return resResult(STATUS.SUCCESS); } /** * @description 从队伍中移除玩家 * @param {{teamCode: string, roleIdToRm: string}} msg 队伍编号;要移除的玩家 Id * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ 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) return resResult(STATUS.COM_BATTLE_CAP_ONLY); // 只有队长可以移除玩家 // 移除操作 let team = await ComBattleTeamModel.removeRole(teamCode, roleIdToRm); if (!team) return resResult(STATUS.COM_BATTLE_RM_TEAMMATE_ERR); let roleIdx = teamStatus.roleIds.indexOf(roleIdToRm); teamStatus.roleIds.splice(roleIdx, 1); teamStatus.roleStatus.some((elem, idx) => { if (elem.roleId === roleIdToRm) { teamStatus.roleStatus.splice(idx, 1); } }); // 推送移除消息 let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); let users = channel.getMembers(); if (users.indexOf(roleIdToRm) !== -1) { channel.removeMember(roleIdToRm); } channel.pushMessage('onLeaveTeam', {teamCode, roleId: roleIdToRm}); return resResult(STATUS.SUCCESS); } /** * @description 队长解散队伍 * @param {{teamCode: string}} msg 要解散的队伍编号 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async dismiss(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 (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); let team = await ComBattleTeamModel.removeTeam(teamCode); if (!team) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); let rmSt = this.teamMap.delete(teamCode); if (!rmSt) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); channel.pushMessage('onTeamDismiss', {teamCode}); channel.destroy(); return resResult(STATUS.SUCCESS); } /** * @description 开始战斗,队长操作或机器人队伍操作 * @param {{teamCode: string}} msg 队伍编号 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ 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 && 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); } /** * @description 战场中的状态同步,战斗结果判定 * @param {{teamCode: string, bossHurts: Array<{dataId: number, hurtHp: number}>, killed: Array, curRnd: number}} msg 队伍编号;boss 承伤;武将阵亡;当前回合 * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async action(msg: {teamCode: string, bossHurts: Array<{dataId: number, hurtHp: number}>, killed: Array, curRnd: number}, session: BackendSession) { let roleId = session.get('roleId'); let { teamCode, killed, bossHurts, curRnd } = 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.status !== COM_TEAM_STATUS.FIGHTING) return resResult(STATUS.COM_BATTLE_NOT_START); // 重置总血量,计算真实伤害 let totalHurtHp = 0; teamStatus.bossHpArr.forEach(boss => { for (let bh of bossHurts) { if (boss.dataId === bh.dataId && bh.hurtHp < 0) { let deltaHp = Math.abs(bh.hurtHp); if (boss.curHp >= deltaHp) { totalHurtHp += deltaHp; boss.curHp -= deltaHp; } else { totalHurtHp += deltaHp; boss.curHp = 0; } } } }); // 更新玩家武将阵亡情况,计算玩家总伤害,计算机器人造成的伤害 teamStatus.roleStatus.forEach(roleSt => { if (roleSt.roleId === roleId) { if (killed && killed.length) { killed.forEach(killedHid => { if (roleSt.killed.indexOf(killedHid) === -1) { roleSt.killed.push(killedHid); } }); } roleSt.totalDmg += totalHurtHp; } else if (curRnd > teamStatus.curRnd && curRnd <= COM_BATTLE_ROBOT_ROUND_LMT && roleSt.isRobot) { // 机器人的伤害为:boss 血量的一定比例,平均到一定回合数内,再平均到每个敌军,上下浮动一定比例 let eachHurtHp = getRandValue(teamStatus.bossHp / COM_BATTLE_ROBOT_ROUND_LMT * COM_BATTLE_ROBOT_HURT_RATIO / 5, COM_BATTLE_ROBOT_HURT_CH_RATIO, 0); let robotTotalHurt = 0; teamStatus.bossHpArr.forEach(boss => { if (boss.curHp >= eachHurtHp) { robotTotalHurt += eachHurtHp; boss.curHp -= eachHurtHp; } else { // 丢弃溢出的伤害 robotTotalHurt += boss.curHp; boss.curHp = 0; } }); teamStatus.bossCurHp -= robotTotalHurt; roleSt.totalDmg += robotTotalHurt; // 输出回合一到机器人武将集体阵亡 if (curRnd === COM_BATTLE_ROBOT_ROUND_LMT) { roleSt.killed === roleSt.heroes; } } }); 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; let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, false); if (isSuccess && teamStatus.bossCurHp <= 0) { 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); if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); if (team.status === COM_TEAM_STATUS.LOOSE) { channel.pushMessage('onTeamComplete', {teamCode, result: isSuccess}); } else { channel.pushMessage('onTeammateAct', {teamCode, bossCurHp: teamStatus.bossCurHp, roleStatus: {roleId, battleStatus: 2}}); } } return resResult(STATUS.SUCCESS, { bossCurHp: teamStatus.bossCurHp }); } /** * @description 获取自己一段时间内的寻宝记录 * @param {{}} msg * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ 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)); if (!teams) return resResult(STATUS.COM_BATTLE_NO_RECENT_REC); return resResult(STATUS.SUCCESS, {teamInfos: teams}); } /** * @description 藏宝图合成 * @param {{original: Array<{id: number, count: number}>}} msg * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async composeBlueprt(msg: {original: Array<{id: number, count: number}>}, session: BackendSession) { const roleId = session.get('roleId'); const roleName = session.get('roleName'); const { original } = msg; // 原材料检查 let originalQuality: number, originalSum: number = 0; for(let {id, count} of original) { const goodInfo = getGoodById(id); if(!originalQuality) originalQuality = goodInfo.quality; if(originalQuality != goodInfo.quality) { return resResult(STATUS.COM_BLUEPRT_QUALITY_ERROR); } if(goodInfo.itid == IT_TYPE.BLUEPRT) { originalSum += count; } } const dicCompose = getBlueprtComposeByQuality(originalQuality); if(!dicCompose) { return resResult(STATUS.COM_BLUEPRT_QUALITY_CANNOT_COMPOSE); } if(originalSum != dicCompose.blueprtNum) { return resResult(STATUS.COM_BLUEPRT_COUNT_ERROR); } // 检查元宝 const role = await RoleModel.findByRoleId(roleId); const costGold = calculateNum(GOLD_COST_RATIO.BLUEPRT_COMPOSE_COST, {num: originalQuality}, 1000); if(!role || role.gold < costGold) { return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); } // 添加寻宝币 original.push({ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.TREASURE_POINT), count: dicCompose.coinNum }); // 消耗藏宝图和寻宝币 const rec = await ItemModel.decreaseItems(roleId, original); if(!rec) { return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); } // 消耗元宝 await RoleModel.costGold(roleId, costGold); const targetList = getBluePrtByQuality(dicCompose.targetQuality); const target = getRandomByLen(targetList); const reward = [{gid: target, count: 1}]; const goods = await handleReward(roleId, roleName, reward); return resResult(STATUS.SUCCESS, { ...goods, costGold }); } }