diff --git a/game-server/app.ts b/game-server/app.ts index ad6e40c39..5e328d422 100644 --- a/game-server/app.ts +++ b/game-server/app.ts @@ -207,7 +207,10 @@ async function treatStartLogic(app: _pinus.Application) { setGVGServerGroup(); } if(app.getServerType() == 'guild') { - setGVGConfig().then(initTeamToMem); + setGVGConfig(); + app.event.on('start_all', () => { + initTeamToMem(); + }); } if(app.isMaster()) { diff --git a/game-server/app/servers/guild/handler/gvgBattleHandler.ts b/game-server/app/servers/guild/handler/gvgBattleHandler.ts index 31e725426..c9c7a1ba9 100644 --- a/game-server/app/servers/guild/handler/gvgBattleHandler.ts +++ b/game-server/app/servers/guild/handler/gvgBattleHandler.ts @@ -8,7 +8,7 @@ import { Application, BackendSession, ChannelService, HandlerService } from "pin import { resResult, genCode } from "../../../pubUtils/util"; import { GVGLeagueModel } from '../../../db/GVGLeague'; import { checkGVGPeriod, getGroupIdOfServer, getGVGConfig, getGVGPeriodData, getGVGServerType } from '../../../services/gvg/gvgService'; -import { calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBirthAreaOfCity, getGVGWarId, getOppHeroes, initRobots, teamBreak } from '../../../services/gvg/gvgBattleService'; +import { addBattleRankScore, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanks, getBirthAreaOfCity, getGVGWarId, getOppHeroes, initRobots, teamBreak } from '../../../services/gvg/gvgBattleService'; import { getGVGBattleData } from '../../../services/gvg/gvgBattleMemory'; import { nowSeconds } from '../../../pubUtils/timeUtil'; import { GVGBattleRecModel } from '../../../db/GVGBattleRec'; @@ -23,7 +23,7 @@ import { sendMessageToUserWithSuc } from '../../../services/pushService'; import { GVGHeroInfo } from '../../../domain/dbGeneral'; import { ArtifactModel } from '../../../db/Artifact'; import { getHeroesAttributes } from '../../../services/playerCeService'; -import { gvgBattleStartSchedule } from '../../../services/timeTaskService'; +import { gvgBattleEndSchedule, gvgBattleStartSchedule } from '../../../services/timeTaskService'; export default function (app: Application) { new HandlerService(app, {}); @@ -204,10 +204,11 @@ export class GVGBattleHandler { const recs = await GVGRecModel.findByCity(cityId, configId); const teamResult = teams.map(team => new MyTeamInfo(team)); + const { ranks, myRank } = await getBattleRanks(configId, groupId, serverType, cityId, myLeague); return resResult(STATUS.SUCCESS, { cityId, - ranks: [], // ! redis 中积分排行榜 + ranks, myRank, recs, teams: teamResult, }); @@ -450,18 +451,15 @@ export class GVGBattleHandler { // 计算并更新两支队伍耐久 let { win, fail } = gameData.gvgBattleDurabilityMinus; - attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, calBattleScoreByCe(isSuccess, attackTeam.lineupCe)); - defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, calBattleScoreByCe(isSuccess, defenseTeam.lineupCe)); - - if(attackTeam.durability <= 0) { - attackTeam = await teamBreak(city, attackTeam); - } - if(defenseTeam.durability <= 0) { - if(defenseTeam.pointId > 0 && attackTeam.durability > 0) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 - attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.pointId); - } - defenseTeam = await teamBreak(city, defenseTeam); + let attackScore = calBattleScoreByCe(isSuccess, attackTeam.lineupCe); + let defenseScore = calBattleScoreByCe(!isSuccess, defenseTeam.lineupCe); + attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, attackScore, getBirthAreaOfCity(city, attackTeam.leagueCode)); + defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, defenseScore, getBirthAreaOfCity(city, defenseTeam.leagueCode)); + if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !attackTeam.curTeamBreak) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 + attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); } + await addBattleRankScore(attackTeam, attackScore); + await addBattleRankScore(defenseTeam, defenseScore); // 更新内存 let teamObj = getGVGBattleData(groupId, serverType); @@ -513,5 +511,11 @@ export class GVGBattleHandler { async debugStartSchedule() { await gvgBattleStartSchedule(); + return resResult(STATUS.SUCCESS); + } + + async debugEndSchedule() { + await gvgBattleEndSchedule(); + return resResult(STATUS.SUCCESS); } } diff --git a/game-server/app/servers/guild/handler/gvgHandler.ts b/game-server/app/servers/guild/handler/gvgHandler.ts index 5b0370ece..e7032d8b2 100644 --- a/game-server/app/servers/guild/handler/gvgHandler.ts +++ b/game-server/app/servers/guild/handler/gvgHandler.ts @@ -357,10 +357,6 @@ export class GVGHandler { if (!!res.err) return resResult(STATUS.REDLOCK_ERR); let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - if(!leaguePrepare || leaguePrepare.lv < dicTech.levelLimit) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_LV_NOT_ENOUGH); - } if(checkTechIsIng(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) { res.releaseCallback(); @@ -409,6 +405,9 @@ export class GVGHandler { if(!checkTechIsIng(techId, [], leaguePrepare?.techQueue||[])) { return resResult(STATUS.GVG_TECH_NOT_QUEUE); } + if(!leaguePrepare || leaguePrepare.lv < dicTech.levelLimit) { + return resResult(STATUS.GVG_TECH_LV_NOT_ENOUGH); + } // 扣战功 const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.BATTLE_FEAT, count: battleFeats }], [], ITEM_CHANGE_REASON.GVG_ACTIVE_TECH); diff --git a/game-server/app/servers/guild/remote/guildRemote.ts b/game-server/app/servers/guild/remote/guildRemote.ts index d856a230c..b7e698933 100644 --- a/game-server/app/servers/guild/remote/guildRemote.ts +++ b/game-server/app/servers/guild/remote/guildRemote.ts @@ -8,7 +8,7 @@ import { setHiddenData } from '../../../services/dataService'; import { setKvToMemory } from '../../../services/pushService'; import { getGVGConfig, setGVGConfig, setGVGServerGroup } from '../../../services/gvg/gvgService'; import { GVGConfigType } from '../../../db/GVGConfig'; -import { catapultHurt, gvgBattleStart, initCatapult } from '../../../services/gvg/gvgBattleService'; +import { catapultHurt, gvgBattleEnd, gvgBattleSeconds, gvgBattleStart, initCatapult } from '../../../services/gvg/gvgBattleService'; export default function (app: Application) { new HandlerService(app, {}); @@ -143,4 +143,20 @@ export class GuildRemote { errlogger.error(`remote ${__filename} \n ${e.stack}`); } } + + public async gvgBattleSeconds() { + try { + return await gvgBattleSeconds(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gvgBattleEnd() { + try { + return await gvgBattleEnd(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } } \ No newline at end of file diff --git a/game-server/app/services/gvg/gvgBattleMemory.ts b/game-server/app/services/gvg/gvgBattleMemory.ts index 38fd8ae20..188125777 100644 --- a/game-server/app/services/gvg/gvgBattleMemory.ts +++ b/game-server/app/services/gvg/gvgBattleMemory.ts @@ -15,7 +15,7 @@ class GVGBattleData { public serverType: number; // 单服还是跨服 private teams: Map = new Map(); // 队伍, teamCode => team - private rolePoints: Map> = new Map(); // roleId => pointId[],用于更新玩家的积分 + private rolePoints: Map> = new Map(); // roleId => pointId[],用于更新玩家的积分 private roleToTeam: Map = new Map(); // roleId => teamCode private areaToTeams: Map> = new Map(); // areaId => teamCode set,用于定时下发地图玩家数据 @@ -63,9 +63,9 @@ class GVGBattleData { this.teams.set(team.teamCode, new GVGTeamMem(team)) } this.teams.get(team.teamCode).setCity(team.cityId, team.areaId, team.pointId); - if(team.pointId > 0) { - if(!this.rolePoints.has(team.roleId)) this.rolePoints.set(team.roleId, new Set()); - this.rolePoints.get(team.roleId).add(team.pointId); + if(team.pointId > 0 && !team.isRobot) { + if(!this.rolePoints.has(team.roleId)) this.rolePoints.set(team.roleId, new Map()); + this.rolePoints.get(team.roleId).set(team.pointId, team.teamCode); } let teamCodesOfRole = this.roleToTeam.get(team.roleId)||[]; if(teamCodesOfRole.indexOf(team.teamCode) == -1) teamCodesOfRole.push(team.teamCode); @@ -87,14 +87,14 @@ class GVGBattleData { } } - private setRolePoints(roleId: string, fromPointId: number, pointId: number) { + private setRolePoints(roleId: string, fromPointId: number, pointId: number, teamCode: string) { if(fromPointId > 0 && pointId == 0) { // 被打得撤离积分点 if(this.rolePoints.has(roleId) && this.rolePoints.get(roleId).has(pointId)) { this.rolePoints.get(roleId).delete(pointId); } } else if (fromPointId == 0 && pointId > 0) { - if(!this.rolePoints.has(roleId)) this.rolePoints.set(roleId, new Set()); - this.rolePoints.get(roleId).add(pointId); + if(!this.rolePoints.has(roleId)) this.rolePoints.set(roleId, new Map()); + this.rolePoints.get(roleId).set(pointId, teamCode); } } @@ -117,7 +117,7 @@ class GVGBattleData { let teamMem = this.teams.get(teamCode); if(!teamMem) return; let { pointId: fromPointId } = teamMem; - this.setRolePoints(roleId, fromPointId, pointId); + this.setRolePoints(roleId, fromPointId, pointId, teamCode); teamMem.pointId = pointId; } @@ -130,7 +130,7 @@ class GVGBattleData { } let { areaId: fromAreaId, pointId: fromPointId } = teamMem; teamMem.updateTeam(team); - this.setRolePoints(team.roleId, fromPointId, team.pointId); + this.setRolePoints(team.roleId, fromPointId, team.pointId, team.teamCode); this.setAreaMap(team.teamCode, fromAreaId, team.areaId); } } @@ -140,6 +140,18 @@ class GVGBattleData { let teamCodes = this.roleToTeam.get(GVG_CATAPULT)||[]; return teamCodes.map(teamCode => this.teams.get(teamCode)); } + + // 积分点情况 + public findSettledPoint() { + let teams: GVGTeamMem[] = []; + for(let [_roleId, pointIds] of this.rolePoints) { + for(let [pointId, teamCode] of pointIds) { + let team = this.teams.get(teamCode); + if(pointId > 0 && team) teams.push(team); + } + } + return teams; + } } export function getGVGBattleData(groupId: number, serverType: number) { @@ -156,6 +168,7 @@ export function getGVGBattleMap() { export async function initTeamToMem() { let sid = pinus.app.getServerId(); + console.log('##### initTeamToMem', sid) let servers = pinus.app.getServersByType('guild'); let { configId, period } = getGVGPeriodData(); // if(period != GVG_PERIOD.BATTLE) return; diff --git a/game-server/app/services/gvg/gvgBattleService.ts b/game-server/app/services/gvg/gvgBattleService.ts index 2757b9430..54118532c 100644 --- a/game-server/app/services/gvg/gvgBattleService.ts +++ b/game-server/app/services/gvg/gvgBattleService.ts @@ -3,7 +3,7 @@ import { GVGLeagueType } from "../../db/GVGLeague"; import { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from "../../db/GVGTeam"; import { GVGCityModel, GVGCityType } from "../../db/GVGCity"; import { gameData } from "../../pubUtils/data"; -import { GVG_AREA_TYPE, GVG_TECH_TYPE, STATUS } from "../../consts"; +import { GVG_AREA_TYPE, GVG_TECH_TYPE, REDIS_KEY, STATUS } from "../../consts"; import { nowSeconds } from "../../pubUtils/timeUtil"; import { DicGVGAreaPoint } from "../../pubUtils/dictionary/DicGVGAreaPoint"; import { getGVGBattleData, getGVGBattleMap } from "./gvgBattleMemory"; @@ -15,6 +15,9 @@ import { getGVGConfig } from "./gvgService"; import { GVGLeaguePrepareModel } from "../../db/GVGLeaguePrepare"; import { pinus } from "pinus"; import { dispatch } from "../../pubUtils/dispatcher"; +import { Rank } from "../rankService"; +import { LeagueRankInfo } from "../../domain/rank"; +import { findKeys } from "../redisService"; /** @@ -79,19 +82,19 @@ export function checkMoveStatus(team: GVGTeamType, cityId: number, areaId: numbe return STATUS.SUCCESS; } -export async function initRobots(confidId: number, groupId: number, serverType: number, cityId: number) { +export async function initRobots(configId: number, groupId: number, serverType: number, cityId: number) { let robotTeams = await GVGTeamModel.findRobotTeams(groupId, serverType, cityId); let updateDicPoints: DicGVGAreaPoint[] = []; let { areaIds = []} = gameData.gvgCity.get(cityId); for(let [_, point] of gameData.gvgAreaPoint) { if(areaIds.indexOf(point.areaId) == -1) continue; let robotTeam = robotTeams.find(team => team.pointId == point.pointId); - if(!robotTeam || (!robotTeam.isBroken && robotTeam.configId != confidId) ) { + if(!robotTeam || (!robotTeam.isBroken && robotTeam.configId != configId) ) { updateDicPoints.push(point); } } if(updateDicPoints.length > 0) { - robotTeams = await GVGTeamModel.initRobots(confidId, groupId, serverType, cityId, updateDicPoints); + robotTeams = await GVGTeamModel.initRobots(configId, groupId, serverType, cityId, updateDicPoints); // 存入内存 let teamObj = getGVGBattleData(groupId, serverType); teamObj.enterCity(...robotTeams); @@ -169,6 +172,7 @@ export function checkGVGBattleStart(roleId: string, attackTeam: GVGTeamType, def return STATUS.SUCCESS; } +// —————————— 定时器相关 —————————— // // gvg激战期开始定时器 export async function gvgBattleStart() { let servers = pinus.app.getServersByType('guild'); @@ -209,7 +213,7 @@ export async function initCatapult(cityId: number, groupId: number, serverType: // 投石车投伤害 export async function catapultHurt() { - for(let [_, teamObj] of getGVGBattleMap()) { + for(let [_key, teamObj] of getGVGBattleMap()) { let teams = teamObj.findCatapult(); for(let catapult of teams) { if(catapult.isBroken) continue; @@ -221,4 +225,79 @@ export async function catapultHurt() { teamObj.battleEnd(teams); } } +} + +// 排行榜积分更新 +export async function addBattleRankScore(gvgTeam: GVGTeamType, incScore: number) { + let { configId, groupId, serverType, cityId, roleId, leagueCode, isRobot } = gvgTeam; + if(isRobot) return; + + let r1 = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupId, serverType, cityId }); + r1.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true); + + let r2 = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupId, serverType, cityId }); + r2.setRankWithLeagueInfo(leagueCode, incScore, Date.now(), null, true); +} + +// 获取排行榜 +export async function getBattleRanks(configId: number, groupId: number, serverType: number, cityId: number, myLeague: GVGLeagueType) { + let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupId, serverType, cityId }); + r.setGenerFieldsFun((obj => { + if(obj instanceof LeagueRankInfo) { + return { rank: obj.rank, leagueCode: obj.code, leagueName: obj.name, score: obj.num } + } + return obj + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ leagueCode: myLeague.leagueCode }); + if (!myRank) { + myRank = await r.generMyRankWithLeague(myLeague.leagueCode, 0, 0, myLeague); + } + return { ranks, myRank } +} + +// 每5秒一次结算 +export async function gvgBattleSeconds() { + // 每5秒给据点上的人加积分 + for(let [_key, teamObj] of getGVGBattleMap()) { + let teams = teamObj.findSettledPoint(); + for(let teamMem of teams) { + if(teamMem.isBroken || teamMem.durability <= 0) continue; + let addScore = gameData.gvgAreaPoint.get(teamMem.pointId)?.score||0; + let team = await GVGTeamModel.addScore(teamMem.teamCode, addScore); + await addBattleRankScore(team, addScore); + } + } + // 向下推送区域数据 + +} + +export async function gvgBattleEnd() { + let { configId } = getGVGConfig(); + let guardLeagueCnt = new Map(); + + // 城池占领情况 + let keys = await findKeys(`${REDIS_KEY.GVG_BATTLE_LEAGUE_RANK}:${configId}:`); + let rankKeys = keys.map(key => { + let [,, _groupId, _serverType, _cityId] = key.split(':'); + return { groupId: parseInt(_groupId), serverType: parseInt(_serverType), cityId: parseInt(_cityId) }; + }).sort((a, b) => b.cityId - a.cityId); + + for(let { groupId, serverType, cityId } of rankKeys) { + let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupId, serverType, cityId }); + let ranks = await r.getRankByRange(); + for(let obj of ranks) { // 排名最高 + let rank = obj; + let cnt = guardLeagueCnt.get(rank.code)||0; + if(cnt < GVG.GVG_CITY_OCCUPIED_NUMBER) { + await GVGCityModel.guardCity(configId, groupId, serverType, cityId, rank); + guardLeagueCnt.set(rank.code, cnt + 1); + break; + } + } + } + + // 排行榜发放奖励 + + } \ No newline at end of file diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index f07a433e2..0c92c403d 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -16,6 +16,7 @@ import { RoleModel, RoleType } from '../db/Role'; import { GuildType } from '../db/Guild'; import { ActivityGroupModel } from '../db/ActivityGroup'; import { LadderMatchModel, LadderMatchType } from '../db/LadderMatch'; +import { isDevelopEnv } from './utilService'; /** * 在服务重新启动时,将信息存入redis @@ -50,7 +51,8 @@ export async function initAllRank() { await delKeys(REDIS_KEY.LADDER); await delKeys(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL); await delKeys(REDIS_KEY.GVG_VESTIGE_LEAGUE); - await delKeys(REDIS_KEY.LEAGUE_INFO); + // 测试服特殊处理,由于重启较频繁且联军数据较少,数据先不删,正式服激战期间不会重启 + if(!isDevelopEnv()) await delKeys(REDIS_KEY.LEAGUE_INFO); await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {}); await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, {}); diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 529c838da..8c8c91321 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -32,7 +32,7 @@ import { TimeLimitRankData } from '../domain/activityField/timeLimitRankField'; import { sendRankMail, takeSnapshot } from './activity/timeLimitRankService'; import { ActivityGroupModel } from '../db/ActivityGroup'; import { sendMessageToServer } from './pushService'; -import { resResult } from '../pubUtils/util'; +import { getRandEelm, getRandSingleEelm, resResult } from '../pubUtils/util'; import { checkPopUpConditionWhenGuildActivityEnd } from './activity/popUpShopService'; import { pushRefreshTime } from './connectorService'; import { sendUnReceivedActivityDailyCoin } from './activity/dailyCoinService'; @@ -45,6 +45,7 @@ import { setHiddenData, setHiddenDataToMemory } from './dataService'; import { GVGConfigModel } from '../db/GVGConfig'; import { createNewGVGConfig, initLeaguePrepare } from './gvg/gvgService'; import { getFightTimeByPeriod, saveVestigeRankSchedule } from './gvg/gvgFightService'; +import { gvgBattleEnd } from './gvg/gvgBattleService'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -928,7 +929,7 @@ export async function gvgBattleStartSchedule() { // 初始化投石车 let guildServers = pinus.app.getServersByType('guild'); if(guildServers.length > 0) { - pinus.app.rpc.guild.guildRemote.gvgBattleStart.toServer(guildServers[0].id); + pinus.app.rpc.guild.guildRemote.gvgBattleStart.toServer(getRandSingleEelm(guildServers).id); } // 发放道具 if(gvgBattleSecondJob) gvgBattleSecondJob.cancel(); @@ -939,7 +940,8 @@ export async function gvgBattleStartSchedule() { // 每隔5秒的积分计算定时器 async function gvgBattleSecondSchedule() { - // console.log('********** gvgBattleSecondJob *************'); + console.log('********** gvgBattleSecondJob *************'); + pinus.app.rpc.guild.guildRemote.gvgBattleSeconds.broadcast(); } // 每隔10秒的投石车投机定时器 @@ -949,9 +951,11 @@ async function gvgBattleCatapult() { } // gvg激战期结束定时器 -async function gvgBattleEndSchedule() { - // 排行榜发放奖励 - // 城池占领情况 +export async function gvgBattleEndSchedule() { + let guildServers = pinus.app.getServersByType('guild'); + if(guildServers.length > 0) { + pinus.app.rpc.guild.guildRemote.gvgBattleEnd.toServer(getRandSingleEelm(guildServers).id); + } // 定时器关闭 if(gvgBattleSecondJob) { gvgBattleSecondJob.cancel(); diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index d7b9cd806..9ed6b956e 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -259,6 +259,8 @@ export enum REDIS_KEY { GVG_VESTIGE_MEMBER_ALL = 'vestigeUsrAll', // 玩家所有遗迹积分 GVG_VESTIGE_LEAGUE = 'vestigeLeague', // 联军所有遗迹积分 LEAGUE_INFO ="leagueInfo", // 联军信息 + GVG_BATTLE_RANK ="gvgBattleUsr", // 激战期个人排行榜 + GVG_BATTLE_LEAGUE_RANK = "gvgBattleLeague", // 激战期联军排行榜 } // 各排行榜对应hash的key @@ -314,7 +316,11 @@ export function getInfoKeyByRedisKey(redisKey: REDIS_KEY) { case REDIS_KEY.GVG_VESTIGE_MEMBER_ALL: // 全遗迹玩家排行榜 return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; case REDIS_KEY.GVG_VESTIGE_LEAGUE: // 遗迹联军排行榜 - return { infoKey: REDIS_KEY.LEAGUE_INFO, extraKey: [] } + return { infoKey: REDIS_KEY.LEAGUE_INFO, extraKey: [] }; + case REDIS_KEY.GVG_BATTLE_RANK: // 激战期玩家排行榜 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.GVG_BATTLE_LEAGUE_RANK: // 激战期联军排行榜 + return { infoKey: REDIS_KEY.LEAGUE_INFO, extraKey: [] }; default: return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; } @@ -414,6 +420,8 @@ export const KEY_TO_COMPOSE_FIELD = new Map([ [REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, COMPOSE_FIELD_TYPE.ROLE], [REDIS_KEY.GVG_VESTIGE_LEAGUE, COMPOSE_FIELD_TYPE.LEAGUE], [REDIS_KEY.LEAGUE_INFO, COMPOSE_FIELD_TYPE.LEAGUE], + [REDIS_KEY.GVG_BATTLE_RANK, COMPOSE_FIELD_TYPE.ROLE], + [REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, COMPOSE_FIELD_TYPE.LEAGUE], ]); diff --git a/shared/db/GVGCity.ts b/shared/db/GVGCity.ts index b50c42ffa..afaab25c2 100644 --- a/shared/db/GVGCity.ts +++ b/shared/db/GVGCity.ts @@ -1,5 +1,6 @@ import BaseModel from "./BaseModel"; import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; +import { LeagueRankInfo } from "../domain/rank"; class Player { @prop({ required: true }) @@ -44,14 +45,6 @@ export default class GVGCity extends BaseModel { @prop({ required: true, default: 0 }) userCnt: number; // 城池人数 - // 创建城市 - public static async createCity(configId: number, groupId: number, serverType: number, cityId: number) { - let doc = new GVGCityModel(); - let update = Object.assign(doc.toJSON(), { configId, cityId, groupId, serverType}); - const city: GVGCityType = await GVGCityModel.findOneAndUpdate({ configId, cityId, groupId, serverType }, { $setOnInsert: update }, { upsert: true, new: true }).lean(); - return city; - } - // 通过 cityId 获取城市 public static async findByCityId(configId: number, groupId: number, serverType: number, cityId: number) { const city: GVGCityType = await GVGCityModel.findOne({ configId, groupId, serverType, cityId }).lean(); @@ -81,6 +74,15 @@ export default class GVGCity extends BaseModel { const cities: GVGCityType[] = await GVGCityModel.find({ configId, hasGuard: true }).lean(); return cities } + + // 占领城池 + public static async guardCity(configId: number, groupId: number, serverType: number, cityId: number, league: LeagueRankInfo) { + console.log('##### guardCity', configId, groupId, serverType, cityId) + const city: GVGCityType = await GVGCityModel.findOneAndUpdate({ configId: configId + 1, cityId, groupId, serverType }, { $set: { + hasGuard: true, guardLeague: league.code, guardLeagueName: league.name, guardLeagueIcon: league.icon + } }, { upsert: true, new: true }).lean(); + return city; + } } diff --git a/shared/db/GVGTeam.ts b/shared/db/GVGTeam.ts index 52f41854c..58dfff809 100644 --- a/shared/db/GVGTeam.ts +++ b/shared/db/GVGTeam.ts @@ -253,30 +253,42 @@ export default class GVGTeam extends BaseModel { } // 结算挑战方 - public static async battleEndAttack(teamCode: string, hpInc: number, playerScoreInc: number) { - const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $inc: { durability: hpInc, playerScore: playerScoreInc } }, { new: true }).lean(); + public static async battleEndAttack(teamCode: string, hpInc: number, playerScoreInc: number, rebirthAreaId: number) { + let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $inc: { durability: hpInc, score: playerScoreInc } }, { new: true }).lean(); + if(team.durability <= 0) { + team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId); + } return team; } + originPointId: number; // 结算防守方 - public static async battleEndDefense(teamCode: string, hpInc: number, playerScoreInc: number) { - const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { defenseTime: nowSeconds() + GVG.GVG_DEFAULT_DEFENSE_CD, lockTime: 0, lockTeamCode: '' }, $inc: { durability: hpInc, playerScore: playerScoreInc } }, { new: true }).lean(); + public static async battleEndDefense(teamCode: string, hpInc: number, playerScoreInc: number, rebirthAreaId: number) { + let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { defenseTime: nowSeconds() + GVG.GVG_DEFAULT_DEFENSE_CD, lockTime: 0, lockTeamCode: '' }, $inc: { durability: hpInc, score: playerScoreInc } }, { new: true }).lean(); + if(team.durability <= 0) { + let originPointId = team.pointId; + team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId); + team.originPointId = originPointId; + } return team; } + curTeamBreak: boolean; // 队伍进入修整器 public static async teamBreak(teamCode: string, isRobot: boolean, maxDurability: number, areaId: number) { if(!isRobot) { const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { restartTime: nowSeconds() + GVG.GVG_DEFAULT_DEFENSE_CD, stopMoveTime: nowSeconds(), areaId, durability: maxDurability } }, { new: true }).lean(); + team.curTeamBreak = true; return team; } else { const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { durability: 0, isBroken: true } }, { new: true }).lean(); + team.curTeamBreak = true; return team; } } public static async findByAreaId(groupId: number, serverType: number, cityId: number, areaId: number) { - const team: GVGTeamType[] = await GVGTeamModel.find({ groupId, serverType, cityId, areaId, stopMoveTime: { $lte: nowSeconds() } }).lean(); + const team: GVGTeamType[] = await GVGTeamModel.find({ groupId, serverType, cityId, areaId, stopMoveTime: { $lte: nowSeconds() }, isBroken: false }).lean(); return team; } @@ -287,7 +299,7 @@ export default class GVGTeam extends BaseModel { // 这个编队上是否已经有队伍了 public static async checkPoint(configId: number, groupId: number, serverType: number, pointId: number) { - return await GVGTeamModel.exists({ configId, groupId, serverType, pointId }); + return await GVGTeamModel.exists({ configId, groupId, serverType, pointId, isBroken: false }); } // 投石车伤害 @@ -303,6 +315,12 @@ export default class GVGTeam extends BaseModel { let teams: GVGTeamType[] = await GVGTeamModel.find({ batchCode }).lean(); return teams } + + // 加积分 + public static async addScore(teamCode: string, incScore: number) { + let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $inc: { score: incScore } }, { new: true }).lean(); + return team; + } } diff --git a/shared/domain/rank.ts b/shared/domain/rank.ts index a96e834c2..b203adda2 100644 --- a/shared/domain/rank.ts +++ b/shared/domain/rank.ts @@ -366,6 +366,7 @@ export class KeyName { groupId?: number; serverType?: number; day?: string; + configId?: number; constructor(key: string, param: KeyNameParam) { this.key = key; @@ -380,6 +381,7 @@ export class KeyName { if(param.groupId) this.groupId = param.groupId; if(param.serverType) this.serverType = param.serverType; if(param.day) this.day = param.day; + if(param.configId) this.configId = param.configId; } public getName() { @@ -418,6 +420,10 @@ export class KeyName { return `${this.key}:${this.day}:${this.groupId}:${this.serverType}`; case REDIS_KEY.GVG_VESTIGE_LEAGUE: return `${this.key}:${this.day}:${this.groupId}:${this.serverType}`; + case REDIS_KEY.GVG_BATTLE_RANK: + return `${this.key}:${this.configId}:${this.groupId}:${this.serverType}:${this.cityId}`; + case REDIS_KEY.GVG_BATTLE_LEAGUE_RANK: + return `${this.key}:${this.configId}:${this.groupId}:${this.serverType}:${this.cityId}`; default: return this.key; }