🐞 fix(gvg): 投石车定时任务

This commit is contained in:
luying
2023-02-15 22:03:05 +08:00
parent 4359bfd9cc
commit 7543baa8cb
17 changed files with 304 additions and 52 deletions

View File

@@ -1,6 +1,6 @@
import { GVGCityType } from './../../../db/GVGCity';
import { GVGRecModel } from '../../../db/GVGRec';
import { GVGAreaInMap, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, LeagueGood, MyTeamInfo } from '../../../domain/gvgField/returnData';
import { GVGAreaInMap, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, LeagueGood, MyTeamInfo, MyTeamSimpleInfo } from '../../../domain/gvgField/returnData';
import { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from '../../../db/GVGTeam';
import { GVGUserDataModel } from '../../../db/GVGUserData';
import { GVGCityModel } from '../../../db/GVGCity';
@@ -23,6 +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';
export default function (app: Application) {
new HandlerService(app, {});
@@ -40,8 +41,8 @@ export class GVGBattleHandler {
async getTeams(msg: {}, session: BackendSession) {
const roleId = session.get('roleId');
const teams = await GVGTeamModel.findByRole(roleId, '-_id teamCode index head frame spine lineup')
return resResult(STATUS.SUCCESS, { teams });
return resResult(STATUS.SUCCESS, { teams: teams.map(team => new MyTeamSimpleInfo(team)) });
}
// 保存队伍
@@ -101,7 +102,7 @@ export class GVGBattleHandler {
if (!team) {
return resResult(STATUS.GVG_SAVE_TEAM_FAILED);
}
return resResult(STATUS.SUCCESS, { curTeam: pick(team, ['teamCode', 'index', 'head', 'frame', 'spine', 'lineup']) });
return resResult(STATUS.SUCCESS, { curTeam: new MyTeamSimpleInfo(team) });
}
// 获取城池信息
@@ -509,4 +510,8 @@ export class GVGBattleHandler {
// ! 重新组织每个城市的数据,添加据点和积分点的信息
return resResult(STATUS.SUCCESS, { cities });
}
async debugStartSchedule() {
await gvgBattleStartSchedule();
}
}

View File

@@ -145,7 +145,7 @@ export class GVGProduceHandler {
let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
result.setRobot(dicGVGVestige, dicWarJson, serverNames[serverId]);
} else {
let hisVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId);
let hisVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId);
if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND);
let role = await RoleModel.findByRoleId(hisVestigeRank.roleId, 'roleId roleName serverId guildName title lv heads head spines spine frames frame')

View File

