diff --git a/game-server/app/servers/battle/handler/comBattleHandler.ts b/game-server/app/servers/battle/handler/comBattleHandler.ts index 08c0bcb63..754f02039 100644 --- a/game-server/app/servers/battle/handler/comBattleHandler.ts +++ b/game-server/app/servers/battle/handler/comBattleHandler.ts @@ -29,11 +29,12 @@ class ComTeam { capId: string; // 战力限制 ceLimit: number; + // boss 血量 + bossHp: number; } export class ComBattleHandler { constructor(private app: Application) { } - private bossHp: number = 10000; private teamMap: Map = new Map(); async createTeam(msg: {blueprtId: number, heroes: [ number ], pub: boolean, ceLimit: number}, session: BackendSession) { @@ -55,7 +56,7 @@ export class ComBattleHandler { // 检查是否有已创建未结束的寻宝,预先占用一张藏宝图 let teams = await ComBattleTeamModel.findTeamByCapAndStatus(roleId, COM_TEAM_STATUS.FIGHTING); if (teams && blueprt.count <= teams.length) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); - //TODO: 检查武将是否拥有 + // TODO: 检查武将是否拥有 // 创建队伍数据结构 let comTeam = new ComTeam(); @@ -66,6 +67,8 @@ export class ComBattleHandler { comTeam.roleIds = [roleId]; comTeam.status = COM_TEAM_STATUS.DEFAULT; comTeam.ceLimit = ceLimit; + // TODO: boss 血量读表 + comTeam.bossHp = 10000; let roleStatus = new RoleStatus(); roleStatus.heroes = heroes; @@ -73,6 +76,8 @@ export class ComBattleHandler { roleStatus.headHid = headHid; roleStatus.topFiveCe = topFiveCe; roleStatus.roleId = roleId; + roleStatus.isReady = true; + roleStatus.totalDmg = 0; comTeam.roleStatus = [roleStatus]; this.teamMap.set(teamCode, comTeam); @@ -94,11 +99,10 @@ export class ComBattleHandler { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); - console.log('role in joinTeam: ', roleId, roleName, msg, this.app.rpc); console.log('teamMap:' + JSON.stringify(this.teamMap)); let { teamCode, isFrd } = msg; let teamStatus = this.teamMap.get(teamCode); - if (teamStatus.status !== 0 || teamStatus.roleIds.length === 3) return resResult(STATUS.COM_BATTLE_MEMBER_LIMIT); + 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); // TODO:助战等级限制,等表 let { lv, headHid, topFiveCe } = await Role.findByRoleId(roleId); @@ -115,6 +119,8 @@ export class ComBattleHandler { roleStatus.topFiveCe = topFiveCe || 0; roleStatus.roleId = roleId; roleStatus.isFrd = isFrd; + roleStatus.isReady = false; + roleStatus.totalDmg = 0; const team = await ComBattleTeamModel.addRole(teamCode, roleStatus); if (!team) { return resResult(STATUS.COM_BATTLE_CREATE_ERR); @@ -144,72 +150,180 @@ export class ComBattleHandler { return resResult(STATUS.SUCCESS, { teamInfos: teams}); } - async startBattle(msg: {}, session: BackendSession) { + async teammateReady(msg: {teamCode: string, heroes: Array}, session: BackendSession) { let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let teamCode = session.get('teamCode'); - console.log('role in startBattle: ', roleId, roleName, teamCode); + 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; + st.isReady = true; + } + }); let channelService = this.app.get('channelService'); - let channel = channelService.getChannel(teamCode, true); - let users = channel.getMembers(); - if (users.indexOf(roleId) === -1) { - channel.add(roleId, sid); - } - - users = channel.getMembers(); - channel.pushMessage('onAdd', {users}); - let tsid = channel.getMember(roleId)['sid']; - channelService.pushMessageByUids('bossHp', {data: 'datadata'}, [{ - uid: roleId, - sid: tsid - }]); - - return resResult(STATUS.SUCCESS, { users, teamCode }); + let channel = channelService.getChannel(teamCode, false); + channel.pushMessage('onTeammateReady', {teamCode, roleId, heroes}); + return resResult(STATUS.SUCCESS); } - /** - * Send messages to users - * - * @param {Object} msg message from client - * @param {Object} session - * - */ - async enterBattle(msg: {battleId: string , target: string}, session: BackendSession) { + async startBattle(msg: {teamCode: string}, session: BackendSession) { let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - console.log('role in enterBattle: ', roleId, roleName, msg, this.app.rpc); + 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.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_ALREADY_START); + + for (let roleSt of teamStatus.roleStatus) { + if (!roleSt.isReady) { + return resResult(STATUS.COM_BATTLE_TEAM_NO_READY); + } + } + teamStatus.status = COM_TEAM_STATUS.FIGHTING; let channelService = this.app.get('channelService'); - let channel = channelService.getChannel(msg.battleId, false); - let users = channel.getMembers(); - if (users.indexOf(roleId) === -1) { - channel.add(roleId, sid); - } else { - return resResult(STATUS.COM_BATTLE_DUP_ENTER); - } - channel.pushMessage('onAddBattle', {users}); - - return resResult(STATUS.SUCCESS, { users }); + let channel = channelService.getChannel(teamCode, false); + channel.pushMessage('onComBtlStart', {teamCode, roleStatus: teamStatus.roleStatus}); + return resResult(STATUS.SUCCESS); } - async hurtHp(msg: {battleId: string, bossHurt: number, actorHurt: [{ actorId: number, actorHurt: number}]}, session: BackendSession) { + async action(msg: {teamCode: string, heroes: Array<{hid: number, hurtHp: number}>, killed: Array}, session: BackendSession) { let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - console.log('role in enterBattle: ', roleId, roleName, msg); + let { teamCode, heroes, killed } = 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; + if (heroes && heroes.length) { + heroes.forEach(hero => { + if (hero.hurtHp > 0) { + totalHurtHp += hero.hurtHp; + } + }); + } + + let curRoleSt = null; + 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; + curRoleSt = roleSt; + teamStatus.bossHp -= totalHurtHp; + } + }); + let channelService = this.app.get('channelService'); + let channel = channelService.getChannel(teamCode, false); + channel.pushMessage('onTeammateAct', {teamCode, bossHp: teamStatus.bossHp, roleStatus: {roleId, totalDmg: curRoleSt.totalDmg, killed}}); + return resResult(STATUS.SUCCESS); + } + + 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(msg.battleId, false); - - this.bossHp -= msg.bossHurt; - if (this.bossHp < 0) { - this.bossHp = 0; - channel.pushMessage('bossHp', {data: 'boss 挂啦!!!!!'}, undefined); + let channel = channelService.getChannel(teamCode, false); + if (isSuccess && teamStatus.bossHp <= 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, bossHp: teamStatus.bossHp, roleStatus: {roleId, battleStatus: 2}}); + } } - channel.pushMessage('bossHp', {bossHp: this.bossHp}, undefined); - - return resResult(STATUS.SUCCESS, { bossHp: this.bossHp}); + return resResult(STATUS.SUCCESS, { bossHp: teamStatus.bossHp }); } + + + + // async startBattle(msg: {}, session: BackendSession) { + // let roleId = session.get('roleId'); + // let roleName = session.get('roleName'); + // let sid = session.get('sid'); + // let teamCode = session.get('teamCode'); + // console.log('role in startBattle: ', roleId, roleName, teamCode); + + // let channelService = this.app.get('channelService'); + // let channel = channelService.getChannel(teamCode, true); + // let users = channel.getMembers(); + // if (users.indexOf(roleId) === -1) { + // channel.add(roleId, sid); + // } + + // users = channel.getMembers(); + // channel.pushMessage('onAdd', {users}); + // let tsid = channel.getMember(roleId)['sid']; + // channelService.pushMessageByUids('bossHp', {data: 'datadata'}, [{ + // uid: roleId, + // sid: tsid + // }]); + + // return resResult(STATUS.SUCCESS, { users, teamCode }); + // } + + // /** + // * Send messages to users + // * + // * @param {Object} msg message from client + // * @param {Object} session + // * + // */ + // async enterBattle(msg: {battleId: string , target: string}, session: BackendSession) { + // let roleId = session.get('roleId'); + // let roleName = session.get('roleName'); + // let sid = session.get('sid'); + // console.log('role in enterBattle: ', roleId, roleName, msg, this.app.rpc); + + // let channelService = this.app.get('channelService'); + // let channel = channelService.getChannel(msg.battleId, false); + // let users = channel.getMembers(); + // if (users.indexOf(roleId) === -1) { + // channel.add(roleId, sid); + // } else { + // return resResult(STATUS.COM_BATTLE_DUP_ENTER); + // } + // channel.pushMessage('onAddBattle', {users}); + + // return resResult(STATUS.SUCCESS, { users }); + // } + + // async hurtHp(msg: {battleId: string, bossHurt: number, actorHurt: [{ actorId: number, actorHurt: number}]}, session: BackendSession) { + // let roleId = session.get('roleId'); + // let roleName = session.get('roleName'); + // console.log('role in enterBattle: ', roleId, roleName, msg); + + // let channelService = this.app.get('channelService'); + // let channel = channelService.getChannel(msg.battleId, false); + + // this.bossHp -= msg.bossHurt; + // if (this.bossHp < 0) { + // this.bossHp = 0; + // channel.pushMessage('bossHp', {data: 'boss 挂啦!!!!!'}, undefined); + // } + // channel.pushMessage('bossHp', {bossHp: this.bossHp}, undefined); + + // return resResult(STATUS.SUCCESS, { bossHp: this.bossHp}); + // } } diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 5c259d4ec..f1af1e3b8 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -80,6 +80,13 @@ export const STATUS = { COM_BATTLE_CE_LIMIT: { code: 20608, simStr: '战力不足' }, COM_BATTLE_JOIN_ERR: { code: 20609, simStr: '加入队伍失败' }, COM_BATTLE_NO_VALID_TEAM: { code: 20610, simStr: '没有合适的队伍' }, + COM_BATTLE_TEAM_INVALID: { code: 20611, simStr: '队伍异常' }, + COM_BATTLE_UPDATE_HEROES_ERR: { code: 20612, simStr: '更新阵容失败' }, + COM_BATTLE_CAP_ONLY: { code: 20613, simStr: '只有队长可以操作' }, + COM_BATTLE_TEAM_NO_READY: { code: 20614, simStr: '队友未准备好' }, + COM_BATTLE_RESULT_ERR: { code: 20615, simStr: '结算信息更新失败' }, + COM_BATTLE_NOT_START: { code: 20616, simStr: '寻宝未开始' }, + COM_BATTLE_ALREADY_START: { code: 20616, simStr: '寻宝已开始' }, // 秘境 20700 - 20799 DUNGEON_REFRESH_TIMES_LACK: { code: 20701, simStr: '购买次数不足' }, diff --git a/shared/db/ComBattleTeam.ts b/shared/db/ComBattleTeam.ts index 5f7329f71..e946f67d5 100644 --- a/shared/db/ComBattleTeam.ts +++ b/shared/db/ComBattleTeam.ts @@ -7,7 +7,7 @@ export class RoleStatus { @prop({ required: true }) isCap: boolean; @prop({ required: true, default: 0 }) - damageNum: number; + totalDmg: number; // 战斗状态 0-挑战中 1-挑战成功 2-挑战失败 @prop({ required: true, default: 0 }) battleStatus: number; @@ -29,6 +29,9 @@ export class RoleStatus { // 前五战力 @prop({ required: true, default: 0 }) topFiveCe: number; + // 是否准备 + @prop({ required: true, default: false }) + isReady: boolean; } @index({ teamCode: 1 }) @@ -51,7 +54,7 @@ export default class ComBattleTeam extends BaseModel { @prop({ required: true }) blueprtId: number; - // 战斗状态 0:未开始,1:已开始,2:胜利,3:失败 + // 战斗状态 0:未开始,1:已开始,2:胜利,3:失败,4:已领奖 @prop({ required: true, default: 0 }) status: number; @@ -76,6 +79,37 @@ export default class ComBattleTeam extends BaseModel { return team; } + public static async updateHeroes(teamCode: string, roleId: string, heroes: Array, lean = true) { + const team = await ComBattleTeamModel.findOneAndUpdate({ teamCode, 'roleStatus.roleId': roleId}, {$set: {'roleStatus.$.heroes': heroes}}, {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 (isSuccess === true) { + team.status = 2; + team.roleStatus.forEach(st => { + if (st.battleStatus !== 2) { + st.battleStatus = 1; + } + }) + } else if (isSuccess === false) { + let loseCnt = 1; + team.roleStatus.forEach(st => { + if (st.battleStatus === 2 && st.roleId !== roleId) { + loseCnt += 1; + } else if (st.roleId === roleId && !st.battleStatus) { + st.battleStatus = 2; + } + }); + if (loseCnt === team.roleStatus.length) { + team.status = 3; + } + } + await team.save(); + return team; + } + public static async findTeamByCapAndStatus(roleId: string, status: number, lean = true) { const teams = await ComBattleTeamModel.find({capId: roleId, status}).lean(lean); return teams;