diff --git a/game-server/app/servers/battle/handler/ladderHandler.ts b/game-server/app/servers/battle/handler/ladderHandler.ts index 1767e61ed..ba92d9077 100644 --- a/game-server/app/servers/battle/handler/ladderHandler.ts +++ b/game-server/app/servers/battle/handler/ladderHandler.ts @@ -5,17 +5,16 @@ import { gameData } from '../../../pubUtils/data'; import { STATUS } from '../../../consts/statusCode'; import { resResult } from '../../../pubUtils/util'; import { LadderMatchModel, LadderUpdateInter } from '../../../db/LadderMatch'; -import { battleEndWhenChange, checkRank, generateInitRecInfo, getBuyCntCost, getLadderData, getLadderOppStatus, ladderBattleEndReward, refreshLadderDaily, refreshLadderEnemies } from '../../../services/ladderService'; +import { battleEndWhenChange, checkRank, generateInitRecInfo, getBuyCntCost, getLadderData, getLadderOppStatus, ladderBattleEndReward, refreshLadderDaily, refreshLadderEnemies, sendLadderDailyReward } from '../../../services/ladderService'; import { LadderDataReturn, LadderDefense, LadderDefenseHero, LadderOppDetailReturn, LadderOppLineupReturn, LadderOppPlayerHeroInfo, LadderOppPlayerReturn } from '../../../domain/battleField/ladder'; import { LadderMatchRecModel } from '../../../db/LadderMatchRec'; import { HeroModel } from '../../../db/Hero'; import { LADDER } from '../../../pubUtils/dicParam'; import { handleCost } from '../../../services/role/rewardService'; -import { ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, REDIS_KEY } from '../../../consts'; +import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, REDIS_KEY } from '../../../consts'; import { getHeroesAttributes } from '../../../services/playerCeService'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; -import { Rank } from '../../../services/rankService'; -import { WarReward } from '../../../services/warRewardService'; +import { ServerlistModel } from '../../../db/Serverlist'; export default function (app: Application) { new HandlerService(app, {}); @@ -40,8 +39,7 @@ export class LadderHandler { let { roleId: targetRoleId, rank } = msg; let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); - if(!checkRank(ladderData.rank, rank)) return resResult(STATUS.LADDER_RANK_ERROR); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); let { oppPlayers = [] } = ladderData; let curOppPlayer = oppPlayers.find(cur => cur.roleId == targetRoleId); @@ -66,7 +64,7 @@ export class LadderHandler { let { roleId: targetRoleId, rank, myRank } = msg; // 检查双方排名等,不行的刷新对手回去 let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); let { status, isRobot, hisLadderData } = await getLadderOppStatus(ladderData, targetRoleId, myRank, rank); if(status != LADDER_OPP_STATUS.BATTLE) { @@ -187,7 +185,7 @@ export class LadderHandler { let rank = rec.defenseInfo.oldRank; let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); // 取消 checkBattle 的倒计时 pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(battleCode); @@ -205,12 +203,12 @@ export class LadderHandler { rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess); } - let isBreak = ladderData.historyRank > atkLadderMatch.rank; - ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: isBreak? atkLadderMatch.rank: ladderData.historyRank, locked: 0 }); + let historyRank = ladderData.historyRank; + ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: historyRank > atkLadderMatch.rank? atkLadderMatch.rank: historyRank, locked: 0 }); result.setLadderData(ladderData, rec); // 获取奖励 - let { battleGoods, breakGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, isSuccess, isBreak, 1); + let { battleGoods, breakGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, isSuccess, historyRank, 1); return resResult(STATUS.SUCCESS, {...pick(result, ['rank', 'historyRank', 'challengeCnt','status', 'time', 'oppPlayers']), battleGoods, breakGoods}); } @@ -226,7 +224,7 @@ export class LadderHandler { } let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); if(ladderData.rank >= rank) return resResult(STATUS.LADDER_RANK_ERR); @@ -244,7 +242,7 @@ export class LadderHandler { ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update); // 获取奖励 - let { battleGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, true, false, count); + let { battleGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, true, rank, count); return resResult(STATUS.SUCCESS, { challengeCnt: ladderData.challengeCnt, @@ -282,7 +280,7 @@ export class LadderHandler { let sid = session.get('sid'); let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); let update: LadderUpdateInter = {}; // 刷新次数 @@ -340,4 +338,31 @@ export class LadderHandler { let list = await LadderMatchRecModel.findRec(roleId); return resResult(STATUS.SUCCESS, { list }); } + + // debug接口 + // 重置挑战次数 & 购买次数 + async resetCnt(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let roleId = session.get('roleId'); + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + await LadderMatchModel.updateByRoleId(roleId, { refDaily: new Date(Date.now() - 86400000) }); + return resResult(STATUS.SUCCESS); + } + + async sendDailyReward(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + for(let { serverId } of servers) { + await sendLadderDailyReward(serverId); + } + return resResult(STATUS.SUCCESS) + } } \ No newline at end of file diff --git a/game-server/app/services/ladderService.ts b/game-server/app/services/ladderService.ts index d1b66521a..d8bc0c1c7 100644 --- a/game-server/app/services/ladderService.ts +++ b/game-server/app/services/ladderService.ts @@ -1,14 +1,15 @@ -import { ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, PUSH_ROUTE, REDIS_KEY } from "../consts"; +import { ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY } from "../consts"; import { HeroType } from "../db/Hero"; import { LadderMatchModel, LadderMatchType, LadderUpdateInter } from "../db/LadderMatch"; import { LadderMatchRecModel } from "../db/LadderMatchRec"; import { RoleModel, RoleType } from "../db/Role"; import { LadderDataReturn, LadderDefense, LadderOppPlayerHeroInfo, LadderOppPlayerInDB, LadderOppPlayerInfo, LadderOppPlayerReturn } from "../domain/battleField/ladder"; import { RoleAndGuildRankInfo, RoleRankInfo } from "../domain/rank"; -import { gameData, getDicLadderMatchByMyRank } from "../pubUtils/data"; +import { gameData, getDicLadderMatchByMyRank, getLadderRankReward } from "../pubUtils/data"; import { EXTERIOR, LADDER } from "../pubUtils/dicParam"; -import { ItemInter } from "../pubUtils/interface"; +import { ItemInter, RewardInter } from "../pubUtils/interface"; import { getRandValueByMinMax, shouldRefresh } from "../pubUtils/util"; +import { sendMailByContent } from "./mailService"; import { sendMessageToUserWithSuc } from "./pushService"; import { Rank } from "./rankService"; import { addItems } from "./role/rewardService"; @@ -92,9 +93,9 @@ async function getOppPlayerDetailByDb(serverId: number, oppPlayers: LadderOppPla } // 获取redis当中的玩家排名数据 -export async function getLadderMatchByRank(serverId: number, from: number, to: number) { +export async function getLadderMatchByRank(serverId: number, max: number|'+inf', min: number|'-inf') { let r = new Rank(REDIS_KEY.LADDER, { serverId }, false, 3000); - let rawResults = await r.getRankByRangeRaw(from, to, false); + let rawResults = await r.getRankByRangeRaw(max, min, false); return rawResults.map(cur => ({ rank: cur.scores[0], roleId: cur.field })) } @@ -102,7 +103,7 @@ export async function refreshLadderEnemies(ladderData: LadderMatchType, update: let rankNumbers = randOppRankNumbers(ladderData.rank); // 随机出想要的排名 let min = rankNumbers[0], max = rankNumbers[rankNumbers.length - 1]; - let ranks = await getLadderMatchByRank(ladderData.serverId, min, max); + let ranks = await getLadderMatchByRank(ladderData.serverId, max, min); let oppPlayers: LadderOppPlayerReturn[] = [], oppPlayersSave: LadderOppPlayerInDB[] = []; for(let rank of rankNumbers) { @@ -188,6 +189,11 @@ export function checkRank(myRank: number, targetRank: number) { } else { // 向前打 if(myRank - dicLadderMatch.rangeBeforeMax > targetRank) return false; } + + if(targetRank <= 10 && !dicLadderMatch.topChallenge) { + return false + } + return true; } @@ -289,14 +295,19 @@ export async function battleEndWhenChange(ladderMatch: LadderMatchType) { return oppPlayers } -export async function ladderBattleEndReward(roleId: string, roleName: string, sid: string, rank: number, isSuccess: boolean, isBreak: boolean, num: number) { +export async function ladderBattleEndReward(roleId: string, roleName: string, sid: string, rank: number, isSuccess: boolean, historyRank: number, num: number) { let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); if(!dicLadderDifficultRatio) return null; let warReward = new WarReward(roleId, roleName, sid, dicLadderDifficultRatio.gkId, isSuccess); warReward.setLadderReward(dicLadderDifficultRatio.randomFailReward, true); warReward.setLadderReward(dicLadderDifficultRatio.randomWinReward, false); let battleGoods = await warReward.saveReward(num); - let breakGoods = isBreak? await addItems(roleId, roleName, sid, dicLadderDifficultRatio?.onceReward||[], ITEM_CHANGE_REASON.LADDER_BATTLE_REWARD): []; + let breakRewards: RewardInter[] = []; + for(let i = historyRank - 1; i >= rank; i--) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(i); + breakRewards.push(...(dicLadderDifficultRatio?.onceReward||[])); + } + let breakGoods = breakRewards.length > 0? await addItems(roleId, roleName, sid, dicLadderDifficultRatio?.onceReward||[], ITEM_CHANGE_REASON.LADDER_BATTLE_REWARD): []; return { battleGoods, breakGoods }; } @@ -315,4 +326,14 @@ export function completeLadderRanks(ranks: RoleAndGuildRankInfo[]) { } } return result; +} + +export async function sendLadderDailyReward(serverId: number) { + let ranks = await getLadderMatchByRank(serverId, '+inf', '-inf'); + for(let { rank, roleId } of ranks) { + let dicRankReward = getLadderRankReward(rank); + if(dicRankReward && dicRankReward.reward && dicRankReward.reward.length > 0) { + await sendMailByContent(MAIL_TYPE.LADDER, roleId, { params: [`${rank}`], goods: dicRankReward.reward }); + } + } } \ No newline at end of file diff --git a/game-server/app/services/rankService.ts b/game-server/app/services/rankService.ts index 92c415c1c..27980ac50 100644 --- a/game-server/app/services/rankService.ts +++ b/game-server/app/services/rankService.ts @@ -708,7 +708,7 @@ export class Rank { } // 获取区间里的排行榜,格式 {rank, field, score}[] - public async getRankByRangeRaw(from: number | string = '+inf', to: number | string = '-inf', isReverse = true) { + public async getRankByRangeRaw(max: number | string = '+inf', min: number | string = '-inf', isReverse = true) { let ranks: { rank: number, field: string, scores: number[] }[] = []; let key = this.keyName.getName(); if (this.isUnion) { @@ -716,8 +716,8 @@ export class Rank { } const rankFromDb = isReverse? - (await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES")): - (await redisClient().zrangebyscoreAsync(key, from, to, "WITHSCORES")); + (await redisClient().zrevrangebyscoreAsync(key, max, min, "WITHSCORES")): + (await redisClient().zrangebyscoreAsync(key, min, max, "WITHSCORES")); let num = 0; for (let ii = 0; ii < rankFromDb.length; ii += 2) { @@ -728,8 +728,8 @@ export class Rank { return ranks } - public async getRankByRange(from: number | string = '+inf', to: number | string = '-inf', isReverse = true) { - let raws = await this.getRankByRangeRaw(from, to, isReverse); + public async getRankByRange(max: number | string = '+inf', min: number | string = '-inf', isReverse = true) { + let raws = await this.getRankByRangeRaw(max, min, isReverse); let ranks = new Array(); for (let { rank, field, scores } of raws) { @@ -1186,7 +1186,7 @@ export async function getRankInHandler(redisKey: REDIS_KEY, type: RANK_TYPE, key return result })); - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId, guildCode }, type == RANK_TYPE.LADDER); + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId, guildCode }, type != RANK_TYPE.LADDER); if (!myRank) { let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); if (type == RANK_TYPE.TOP_LINTUP) { diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 50fc8a3c0..f00e5abfd 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -39,7 +39,7 @@ import { resResult } from '../pubUtils/util'; import { checkPopUpConditionWhenGuildActivityEnd } from './activity/popUpShopService'; import { pushRefreshTime } from './connectorService'; import { sendUnReceivedActivityDailyCoin } from './activity/dailyCoinService'; -import { ladderTimeout } from './ladderService'; +import { ladderTimeout, sendLadderDailyReward } from './ladderService'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -97,6 +97,9 @@ export async function init() { // 限时排行榜 await initTimeLimitRank(); + + // 名将擂台每日奖励 + await ladderDailyReward(); } // 每日刷新 @@ -751,4 +754,12 @@ export async function cancelLadderCountDown(battleCode: string) { } } +async function ladderDailyReward() { + scheduleJob('ladderDailyReward', '0 0 22 * * ?', async () => { + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + for(let { serverId } of servers) { + await sendLadderDailyReward(serverId); + } + }); +} // —————————————— 名将擂台 end —————————————— // \ No newline at end of file diff --git a/shared/consts/constModules/mailConst.ts b/shared/consts/constModules/mailConst.ts index d1386a4f2..64646481c 100644 --- a/shared/consts/constModules/mailConst.ts +++ b/shared/consts/constModules/mailConst.ts @@ -56,6 +56,7 @@ export enum MAIL_TYPE { PVP_BOX = 27, // pvp巅峰之路宝箱 DAILY_COIN = 28, // 招财进宝宝箱 GUILD_DISSMISS = 29, // 军团解散 + LADDER = 30, // 名将擂台 }; export const SEND_NAME = '系统'; diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index bc9141a21..ff7a025c9 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -997,6 +997,16 @@ export function getDicLadderMatchByMyRank(myRank: number) { return null } +export function getLadderRankReward(myRank: number) { + for(let dic of gameData.ladderRankReward) { + let { rankMin, rankMax } = dic; + if(rankMin < myRank && (rankMax >= myRank || rankMax == -1) ) { + return dic; + } + } + return null +} + // 初始加载 function initDatas() { parseDicParam(); diff --git a/shared/pubUtils/dictionary/DicLadderRankReward.ts b/shared/pubUtils/dictionary/DicLadderRankReward.ts index e6e6ac05f..e75541ef9 100644 --- a/shared/pubUtils/dictionary/DicLadderRankReward.ts +++ b/shared/pubUtils/dictionary/DicLadderRankReward.ts @@ -18,7 +18,7 @@ export const dicLadderRankReward: DicLadderRankReward[] = []; export function loadLadderRankReward() { dicLadderRankReward.splice(0, dicLadderRankReward.length); - let arr = readFileAndParse(FILENAME.DIC_LADDER_DIFFICULTRATIO); + let arr = readFileAndParse(FILENAME.DIC_LADDER_RANKREWARD); arr.forEach(o => { o.reward = parseGoodStr(o.reward) dicLadderRankReward.push(o); diff --git a/shared/pubUtils/redis.ts b/shared/pubUtils/redis.ts index b1d6318cc..dd1638e04 100644 --- a/shared/pubUtils/redis.ts +++ b/shared/pubUtils/redis.ts @@ -49,7 +49,7 @@ declare module 'redis' { // 返回有序集中指定分数区间内的成员,分数从高到低排序 zrevrangebyscoreAsync(key: string, max: (string|number), min: (string|number), withscores?: string, limit?:string, offset?: number, count?:number): Promise; // 返回有序集中指定分数区间内的成员,分数从高到低排序 - zrangebyscoreAsync(key: string, max: (string|number), min: (string|number), withscores?: string, limit?:string, offset?: number, count?:number): Promise; + zrangebyscoreAsync(key: string, min: (string|number), max: (string|number), withscores?: string, limit?:string, offset?: number, count?:number): Promise; // 获取有序集合的成员数 zcardAsync(key: string): Promise; // 移除有序集合中给定的排名区间的所有成员 diff --git a/shared/resource/jsons/dic_email_content.json b/shared/resource/jsons/dic_email_content.json index 943b4c404..6105bc229 100644 --- a/shared/resource/jsons/dic_email_content.json +++ b/shared/resource/jsons/dic_email_content.json @@ -208,5 +208,12 @@ "sendName": "&", "content": "很抱歉,您的军团已被解散,振作起来寻找新的军团加入吧", "time": 720 + }, + { + "id": 30, + "title": "&", + "sendName": "&", + "content": "您在昨日的名将擂台中获得了第%d名,排名奖励已发送至您的邮箱,请查收", + "time": 720 } ] \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_ladder_rankReward.json b/shared/resource/jsons/dic_zyz_ladder_rankReward.json index 35790052a..695ab65f2 100644 --- a/shared/resource/jsons/dic_zyz_ladder_rankReward.json +++ b/shared/resource/jsons/dic_zyz_ladder_rankReward.json @@ -3,54 +3,60 @@ "id": 1, "rankMin": 0, "rankMax": 1, - "reward": "31002&1000" + "reward": "31002&900|31001&5000" }, { "id": 2, "rankMin": 1, "rankMax": 10, - "reward": "31002&1000" + "reward": "31002&800|31001&4000" }, { "id": 3, "rankMin": 10, "rankMax": 50, - "reward": "31002&1000" + "reward": "31002&700|31001&3000" }, { "id": 4, "rankMin": 50, "rankMax": 100, - "reward": "31002&1000" + "reward": "31002&600|31001&2000" }, { "id": 5, "rankMin": 100, "rankMax": 200, - "reward": "31002&1000" + "reward": "31002&500|31001&2000" }, { "id": 6, "rankMin": 200, "rankMax": 500, - "reward": "31002&1000" + "reward": "31002&400|31001&2000" }, { "id": 7, "rankMin": 500, "rankMax": 1000, - "reward": "31002&1000" + "reward": "31002&300|31001&2000" }, { "id": 8, "rankMin": 1000, "rankMax": 2000, - "reward": "31002&1000" + "reward": "31002&200|31001&2000" }, { "id": 9, "rankMin": 2000, + "rankMax": 3000, + "reward": "31002&100|31001&1000" + }, + { + "id": 10, + "rankMin": 3000, "rankMax": -1, - "reward": "31002&1000" + "reward": "31002&100|31001&500" } ] \ No newline at end of file