Files
ZYZ/game-server/app/services/guildBossService.ts
2021-09-23 20:36:26 +08:00

225 lines
8.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { BossInstanceType, BossInstanceModel } from '../db/BossInstance';
import { lockData } from '../services/redLockService';
import { findIndex } from 'underscore';
import { sismemberAsync, smembersAsync, saddAsync, delAsync, getRoleOnlineInfo } from '../services/redisService';
import { pinus } from 'pinus';
import { STATUS } from '../consts/statusCode';
import { resResult, shouldRefresh } from '../pubUtils/util';
import { BattleRecordModel } from '../db/BattleRecord';
import { getArmyBossRank, gameData, getAuctionRewardByPoolId } from '../pubUtils/data';
import { sendMailToGuildByContent } from '../services/mailService';
import { MAIL_TYPE, AUCTION_SOURCE } from '../consts';
import { GUILD_BOSS_STATUS } from '../consts/constModules/guildConst';
import { genAuction } from './auctionService';
import { GuildModel, GuildType } from '../db/Guild';
import { UserGuildModel, UserGuildType } from '../db/UserGuild';
/**
* 获得boss界面
* @param bossInstance
* @param roleId
*/
export async function getBossInstanceInfo(guildCode: string, roleId:string, userGuild: UserGuildType, guild?: GuildType) {
let bossInstance = await BossInstanceModel.findBossInstance(guildCode);
if(!guild) guild = await GuildModel.findByCode(guildCode, null, 'code refOpenBossTime openBossCnt');
let refObj = await getRefBossCnt(guild, userGuild); // 刷新次数
let showParamObj = await getLastBossInstance(bossInstance, guildCode, roleId);
if(bossInstance) {
let { warId, ranks, bossHp, bossLv, status, encourageCnt } = bossInstance;
let dicBossBase = gameData.bossBaseByBossLv.get(bossLv);
let rankInfo = getRanks(ranks, roleId);
// 此处showParamObj一定要放在最前
return { ...showParamObj, warId, ...rankInfo, bossHp, status, bossLv, encourageCnt, encourageMax: dicBossBase.encourageSum,...refObj };
} else {
return showParamObj;
}
}
async function getRefBossCnt(guild: GuildType, userGuild: UserGuildType) {
let guildCnt = await refreshGuildOfBoss(guild);
let userGuildCnt = await refreshUserGuildOfBoss(userGuild);
return { ...guildCnt, ...userGuildCnt }
}
export async function refreshGuildOfBoss(guild: GuildType, inc: number = 0) {
let { refOpenBossTime, openBossCnt, code } = guild;
if(shouldRefresh(refOpenBossTime, new Date())) {
openBossCnt = 0;
}
if(inc != 0) {
guild = await GuildModel.updateInfo(code, { refOpenBossTime: new Date(), openBossCnt: openBossCnt + inc });
openBossCnt = guild.openBossCnt;
}
return { leaderOpenCnt: openBossCnt }
}
export async function refreshUserGuildOfBoss(userGuild: UserGuildType, incEncourage = 0, incChallenge = 0) {
let { refBossTime, encourageCnt, bossChallengeCnt } = userGuild;
if(shouldRefresh(refBossTime, new Date())) {
encourageCnt = 0, bossChallengeCnt = 0;
}
if(incEncourage != 0 || incChallenge != 0) {
userGuild = await UserGuildModel.updateInfo(userGuild.roleId, { refBossTime: new Date(), encourageCnt: encourageCnt + incEncourage, bossChallengeCnt: bossChallengeCnt + incChallenge }, {});
encourageCnt = userGuild.encourageCnt;
bossChallengeCnt = userGuild.bossChallengeCnt;
}
return { myChallengeCnt: bossChallengeCnt, myEncourageCnt: encourageCnt }
}
export function getRanks(ranks: {roleId: string; score: number; time: number; job: number;}[], roleId: string ) {
ranks.sort(function(a, b) {
return b.score - a.score + a.time - b.time;
});
let myRank = {};
let lastRanks = ranks.map(({roleId: battleRoleId, score }, index) => {
if (roleId == battleRoleId) {
myRank = { roleId, score, rankLv: index + 1 };
}
return {roleId, score, rankLv: index + 1};
});
return { ranks: lastRanks, myRank }
}
export async function getLastBossInstance(bossInstance: BossInstanceType, guildCode: string, roleId: string) {
if(bossInstance && bossInstance.status == GUILD_BOSS_STATUS.OPEN) return {}
let lastBossInstance = await BossInstanceModel.findLastOverBossInstance(guildCode);
if(lastBossInstance) {
if(lastBossInstance.roleIdRecords.indexOf(roleId) == -1) {
await BossInstanceModel.recordRoleIdWhenCheck(lastBossInstance.code, roleId);
return { status: GUILD_BOSS_STATUS.CLEAR, showParam: { winWarId: lastBossInstance.warId, winBossLv: lastBossInstance.bossLv } }
} else {
return { status: GUILD_BOSS_STATUS.CLEAR }
}
} else {
return { status: GUILD_BOSS_STATUS.WAIT_OPEN }
}
}
/**
* 结算战斗
* @param code
* @param serverId
* @param dataName
* @param damage
* @param roleId
*/
export async function checkBossResult(bossCode: string, guildCode: string, serverId: number, dataName: string, roleId: string, damage: number) {
let res:any = await lockData(serverId, dataName, guildCode);//加锁
if (!!res.err)
return true;
let {status, ranks, warId, bossHp, bossLv } = await BossInstanceModel.findByCode(bossCode);//锁定关卡信息
if (status == GUILD_BOSS_STATUS.CLEAR) { // 已经被打败了
res.releaseCallback();//解锁
await BossInstanceModel.recordRoleIdWhenCheck(bossCode, roleId);
return true;
}
let index = findIndex(ranks, {roleId});
if (index == -1) { // 没有调用过battleBoss
res.releaseCallback();//解锁
return false;
}
ranks[index].score += bossHp; // 可能会把hp扣成负的然后排行榜多加了这里矫正回来
if (bossHp > damage) {//检查造成的伤害是否会让boss死亡
res.releaseCallback();//解锁
return true;
}
await BossInstanceModel.updateBossInstance(bossCode, { bossHp: 0, status: GUILD_BOSS_STATUS.CLEAR, ranks, roleIdRecords:[roleId]}, );
await pushBossHpMessage(guildCode, serverId, 0, true);
res.releaseCallback();//数据修改解锁
// 击杀奖励&伤害奖励
let dicBossBase = gameData.bossBaseByBossLv.get(bossLv);
let dicWar = gameData.war.get(warId);
await sendMailToGuildByContent(MAIL_TYPE.GUILD_BOSS_REWARD, roleId, {
params: [`${dicWar.gk_name}`], goods: dicBossBase.killReward
});
// 加入拍卖行
if(dicBossBase) {
let rewards = getAuctionRewardByPoolId(dicBossBase.rewards);
await genAuction(guildCode, AUCTION_SOURCE.BOSS, bossCode, serverId, rewards);
}
return true;
}
/**
* 获得排名区间奖励
* @param rankLv
*/
export function getArmyBossRankReward(rankLv: number) {
let armybossRankReward = getArmyBossRank();
for (let item of armybossRankReward) {
if (item.rankMin <= rankLv && (rankLv <= item.rankMax || item.rankMax == -1)) {
return item.reward;
}
}
}
/**
* 将玩家加入到正在挑战boss队列中
* @param code
* @param serverId
* @param roleId
*/
export async function addBossInstance(code: string, serverId:number, roleId: string) {
let hisOnlineInfo = await getRoleOnlineInfo(roleId);
if(hisOnlineInfo.isOnline) {
let key = 'serverId_' + serverId + 'guildCode_' + code;
let value = roleId+ '|' + hisOnlineInfo.sid;
await saddAsync(key, [value]);
}
}
/**
* 给当前正在挑战的玩家下发血量同步信息
* @param code
* @param serverId
* @param bossHp
* @param isDelKey
*/
export async function pushBossHpMessage(code: string, serverId:number, bossHp:number, isDelKey?: boolean ) {
let key = 'serverId_' + serverId + 'guildCode_' + code;
let members = await smembersAsync(key);
let uids = members.map(member=>{
let arr = member.split('|');
let uid = arr[0];
let sid = arr[1];
return {uid, sid};
});
pinus.app.channelService.pushMessageByUids('onBossHpUpdate', resResult(STATUS.SUCCESS, {bossHp}), uids);
if (isDelKey) {
delAsync(key);
}
}
/**
* 检查该玩家当前是否正在挑战boss的队列中
* @param code
* @param serverId
* @param roleId
* @param battleCode
*/
export async function checkBossBattleMemberExists(code: string, serverId:number, roleId: string, battleCode:string ) {
let hisOnlineInfo = await getRoleOnlineInfo(roleId);
let key = 'serverId_' + serverId + 'guildCode_' + code ;
let value = roleId+ '|' + hisOnlineInfo.sid;
let flag = await sismemberAsync(key, value);
if (!flag) {
const battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true);
if(!battleRecord || battleRecord.status != 0 || roleId != battleRecord.roleId) {
return false;
}
await addBossInstance(code, serverId, roleId);
flag = true;
}
return flag;
}
/**
* 成员退出删除boss关排行信息
* @param guildCode
* @param roleId
*/
export async function removeBossRank(guildCode: string, roleId: string) {
await BossInstanceModel.removeBossRank(guildCode, roleId);
}