From d0cd3faab54d5bd2958d8f68b1f851ffb5524692 Mon Sep 17 00:00:00 2001 From: liangtongchuan Date: Wed, 20 Jan 2021 13:36:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BB=E5=AE=9D=EF=BC=9A=E4=BB=85=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E7=89=B9=E5=AE=9A=E7=AD=89=E7=BA=A7=E5=8C=BA=E9=97=B4?= =?UTF-8?q?=EF=BC=9B=E4=BF=AE=E5=A4=8D=E6=9C=BA=E5=99=A8=E4=BA=BA=E6=AD=A6?= =?UTF-8?q?=E5=B0=86=E4=B8=8D=E9=98=B5=E4=BA=A1=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../battle/handler/comBattleHandler.ts | 36 ++++++++--------- game-server/app/services/comBattleService.ts | 12 ++++-- game-server/app/services/redisService.ts | 39 +++++++++++++------ shared/consts/constModules/battleConst.ts | 10 +++++ shared/db/ComBattleTeam.ts | 8 +++- shared/pubUtils/dictionary/DicXunbao.ts | 4 +- shared/pubUtils/gamedata.ts | 33 +++++++++++++++- 7 files changed, 104 insertions(+), 38 deletions(-) diff --git a/game-server/app/servers/battle/handler/comBattleHandler.ts b/game-server/app/servers/battle/handler/comBattleHandler.ts index a43a7f4d0..e30374c6b 100644 --- a/game-server/app/servers/battle/handler/comBattleHandler.ts +++ b/game-server/app/servers/battle/handler/comBattleHandler.ts @@ -5,7 +5,7 @@ * @Last Modified time: 2020-12-03 21:36:00 */ import { IT_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, COM_TEAM_STATUS, COM_BTL_CONST, GOOD_QUALITY, CONSUME_TYPE } from './../../../consts'; -import { getGoodById, getBossHpByBlueprtId, getComBtlSetByQuality, getBlueprtComposeByQuality, getBluePrtByQuality, getWarById, getWarIdByBlueprtId } from '../../../pubUtils/gamedata'; +import { getGoodById, getBossHpByBlueprtId, getComBtlSetByQuality, getBlueprtComposeByQuality, getBluePrtByQuality, getWarById, getWarIdByBlueprtId, comBtlRangeInfo, comBtlRangeByLv } from '../../../pubUtils/gamedata'; import { ComBattleTeamModel, BossHp } from '../../../db/ComBattleTeam'; import Role, { RoleModel } from '../../../db/Role'; import { STATUS } from '../../../consts/statusCode'; @@ -16,7 +16,7 @@ import { ItemModel } from '../../../db/Item'; import { handleFixedReward, addItems, handleCost } from '../../../services/rewardService'; import { checkRoleInQueue, getTeamSearchByQuality, rmRoleFromQueue, setTeamSearchReq } from '../../../services/redisService'; import { transBossHpArr } from '../../../services/battleService'; -import { getRandBlueprtId, getRandComBtlRobots, checkComBattleResult, clearComBtlTimer, getRealReward, getAssistTimesByQuality, getFrd, updateRobotHurt, updateRobotHurtByTime } from '../../../services/comBattleService'; +import { getRandBlueprtId, getRandComBtlRobots, checkComBattleResult, clearComBtlTimer, getRealReward, getAssistTimesByQuality, getFrd, updateRobotHurt, updateRobotHurtByTime, comBtlLvInvalid } from '../../../services/comBattleService'; import { setAp } from '../../../services/actionPointService'; import { roleLevelup } from '../../../services/normalBattleService'; @@ -53,6 +53,8 @@ class ComTeam { curRnd: number; // 队伍中人数 roleCnt: number; + // 藏宝图等级所处范围,用来匹配 + lvRange: number; constructor(teamCode: string, pub: boolean, blueprtId: number, status: number, capId: string, ceLimit: number, bossHp: number, quality: number, bossHpArr:Array ) { this.teamCode = teamCode; this.pub = pub; @@ -66,6 +68,8 @@ class ComTeam { this.bossHpArr = bossHpArr; this.curRnd = 0; this.roleCnt = 1; + let { lvLimited } = getGoodById(blueprtId); + this.lvRange = comBtlRangeByLv(lvLimited); } } export class ComBattleHandler { @@ -113,7 +117,7 @@ export class ComBattleHandler { roleStatus.push(capStatus); // 检查是否有正在匹配的符合要求的玩家 - let teammates = await getTeamSearchByQuality(goodData.quality); + let teammates = await getTeamSearchByQuality(goodData.quality, comBtlRangeByLv(goodData.lvLimited)); if (teammates) { for (let teammate of teammates) { let roleInfo = await RoleModel.findByRoleId(teammate.roleId); @@ -196,34 +200,31 @@ export class ComBattleHandler { * @returns * @memberof ComBattleHandler */ - async searchTeam(msg: {qualityArr: [number]}, session: BackendSession) { + async searchTeam(msg: {qualityArr: [number], lvRange: number}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); - const { qualityArr } = msg; + const { qualityArr, lvRange = 1 } = msg; let { lv, headHid = 19, topFiveCe = 1000, sHid = 19 } = await RoleModel.findByRoleId(roleId); - topFiveCe = reduceCe(topFiveCe); - for (let q of qualityArr) { - let setting = getComBtlSetByQuality(q); - if (lv < setting.assistanceLevel) { - return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); - } + + if (comBtlLvInvalid(lv, lvRange)) { + return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); } - const team = await ComBattleTeamModel.getOtherTeamByQualityAndSt(roleId, qualityArr, COM_TEAM_STATUS.DEFAULT, topFiveCe); + const team = await ComBattleTeamModel.getOtherTeamByQualityAndSt(roleId, qualityArr, COM_TEAM_STATUS.DEFAULT, lvRange, topFiveCe); // TODO: 有匹配的队伍还需要重新 joinTeam 加入,有失败可能,体验不好,需优化 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); + await setTeamSearchReq(roleId, sid, qualityArr, lvRange); let thiz = this; // 倒计时匹配两个机器人 setTimeout(async () => { - let inQueue = await checkRoleInQueue(roleId, sid, qualityArr); + let inQueue = await checkRoleInQueue(roleId, sid, qualityArr, lvRange); if (!inQueue) return; - await rmRoleFromQueue(roleId, sid, qualityArr); + await rmRoleFromQueue(roleId, sid, qualityArr, lvRange); let roleStatus = []; let roleIds = []; @@ -273,7 +274,7 @@ export class ComBattleHandler { let roleId = session.get('roleId'); let sid = session.get('sid'); - await rmRoleFromQueue(roleId, sid, GOOD_QUALITY); + await rmRoleFromQueue(roleId, sid, GOOD_QUALITY, null); return resResult(STATUS.SUCCESS); } @@ -297,10 +298,9 @@ export class ComBattleHandler { topFiveCe = reduceCe(topFiveCe); let { quality } = getGoodById(teamStatus.blueprtId); - let { assistanceLevel, assistanceTime } = getComBtlSetByQuality(quality); if (lv < COM_BTL_CONST.ENABLE_LV) { return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); - } else if (lv < assistanceLevel) { + } else if (comBtlLvInvalid(lv, teamStatus.lvRange)) { return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); } else if (topFiveCe < teamStatus.ceLimit) { return resResult(STATUS.COM_BATTLE_CE_LIMIT); diff --git a/game-server/app/services/comBattleService.ts b/game-server/app/services/comBattleService.ts index 007bc7fb0..f8886511f 100644 --- a/game-server/app/services/comBattleService.ts +++ b/game-server/app/services/comBattleService.ts @@ -2,7 +2,7 @@ import { FriendPointModel } from './../db/FriendPoint'; import { STATUS } from './../consts/statusCode'; import { COM_BATTLE_ROBOT_ID_NAME, 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 { getBluePrtByQuality, getComBtlSetByQuality, getRewardByBlueprtId, getWarById, getWarIdByBlueprtId } from "../pubUtils/gamedata"; +import { getBluePrtByQuality, getComBtlSetByQuality, getRewardByBlueprtId, getWarById, getWarIdByBlueprtId, comBtlRangeInfo } from "../pubUtils/gamedata"; import { getRandEelm, getRandValue, resResult, ratioReward } from "../pubUtils/util"; import { getRandRobot } from "./battleService"; import { difference } from 'underscore'; @@ -204,7 +204,7 @@ function updateRobotKilled(bossHp: number, roleSt: RoleStatus) { const newKilledCnt = dmgProgress - roleSt.killed.length; const aliveHeroes = difference(roleSt.heroes, roleSt.killed); const newKilledHeroes = getRandEelm(aliveHeroes, newKilledCnt); - roleSt.killed.concat(newKilledHeroes); + roleSt.killed = roleSt.killed.concat(newKilledHeroes); } } @@ -235,7 +235,7 @@ export function updateRobotHurt(teamStatus, roleSt: RoleStatus, channel: Channel teamStatus.bossCurHp -= robotTotalHurt; roleSt.totalDmg += robotTotalHurt; updateRobotKilled(teamStatus.bossHp, roleSt); - channel.pushMessage('onTeammateAct', resResult(STATUS.SUCCESS, { teamCode: teamStatus.teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus: roleSt, actRoleId: roleSt.roleId, actBossHurts })); + channel.pushMessage('onTeammateAct', resResult(STATUS.SUCCESS, { teamCode: teamStatus.teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus: teamStatus.roleStatus, actRoleId: roleSt.roleId, actBossHurts })); } @@ -259,3 +259,9 @@ export function updateRobotHurtByTime(teamStatus, roleSt: RoleStatus, interval: }, interval * 1000); } +export function comBtlLvInvalid(lv: number, lvRange: number) { + const lvs = comBtlRangeInfo(lvRange); + if (!lvs) return true; + const minLv = lvs[0]; + return lv < minLv; +} diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index eb9155086..05dd7ac42 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -9,7 +9,7 @@ import { PvpDefenseModel } from '../db/PvpDefense'; import { SystemConfigModel } from '../db/SystemConfig'; import { RankParam, GuildRankParam, GuildLeader } from '../pubUtils/interface'; import { GuildModel } from '../db/Guild'; - +import { comBtlRanges } from '../pubUtils/gamedata'; /** * 在服务重新启动时,将信息存入redis */ @@ -216,13 +216,22 @@ export async function removeFromRank(key: string, serverId: number, myId: string /**************** 寻宝相关 start */ +/** + * @description 拼接匹配分组的 key + * @param {number} quality + * @param {number} lvRange + */ +function getComTeamKey(quality: number, lvRange: number) { + return `${REDIS_KEY.COM_TEAM_SEARCH_PRE}:${quality}_${lvRange}`; +} + // 把寻宝的玩家信息存入 redis -export async function setTeamSearchReq(roleId: string, sid: string, qualityArr: Array) { +export async function setTeamSearchReq(roleId: string, sid: string, qualityArr: Array, lvRange: number) { const client: Redis.RedisClient = pinus.app.get('redis'); let cmds = []; qualityArr.forEach(quality => { if (quality) { - cmds.push(['sadd', `${REDIS_KEY.COM_TEAM_SEARCH_PRE}${quality}`, `${roleId}:${sid}`]); + cmds.push(['sadd', getComTeamKey(quality, lvRange), `${roleId}:${sid}`]); } }); const multiClient = client.multi(cmds) as Redis.Multi; @@ -233,22 +242,28 @@ export async function setTeamSearchReq(roleId: string, sid: string, qualityArr: } // 取出 0 - 2 个某品质的匹配中玩家,并在其它品质中删除此玩家信息 -export async function rmRoleFromQueue(roleId: string, sid: string, qualityArr: Array) { +export async function rmRoleFromQueue(roleId: string, sid: string, qualityArr: Array, lvRange: number) { const client: Redis.RedisClient = pinus.app.get('redis'); let cmds = []; for (let q of qualityArr) { - cmds.push(['srem', `${REDIS_KEY.COM_TEAM_SEARCH_PRE}${q}`, `${roleId}:${sid}`]); + if (lvRange) { + cmds.push(['srem', getComTeamKey(q, lvRange), `${roleId}:${sid}`]); + } else { + for (let range of comBtlRanges()) { + cmds.push(['srem', getComTeamKey(q, range), `${roleId}:${sid}`]); + } + } }; const multiClient = client.multi(cmds) as Redis.Multi; const newMulti = promisifyAll(multiClient) as Redis.Multi; await newMulti.execAsync(); } -export async function getTeamSearchByQuality(quality: number) { +export async function getTeamSearchByQuality(quality: number, lvRange: number) { const client: Redis.RedisClient = pinus.app.get('redis'); // TODO: 操作不具有原子性 - const userInfos = await client.srandmemberAsync(`${REDIS_KEY.COM_TEAM_SEARCH_PRE}${quality}`, 2); + const userInfos = await client.srandmemberAsync(getComTeamKey(quality, lvRange), 2); console.log('getTeamSearchByQuality: ' + userInfos); if (!userInfos || !userInfos.length) return null; @@ -260,7 +275,7 @@ export async function getTeamSearchByQuality(quality: number) { res.push({roleId: decodeData[0], sid: decodeData[1]}); GOOD_QUALITY.forEach((q) => { - cmds.push(['srem', `${REDIS_KEY.COM_TEAM_SEARCH_PRE}${q}`, userInfo]); + cmds.push(['srem', getComTeamKey(q, lvRange), userInfo]); }) const multiClient = client.multi(cmds) as Redis.Multi; const newMulti = promisifyAll(multiClient) as Redis.Multi; @@ -270,10 +285,10 @@ export async function getTeamSearchByQuality(quality: number) { return res; } -export async function checkRoleInQueue(roleId: string, sid: string, qualityArr: Array) { +export async function checkRoleInQueue(roleId: string, sid: string, qualityArr: Array, lvRange: number) { const client: Redis.RedisClient = pinus.app.get('redis'); for (let quality of qualityArr) { - let res = await client.sismemberAsync(`${REDIS_KEY.COM_TEAM_SEARCH_PRE}${quality}`, `${roleId}:${sid}`); + let res = await client.sismemberAsync(getComTeamKey(quality, lvRange), `${roleId}:${sid}`); if (res) { return true; } @@ -284,7 +299,9 @@ export async function checkRoleInQueue(roleId: string, sid: string, qualityArr: export async function clearComBtlQueue() { const client: Redis.RedisClient = pinus.app.get('redis'); for (let q of GOOD_QUALITY) { - await client.delAsync(`${REDIS_KEY.COM_TEAM_SEARCH_PRE}${q}`); + for (let lvRange of comBtlRanges()) { + await client.delAsync(getComTeamKey(q, lvRange)); + } } } diff --git a/shared/consts/constModules/battleConst.ts b/shared/consts/constModules/battleConst.ts index 46e77426c..b84fcf02b 100644 --- a/shared/consts/constModules/battleConst.ts +++ b/shared/consts/constModules/battleConst.ts @@ -147,6 +147,16 @@ export const COM_BTL_CONST = { ASSIST_REWARD_RATIO: 0.5, // 队员奖励比例 } +// 寻宝等级区间 +export const COM_BTL_LV_RANGE = [ + {id: 1, minLv: 1, maxLv: 19}, + {id: 2, minLv: 20, maxLv: 39}, + {id: 3, minLv: 40, maxLv: 59}, + {id: 4, minLv: 60, maxLv: 79}, + {id: 5, minLv: 80, maxLv: 99}, + {id: 6, minLv: 100, maxLv: 100}, +]; + // 机器人名字随机 export const COM_BATTLE_ROBOT_ID_NAME = [ {robotRoleId: 'cd9h0iy8', robotRoleName: '徐埋农'}, diff --git a/shared/db/ComBattleTeam.ts b/shared/db/ComBattleTeam.ts index 9b7ffedac..f7970da8e 100644 --- a/shared/db/ComBattleTeam.ts +++ b/shared/db/ComBattleTeam.ts @@ -121,6 +121,10 @@ export default class ComBattleTeam extends BaseModel { @prop({ required: true, default: 1 }) roleCnt: number; + // 藏宝图等级所处范围,用来匹配 + @prop({ required: true, default: 1 }) + lvRange: number; + // 单个 boss 血量状态 @prop({ required: false, type: BossHp, default: [] }) bossHpArr: Array; @@ -218,9 +222,9 @@ export default class ComBattleTeam extends BaseModel { return team; } - public static async getOtherTeamByQualityAndSt(roleId: string, qualityArr: Array, status: number, ce = 0, pub = true, cntLmt = 2, lean = true) { + public static async getOtherTeamByQualityAndSt(roleId: string, qualityArr: Array, status: number, lvRange: number, ce = 0, pub = true, cntLmt = 2, lean = true) { const curTime = new Date(Date.now() - 10 * 60 * 1000); // 10分钟之前 - const team: ComBattleTeamType = await ComBattleTeamModel.findOne({quality: {$in: qualityArr}, status, ceLimit: {$lte: ce}, pub, roleCnt: {$lte: cntLmt}, roleIds: {$nin: [roleId]}, updatedAt: {$gte: curTime}}).lean(lean); + const team: ComBattleTeamType = await ComBattleTeamModel.findOne({quality: {$in: qualityArr}, status, lvRange, ceLimit: {$lte: ce}, pub, roleCnt: {$lte: cntLmt}, roleIds: {$nin: [roleId]}, updatedAt: {$gte: curTime}}).lean(lean); return team; } diff --git a/shared/pubUtils/dictionary/DicXunbao.ts b/shared/pubUtils/dictionary/DicXunbao.ts index ad59c8ecc..0bac75ffb 100644 --- a/shared/pubUtils/dictionary/DicXunbao.ts +++ b/shared/pubUtils/dictionary/DicXunbao.ts @@ -10,8 +10,8 @@ export interface DicXunbao { readonly name: number; // 协助次数 readonly assistanceTime: number; - // 最低协助等级 - readonly assistanceLevel: number; + // ! 已删除。最低协助等级 + // readonly assistanceLevel: number; } const str = readJsonFile(FILENAME.DIC_XUNBAO); diff --git a/shared/pubUtils/gamedata.ts b/shared/pubUtils/gamedata.ts index e9be304d8..d53e14612 100644 --- a/shared/pubUtils/gamedata.ts +++ b/shared/pubUtils/gamedata.ts @@ -1,6 +1,6 @@ import fs = require('fs'); import path = require('path'); -import { ABI_TYPE, ABI_STAGE } from '../consts'; +import { ABI_TYPE, ABI_STAGE, COM_BTL_LV_RANGE } from '../consts'; import { decodeIdCntArrayStr, getRandEelm } from './util'; import { IT_TYPE } from '../consts'; @@ -20,7 +20,7 @@ const heroSkillInfo = new Map() const seidInfo = new Map(); const olySeidInfo = new Map(); const expeditionInfo = new Map (); -const comBtlInfo = new Map(); +const comBtlInfo = new Map(); const btlBossHpSum = new Map(); const btlBossHp = new Map>(); const blueprtToWar = new Map(); @@ -31,6 +31,7 @@ const fiendShips = new Map(); const fashions = new Map(); const fiendShipHidAandIds = new Map(); const fiendShipLevelMaps = new Map(); +const comBtlLvRange = new Map>(); interface dicStar { id: number; @@ -241,6 +242,17 @@ function parseComBtlData() { }); } +function parseComBtlLvRange() { + const lvRange = COM_BTL_LV_RANGE; + lvRange.forEach(range => { + const lvs = []; + for (let lv = range.minLv; lv <= range.maxLv; lv++) { + lvs.push(lv); + } + comBtlLvRange.set(range.id, lvs); + }); +} + function parseGood() { const file = 'dic_goods'; const data = gamedata['jsons'][file] || []; @@ -402,6 +414,7 @@ function parseData() { parseOlySeidList(); parseExpedition(); parseComBtlData(); + parseComBtlLvRange(); parseGood(); parseBlueprtCompose(); parseFashions(); @@ -528,6 +541,22 @@ export function getComBtlSetByQuality(quality: number) { return comBtlInfo.get(quality); } +export function comBtlRangeInfo(range: number) { + return comBtlLvRange.get(range); +} + +export function comBtlRangeByLv(lv: number) { + for (let [k, v] of comBtlLvRange) { + if (v.indexOf(lv) !== -1) { + return k; + } + } +} + +export function comBtlRanges() { + return Array.from(comBtlLvRange.keys()); +} + export function getBossHpByWarId(warId: number) { let bossHpSum = btlBossHpSum.get(warId) || 0; let bossHpArr = btlBossHp.get(warId) || [];