@@ -1,9 +1,9 @@
import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus";
import { GVG_ITEM, DATA_NAME, GVG_ACTIVE_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, LEAGUE_MANAGE_TYPE, STATUS, GVG_REC_TYPE, TASK_TYPE } from "../../../consts";
import { GVG_ITEM, DATA_NAME, GVG_ACTIVE_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, LEAGUE_MANAGE_TYPE, STATUS, GVG_REC_TYPE, TASK_TYPE, GVG_TECH_TYPE } from "../../../consts";
import { GVGLeagueModel } from "../../../db/GVGLeague";
import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare";
import { GVGMainData, LeagueContributeInfo, LeagueMemberContributeInfo, LeagueMemberListInfo } from "../../../domain/gvgField/returnData";
import { resResult } from "../../../pubUtils/util";
import { getRandEelm, resResult } from "../../../pubUtils/util";
import { calLeagueCe, getGroupIdOfServer, getGVGConfig, getGVGPeriodData, getGVGServerType, getServerTypeByTime } from "../../../services/gvg/gvgService";
import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, checkLeagueAuth, getMyAuth } from "../../../services/gvg/gvgTeamService";
import { getAllServerName } from "../../../services/redisService";
@@ -421,6 +421,14 @@ export class GVGHandler {
let curQueue = leaguePrepare.techQueue.find(cur => cur.id == techId);
if(curQueue.progress >= curQueue.maxProgress) {
leaguePrepare = await GVGLeaguePrepareModel.activate(configId, myLeague.leagueCode, techId);
// 发放连弩
if(dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_KNIFE) {
let members = myLeague.members||[];
let randMembers = getRandEelm(members, dicTech.param[0]);
for(let { roleId } of randMembers) {
await addGVGReward(roleId, '', myLeague.leagueCode, null, [{ id: GVG_ITEM.KNIFE, count: dicTech.param[1] }], [], ITEM_CHANGE_REASON.GVG_TECH_SEND_KNIFE);
}
}
}
// 添加 活跃

View File

@@ -8,6 +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';
export default function (app: Application) {
new HandlerService(app, {});
@@ -118,4 +119,28 @@ export class GuildRemote {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async gvgBattleStart() {
try {
return await gvgBattleStart();
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async initCatapult(cityId: number, groupId: number, serverType: number, leagueCode: string, leagueName: string) {
try {
return await initCatapult(cityId, groupId, serverType, leagueCode, leagueName);
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public async catapultHurt() {
try {
return await catapultHurt();
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
}

View File

@@ -1,7 +1,7 @@
// 存在激战期的内存数据
import { pinus } from "pinus";
import { GVG_PERIOD } from "../../consts";
import { GVG_CATAPULT, GVG_PERIOD } from "../../consts";
import { GVGTeamModel, GVGTeamType } from "../../db/GVGTeam";
import { GVGTeamMem } from "../../domain/battleField/gvgBattle";
import { dispatch } from "../../pubUtils/dispatcher";
@@ -34,6 +34,18 @@ class GVGBattleData {
return teams.slice(0, 20);
}
public findCatapultAttackTeam(areaIds: number[], leagueCode: string) {
let teams: string[] = [];
for(let areaId of areaIds) {
let teamCodes = this.areaToTeams.get(areaId)||new Set();
for(let teamCode of teamCodes) {
let team = this.teams.get(teamCode);
if(team && team.leagueCode != leagueCode && !team.isRobot) teams.push(teamCode);
}
}
return teams;
}
public leaveCity(roleId: string) {
let teamCodes = this.roleToTeam.get(roleId)||[];
for(let teamCode of teamCodes) {
@@ -117,11 +129,17 @@ class GVGBattleData {
this.enterCity(team); continue;
}
let { areaId: fromAreaId, pointId: fromPointId } = teamMem;
teamMem.battleEnd(team);
teamMem.updateTeam(team);
this.setRolePoints(team.roleId, fromPointId, team.pointId);
this.setAreaMap(team.teamCode, fromAreaId, team.areaId);
}
}
// 投石车
public findCatapult() {
let teamCodes = this.roleToTeam.get(GVG_CATAPULT)||[];
return teamCodes.map(teamCode => this.teams.get(teamCode));
}
}
export function getGVGBattleData(groupId: number, serverType: number) {
@@ -132,11 +150,15 @@ export function getGVGBattleData(groupId: number, serverType: number) {
return gvgBattleMap.get(key);
}
export function getGVGBattleMap() {
return gvgBattleMap;
}
export async function initTeamToMem() {
let sid = pinus.app.getServerId();
let servers = pinus.app.getServersByType('guild');
let { configId, period } = getGVGPeriodData();
if(period != GVG_PERIOD.BATTLE) return;
// if(period != GVG_PERIOD.BATTLE) return;
let teams = await GVGTeamModel.findByConfigId(configId);
for(let team of teams) {
if(dispatch(team.cityId.toString(), servers)?.id == sid) {

View File

@@ -3,14 +3,18 @@ import { GVGLeagueType } from "../../db/GVGLeague";
import { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from "../../db/GVGTeam";
import { GVGCityModel, GVGCityType } from "../../db/GVGCity";
import { gameData } from "../../pubUtils/data";
import { STATUS } from "../../consts";
import { GVG_AREA_TYPE, GVG_TECH_TYPE, STATUS } from "../../consts";
import { nowSeconds } from "../../pubUtils/timeUtil";
import { DicGVGAreaPoint } from "../../pubUtils/dictionary/DicGVGAreaPoint";
import { getGVGBattleData } from "./gvgBattleMemory";
import { getGVGBattleData, getGVGBattleMap } from "./gvgBattleMemory";
import { GVGCityMapInfo } from "../../domain/gvgField/returnData";
import { pick } from "underscore";
import { GVG } from "../../pubUtils/dicParam";
import { GVGHeroInfo, PvpEnemies, PvpHeroInfo } from "../../domain/dbGeneral";
import { getGVGConfig } from "./gvgService";
import { GVGLeaguePrepareModel } from "../../db/GVGLeaguePrepare";
import { pinus } from "pinus";
import { dispatch } from "../../pubUtils/dispatcher";
/**
@@ -63,6 +67,7 @@ export function getBirthAreaOfCity(city: GVGCityType, leagueCode: string) {
return isGuard? dicGVGCity.defenseBirth: dicGVGCity.attackBirth;
}
// guild.gvgBattleHandler.startMove 检测
export function checkMoveStatus(team: GVGTeamType, cityId: number, areaId: number) {
if(!team) return STATUS.GVG_BATTLE_TEAM_NOT_FOUND;
if(team.cityId != cityId) return STATUS.GVG_BATTLE_IS_NOT_IN_CITY;
@@ -122,6 +127,7 @@ export function getGVGWarId(defenseTeam: GVGTeamType) {
return GVG.GVG_ROBOT_WARJSON; // 据点守卫使用
}
// guild.gvgBattleHandler.battleStart 里的heroes返回
export function getOppHeroes(warId: number, isRobot: boolean, lineup: GVGHeroInfo[]) {
let heroes: PvpEnemies[] = [];
const dicWar = gameData.war.get(warId);
@@ -147,6 +153,7 @@ export function getOppHeroes(warId: number, isRobot: boolean, lineup: GVGHeroInf
return heroes
}
// guild.gvgBattleHandler.battleStart 检测
export function checkGVGBattleStart(roleId: string, attackTeam: GVGTeamType, defenseTeam: GVGTeamType) {
if(!attackTeam || !defenseTeam) return STATUS.GVG_BATTLE_TEAM_INVALID;
@@ -160,4 +167,58 @@ export function checkGVGBattleStart(roleId: string, attackTeam: GVGTeamType, def
if(defenseTeam.durability <= 0) return STATUS.GVG_DEFENSE_TEAM_BROKEN;
return STATUS.SUCCESS;
}
// gvg激战期开始定时器
export async function gvgBattleStart() {
let servers = pinus.app.getServersByType('guild');
let { configId } = getGVGConfig();
let guardCities = await GVGCityModel.findAllGuardCities(configId);
for(let { cityId, groupId, serverType, guardLeague, guardLeagueName } of guardCities) {
let sid = dispatch(cityId.toString(), servers)?.id;
await pinus.app.rpc.guild.guildRemote.initCatapult.toServer(sid, cityId, groupId, serverType, guardLeague, guardLeagueName);
}
}
// 每次活动开始初始化投石车
export async function initCatapult(cityId: number, groupId: number, serverType: number, leagueCode: string, leagueName: string) {
let { configId } = getGVGConfig();
let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode);
let activeTech = leaguePrepare?.activeTech||[];
let hasCatapult = false, atk = 0, durability = 0;
for(let techId of activeTech) {
let dicTech = gameData.gvgTech.get(techId);
if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_CATAPULT) {
hasCatapult = true, atk = dicTech.param[0]; durability = dicTech.param[1];
}
}
if(hasCatapult) {
let dicCity = gameData.gvgCity.get(cityId);
let areaIds = (dicCity?.areaIds||[]).filter(areaId => {
let dicArea = gameData.gvgArea.get(areaId);
return dicArea && dicArea.areaType == GVG_AREA_TYPE.CATAPULT;
});
let teams = await GVGTeamModel.initCatapult(configId, groupId, serverType, cityId, leagueCode, leagueName, areaIds, atk, durability);
// 处理内存
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.enterCity(...teams);
}
}
// 投石车投伤害
export async function catapultHurt() {
for(let [_, teamObj] of getGVGBattleMap()) {
let teams = teamObj.findCatapult();
for(let catapult of teams) {
if(catapult.isBroken) continue;
let dicArea = gameData.gvgArea.get(catapult.areaId);
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)
teamObj.battleEnd(teams);
}
}
}

View File

@@ -31,13 +31,13 @@ import { addVestigeLeagueRankRec } from "./gvgRecService";
import { getGroupIdOfServer, getGVGServerType } from "./gvgService";
// 备战期的遗迹和激战期的开始结束战斗时间
export function getFightTimeByPeriod(period: GVG_PERIOD) {
export function getFightTimeByPeriod(period: GVG_PERIOD, time?: number) {
let dicPeriod = gameData.gvgPeriod.get(period);
if(!dicPeriod) return { startFightTime: 0, endFightTime: 0 };
return {
startFightTime: <number>getTimeFun().getTimeWithHour(dicPeriod.startHour, dicPeriod.startMinute, dicPeriod.startSecond),
endFightTime: <number>getTimeFun().getTimeWithHour(dicPeriod.endHour, dicPeriod.endMinute, dicPeriod.endSecond),
startFightTime: <number>getTimeFun(time).getTimeWithHour(dicPeriod.startHour, dicPeriod.startMinute, dicPeriod.startSecond),
endFightTime: <number>getTimeFun(time).getTimeWithHour(dicPeriod.endHour, dicPeriod.endMinute, dicPeriod.endSecond),
}
}

View File

@@ -32,6 +32,7 @@ export async function createNewGVGConfig() {
if(!await checkHasCities(league)) needDissmissLeagueId.push(league._id);
}
await GVGLeagueModel.dismissByIds(needDissmissLeagueId);
await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast();
return config;
}

View File

@@ -5,7 +5,7 @@ import { nowSeconds, getTimeFun, getSeconds } from '../pubUtils/timeUtil';
import { getTodayGuildActivity, gameData } from '../pubUtils/data';
import { pvpSeasonEnd } from './pvpService';
import { getAllOnlineRoles, getAllServers, delGuildActivityRank, getServerCreateTime } from './redisService';
import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_TIMER, ACTIVITY_TYPE, PUSH_ROUTE, STATUS, LADDER_STATUS, LADDER_SERVER_GAP_TIME } from '../consts';
import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_TIMER, ACTIVITY_TYPE, PUSH_ROUTE, STATUS, LADDER_STATUS, LADDER_SERVER_GAP_TIME, GVG_PERIOD } from '../consts';
import { pinus } from 'pinus';
import { settleGuildWeekly } from './guildService';
import { SendMailFun, sendMailsByGmMail, } from './mailService';
@@ -16,7 +16,7 @@ import { dispatch } from '../pubUtils/dispatcher';
import { createNewServer, initMarquee, setServerMainten } from './gmService';
import moment = require('moment');
import { reportOneOnline } from './authenticateService';
import { LADDER, PVP } from '../pubUtils/dicParam';
import { GVG, LADDER, PVP } from '../pubUtils/dicParam';
import { fetch37Words } from './sdkService';
import { GMMailModel, GMMailType } from '../db/GMMail';
import { Maintenance, ServerlistModel, ServerlistType } from '../db/Serverlist';
@@ -44,7 +44,7 @@ import { HiddenDataModel, HiddenDataModelType } from '../db/HiddenData';
import { setHiddenData, setHiddenDataToMemory } from './dataService';
import { GVGConfigModel } from '../db/GVGConfig';
import { createNewGVGConfig, initLeaguePrepare } from './gvg/gvgService';
import { saveVestigeRankSchedule } from './gvg/gvgFightService';
import { getFightTimeByPeriod, saveVestigeRankSchedule } from './gvg/gvgFightService';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
@@ -913,5 +913,54 @@ export async function initGVGConfigSchedule() {
}
scheduleJob('gvgFightSchedule', '0 0 22 * * ?', saveVestigeRankSchedule);
let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.BATTLE, config.battleTime);
scheduleJob(`gvgBattleStartSchedule`, startFightTime * 1000, gvgBattleStartSchedule);
scheduleJob(`gvgBattleEndSchedule`, endFightTime * 1000, gvgBattleEndSchedule);
}
let gvgBattleSecondJob: Job; // gvg每5秒的定时器
let gvgBattleCatapultJob: Job; // gvg投石车定时器
// gvg激战期开始定时器
export async function gvgBattleStartSchedule() {
// 初始化投石车
let guildServers = pinus.app.getServersByType('guild');
if(guildServers.length > 0) {
pinus.app.rpc.guild.guildRemote.gvgBattleStart.toServer(guildServers[0].id);
}
// 发放道具
if(gvgBattleSecondJob) gvgBattleSecondJob.cancel();
gvgBattleSecondJob = scheduleJob('gvgBattleSecondJob', '*/5 * * * * *', gvgBattleSecondSchedule);
if(gvgBattleCatapultJob) gvgBattleCatapultJob.cancel();
gvgBattleCatapultJob = scheduleJob('gvgBattleCatapultJob', `*/${GVG.GVG_CATAPULT_TIME} * * * * *`, gvgBattleCatapult);
}
// 每隔5秒的积分计算定时器
async function gvgBattleSecondSchedule() {
// console.log('********** gvgBattleSecondJob *************');
}
// 每隔10秒的投石车投机定时器
async function gvgBattleCatapult() {
console.log('********** gvgBattleCatapultJob *************');
pinus.app.rpc.guild.guildRemote.catapultHurt.broadcast();
}
// gvg激战期结束定时器
async function gvgBattleEndSchedule() {
// 排行榜发放奖励
// 城池占领情况
// 定时器关闭
if(gvgBattleSecondJob) {
gvgBattleSecondJob.cancel();
gvgBattleSecondJob = undefined;
}
if(gvgBattleCatapultJob) {
gvgBattleCatapultJob.cancel();
gvgBattleCatapultJob = undefined;
}
}
// —————————————— gvg end —————————————— //

View File

@@ -75,6 +75,7 @@ export enum GVG_ITEM {
PRODUCE_COIN = 10, // 内政令
FIGHT_COIN = 11, // 征战令
BATTLE_FEAT = 12, // 战功
KNIFE = 14, // 诸葛连弩
}
export enum GVG_RESOURCE_TYPE {
@@ -130,4 +131,15 @@ export enum VESTIGE_STATUS {
CHECK = 1, // 出兵中
BATTLE = 2, // 战斗中
COMPLETE = 3, // 战斗结束
}
}
export enum GVG_AREA_TYPE {
DEFENSER = 1, // 1-守方备战区
ATTACKER = 2, // 2-攻方备战区
BIG = 3, // 3-大据点区
MIDDLE = 4, // 4-中据点区
SMALL = 5, // 5-小据点区
CATAPULT = 6, // 6-投石车区
}
export const GVG_CATAPULT = 'catapult';

View File

@@ -1116,6 +1116,7 @@ export enum ITEM_CHANGE_REASON {
GVG_VESTIGE_START = 170, // gvg征战中原挑战
GVG_VESTIGE_END = 171, // gvg征战中原挑战
GVG_VESTIGE_RECEIVE_RANK = 172, // gvg征战中原领取排行榜奖励
GVG_TECH_SEND_KNIFE = 173, // gvg点科技树发放诸葛连弩
}
export enum TA_EVENT {

View File

@@ -75,6 +75,12 @@ export default class GVGCity extends BaseModel {
const cities: GVGCityType[] = await GVGCityModel.find({ configId, groupId, serverType, hasGuard: true }).lean();
return cities
}
// 查询有联军驻守的城池
public static async findAllGuardCities(configId: number) {
const cities: GVGCityType[] = await GVGCityModel.find({ configId, hasGuard: true }).lean();
return cities
}
}

View File

@@ -141,6 +141,11 @@ export default class GVGLeaguePrepare extends BaseModel {
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({ configId, leagueCode }, { $set: { lv }}, { new: true }).lean();
return result;
}
public static async findByConfigId(configId: number) {
const result: GVGLeaguePrepareType[] = await GVGLeaguePrepareModel.aggregate([{ $match: {configId} }]);
return result;
}
}
export const GVGLeaguePrepareModel = getModelForClass(GVGLeaguePrepare);

View File

@@ -3,10 +3,11 @@ import BaseModel from "./BaseModel";
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { genCode } from "../pubUtils/util";
import { nowSeconds } from "../pubUtils/timeUtil";
import { GVG } from "../pubUtils/dicParam";
import { EXTERIOR, GVG } from "../pubUtils/dicParam";
import { DicGVGAreaPoint } from "../pubUtils/dictionary/DicGVGAreaPoint";
import { InitTeamParam, SaveTeamUpdateParam } from "../domain/gvgField/gvgDb";
import { GVGHeroInfo } from "../domain/dbGeneral";
import { GVG_CATAPULT } from "../consts";
@index({ roleId: 1, index: 1 })
@index({ teamCode: 1 })
@@ -106,12 +107,18 @@ export default class GVGTeam extends BaseModel {
@prop({ required: true, default: false })
isRobot: boolean; // 是否是机器人
@prop({ required: true, default: false })
captapultAtk: number; // 投石车的攻击力
@prop({ required: true, default: false })
isCatapult: boolean; // 是否是投石车
@prop({ required: true, default: false })
isBroken: boolean; // 机器人是否被击破,如果没有被击破,那么这个位置上就还是机器人,如果被击破了,这个位置就空出给玩家
@prop({ required: false })
batchCode: string; // 批量编号
// 创建队伍
public static async saveTeam(roleId: string, index: number, updateParam: SaveTeamUpdateParam, initParam: InitTeamParam) {
const doc = new GVGTeamModel();
@@ -192,7 +199,10 @@ export default class GVGTeam extends BaseModel {
return {
updateOne: {
filter: { groupId, serverType, cityId, areaId, pointId },
update: { $setOnInsert: { teamCode: genCode(8), maxDurability: durability, roleName: name, head, spine, lineupCe: ce, isRobot: true, isBroken: false, startMoveTime: 0, stopMoveTime: 0 }, $set: { configId, durability } },
update: { $setOnInsert: {
teamCode: genCode(8), maxDurability: durability, roleName: name, head, spine, frame: EXTERIOR.EXTERIOR_FACECASE, lineupCe: ce, isRobot: true,
isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', leagueCode: '', leagueName: ''
}, $set: { configId, durability } },
upsert: true
}
}
@@ -200,6 +210,30 @@ export default class GVGTeam extends BaseModel {
return await this.findRobotTeams(groupId, serverType, cityId);
}
public static async findCatapultTeams(groupId: number, serverType: number, cityId: number) {
const team: GVGTeamType[] = await GVGTeamModel.find({ groupId, serverType, cityId, isRobot: true, isCatapult: true }).lean();
return team;
}
// 生成投石车
public static async initCatapult(configId: number, groupId: number, serverType: number, cityId: number, leagueCode: string, leagueName: string, areaIds: number[], atk: number, durability: number) {
await GVGTeamModel.bulkWrite(areaIds.map(areaId => {
return {
updateOne: {
filter: { groupId, serverType, cityId, areaId },
update: { $setOnInsert: {
teamCode: genCode(8), maxDurability: durability, captapultAtk: atk, leagueCode, leagueName,
roleName: GVG.GVG_CATAPULT_NAME, head: GVG.GVG_CATAPULT_HEAD, spine: GVG.GVG_CATAPULT_SPINE, frame: EXTERIOR.EXTERIOR_FACECASE, lineupCe: GVG.GVG_CATAPULT_CE,
isRobot: true, isCatapult: true,
isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', pointId: 0, roleId: GVG_CATAPULT
}, $set: { configId, durability } },
upsert: true
}
}
}));
return await this.findCatapultTeams(groupId, serverType, cityId);
}
// 攻击方攻击cd
public static async battleStartLockAttack(teamCode: string) {
const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { attackTime: nowSeconds() + GVG.GVG_DEFAULT_ATTACK_CD } }, { new: true }).lean();
@@ -256,6 +290,19 @@ export default class GVGTeam extends BaseModel {
return await GVGTeamModel.exists({ configId, groupId, serverType, pointId });
}
// 投石车伤害
public static async attackByCatapult(teamCodes: string[], inc: number, rebirthAreaId: number) {
let batchCode = genCode(8);
await GVGTeamModel.updateMany({ teamCode: { $in: teamCodes } }, { $inc: { durability: -inc }, $set: { batchCode } });
let brokenTeams: GVGTeamType[] = await GVGTeamModel.find({ batchCode, durability: { $lte: 0 } }).lean();
if(brokenTeams.length > 0) {
await GVGTeamModel.bulkWrite(brokenTeams.map(({ teamCode, maxDurability }) => {
return { updateOne: { filter: { teamCode }, update: { $set: { areaId: rebirthAreaId, pointId: 0, durability: maxDurability } }}}
}));
}
let teams: GVGTeamType[] = await GVGTeamModel.find({ batchCode }).lean();
return teams
}
}

View File

@@ -1,4 +1,5 @@
import GVGTeam, { GVGTeamType } from "../../db/GVGTeam";
import { nowSeconds } from "../../pubUtils/timeUtil";
// 积分点分类统计1-3级积分点代表从小到大
export class LeagueCityPoint {
@@ -25,27 +26,14 @@ export class GVGTeamMem extends GVGTeam {
constructor(team: GVGTeamType) {
super();
this.roleId = team.roleId;
this.roleName = team.roleName;
this.serverId = team.serverId;
this.teamCode = team.teamCode;
this.index = team.index;
this.leagueCode = team.leagueCode;
this.guildCode = team.guildCode;
this.areaId = team.areaId;
this.fromAreaId = team.fromAreaId;
this.cityId = team.cityId;
this.pointId = team.pointId;
this.head = team.head;
this.spine = team.spine;
this.frame = team.frame;
this.durability = team.durability;
this.restartTime = team.restartTime;
this.attackTime = team.attackTime;
this.defenseTime = team.defenseTime;
this.startMoveTime = team.startMoveTime;
this.stopMoveTime = team.stopMoveTime;
this.score = team.score;
this.updateTeam(team);
}
public updateTeam(team: GVGTeamType) {
for(let key in team) {
this[key] = team[key];
}
this.isMoving = this.stopMoveTime > nowSeconds();
}
public setCity(cityId: number, areaId = 0, pointId = 0) {
@@ -60,11 +48,4 @@ export class GVGTeamMem extends GVGTeam {
this.startMoveTime = startMoveTime;
this.stopMoveTime = stopMoveTime;
}
public battleEnd(team: GVGTeamType) {
this.durability = team.durability;
this.restartTime = team.restartTime;
this.defenseTime = team.defenseTime;
this.stopMoveTime = team.stopMoveTime;
}
}

View File

@@ -623,6 +623,10 @@ export class GVGTeamSpineInMap {
isMoving: boolean = false;
pointId: number = 0;
fromAreaId: number = 0;
teamCode: string = '';
leagueCode: string = '';
leagueName: string = '';
constructor(obj: GVGTeamMem, serverNames: {[serverId: string]: string}) {
this.spine = obj.spine;
@@ -633,6 +637,9 @@ export class GVGTeamSpineInMap {
this.isMoving = nowSeconds() < this.stopMoveTime;
this.pointId = obj.pointId;
this.fromAreaId = obj.fromAreaId;
this.teamCode = obj.teamCode;
this.leagueCode = obj.leagueCode;
this.leagueName = obj.leagueName;
}
}
@@ -680,6 +687,27 @@ export class GVGTeamInListOnPoint extends GVGTeamInList {
}
}
export class MyTeamSimpleInfo {
teamCode: string; // 队伍唯一id
index: number; // 队伍位置
head: number; // 保存头像
frame: number; // 保存相框
spine: number; // 保存形象
lineup: {
actorId: number; // 武将
dataId: number; // 出兵表上的位置
order: number; // 行动
}[];
constructor(team: GVGTeamType) {
this.teamCode = team.teamCode;
this.index = team.index;
this.head = team.head;
this.frame = team.spine;
this.lineup = team.lineup.map(({ actorId, dataId, outIndex }) => ({ actorId, dataId, order: outIndex }));
}
}
// 更新自己队伍时候的比较详细点的数据
export class MyTeamInfo {
teamCode: string; // 队伍唯一id

View File

@@ -371,14 +371,15 @@ export const ARTIFACT = {
};
export const GUIDE = {
GUIDE_FINGER_GK: 104, // 需要手指软引导的关卡
GUIDE_DEFEAT_GK: 104, // 通过该关卡后开启首次失败引导
};
export const GVG = {
GVG_LEAGUE_COMPOSE: 3, // 一个联军有最多多少军团组成
GVG_CROSS_SERVICE_STARTTIME: 4, // 开服几周后开始跨服玩法
GVG_ROLE_TOTAL_RATIO: 1.2, // 贤臣+猛将总人数上限系数
GVG_ROLE_RATIO: 1.2, // 贤臣/猛将各职能选择人数上限系数
GVG_PRODUCER_GET: '10&4|11&2', // 贤臣每天发多少令
GVG_FIGHTER_GET: '10&2|11&4', // 猛将每天发多少令
GVG_ROLE_RATIO: 1, // 贤臣/猛将各职能选择人数上限系数
GVG_PRODUCER_GET: '10&6|11&2', // 贤臣每天发多少令
GVG_FIGHTER_GET: '10&2|11&6', // 猛将每天发多少令
GVG_LEAGUE_TECH_LIST: 3, // 科技树解锁队列数量
GVG_LEAGUE_ACTIVE_POINT: '1&2|2&2|3&2|4&2', // 活跃的来源
GVG_SERVICETYPE_VESTIGE: '1&1|2&3', // 单服和跨服随机出几个遗迹点