Files
ZYZ/game-server/app/services/comBattleService.ts
T
2022-07-29 17:34:29 +08:00

679 lines
28 KiB
TypeScript

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 { getTeamSearchByLv, rmRoleFromQueue } 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<string, NodeJS.Timer>) {
let timer = timerMap.get(teamCode);
if (timer) {
clearTimeout(timer);
}
}
export function setComBtlTimer(teamCode: string, timer: NodeJS.Timer, timerMap: Map<string, NodeJS.Timer>) {
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<ComBattleReward[]> {
let dicReward = getRewardByBlueprtId(blueprtId);
if(!dicReward) return [];
let fixRewards: RewardInter[] = [], extraRewards: RewardInter[] = [];
if (roleSt.isCap) {
fixRewards.push(...dicReward.captainReward);
} 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);
}
} else {
fixRewards.push(...dicReward.teammateReward)
}
}
if(hasTimeExtraReward) {
let sameGuildCnt = roleSts.filter(cur => 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);
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;
}
/**
* @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<string, NodeJS.Timer>, teamMap: Map<string, MemComBtlTeam>) {
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);
if(!st.isRobot) {
await addItems(st.roleId, st.roleName, st.sid, st.rewards, ITEM_CHANGE_REASON.COM_BATTLE_END);
await ComBattleTeamModel.updateRewardSt(teamCode, st.roleId, true);
}
};
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<string, NodeJS.Timer>} robotHurtTimer
*/
export function updateRobotHurtByTime(teamStatus: MemComBtlTeam, roleSt: RoleStatus, interval: number, robotHurtTimer: Map<string, NodeJS.Timer>, teamMap: Map<string, MemComBtlTeam>) {
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<string, NodeJS.Timer>} robotHurtTimer
*/
export function clearRobotHurtTimer(teamStatus, robotHurtTimer: Map<string, NodeJS.Timer>) {
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<string, MemComBtlTeam>, roleId: string, teamDisTimer: Map<string, NodeJS.Timer>) {
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);
sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_DISMISS, { teamCode });
delTeamChannel(teamCode);
clearComBtlTimer(teamCode, teamDisTimer); // 队伍解散停止解散计时
return resResult(STATUS.SUCCESS);
}
export function setDismissTimer(teamStatus: MemComBtlTeam, teamMap: Map<string, MemComBtlTeam>, roleId: string, teamDisTimer: Map<string, NodeJS.Timer>) {
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<RoleType>} roleInfo 要加入玩家的信息
* @param {string} roleId 要加入玩家的 id
* @param {string[]} roleIds 队伍中当前玩家列表
* @param {number} ceLimit
* @returns
*/
async function teammateValid(roleInfo: Partial<RoleType>, 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];
}
/**
* @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 } }));
}
}
/**
* @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<string, MemComBtlTeam>, teamDisTimer: Map<string, NodeJS.Timer>, 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<string, MemComBtlTeam>} teamMap
* @param {Map<string, NodeJS.Timer>} teamDisTimer
*/
export async function addRobotsLater(comTeam: MemComBtlTeam, roleInfo: RoleType, teamMap: Map<string, MemComBtlTeam>, teamDisTimer: Map<string, NodeJS.Timer>) {
const teamStatus = comTeam;
const { teamCode } = teamStatus;
const { roleId, lv } = roleInfo;
let { topLineupCe = 1000 } = roleInfo;
if (validToJoin(teamStatus)) {
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) {
let battles = pinus.app.getServersByType('battle');
let hasMyTeam = false;
for(let server of battles) {
let checkResult = await pinus.app.rpc.battle.comBattleRemote.checkMyTeam.toServer(server.id, roleId);
if(checkResult) {
hasMyTeam = true; break;
}
}
return hasMyTeam;
}
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);
}
}