import { MemComBtlTeam } from './../domain/battleField/ComBattleTeamField'; import { ItemModel } from './../db/Item'; import { BATTLE_REWARD_TYPE, ITEM_CHANGE_REASON, IT_TYPE, PUSH_ROUTE } from './../consts'; import { FriendRelationModel } from './../db/FriendRelation'; import { RoleModel, RoleType } from './../db/Role'; import { EquipPrintDropType, EquipPrintDropModel } from './../db/EquipPrintDrop'; import { STATUS } from './../consts/statusCode'; import { COM_TEAM_STATUS, FRIEND_DROP_TYPE, COM_BTL_CONST, FRIEND_DROP_MAX } from './../consts'; import { RoleStatus, ComBattleTeamModel, ComBattleTeamType, ComBattleReward } from './../db/ComBattleTeam'; import { getRandEelm, getRandValue, resResult, ratioReward, getRandValueByMinMax, getRandEelmWithWeight, getRobotInfo, getRandSingleEelm } from "../pubUtils/util"; import { getRandRobot } from "./battleService"; import { Channel, ChannelService, pinus } from 'pinus'; import { TREASURE, EXTERIOR, FRIEND } from '../pubUtils/dicParam'; import { getFriendLvAdd } from './friendService'; import { getRoleIds } from '../pubUtils/friendUtil'; import { getComTeamSidByCode, getCreatedTeamByLv, getTeamSearchByLv, rmCreatedTeamFromRedis, rmRoleFromQueue, setCreatedTeamToRedis } from './redisService'; import { getRewardByBlueprtId, gameData, getBossHpByBlueprtId, getDicBlueprtById } from '../pubUtils/data'; import { getZeroPointD, nowSeconds } from '../pubUtils/timeUtil'; import { addItems, getFriendPointObject, handleCost } from './role/rewardService'; import { addUserToTeamChannel, delTeamChannel, sendMessageToTeam, sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from './pushService'; import { checkTaskInComBattleEnd } from './task/taskService'; import moment = require('moment'); import { RewardInter } from '../pubUtils/interface'; import { FriendPointModel } from '../db/FriendPoint'; /** * 在给定的品质列表中随机返回一定数量的藏宝图Id * @param lv 品质数组,在所有给定品质的藏宝图中筛选1 * @param cnt 返回藏宝图数量 */ export function getRandBlueprtId(lvs: number[], cnt = 1) { if (!lvs || !lvs.length) return null; let blueprtIdArr: number[] = []; for (let lv of lvs) { blueprtIdArr = blueprtIdArr.concat(gameData.blueprtByLv.get(lv)); } if (blueprtIdArr.length === 0) return null; const res = getRandEelm(blueprtIdArr, cnt); // console.log('******** getRandBlueprtId', blueprtIdArr, cnt, res) return res; } export function getRandComBtlRobots(topLineupCe: number, ceLimit: number, lv: number, cnt: number) { let robotHeroes = getRandRobot(cnt); // 随机几个阵容 let robotInfos: { robotRoleName: string, robotRoleId: string }[] = []; // 随机几个机器人信息 for (let i = 0; i < cnt; i++) { robotInfos.push(getRobotInfo()); } // 创建并添加机器人 let robotStArr: RoleStatus[] = [], robotIdArr: string[] = []; if (robotHeroes && robotInfos && robotHeroes.length && robotInfos.length && robotInfos.length === robotHeroes.length) { robotHeroes.forEach((robot, idx) => { let robotCe = 0; if (ceLimit && ceLimit > 0) { robotCe = getRandValueByMinMax(ceLimit, (topLineupCe || 0) * (1 + COM_BTL_CONST.ROBOT_CE_RATIO), 0); } else { robotCe = getRandValue(topLineupCe || 0, COM_BTL_CONST.ROBOT_CE_RATIO, 0); } let robotLv = getRandValue(lv, COM_BTL_CONST.ROBOT_CE_RATIO, 0); if(robotLv > gameData.maxPlayerLv.max) robotLv = gameData.maxPlayerLv.max; // const imgHid = robot[Math.floor(Math.random() * robot.length)]; const { robotRoleId, robotRoleName } = robotInfos[idx]; let robotStatus = new RoleStatus({ roleId: robotRoleId, roleName: robotRoleName, topLineupCe: robotCe, lv: robotLv }, '', false, false, robot, true); robotStArr.push(robotStatus); robotIdArr.push(robotRoleId); }); } return { robotStArr, robotIdArr } } export function checkComBattleResult(teamStatus) { if (teamStatus.bossCurHp === 0) { return COM_TEAM_STATUS.WIN; } else { let allPlayerKilled = true; let robotRestHurt = 0; // 看看是否还有活人 teamStatus.roleStatus.forEach(st => { // 设置了阵容,且阵容人数和阵亡人数一样,说明玩家战败 if (!st.isRobot && st.battleStatus != 2 && st.heroes && ((st.heroes.length > 0 && st.killed.length < st.heroes.length) || st.heroes.length === 0 )) { allPlayerKilled = false } }); // 没有活人的话看看还有没有机器人没打完伤害 if (allPlayerKilled && teamStatus.curRnd < COM_BTL_CONST.ROBOT_RND_LMT) { teamStatus.roleStatus.forEach(st => { if (st.isRobot) { const deltaRnd = COM_BTL_CONST.ROBOT_RND_LMT - teamStatus.curRnd; let hurtHp = getRandValue(teamStatus.bossHp / COM_BTL_CONST.ROBOT_RND_LMT * COM_BTL_CONST.ROBOT_HURT_RATIO, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) * deltaRnd; // 1 个机器人对 boss 造成的总伤害 robotRestHurt += hurtHp; } }) } if (allPlayerKilled) { // 没有活人且机器人剩余伤害打不死 boss,战败 if (teamStatus.bossCurHp > robotRestHurt) { return COM_TEAM_STATUS.LOOSE; } else { return COM_TEAM_STATUS.WIN; } } } return COM_TEAM_STATUS.FIGHTING; } // /** // * ! deprecated // * @description 计算寻宝结算 // * @export // * @param {string} roleId // * @param {string} battleCode // * @returns // */ // export async function checkComBattleDrop(roleId: string, battleCode: string) { // let team = await ComBattleTeamModel.getTeamByRoleAndBattleCode(roleId, battleCode); // if (team.status !== COM_TEAM_STATUS.WIN) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) }; // let roleSt = null; // team.roleStatus.forEach(st => { // if (st.roleId === roleId) { // roleSt = st; // } // }); // if (!roleSt || roleSt.gotReward) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) }; // let { fixReward, teammateReward } = getRewardByBlueprtId(team.blueprtId); // if (!roleSt.isCap) { // if (roleSt.isFrd) { // fixReward = []; // } else { // fixReward = teammateReward; // } // } // await ComBattleTeamModel.updateRewardSt(team.teamCode, roleId, true); // return { status: 0, fixReward }; // } export function clearComBtlTimer(teamCode: string, timerMap: Map) { let timer = timerMap.get(teamCode); if (timer) { clearTimeout(timer); } } export function setComBtlTimer(teamCode: string, timer: NodeJS.Timer, timerMap: Map) { let preTimer = timerMap.get(teamCode); if (preTimer) { clearTimeout(preTimer); } timerMap.set(teamCode, timer); } export async function getRealReward(blueprtId: number, roleSts: RoleStatus[], roleSt: RoleStatus, hasTimeExtraReward: boolean): Promise { let dicReward = getRewardByBlueprtId(blueprtId); if(!dicReward) return []; let fixRewards: RewardInter[] = [], extraRewards: RewardInter[] = [], hasExtraReward = true; if (roleSt.isCap) { fixRewards.push(...dicReward.captainReward); if(roleSt.isFrd && !roleSt.isRobot) { hasExtraReward = false; } } else { if (roleSt.isFrd && !roleSt.isRobot) { // 情谊值有上限,送到上限为止 let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleSt.roleId, FRIEND_DROP_TYPE.COM_BATTLE); let { comBattleCnt = 0 } = frdPointRec || {}; if(comBattleCnt < FRIEND.FRIEND_FRIENDPOINT_MAX) { let count = FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt > TREASURE.REWARD_FRIENDPOINT? TREASURE.REWARD_FRIENDPOINT: FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt; fixRewards.push(getFriendPointObject(count)); await FriendPointModel.updateComBattleCntToday(roleSt.roleId, roleSt.roleName, count, FRIEND.FRIEND_FRIENDPOINT_MAX, FRIEND_DROP_TYPE.COM_BATTLE); } hasExtraReward = false; } else { fixRewards.push(...dicReward.teammateReward) } } if(hasTimeExtraReward && hasExtraReward) { let sameGuildCnt = roleSts.filter(cur => !!roleSt.guildCode && cur.guildCode == roleSt.guildCode && cur.roleId != roleSt.roleId).length; if(sameGuildCnt > 0) { let dicGuildReward = roleSt.isCap? dicReward.captainTimeGuildReward: dicReward.teammateTimeGuildReward; let guildRewards = dicGuildReward.get(sameGuildCnt)||[] extraRewards.push(...guildRewards); } else { let guildRewards = roleSt.isCap? dicReward.captainTimeReward: dicReward.teammateTimeReward; extraRewards.push(...guildRewards); } } return [ ...fixRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.FIX_REWARD, ...reward })), ...extraRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.EXTRA_REWARD, ...reward })) ] } export async function getAllAssistCnt(roleId: string) { let teams = await ComBattleTeamModel.getAssistTeamsByTime(roleId, getZeroPointD(), true); if (teams.length > 0) { // 过滤掉情谊助战次数 teams = teams.filter(team => { let roleSt = team.roleStatus.find(st => st.roleId === roleId); return !roleSt.isFrd; }); } return teams.length; } export async function getCapExtraCnt(roleId: string) { let teams = await ComBattleTeamModel.getCapExtraRewardCnt(roleId, getZeroPointD()); return teams.length; } export async function getFrd(roleId: string) { let isFrd = false; let cnt = await getAllAssistCnt(roleId); if (cnt >= TREASURE.TREASURE_ASSIST_TIME) isFrd = true; return isFrd; } export async function getCapFrd(roleId: string) { let isFrd = false; let cnt = await getCapExtraCnt(roleId); if (cnt >= TREASURE.TREASURE_CAP_EXTRA_TIME) isFrd = true; return isFrd; } /** * @description 更新队伍状态 * @export * @param {number} preStatus 更新前状态,作为筛选条件 * @param {number} newStatus 要设置的新状态 */ export async function updateTeamStatus(preStatus: number, newStatus: number) { if (preStatus === newStatus) return; await ComBattleTeamModel.updateStatusByStatus(preStatus, newStatus); } /** * @description 计算机器人每次对 boss 造成的伤害 * @param {number} bossHp boss 总血量 */ function robotEachHurt(bossHp: number, bossCnt: number) { const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; const robotAverageHurt = robotTotalHurt / COM_BTL_CONST.ROBOT_ACT_LMT / bossCnt; return getRandValue(robotAverageHurt, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) } /** * @description 更新机器人阵亡情况 * @param {number} bossHp * @param {RoleStatus} roleSt */ function updateRobotKilled(bossHp: number, roleSt: RoleStatus) { const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; // 让阵亡人数和打出伤害的进度同步,比如有 5 个武将,每打出目标总伤害的 1 / 5 应该增加一个阵亡武将 const dmgProgress = Math.floor(roleSt.totalDmg / (robotTotalHurt / roleSt.heroes.length)); if (dmgProgress > roleSt.killed.length && dmgProgress <= roleSt.heroes.length) { const newKilledCnt = dmgProgress - roleSt.killed.length; const aliveHeroes = roleSt.heroes.filter(hero => { return roleSt.killed.indexOf(hero.id) == -1; }).map(cur => cur.id); const newKilledHeroes = getRandEelm(aliveHeroes, newKilledCnt); roleSt.killed = roleSt.killed.concat(newKilledHeroes); } } export async function handleComBtlProgress(teamStatus: MemComBtlTeam, robotHurtTimer: Map, teamMap: Map) { const { teamCode } = teamStatus; // 判断战斗是否结束 let battleSt = checkComBattleResult(teamStatus); teamStatus.status = battleSt; if (battleSt === COM_TEAM_STATUS.WIN || battleSt === COM_TEAM_STATUS.LOOSE) { let result = battleSt === COM_TEAM_STATUS.WIN; if (result) { teamStatus.bossHpArr.forEach(bs => { bs.curHp = 0; }); for (let st of teamStatus.roleStatus) { st.rewards = await getRealReward(teamStatus.blueprtId, teamStatus.roleStatus, st, teamStatus.hasTimeExtraReward); }; await checkTaskInComBattleEnd(teamStatus.roleStatus, teamStatus.capId); } let team = await ComBattleTeamModel.syncTeamData({ teamCode, status: battleSt, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr, endTime: teamStatus.endTime }); if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); // 战斗胜利队长扣减藏宝图 if (result && teamStatus.capId != 'robot') { let res = await handleCost(teamStatus.capId, teamStatus.sid, [{ id: teamStatus.blueprtId, count: 1 }], ITEM_CHANGE_REASON.COM_BATTLE_USE_BLUEPRT); if (res === false) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); } clearRobotHurtTimer(teamStatus, robotHurtTimer); sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result }); teamMap.delete(teamCode); } } /** * @description 更新机器人对 boss 的伤害 * @export * @param {*} teamStatus 要更新的队伍信息 * @param {RoleStatus} roleSt 要更新的玩家信息 */ export function updateRobotHurt(teamStatus: MemComBtlTeam, roleSt: RoleStatus) { // 机器人的伤害为:boss 血量的一定比例,平均到一定回合数内,再平均到每个敌军,上下浮动一定比例 let eachHurtHp = robotEachHurt(teamStatus.bossHp, teamStatus.bossHpArr.length); let robotTotalHurt = 0; let actBossHurts = []; let hero = getRandSingleEelm(roleSt.heroes); for (let boss of teamStatus.bossHpArr) { if (boss.curHp === 0) continue; if (boss.curHp >= eachHurtHp) { actBossHurts.push({ dataId: boss.dataId, hurtHp: eachHurtHp }); robotTotalHurt += eachHurtHp; boss.curHp -= eachHurtHp; hero.addDamage(eachHurtHp); } else if (boss.curHp > 0) { // 丢弃溢出的伤害 actBossHurts.push({ dataId: boss.dataId, hurtHp: boss.curHp }); robotTotalHurt += boss.curHp; hero.addDamage(boss.curHp); boss.curHp = 0; } break; } teamStatus.bossCurHp -= robotTotalHurt; roleSt.totalDmg += robotTotalHurt; updateRobotKilled(teamStatus.bossHp, roleSt); sendMessageToTeam(teamStatus.teamCode, PUSH_ROUTE.TEAMMATE_ACT, { teamCode: teamStatus.teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus: teamStatus.roleStatus, actRoleId: roleSt.roleId, actBossHurts }); } /** * @description 按一定时间间隔刷新机器人伤害 * @export * @param {*} teamStatus * @param {RoleStatus} roleSt * @param {number} interval * @param {Channel} channel * @param {Map} robotHurtTimer */ export function updateRobotHurtByTime(teamStatus: MemComBtlTeam, roleSt: RoleStatus, interval: number, robotHurtTimer: Map, teamMap: Map) { const timerKey = `${teamStatus.teamCode}_${roleSt.roleId}`; const robotTimer = setInterval(() => { const robotTotalHurt = teamStatus.bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; if (roleSt.totalDmg < robotTotalHurt && teamStatus.bossCurHp > 0 && teamMap.has(teamStatus.teamCode)) { updateRobotHurt(teamStatus, roleSt); handleComBtlProgress(teamStatus, robotHurtTimer, teamMap); } else { clearInterval(robotTimer); } }, interval * 1000); if (!robotHurtTimer.has(timerKey)) { robotHurtTimer.set(timerKey, robotTimer); } } /** * @description 清理机器人伤害的 timer * @export * @param {*} teamStatus 寻宝队伍状态 * @param {Map} robotHurtTimer */ export function clearRobotHurtTimer(teamStatus, robotHurtTimer: Map) { teamStatus.roleStatus.forEach(st => { const timerKey = `${teamStatus.teamCode}_${st.roleId}`; if (st.isRobot === true && robotHurtTimer.has(timerKey)) { clearInterval(robotHurtTimer.get(timerKey)); } }); } /** * @description 检查寻宝等级是否合法 * @export * @param {number} playerLv 玩家等级 * @param {number} blueprtLv 藏宝图等级 * @returns */ export function comBtlLvInvalid(playerLv: number, blueprtLvs: number[]) { for(let blueprtLv of blueprtLvs) { const range = gameData.comBtlLvRange.get(blueprtLv); if (!range) return true; let { min, max } = range; if(playerLv < min || playerLv > max) return true; } return false } export function getComBtlLvByPlayerLv(playerLv: number) { let lvs: number[] = []; for(let [lv, {min, max}] of gameData.comBtlLvRange) { if(playerLv >= min && playerLv <= max) lvs.push(lv); } let minLv = Math.min(...lvs); let maxLv = Math.max(...lvs); return { minLv, maxLv } } export async function dismissTeam(teamStatus: MemComBtlTeam, teamMap: Map, roleId: string, teamDisTimer: Map) { 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); 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 = teamMap.delete(teamCode); if (!rmSt) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); rmCreatedTeamFromRedis(teamCode, teamStatus.lv); sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_DISMISS, { teamCode }); delTeamChannel(teamCode); clearComBtlTimer(teamCode, teamDisTimer); // 队伍解散停止解散计时 return resResult(STATUS.SUCCESS); } export function setDismissTimer(teamStatus: MemComBtlTeam, teamMap: Map, roleId: string, teamDisTimer: Map) { // if (teamIsFullToStart(teamStatus)) { clearComBtlTimer(teamStatus.teamCode, teamDisTimer); let timer = setTimeout(async () => { await dismissTeam(teamStatus, teamMap, roleId, teamDisTimer); }, COM_BTL_CONST.CAP_START_TIME); teamDisTimer.set(teamStatus.teamCode, timer); // } } /** * 按照好友关系,新增加成 * * @param {RoleStatus[]} roleStatus 队伍内的所有队友 */ export async function getComBattleFriendAdd(roleStatus: RoleStatus[]) { let hasAdd: string[] = []; //roleIds for (let myRoleStatus of roleStatus) { for (let rs of roleStatus) { if (myRoleStatus.roleId == rs.roleId) continue; if (myRoleStatus.isRobot || rs.isRobot) continue; let { roleIds } = getRoleIds([myRoleStatus.roleId, rs.roleId]); if (hasAdd.includes(roleIds)) continue; let add = await getFriendLvAdd(myRoleStatus.roleId, rs.roleId); rs.addFrdRatio(add); myRoleStatus.addFrdRatio(add); hasAdd.push(roleIds); } } } /** * @description 检查玩家是否符合加入队伍的条件 * @param {Partial} roleInfo 要加入玩家的信息 * @param {string} roleId 要加入玩家的 id * @param {string[]} roleIds 队伍中当前玩家列表 * @param {number} ceLimit * @returns */ async function teammateValid(roleInfo: Partial, roleId: string, roleIds: string[], ceLimit: number) { if (!roleInfo || roleIds.indexOf(roleId) !== -1) return false; const isBlack = await teammateInBlackList(roleId, roleIds); if (isBlack) return false; let { topLineupCe } = roleInfo; if (topLineupCe < ceLimit) return false; return true; } /** * @description 将用户信息转换成寻宝组队所需的 RoleStatus * @export * @param {string} roleId 要加入玩家的信息 * @param {string[]} roleIds 队伍中当前玩家列表 * @param {number} ceLimit * @returns */ export async function getValidTeammateRoleSt(roleId: string, roleIds: string[], ceLimit: number, sid: string) { let roleInfo = await RoleModel.findByRoleId(roleId, null, true); const valid = await teammateValid(roleInfo, roleId, roleIds, ceLimit); if (!valid) return null; let isFrd = await getFrd(roleId); const result = new RoleStatus(roleInfo, sid, false, isFrd); return result; } /** * @description 检查队伍中是否有人互为黑名单 * @export * @param {string} roleId 要加入队伍的玩家 id * @param {string[]} roleIds 队伍中已有的玩家 id * @returns */ export async function teammateInBlackList(roleId: string, roleIds: string[]) { for (let teammateRoleId of roleIds) { const isBlack = await FriendRelationModel.isInBlackList(roleId, teammateRoleId); if (isBlack === true) return true; } return false; } export function blueprtIdValid(id: number) { return gameData.blueprt.has(id); } /** * @description 检查是否有足够的藏宝图,未结束的战斗也占用一张藏宝图 * @export * @param {string} roleId * @param {number} blueprtId * @returns */ export async function hasEnoughBlueprt(roleId: string, sid: string, blueprtId: number) { let blueprt = await ItemModel.findbyRoleAndGidAndCount(roleId, blueprtId, 1); if (!blueprt || blueprt.count <= 0) return false; // 检查是否有已创建未结束的寻宝,预先占用一张藏宝图 // // 背包中占用的藏宝图不显示,所以这里就扣掉,结束再加回去 // let result = await handleCost(roleId, sid, [{ id: blueprtId, count: 1 }]); // return result; let teams = await ComBattleTeamModel.getBlueprtInUse(roleId, COM_TEAM_STATUS.FIGHTING, blueprtId); console.log('hasEnoughBlueprt', blueprt.count, teams.length) if (teams && blueprt.count <= teams.length) return false; return true } /** * @description 将玩家加入到队伍数据结构中,需将玩家信息做转化 * @export * @param {MemComBtlTeam} comTeam 队伍数据结构 * @param {RoleType} roleInfo 原始玩家信息 * @param {boolean} isCap * @param {boolean} isFrd */ export function addRoleToTeam(comTeam: MemComBtlTeam, roleInfo: RoleType, sid: string, isCap: boolean, isFrd: boolean) { const roleSt = new RoleStatus(roleInfo, sid, isCap, isFrd); addRoleStToTeam(comTeam, roleSt); } /** * @description 将玩家加入到队伍数据结构中 * @export * @param {MemComBtlTeam} comTeam 队伍数据结构 * @param {RoleStatus} roleSt 要加入的玩家数据 */ export function addRoleStToTeam(comTeam: MemComBtlTeam, roleSt: RoleStatus) { const { roleStatus = [], roleIds = [] } = comTeam; comTeam.roleStatus = [roleSt, ...roleStatus]; comTeam.roleIds = [roleSt.roleId, ...roleIds]; if(!validToJoin(comTeam)) { // 无人可匹配时,删除存在redis中的匹配信息 rmCreatedTeamFromRedis(comTeam.teamCode, comTeam.lv); } } /** * @description 将符合要求的用户匹配到队伍中 * @export * @param {MemComBtlTeam} comTeam 队伍数据 * @param {string} sid 当前用户 sid * @returns */ export async function addValidSearchingRoles(comTeam: MemComBtlTeam) { const { lv } = getDicBlueprtById(comTeam.blueprtId); let teammates = await getTeamSearchByLv(lv); if (teammates && teammates.length) { for (let teammate of teammates) { const { roleId: teammateRoleId, sid } = teammate; const st = await getValidTeammateRoleSt(teammateRoleId, comTeam.roleIds, comTeam.ceLimit, sid); if (!st) continue; await rmRoleFromQueue(teammateRoleId, sid); // 匹配成功后删除redis中该用户的匹配记录 addRoleStToTeam(comTeam, st); addUserToTeamChannel(comTeam.teamCode, false, teammateRoleId, sid); } sendMessageToUsersWithSuc(PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }, teammates.map(t => { return { uid: t.roleId, sid: t.sid } })); } } export async function addToSearchingTeams(roleId: string, sid: string, lvs: number[]) { let teamCodes = await getCreatedTeamByLv(lvs); if(teamCodes.length <= 0) return false; let {lv, teamCode} = getRandSingleEelm(teamCodes); let battleServer = await getComTeamSidByCode(lv, teamCode); if(!battleServer) return false; return await pinus.app.rpc.battle.comBattleRemote.addToSearchingTeams.toServer(battleServer, teamCode, roleId, sid); } export async function _addToSearchingTeams(teamCode: string, roleId: string, sid: string) { let teamMap = pinus.app.get('teamMap'); let teamStatus: MemComBtlTeam = teamMap && teamMap.get(teamCode); if(!teamStatus) return false; if(!validToJoin(teamStatus, roleId)) return false; const st = await getValidTeammateRoleSt(roleId, teamStatus.roleIds, teamStatus.ceLimit, sid); if (!st) return false; addRoleStToTeam(teamStatus, st); await rmRoleFromQueue(roleId, sid); // 匹配成功后删除redis中该用户的匹配记录 addUserToTeamChannel(teamCode, false, roleId, sid); sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: teamStatus }); await ComBattleTeamModel.addRole(teamCode, st); } /** * @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, count = 1) { const { teamCode, roleStatus } = comTeam; let hasCap = roleStatus.findIndex(cur => cur.isCap) != -1; const { robotStArr, robotIdArr } = getRandComBtlRobots(roleCe, comTeam.ceLimit, roleLv, count); for (let st of robotStArr) { if(!hasCap) { st.isCap = true; hasCap = true; } addRoleStToTeam(comTeam, st); await ComBattleTeamModel.addRole(teamCode, st); } sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }) setDismissTimer(comTeam, teamMap, roleId, teamDisTimer); } /** * @description 在不同的时间加入机器人 * @export * @param {MemComBtlTeam} comTeam * @param {RoleType} roleInfo * @param {Map} teamMap * @param {Map} teamDisTimer */ export async function addRobotsLater(comTeam: MemComBtlTeam, roleInfo: RoleType, teamMap: Map, teamDisTimer: Map) { const teamStatus = comTeam; const { teamCode, lv: blueprtLv } = teamStatus; const { roleId, lv } = roleInfo; let { topLineupCe = 1000 } = roleInfo; if (validToJoin(teamStatus)) { // 如果可以匹配 await setCreatedTeamToRedis(teamCode, blueprtLv); 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, topLineupCe, lv, teamMap, teamDisTimer, 1); } }, joinTime); } } } /** * @description 从数组里找出第一个不在黑名单的队伍 * @export * @param {ComBattleTeamType[]} teams 队伍数组 * @param {string} roleId 要加入的玩家 id * @returns */ export async function oneTeamNotInBlack(teams: ComBattleTeamType[], roleId: string) { for (let team of teams) { let { roleIds } = team; const inBlackList = await teammateInBlackList(roleId, roleIds); if (!inBlackList) { return team; } } return null; } // export async function setComBtlOnUserLeave(roleId: string, teamCode: string) { // let res = dispatch(teamCode, pinus.app.getServersByType('battle'), 'battle'); // await pinus.app.rpc.battle.comBattleRemote.leaveFromBattle.toServer(res.id, roleId, teamCode); // } export async function checkHasMyTeam(roleId: string) { return await ComBattleTeamModel.checkHasTeamByRoleId(roleId); } export async function checkTeamStatusAndSend(teamCode: string, roleId: string, sid: string) { let team = await ComBattleTeamModel.getTeamByCode(teamCode); if(team && (team.status == 2|| team.status == 3)) { await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result: team.status == 2? true: false, timeout: team.timeout }, sid); } }