diff --git a/game-server/app/servers/guild/handler/gvgFighterHandler.ts b/game-server/app/servers/guild/handler/gvgFighterHandler.ts new file mode 100644 index 000000000..8a7345689 --- /dev/null +++ b/game-server/app/servers/guild/handler/gvgFighterHandler.ts @@ -0,0 +1,78 @@ +import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GVGProduceHandler(app); +} + +export class GVGProduceHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 领取排行榜获得的每日奖励 + async receiveBox(msg: { vestigeId: number }, session: BackendSession) { + + } + + // 遗迹页面 + async getVestige(msg: { vestigeId: number }, session: BackendSession) { + + } + + // 编辑阵容 + async saveLineup(msg: { vestigeId: number, lineup: [{ actorId: number, dataId: number, order: number }] }, session: BackendSession) { + + } + + // 获取对手阵容消息 + async getOppLineup(msg: { vestigeId: number, roleId: string, rank: number }, session: BackendSession) { + + } + + // 刷新对手 + async refreshOpp(msg: {}, session: BackendSession) { + + } + + // 选择对手 + async chooseOpp(msg: { vestigeId: number, rank: number, myRank: number }, session: BackendSession) { + + } + + // 出战界面撤退 + async giveupCheck(msg: { battleCode: string }, session: BackendSession) { + + } + + // 获取对手具体战场数据 + async getOppData(msg: { battleCode: string }, session: BackendSession) { + + } + + // 布完阵开始挑战 + async checkBattle(msg: { battleCode: string, heroes: [{ actorId: number, dataId: number, order: number }] }, session: BackendSession) { + + } + + // 挑战结算 + async battleEnd(msg: { battleCode: string, isSuccess: boolean }, session: BackendSession) { + + } + + // 征战中原简单小排行榜 + async getLeagueRank(msg: {}, session: BackendSession) { + + } + + // 联军详细排名 + async getLeagueDetailRank(msg: {}, session: BackendSession) { + + } + + // 玩家排行 + async getPlayerRank(msg: { vestigeId: number }, session: BackendSession) { + + } +} \ No newline at end of file diff --git a/game-server/app/servers/guild/handler/gvgHandler.ts b/game-server/app/servers/guild/handler/gvgHandler.ts index e85ea4199..abdc60da6 100644 --- a/game-server/app/servers/guild/handler/gvgHandler.ts +++ b/game-server/app/servers/guild/handler/gvgHandler.ts @@ -18,9 +18,10 @@ import { gameData } from "../../../pubUtils/data"; import { lockLeagueData } from "../../../services/redLockService"; import { addGVGReward, handleGVGCost } from "../../../services/gvg/gvgItemService"; import { RewardInter } from "../../../pubUtils/interface"; -import { getGVGCities } from "../../../services/gvg/gvgBattleService"; +import { getGVGCities, getGVGCitiesInfo } from "../../../services/gvg/gvgBattleService"; import { GVGRecModel } from "../../../db/GVGRec"; import { checkGVGTask } from "../../../services/task/taskService"; +import { getFightTimeByPeriod, getVestiges } from "../../../services/gvg/gvgFightService"; export default function (app: Application) { new HandlerService(app, {}); @@ -75,6 +76,26 @@ export class GVGHandler { return resResult(STATUS.SUCCESS, data) } + async getMap(msg: {}, session: BackendSession) { + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId, period, countdownTime } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + + let cities = await getGVGCitiesInfo(myLeague); + let vestiges = await getVestiges(serverId); + + return resResult(STATUS.SUCCESS, { + configId, period, countdownTime, startFightTime, endFightTime, + cities, + vestiges + }); + } + // 获取动态 async getRec(msg: {}, session: BackendSession) { const guildCode = session.get('guildCode'); diff --git a/game-server/app/services/gvg/gvgBattleService.ts b/game-server/app/services/gvg/gvgBattleService.ts index cae0702b8..ca29b5f3d 100644 --- a/game-server/app/services/gvg/gvgBattleService.ts +++ b/game-server/app/services/gvg/gvgBattleService.ts @@ -7,4 +7,12 @@ import { GVGLeagueType } from "../../db/GVGLeague"; */ export async function getGVGCities(league: GVGLeagueType) { return [] +} + +/** + * TODO 获取当前城池状态 + * @returns [{cityId: number, guardLeagueName: string, teamCnt: number }] + */ +export async function getGVGCitiesInfo(league: GVGLeagueType): Promise<{cityId: number, guardLeagueName: string, teamCnt: number }[]> { + return []; } \ No newline at end of file diff --git a/game-server/app/services/gvg/gvgFightService.ts b/game-server/app/services/gvg/gvgFightService.ts new file mode 100644 index 000000000..698c307dc --- /dev/null +++ b/game-server/app/services/gvg/gvgFightService.ts @@ -0,0 +1,33 @@ +// 征战中原相关 + +import { GVG_PERIOD } from "../../consts"; +import { GVGVestigeModel } from "../../db/GVGVestige"; +import { gameData } from "../../pubUtils/data"; +import { getTimeFun } from "../../pubUtils/timeUtil"; +import { getRandEelm } from "../../pubUtils/util"; +import { getGroupIdOfServer, getGVGServerType } from "./gvgService"; + +// 备战期的遗迹和激战期的开始结束战斗时间 +export function getFightTimeByPeriod(period: GVG_PERIOD) { + let dicPeriod = gameData.gvgPeriod.get(period); + if(!dicPeriod) return { startFightTime: 0, endFightTime: 0 }; + + return { + startFightTime: getTimeFun().getTimeWithHour(dicPeriod.startHour, dicPeriod.startMinute, dicPeriod.startSecond), + endFightTime: getTimeFun().getTimeWithHour(dicPeriod.endHour, dicPeriod.endMinute, dicPeriod.endSecond), + } +} + +// 征战中原每天随机的遗迹点 +export async function getVestiges(serverId: number) { + let groupId = await getGroupIdOfServer(serverId); + let serverType = await getGVGServerType(serverId); + let vestige = await GVGVestigeModel.getVestigate(groupId); + if(!vestige) { + let dicGVGVestige = gameData.gvgVestigeByServerType.get(serverType)||[]; + let cnt = gameData.gvgVestigeCntByServerType.get(serverType)||0; + let randResult = getRandEelm(dicGVGVestige, cnt); + vestige = await GVGVestigeModel.initTodayVestigate(groupId, serverType, randResult); + } + return vestige.vestiges||[]; +} \ No newline at end of file diff --git a/game-server/app/services/gvg/gvgService.ts b/game-server/app/services/gvg/gvgService.ts index 0b7d7b3e5..4612bb177 100644 --- a/game-server/app/services/gvg/gvgService.ts +++ b/game-server/app/services/gvg/gvgService.ts @@ -38,9 +38,9 @@ export function getPeriodTime() { let battleConfig = gameData.gvgPeriod.get(GVG_PERIOD.BATTLE); // 如果现在是周日,那么就是本周期的组队开始时间,如果是其他日子(启动初始化),就是下周期的组队开始时间 - let _teamTime = getTimeFun().getTimeWithWeek(teamConfig.startDay, teamConfig.startHour, teamConfig.startMinute, teamConfig.startSecond); - let _prepareTime = getTimeFun().getTimeWithWeek(prepareConfig.startDay, prepareConfig.startHour, prepareConfig.startMinute, prepareConfig.startSecond); - let _battleTime = getTimeFun().getTimeWithWeek(battleConfig.startDay, battleConfig.startHour, battleConfig.startMinute, battleConfig.startSecond); + let _teamTime = getTimeFun().getTimeWithWeek(teamConfig.startDay); + let _prepareTime = getTimeFun().getTimeWithWeek(prepareConfig.startDay); + let _battleTime = getTimeFun().getTimeWithWeek(battleConfig.startDay); console.log('_teamTime: ', _teamTime); let teamTime = curDay == 0? _teamTime: _teamTime - 7 * 86400; @@ -61,7 +61,6 @@ export async function setGVGConfig(config?: GVGConfigType) { if(!config) { config = await GVGConfigModel.findConfig(); } - console.log('##### setGVGConfig', config) pinus.app.set('gvgConfigId', config.configId); pinus.app.set('gvgTeamTime', config.teamTime); pinus.app.set('gvgPrepareTime', config.prepareTime); @@ -99,14 +98,12 @@ function getCurrentTeamTime(time: number) { } export async function getGVGServerType(serverId: number) { - console.log('#### serverId', serverId) let openTime = await getServerCreateTime(serverId); return getServerTypeByTime(openTime) } export function getGVGPeriodData() { let { configId, teamTime, prepareTime, battleTime, scheduleTime } = getGVGConfig(); - console.log('#### getGVGPeriodData', configId, teamTime, prepareTime, battleTime, scheduleTime) let period = getCurPeriod(); let countdownTime = teamTime; switch(period) { @@ -166,7 +163,6 @@ export async function getServersOfSameGroup(type: GVG_SERVER_TYPE, id: number) { if(type == GVG_SERVER_TYPE.SINGLE) return [id]; let groupId = await getGroupIdOfServer(id); - console.log('###### getServersOfSameGroup', type, groupId, id); return await getServersByGroupId(groupId); } diff --git a/game-server/app/services/task/taskObj.ts b/game-server/app/services/task/taskObj.ts index 0aa4bd619..7a41f6a27 100644 --- a/game-server/app/services/task/taskObj.ts +++ b/game-server/app/services/task/taskObj.ts @@ -196,7 +196,6 @@ export class CheckSingleTask { // 联军任务 let dicGVGTasks = getGVGTasksByType(taskType); - console.log('#####', taskType, dicGVGTasks) for(let { taskId, taskType, taskParam } of dicGVGTasks) { let taskUpdateParam = await this.checkIsMatch(taskParam, async () => []); if (taskUpdateParam) { diff --git a/shared/db/GVGLeagueFarm.ts b/shared/db/GVGLeagueFarm.ts index 38ee1a59c..629b1f6d1 100644 --- a/shared/db/GVGLeagueFarm.ts +++ b/shared/db/GVGLeagueFarm.ts @@ -5,6 +5,7 @@ import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoo import { getFutureTime, nowSeconds } from '../pubUtils/timeUtil'; import { genCode } from '../pubUtils/util'; import { GVG } from '../pubUtils/dicParam'; +import { GVG_RESOURCE_TYPE } from '../consts'; @index({ leagueCode: 1, configId: 1 }) @index({ fieldId: 1 }) @@ -138,9 +139,10 @@ export default class GVGLeagueFarm extends BaseModel { public static async lockMineOrForestry(configId: number, leagueCode: string, farmId: number, type: number, roleId: string, fieldId: number, itemId: number) { // 先创建 await GVGLeagueFarmModel.findOneAndUpdate({ configId, leagueCode, farmId, fieldId }, { $setOnInsert: { unlockTime: 0, itemId: 0, type } }, { upsert: true }); + let unlockTime = nowSeconds() + type == GVG_RESOURCE_TYPE.MINERAL? GVG.GVG_MINE_LOCK_TIME: GVG.GVG_FORESTRY_LOCK_TIME; const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOneAndUpdate( { configId, leagueCode, farmId, fieldId, $or:[{ unlockTime: { $lt: nowSeconds() } }, {lockRoleId: roleId}] }, - { $set: { unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId, itemId } }, + { $set: { unlockTime, lockRoleId: roleId, itemId } }, { new: true }).lean(); return result; } diff --git a/shared/db/GVGUserTask.ts b/shared/db/GVGUserTask.ts index 6c271ea50..6750cb62d 100644 --- a/shared/db/GVGUserTask.ts +++ b/shared/db/GVGUserTask.ts @@ -4,7 +4,7 @@ import { getZeroPointD } from '../pubUtils/timeUtil'; import { TASK_FUN_TYPE } from '../consts'; import { UpdateTaskParam } from '../domain/roleField/task'; -@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 }) +@index({ leagueCode: 1, roleId: 1, configId: 1 }) export default class GVGUserTask extends BaseModel { @prop({ required: true, default: '' }) diff --git a/shared/db/GVGVestige.ts b/shared/db/GVGVestige.ts new file mode 100644 index 000000000..4aba3972b --- /dev/null +++ b/shared/db/GVGVestige.ts @@ -0,0 +1,46 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; +import { getZeroPoint } from '../pubUtils/timeUtil'; + +class Vestige { + @prop({ required: true }) + vestigeId: number; // 遗迹点 + + @prop({ required: true }) + position: string; // 遗迹点位置 +} + +@index({ groupId: 1, day: 1 }) +export default class GVGVestige extends BaseModel { + + @prop({ required: true }) + groupId: number; // 战区id + + @prop({ required: true }) + type: number; // 1-单服 2-跨服 + + @prop({ required: true, type: Vestige, _id: false }) + vestiges: Vestige[]; // 今天的遗迹点 + + @prop({ required: true }) + day: number; // 每天5点 + + public static async getVestigate(groupId: number) { + let day = getZeroPoint(); + let result: GVGVestigeType = await GVGVestigeModel.findOne({ groupId, day }).lean(); + return result; + } + + public static async initTodayVestigate(groupId: number, type: number, vestiges: Vestige[]) { + let day = getZeroPoint(); + let result: GVGVestigeType = await GVGVestigeModel.findOneAndUpdate({ groupId, day }, { $setOnInsert: { type, vestiges } }, { new: true, upsert: true }).lean(); + return result; + } +} + +export const GVGVestigeModel = getModelForClass(GVGVestige); + +export interface GVGVestigeType extends Pick, keyof GVGVestige> { + id: number; +}; +export type GVGVestigeUpdate = Partial; // 将所有字段变成可选项 diff --git a/shared/db/GVGVestigeRank.ts b/shared/db/GVGVestigeRank.ts new file mode 100644 index 000000000..bce91864b --- /dev/null +++ b/shared/db/GVGVestigeRank.ts @@ -0,0 +1,44 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose'; +import Role from './Role'; + +@index({ groupId: 1, vestigeId: 1 }) +export default class GVGVestige extends BaseModel { + + @prop({ required: true }) + configId: number; // 赛期 + + @prop({ required: true }) + day: number; // 每天5点 + + @prop({ required: true }) + groupId: number; // 战区id + + @prop({ required: true }) + vestigeId: number; // 遗迹id + + @prop({ required: true }) + roleId: string; // 玩家 + + @prop({ ref: 'Role', type: mongoose.Schema.Types.ObjectId }) + role: Ref; + + @prop({ required: true, default: 0 }) + rank: number; // 排名 + + @prop({ required: true, default: 0 }) + oldRank: number; // 交换前排名 + + @prop({ required: true, default: 0 }) + historyRank: number; // 历史最高排名 + + @prop({ required: true, default: 0 }) + locked: number; // 是否被挑战 +} + +export const GVGVestigeModel = getModelForClass(GVGVestige); + +export interface GVGVestigeType extends Pick, keyof GVGVestige> { + id: number; +}; +export type GVGVestigeUpdate = Partial; // 将所有字段变成可选项 diff --git a/shared/pubUtils/dicParam.ts b/shared/pubUtils/dicParam.ts index e8999dfc1..908410ddf 100644 --- a/shared/pubUtils/dicParam.ts +++ b/shared/pubUtils/dicParam.ts @@ -384,12 +384,13 @@ export const GVG = { GVG_SERVICETYPE_VESTIGE: '1&1|2&3', // 单服和跨服随机出几个遗迹点 GVG_ARMY_LEAGUE_TIME: 3, // GVG开启军团等级开启限制 GVG_ROLE_TYPE: '1&贤臣|2&猛将', // GVG中职能选择 - GVG_SP_FIELD_ADD: 0.2, - GVG_FIELD_TYPE_RATIO: '1&10|2&20|3&10', - GVG_SP_FIELD_RATIO: '30&60', - GVG_FARM_LOCK_TIME: 180, - GVG_MINE_LOCK_TIME: 180, GVG_TEAM_NUMBER: '1&1&100|2&50&100|3&80&100', // GVG编队,index&lv&durability GVG_CATAPULT: '3000&30&10', // 科技树投石车的耐久&单次伤害&间隔时间 GVG_CITY_OCCUPIED_NUMBER: 2, // 一个联军最多可以占领的城池数量 + GVG_SP_FIELD_ADD: 0.2, // 农田特殊格子上种植对应的植物的加成 + GVG_FARM_LOCK_TIME: 300, // 农田锁定时间(秒) + GVG_MINE_LOCK_TIME: 300, // 矿山锁定时间(秒) + GVG_FORESTRY_LOCK_TIME: 300, // 林场锁定时间(秒) + GVG_FIELD_TYPE_RATIO: '1&5|2&10|3&10', // 全联盟的特殊格子上限百分比(a%的格子为小麦这个)1&a|2&b|3&c + GVG_SP_FIELD_RATIO: '10&30', // 分配给玩家的时候有多少特殊格子 min&max 填最大最小百分比即可 };