diff --git a/game-server/app/servers/guild/handler/gvgBattleHandler.ts b/game-server/app/servers/guild/handler/gvgBattleHandler.ts index ca9467cc0..cadcc1055 100644 --- a/game-server/app/servers/guild/handler/gvgBattleHandler.ts +++ b/game-server/app/servers/guild/handler/gvgBattleHandler.ts @@ -15,7 +15,7 @@ import { gameData, getReviveGold } from '../../../pubUtils/data'; import { getAllServerName } from '../../../services/redisService'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { SaveTeamParam, SaveTeamUpdateParam } from '../../../domain/gvgField/gvgDb'; -import { GVG_ITEM, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { GVG_AREA_TYPE, GVG_ITEM, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; import { GVGHeroInfo } from '../../../domain/dbGeneral'; import { ArtifactModel } from '../../../db/Artifact'; import { getHeroesAttributes } from '../../../services/playerCeService'; @@ -24,6 +24,7 @@ import { nowSeconds } from '../../../pubUtils/timeUtil'; import { GVGUserItemModel } from '../../../db/GVGUserItem'; import { handleGVGCost } from '../../../services/gvg/gvgItemService'; import { getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { GVGCityAreaPointModel } from '../../../db/GVGCityAreaPoint'; export default function (app: Application) { new HandlerService(app, {}); @@ -380,7 +381,7 @@ export class GVGBattleHandler { async teamSettle(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) { const roleId = session.get('roleId'); const serverId = session.get('serverId'); - const { pointId, teamCode } = msg; + const { cityId, areaId, pointId, teamCode } = msg; let { configId, period } = getGVGPeriodData(); // if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); // TODO 测试临时注 @@ -394,8 +395,8 @@ export class GVGBattleHandler { let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); - let hasOtherTeam = await GVGTeamModel.checkPoint(configId, groupId, serverType, pointId); - if(hasOtherTeam) return resResult(STATUS.GVG_POINT_HAS_SETTLED); + let point = await GVGCityAreaPointModel.settlePoint(cityId, areaId, pointId, myTeam); + if(!point) return resResult(STATUS.GVG_POINT_HAS_SETTLED); const curTeam = await GVGTeamModel.settlePoint(teamCode, pointId); let teamObj = getGVGBattleData(groupId, serverType); @@ -409,6 +410,9 @@ export class GVGBattleHandler { const serverId = session.get('serverId'); const { pointId, teamCode } = msg; + let { configId, period } = getGVGPeriodData(); + // if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); // TODO 测试临时注 + let groupId = await getGroupIdOfServer(serverId); let serverType = await getGVGServerType(serverId); @@ -418,6 +422,7 @@ export class GVGBattleHandler { if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); const curTeam = await GVGTeamModel.settlePoint(teamCode, 0); + await GVGCityAreaPointModel.leavePoint(configId, groupId, serverType, pointId); let teamObj = getGVGBattleData(groupId, serverType); teamObj.teamSettle(roleId, teamCode, pointId); @@ -477,8 +482,13 @@ export class GVGBattleHandler { let { win, fail } = gameData.gvgBattleDurabilityMinus; attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, getBirthAreaOfCity(city, attackTeam.leagueCode), await getTechReviveMinus(configId, attackTeam.leagueCode)); defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, getBirthAreaOfCity(city, defenseTeam.leagueCode), await getTechReviveMinus(configId, defenseTeam.leagueCode)); - if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !attackTeam.curTeamBreak) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 - attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); + if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 + if(!attackTeam.curTeamBreak) { + attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); + await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam); + } else { + await GVGCityAreaPointModel.leavePoint(configId, groupId, serverType, defenseTeam.originPointId); + } } if(defenseTeam.curTeamBreak) { let attackScore = calBattleScoreByCe(isSuccess, defenseTeam.lineupCe); @@ -526,8 +536,14 @@ export class GVGBattleHandler { if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND); defenseTeam = await GVGTeamModel.battleEndDefense(teamCode, await getTechKnifeHurt(configId, attackTeam.leagueCode), getBirthAreaOfCity(city, defenseTeam.leagueCode), await getTechReviveMinus(configId, defenseTeam.leagueCode)); - if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !attackTeam.curTeamBreak) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 - attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); + if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 + if(!attackTeam.curTeamBreak) { + attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); + await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam); + } else { + await GVGCityAreaPointModel.leavePoint(configId, groupId, serverType, defenseTeam.originPointId); + } + } if(defenseTeam.curTeamBreak) { let attackScore = calBattleScoreByCe(true, defenseTeam.lineupCe); @@ -597,9 +613,34 @@ export class GVGBattleHandler { // 获取概况 async getOverview(msg: {}, session: BackendSession) { - const cities = await GVGCityModel.find({}).lean(); - // ! 重新组织每个城市的数据,添加据点和积分点的信息 - return resResult(STATUS.SUCCESS, { cities }); + const serverId = session.get('serverId'); + + let { configId } = getGVGPeriodData(); + let groupId = await getGroupIdOfServer(serverId); + let serverType = await getGVGServerType(serverId); + + const cities = await GVGCityModel.findByConfig(configId, groupId, serverType); + const points = await GVGCityAreaPointModel.findByConfig(configId, groupId, serverType); + + let result: { cityId: number, guardLeagueName: string, areas: { areaId: number, points: { pointId: number, guardLeagueName: string }[] }[] }[] = []; + for(let [ cityId, { areaIds }] of gameData.gvgCity) { + let areas: { areaId: number, points: {pointId: number, guardLeagueName: string }[]}[] = []; + for(let areaId of areaIds) { + let dicArea = gameData.gvgArea.get(areaId); + if(!dicArea || (dicArea.areaType != GVG_AREA_TYPE.BIG && dicArea.areaType != GVG_AREA_TYPE.MIDDLE && dicArea.areaType == GVG_AREA_TYPE.SMALL) ) continue; + let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; + let pointArrs: { pointId: number, guardLeagueName: string }[] = []; + for(let pointId of pointIds) { + let playerPoint = points.find(cur => cur.pointId == pointId); + pointArrs.push({ pointId, guardLeagueName: playerPoint? playerPoint.leagueName: '' }); + } + if(pointArrs.length > 0) areas.push({ areaId, points: pointArrs }); + } + let city = cities.find(cur => cur.cityId == cityId); + result.push({ cityId, guardLeagueName: city?.guardLeagueName||'', areas }); + } + + return resResult(STATUS.SUCCESS, { cities: result }); } async debugStartSchedule() { diff --git a/game-server/app/services/gvg/gvgBattleService.ts b/game-server/app/services/gvg/gvgBattleService.ts index 70c8bba32..97ec23e48 100644 --- a/game-server/app/services/gvg/gvgBattleService.ts +++ b/game-server/app/services/gvg/gvgBattleService.ts @@ -19,6 +19,7 @@ import { LeagueRankInfo, RoleRankInfo } from "../../domain/rank"; import { findKeys, getAllServerName } from "../redisService"; import { sendMessageToGVGAreaByTeamWithSuc, sendMessageToGVGAreaWithSuc, sendMessageToGVGCityWithSuc } from "../pushService"; import { sendMailToLeagueByContent } from "../mailService"; +import { GVGCityAreaPointModel } from "../../db/GVGCityAreaPoint"; /** @@ -237,6 +238,7 @@ export async function initCatapult(cityId: number, groupId: number, serverType: // 投石车投伤害 export async function catapultHurt() { + let { configId } = getGVGConfig(); for(let [_key, teamObj] of getGVGBattleMap()) { let teams = teamObj.findCatapult(); for(let catapult of teams) { @@ -245,13 +247,16 @@ export async function catapultHurt() { let relateArea = dicArea?.relateArea||[]; let teamCodes = teamObj.findCatapultAttackTeam(relateArea, catapult.leagueCode); let dicGVGCity = gameData.gvgCity.get(catapult.cityId); - let teams = await GVGTeamModel.attackByCatapult(teamCodes, catapult.captapultAtk, dicGVGCity.attackBirth) + let teams = await GVGTeamModel.attackByCatapult(teamCodes, catapult.captapultAtk, dicGVGCity.attackBirth); teamObj.battleEnd(teams); await sendMessageToGVGAreaByTeamWithSuc(teamObj.groupId, teamObj.serverType, catapult.areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { cityId: catapult.cityId, areaId: catapult.areaId, attackType: 1, teams: teams.map(team => new GVGTeamInList(team)) }); for(let team of teams) { await pushTeamBeHurtMessage(team); + if(team.curTeamBreak && team.originPointId > 0) { + await GVGCityAreaPointModel.leavePoint(configId, teamObj.groupId, teamObj.serverType, team.originPointId); + } } } } diff --git a/shared/db/GVGCity.ts b/shared/db/GVGCity.ts index afaab25c2..41896182b 100644 --- a/shared/db/GVGCity.ts +++ b/shared/db/GVGCity.ts @@ -11,7 +11,6 @@ class Player { teamCnt: number; } - @index({ configId: 1, cityId: 1, groupId: 1, serverType: 1 }) // GVGCity 类,继承自 BaseModel export default class GVGCity extends BaseModel { @@ -77,12 +76,16 @@ export default class GVGCity extends BaseModel { // 占领城池 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; } + + public static async findByConfig(configId: number, groupId: number, serverType: number) { + const cities: GVGCityType[] = await GVGCityModel.find({ configId, groupId, serverType, hasGuard: true }).lean(); + return cities + } } diff --git a/shared/db/GVGCityAreaPoint.ts b/shared/db/GVGCityAreaPoint.ts new file mode 100644 index 000000000..dad71bd74 --- /dev/null +++ b/shared/db/GVGCityAreaPoint.ts @@ -0,0 +1,68 @@ +import BaseModel from "./BaseModel"; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; +import { GVGTeamType } from "./GVGTeam"; + +@index({ configId: 1, pontId: 1, groupId: 1, serverType: 1 }) +// GVGCityAreaPoint 类,继承自 BaseModel +export default class GVGCityAreaPoint extends BaseModel { + @prop({ required: true, default: 1 }) + configId: number; // config唯一id + + @prop({ required: true, default: 1 }) + groupId: number; // 战区 + + @prop({ required: true, default: 1 }) + serverType: number; // 1-单服 2-跨服 + + @prop({ required: true }) + cityId: number; // 城池id + + @prop({ required: true }) + areaId: number; // 区域 + + @prop({ required: true }) + pointId: number; // 积分点 + + @prop({ required: true }) + leagueCode: string; // 联军 + + @prop({ required: true }) + leagueName: string; // 联军 + + @prop({ required: true }) + roleId: string; // 玩家 + + @prop({ required: true }) + roleName: string; // 玩家 + + @prop({ required: true }) + teamCode: string; // 玩家的编队 + + public static async settlePoint(cityId: number, areaId: number, pointId: number, team: GVGTeamType) { + let { configId, groupId, serverType, leagueCode, leagueName, roleId, roleName, teamCode } = team; + await GVGCityAreaPointModel.findOneAndUpdate({ configId, groupId, serverType, pointId }, { $setOnInsert: { teamCode: '' }}, { upsert: true }); + let result: GVGCityAreaPointType = await GVGCityAreaPointModel.findOneAndUpdate( + { configId, groupId, serverType, pointId }, + { $set: { cityId, areaId, leagueCode, leagueName, roleId, roleName, teamCode } }, + { new: true }).lean(); + return result; + } + + public static async leavePoint(configId: number, groupId: number, serverType: number, pointId: number) { + let result: GVGCityAreaPointType = await GVGCityAreaPointModel.findOneAndUpdate({ configId, groupId, serverType, pointId }, { $set: { teamCode: '' }}, { new: true }).lean(); + return result; + } + + public static async findByConfig(configId: number, groupId: number, serverType: number) { + let result: GVGCityAreaPointType[] = await GVGCityAreaPointModel.find({ configId, groupId, serverType }).lean(); + return result + } +} + + +export const GVGCityAreaPointModel = getModelForClass(GVGCityAreaPoint); + +export interface GVGCityAreaPointType extends Pick, keyof GVGCityAreaPoint> {}; + +export type GVGCityAreaPointUpdate = Partial; // 将所有字段变成可选项 + diff --git a/shared/db/GVGTeam.ts b/shared/db/GVGTeam.ts index b5cab78a1..ce65b43e8 100644 --- a/shared/db/GVGTeam.ts +++ b/shared/db/GVGTeam.ts @@ -84,7 +84,10 @@ export default class GVGTeam extends BaseModel { startMoveTime: number; @prop({ required: true, default: 0 }) - stopMoveTime: number; // 移动冷却时间 + moveCdTime: number; // 移动冷却时间 + + @prop({ required: true, default: 0 }) + stopMoveTime: number; // 移动时间 @prop({ required: true, default: 0 }) defenseTime: number; // 防守保护时间 @@ -164,7 +167,7 @@ export default class GVGTeam extends BaseModel { // 移动 public static async startMove(teamCode: string, areaId: number, fromAreaId: number) { - const res: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { areaId, fromAreaId, stopMoveTime: nowSeconds() + GVG.GVG_DEFAULT_MOVE_CD } }, { new: true }).lean(); + const res: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { areaId, fromAreaId, stopMoveTime: nowSeconds() + GVG.GVG_DEFAULT_MOVE_CD, moveCdTime: nowSeconds() + GVG.GVG_DEFAULT_MOVE_CD } }, { new: true }).lean(); return res; }